Ignore supplied issuers for the default application group and validate
replacements using installed CA certificates. Add regression tests.
# Description
Certificate renewal could fail when the client omitted the issuer
certificate, even though that CA was already installed on the server.
Use the server’s configured trust stores and ignore supplied issuers for
the default application group. Clients must install CA trust material
before renewal; supplied issuers are no longer imported.
Existing validation policy and ApplyChanges behavior are preserved.
## Checklist
_Put an `x` in the boxes that apply. You can complete these step by step
after opening the PR._
- [X] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [X] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [ ] I have added all necessary documentation.
- [ ] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
Populate ApplicationUri and ProductUri from application configuration,
guarding absent optional nodes. Add push tests verifying both values
match the advertised server identity.
# Description
Addresses the reported CTT complaint for Push Model for Global
Certificate and TrustList Management, where these ServerConfiguration
properties returned null:
- ApplicationUri (ns=0;i=25706)
- ProductUri (ns=0;i=25725)
Initializes both properties from the application configuration, with
guards for absent optional nodes.
Validation: regression tests verify Good status and nonempty values
matching the advertised server identity. All five variants pass; the
full push fixture reports 116 passed, 9 expected skips, and no failures
on .NET 10. CTT itself has not been rerun.
## Checklist
_Put an `x` in the boxes that apply. You can complete these step by step
after opening the PR._
- [X ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [X] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [ ] I have added all necessary documentation.
- [X] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
## Proposed changes
Backport of the #3931 fix to master378. On this branch, server-side GDS
Push `UpdateCertificate` validated the new application certificate with
a throwaway `CertificateValidator` that was never seeded with the
server's `SecurityConfiguration`. It therefore enforced hard-coded
defaults (`MinimumCertificateKeySize = 2048`,
`RejectSHA1SignedCertificates = true`) regardless of operator
configuration — e.g. a server configured for a 1024-bit minimum still
rejected a re-issued 1024-bit certificate with
`BadCertificatePolicyCheckFailed`. Regression originated in #3795
(integrity check switched from a lenient `X509Chain` check to the full
validator).
The master branch reworked this area entirely, so the fix is
re-implemented from scratch here, adapted to master378's
`X509Certificate2` types.
- **`ConfigurationNodeManager.UpdateCertificateAsync`**: replaced the
throwaway `CertificateValidator` with a lenient `X509Chain` integrity
check that verifies only chain integrity — valid signatures and a
complete issuer chain — using the caller-supplied issuers as the trust
anchor (`AllowUnknownCertificateAuthority`, revocation `NoCheck`,
downloads disabled). Policy (min key size, SHA-1, revocation) is
intentionally **not** applied here; it remains governed by the server's
`SecurityConfiguration` on its normal communication channels, so
configured values are honored in both stricter and more-lenient
directions.
Chain status handling: `NoError`/`UntrustedRoot` pass;
`NotSignatureValid`/`PartialChain`/`NotValidForUsage`/`InvalidBasicConstraints`
fail with `BadSecurityChecksFailed`; and the chain element count must
match the supplied issuer count to reject incomplete chains.
This pull request modernizes the OPC UA .NET codebase and tests, removes .NET Standard 2.0 support from certificate/security code, and updates test code to use C# 12 and .NET 8+ features for clarity and maintainability.
- Certificate and BouncyCastle interop files (e.g., CertificateBuilder.cs, X509Extensions.cs, X509SignatureFactory.cs) are refactored to drop NETSTANDARD2_0 support and use modern .NET APIs and conditional compilation.
- Test code across the codebase is updated to use default, strongly-typed Parse methods, collection expressions, and improved async/await patterns.
- Exception handling and assertions in tests are modernized, and test method naming is made consistent with Async suffixes.
- The project and build files are updated to clarify Roslynator analyzer usage and remove obsolete netstandard tags.
- General code and test cleanup includes improved null safety, type safety, and removal of deprecated or unused code.
Refactor to make OPC UA server subscription and monitored item management fully asynchronous, improving scalability and responsiveness. All key methods in ISubscription, ISubscriptionManager, and related classes are now async, with synchronous counterparts removed.
This change adds a **new Opc.Ua.Types** nuget that contains core types that do not rely on generated code. Why the name? Because almost all code that was in the Types subfolder is part of it, and because we do not want to change the name of the Opc.Ua.Core nuget/assembly because code relies on it. Any other name like base or bootstrap felt out of place due to the current structure already defining the name "types". Key design is to depend on only a small set of libraries with limited transitive dependencies, that includes hashcode, logging.abstraction, and for non standard20 builds System.Text.Json (needed for localizedText mul parsing). Also, key is to support .netstd 2.0 to support source generators and to allow removal of EEC_SUPPORT defines by removing std2.0 from core and all libraries.
The changes are mostly restructuring, and thus small but contain some key changes:
- **Status code** struct now comes with a Symbol field, which is used to carry symbols in case the code is not generated. Currently (until generated) the status code struct must be manually created with a symbol or the ToSymbolicId extension must be called in the core project. Future will generate Status code constants just like NodeId that contain the symbol which also removes the reflection-based lookup. Several tests needed to be adjusted as they checked the status code symbol strings instead of the code.
- **Core identifiers** are copied as they were needed for code to compile, that includes attributes, a subset of status codes and node identifiers. These will never change so no need to generate them.
- The types folder now contains **encoders**, except for json which is still in core. Once the json encoder is ported to system.text.json it will also be included and Newtonsoft.Json dropped as dependency (-> #3329).
- Since types relies on **IOperationContext** and **ISystemContext**, and these export IUserIdentity which relies on crypto, these were split and extended in core with ISessionOperationContext and ISessionSystemContext, which mean changes to ServerSystemContext and introduction of SessionOperationContext and SessionSystemContext classes that extend OperationContext and SystemContext. Some runtime checks in the server are therefore needed to get at the session and auth info, however, those are anyway optional fields and are not on the critical paths, and thus a type check is in order (and was done in the past already, but against OperationContext class).
- **Manifest resources** are now split between Core (nodeset zip, some generated resoures) and Types (built in bsd/xsds). This needs to be revisited later if the bsd/xsd need to be regenerated during type generation. Note that the embedded resource names changed as a result. Since these are only used internally and do not constitute public API this feels reasonable vs duplication of resources in 2 assemblies.
- Reflection however now needs to load not just the built in **encodeables** from Opc.Ua.Types assembly, but also the generated encodeables from Opc.Ua.Core assembly. For this a new helper Utils method was added to get the Core assembly when linked against Opc.Ua.Core otherwise null.
- Whatever utils methods needed to be split out into the new Opc.Ua.Types assembly, they are now in **CoreUtils** static class in Opc.Ua.Types, and Utils.xxxx forwards to them to ensure minimal changes. Later we would want to obsolete them in favor of CoreUtils, although it might make sense to split them again into domain specific utilities, such as networking, files, etc
* Added RejectCertificateUriMismatch property and explicit ApplicationUri validation after certificates are loaded
* Perform duplicate detection on thumbprint only
* Ported handle multiple ApplictionUri, removed assign ApplictionUri from certificate
* Missing letter
* Fixed LoadPrivateKeyAsync when no applicationUri is passed.
* Add tests for validating certificates with multiple AplicationUris on ApplicationInstance level and server side
* Renamed into CheckOrCreateCertificateAsync, logged Certificate, improved tests
* Added retry logic for transient connect errors in CreateSessionApplicationUriValidationTests
* Added TODO log when telemetry instance available
* Removed unused ValidateServerCertificateApplicationUri(X509Certificate2 serverCertificate)
* Include domains and applicationName in ServerCertificate for CreateSigningRequestAsync with parameter regeneratePrivateKey = true
* Update Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- Allow setting ReturnDiagnostics on the session factory to ensure the diagnostic settings are part of "Create" also. Set them to SymbolicIdAndText by default.
- Better logging in unit tests, now also logs to progress including exception traces, also prefixes SERVER and TEST on console to attach the logs to the server or client side.
- GDS client stability improvements to ensure client reliably reconnects between calls when connection is lost.
- Do not dispose the application certificate when it is updated from GDS client to avoid existing sessions to crash with CryptographicException. This needs more improvements later on because it is rather hacky today.
- Remove the certificate cache in CertificateFactory (as per discussion and agreement) which allowed re-enabling the older UserIdentity API
- Logging improvements here and there to analyze issues in unit tests better
* Update GDS Client to use async Client API
* Make GDS Tests use ECC for connection. Update Certifiacte wait check to use polling mechanism
* Use Async Server Methods
* Add specialized ECC Test procdure
* Add Exception handling to allow errors during server application certificate exchange
---------
Co-authored-by: Marc Schier <marcschier@users.noreply.github.com>
* Implement support for async method Call in the server
* Implement Cancellation
* Add new generated async supported Endpoints & Server Methods
* Make SecureChannelContext AsyncLocal
* Implement SubscriptionAsync
* Add Async Request Queue
* Implement sync calls for async NodeManagers. Add Warning
* Use second file for Async Interface
* Generate ECC Certificates in Client Tests
* Add more tests
* reenable check of certificate
* fix tests
* Dont use random in test
* fix unsupported certificate types
* fix Hash algorithm for nistP384 curve on linux as the friendly name is ECDSA_P384 instead of nistP384
* use friendly name by default and add special case only for linux while taking care of nullability
* disable special casing for finding correct certificates
* fix tests on net 462
* update Certificate Identifier
* update ServerConfiguration Node to support multiple Application Certificates. Trust List Support for User Certificates & Https Certificates
* GDS ready for ECC Step1
* fix test
* fix build
* ensure hash algorithm is set
* update configurations to new format, fix minor ecc bugs
* implicitly set certificate type of certificate identifier
extend CertificateFactory to allow Revocation with ECC Issuer Certificate
* Revert "update configurations to new format, fix minor ecc bugs"
This reverts commit 9ee17f3aff.
* Allow GDS Certificate Group to have multiple CA Certificates with different Certificate Types
* fix minor bugs
* adress review feedback
* fix some issues
* fix creation of CA signed ECC Certificates
* Update configurations to new ApplicationCertificateFormat and add extra CA Certificates for ECC Certificates
* remove brainpool certs from configuration
* Generate ECC Certificates in Client Tests
* Revert "Generate ECC Certificates in Client Tests"
This reverts commit 90b395f4ff.
* fix crl tests on platforms not supporting ECC
* fix crl test
* Update READMEs for ECC
- Port support for ECC NIST/Brainpool profiles from prototyping_ecc branch
- Implement CertProvider to load certs per connection / profile
- Backward compatibility of configuration for existing apps
- SecurityConfiguration specifies app cert types for each profile
- Autodetect the ECC support for brainpool/nist based on platform (mac OS 10 doesn't support brainpool)
- ECC supported on net48 / net5.0 / net 6.0 / netstandard2.1
- ECC supported on windows / linux / macOS (brainpool not < macOS11)
- Self signed certs for each profile are created on start similar to RSA
- RSA only profiles are supported on .NET standard 2.0
Co-authored-by: Martin Regen <mregen@microsoft.com>
* Enable regeneratePrivatekey for CreateSigningRequest method of Server
* only put needed info into cert, limit lifetime, use public key to get the key size
- Add a light weight AddRejected certificate store method to `ICertificateStore` to ensure rejected cert history remains small and doesn't have a lot of overhead.
- Number of history certificates is configurable using a new `MaxRejectedCertificates` entry.
- Rejected certs are only saved to directory cert store, others do ignore the attempt
- Fix the caching of `CertificateValidator` and flag some `ÒpenStore` methods deprecated which do not support the caching. Fixes across the board to support the methodology. Basically `store.Close` keeps the cache, `store.Dispose` clears the cache, so recommendation is to use `var store = certStoreIdentifier.OpenStore(); try { ... }-- finally { store.Close }`
* add GetCertificates Method to standard Server & GDS
* fix CheckRevocationStatus to use X509 Chain with Online Revocation Check & remove Check from GetCertificates
-Implement the support for ApplicationSelfAdmin privilege
-implement the workflow in a test to pull the trust list after sucessfully receiving a gds signed certificate.
-this authorization is described here in the OPC Spec: https://reference.opcfoundation.org/GDS/v105/docs/7.6
- move IUserDatabase + RoleBased Identity into standard Server
- subclass SystemConfigurationIdentity from RoleBased Identity for backward compatibility
- add OPC UA Spec Defined Roles to the RoleBasedIdentity
- In order to reduce leaking private key files on windows, `EphemeralKeySet` is used on supporting platforms.
- Keys from the Ephemeral Keyset can not be used with `CopyWithPrivateKey`, add support to copy these keys, e.g. for GDS push support.
- MacOS throws PlatformNotSupported when ephemeral keyset is used.
- Kestrel needs a dedicated key without the ephemeral keyset flag.
- Dispose private keys where possible to reduce number of leaked files in tests.
- For bouncy castle legacy support, do not use the `PersistKey` flag by default on netstandard2.0 and net462. However keys may still leak.
- Preserve the ASN.1 encoding of a CSR Subject in the issued certificate.
- However, a certificate issuer is allowed to change the Subject. Make the check on GDS Push only check the Subject string, to ensure the app config can still find the pushed cert after restart.
- found an issue during debugging the session disconnect may run into unnecessary exceptions as `ChannelShutdown` may be called twice.
* Fix for ReadTrustList test failure.
* fix .NET4.8 GDS push
* include .NET 4.8 in test pipeline
* fix audit event that may throw exception when server is halted
Co-authored-by: Randy Armstrong <randy@sparhawksoftware.com>
-Make the https callbacks fully async / code cleanup.
-Default https client to use MaxConnectionsToServer = 64 for #1550
-Fix https missing reconnect error code
other fixes unrelated to https:
- move trust list audit event to AuditEvents.cs, fix issue that the event is not filtered since reportAuditEvent cannot be used
- fix an issue when BrowseNext for multiple continuation tokens doesn't add the results array properly
- bump up .NET Core 3.1 Nuget dependencies
- improve .NET reference client app for use with https
- Move the auditing flag to server internal
- Hook up new configuration setting to the Auditing node
- A Security Admin can change the Audit setting.
- Refactor audit events to be extensions in one class.
- enable auditing and diagnostics by default for higher test coverage.
- refactor dependency of some events to bindings, e.g. TcpServerChannel should not be used as reportevent parameter
- Certificates should compare X500DistinguishedName with binary ASN.1 compare
- Other compares should follow ordinal and not resort DN entries
- Fix all related issues to pass tests, e.g. GDS certificates accepted with reversed Subject, cert validation
- Add defensive checks in cert validation
Co-authored-by: mrsuciu <Mircea-Adrian.Suciu@softing.com>
- integrate 'LoadPrivateKey' in the interface to allow to implement cert stores which require a passcode to load/store certificates
Change of behavior:
- Introduce a 'NoPrivateKeys' flag to reduce the risk of leaking a private key to a unsecure store.
- CertificateStoreIdentifier opens 'NoPrivateKey' stores
- CertificateTrustList opens 'NoPrivateKey' stores
- CertificateIdentifier opens store with private keys for application or GDS authority certificates
- CertificateTrustList reuses a store if it is not disposed. A user can just close the store to keep the list of certificates in memory.
- DirectoryStore `Load` does not read private keys anymore, only file names for delete. Reading all private keys caused false errors, e.g. here: #1670
Co-authored-by: mheege-abb <marcus.heege@de.abb.com>
Co-authored-by: mheege-abb <85437567+mheege-abb@users.noreply.github.com>
- support for Microsoft.Extensions.Logger.ILogger in Opc.Ua.Core as the new logging interface
- backward compatible with config and TraceEvents
- new API Utils.SetLogger allows to set ILogger
- updated Console samples to demonstrate ILogger support with Serilog
- support for EventSource logging
- see Docs/Logging.md for more info