Certificate security plugin: Difference between revisions

From OPC Labs Knowledge Base
 
(49 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[Category:Plugins]]
[[Category:MQTT]] [[Category:Plugins]]  


== Principles of operation ==
= Concepts =
The certificate security plugin extends its host by operations related to secure communications made with help of PKI (Public Key Infrastructure) certificates.


{{Warning|The Certificate security plugin is not used with OPC UA Client-Server certificates, because of the special needs of OPC UA Client-Server security. Its use is for other purposes, such as secured MQTT communications in OPC UA PubSub.}}
{{Warning|The Certificate security plugin is not used with OPC UA Client-Server certificates, because of the special needs of OPC UA Client-Server security. Its use is for other purposes, such as secured MQTT communications in OPC UA PubSub.}}
=== Get local certificates ===


=== Validate remote certificate ===
= Operations =
There are three operations provided by the certificate security plugin, explained below.


== Certificate security providers ==
== Get local certificates ==
Gets the local PKI (X.509) certificates used for authentication. As an input, the information about the consumer, and the target server is given. This operation returns a list of local certificates to be used for establishing the connection.


== Select local certificate ==
Currently not used by any of the consumers.


=== Composed ===
== Validate remote certificate ==
Verifies the remote PKI (X.509) certificate used for authentication. As an input, the information about the consumer, and the target server is given, as well as the certificate used to authenticate by the remote party, the chain of certificate authorities associated with the remote certificate, and possible transport (SSL) errors associated with the remote certificate. The specified certificate is either accepted or rejected for authentication by this operation.


= Certificate security providers =
The Certificate security plugin is based on concept of Certificate security providers. Each of the providers is capable of performing the security operations in certain way. The Certificate security plugin then composes the individual providers into a single one. Seen from the outside, the Certificate security plugin behavior is as described for the "Composed" provider below. The descriptions for the individual providers then follow.
== Composed ==
The composed certificate security provider, as defined by the Certificate security plugin, takes each of the allowed constituent providers in the order listed in the table below, and asks it to perform the requested operation. The constituent provider can either:
* Perform and finalize the operation. In this case, the subsequent constituent providers will not be involved in the operation.
* Ignore the operation (pass it over). In this case, the composed provider will ask the next constituent provider to perform the operation, and so on.
The overall behavior can be influenced by allowing or disallowing the constituent providers, and parameterizing them as needed.


{| class="wikitable"
{| class="wikitable"
!Order
!Order
!Enabled by
!Enabled by
!Enabled default
!Parameterized by
!Parameterized by
!Description
!Description
Line 22: Line 36:
|1
|1
|{{Style=Identifier|AllowStatic}}
|{{Style=Identifier|AllowStatic}}
|True
|{{Style=Identifier|StaticCertificateSecurityParameters}}
|{{Style=Identifier|StaticCertificateSecurityParameters}}
|
|Configuration settings determine how the security choices will be made.
|-
|-
|2
|2
|{{Style=Identifier|AllowHandler}}
|{{Style=Identifier|AllowHandler}}
|
|True
|
| -
|A code written by the developer and hooked to event handlers makes the security choices.
|-
|-
|3
|3
|{{Style=Identifier|AllowInteractive}}
|{{Style=Identifier|AllowInteraction}}
|
|True
|
| -
|The security choices are made by the end user interactively.
|}
|}
In order to make it clearer what is the effect of various combinations, the table below lists the resulting behavior for various combinations of {{Style=Identifier|AllowXXXX}} settings. For simplicity, it is assumed that there is no custom code attached by the Handler certificate security provider (or that this provider is disabled).
The "consumer" is the part of the software that has requested the certificate security operation. In might be e.g. one of the [[MQTT communication packages]].


{| class="wikitable"
{| class="wikitable"
! {{Style=Identifier|AllowStatic}} setting
! {{Style=Identifier|AllowStatic}} setting
! {{Style=Identifier|AllowInteractive}} setting
! {{Style=Identifier|AllowInteraction}} setting
! Get local certificates
! Get local certificates
! Validate remote certificate
! Validate remote certificate
Line 54: Line 74:
|True
|True
|False
|False
|Local certificates are obtained according to {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|LocalCertificatesQuery}} setting (certificates can be read from certificate files, and/or looked up according to specified criteria in a certificate store).
|rowspan="2"|Local certificates are obtained according to {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|LocalCertificatesQuery}} setting (certificates can be read from certificate files, and/or looked up according to specified criteria in a certificate store). The default {{Style=Identifier|LocalCertificatesQuery}} returns no local certificates.
|The remote certificate is accepted if it complies with the {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|RemoteCertificateAcceptancePolicy}} setting.
|The remote certificate is accepted if it complies with the {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|RemoteCertificateAcceptancePolicy}} setting.
|-
|-
|True
|'''True'''
|True
|'''True'''
|Local certificates are obtained according to {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|LocalCertificatesQuery}} setting (certificates can be read from certificate files, and/or looked up according to specified criteria in a certificate store).
|The remote certificate is accepted if it complies with the {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|RemoteCertificateAcceptancePolicy}} setting. Otherwise, the user is allowed to accept or reject the remote certificate.
|The remote certificate is accepted if it complies with the {{Style=Identifier|StaticCertificateSecurityParameters}}.{{Style=Identifier|RemoteCertificateAcceptancePolicy}} setting. Otherwise, the user is allowed to accept or reject the remote certificate.
|}
|}


=== Static ===
== Static ==
The Static certificate security provider does not distinguish between (ignores) the different purposes/consumers of the operation (such as that the local certificates may be provided for MQTT, or for AMQP), and also different targets (for which server are the local certificates intended, or from which server the remote certificate came). If you need that level of granularity, use the Handler certificate security provider (and make the distinction in your code), or the Interaction certificate security provider (and let the end user make the decisions).


=== Handler ===
=== Local certificate queries ===
The parameters in the {{Style=Identifier|LocalCertificatesQueries}} specify queries for supplying local certificates. Each query returns a certificates located in the file system or in a specified certificate store. The {{Style=Identifier|SourceType}} property in the {{Style=Identifier|CertificatesQuery}} determines where the certificates will come from.


=== Interactive ===
Certificates located in the file system are specified using the {{Style=Identifier|FileName}} property. Use an absolute path (recommended), or a path relative to the current directory.


Certificates located in a PKI certificate store are specified using a combination of following properties:
* {{Style=Identifier|FindValue}}: Specifies one or more sources of security certificates.
* {{Style=Identifier|StoreLocation}}: Specifies the location of the PKI certificate store.<ref>For more information, see https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.storelocation .</ref>
* {{Style=Identifier|StoreName}}: Specifies the name of the PKI certificate store.<ref>For more information, see https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.storename .</ref>
* {{Style=Identifier|PkiFindType}}: Specifies the type of value to search for in PKI certificate store.<ref>For more information, see https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509findtype .</ref>
A typical query might specify to find certificates with certain subject name, or certain template name.


== Usage ==
=== Remote certificate acceptance policy ===
The certificate acceptance policy has following properties:
* {{Style=Identifier|AcceptAnyCertificate}}: Determines whether any certificate will be accepted, even if a certificate validation error occurs. Note: When this property is True, it effectively bypasses an important security feature. Use this value only for testing and development purposes, or if your application does not require  the certificate check.


=== In code ===
== Handler ==
With the Handler certificate security provider, you achieve the highest level of control over the certificate security operations - at the expense of having to write the code the handles them. When the {{Style=Identifier|AllowHandler}} property in the Certificate security plugin is True (the default), the plugin places an {{Style=Identifier|ICertificateSecurityHandler}} service into the service container of the plugin host. You can can retrieve the {{Style=Identifier|ICertificateSecurityHandler}} service from the host, and hook your own event handlers to it. The {{Style=Identifier|ICertificateSecurityHandler}} service exposes following events:
* {{Style=Identifier|GetLocalCertificates}}: Raised to supply the local certificates used for authentication.
* {{Style=Identifier|ValidateRemoteCertificate}}: Raised to verify the remote certificate used for authentication.
The events have event arguments that contain all inputs needed for the operation, and also provide a place for your code to place the result. When getting local certificates, your code needs to fill in the {{Style=Identifier|GetCertificatesEventArgs}}.{{Style=Identifier|CertificatesResult}} property (a value result with collection of certificates obtained). When validating the remote certificate, your code needs to fill in the {{Style=Identifier|GetCertificatesEventArgs}}.{{Style=Identifier|ValidationResult}} property (a Boolean - determines whether the specified certificate is accepted for authentication).


=== In command-line tools ===
How precisely you retrieve the {{Style=Identifier|ICertificateSecurityHandler}} depends on the hosting software. In QuickOPC (with {{Style=Identifier|EasyUASubscriber}} object), you can use following code:
 
<pre>
ICertificateSecurityHandler certificateSecurityHandler = EasyUASubscriber.SharedServiceProvider.GetService<ICertificateSecurityHandler>();
</pre>
 
== Interaction ==
The Interaction certificate security provider allows the end user to make the security choices (to certain degree).
 
How the interaction actually looks like depends on the technology used by your application, Currently, two types of interaction are possible:
* Console
* Windows Forms (on Windows only)
Which interaction type will actually take place is dynamically decided at run time by the plugin, automatically. The Windows Forms interaction is internally implemented using the Windows Forms technology, but (despite its name) is  suitable for almost any kind of windowed user interface on Windows.
 
User responses are memoized for the lifetime of the process (application domain in .NET Framework). That is, the user will not be asked the same question for the same combination of inputs (e.g. validating the same remote certificate for the same purpose and from the same server).
 
Since the requests for certificate security operations come at generally unpredictable times (such as when the secured connection is being opened), and the user interaction mechanism is largely unaware of other user interface activities that are going on in the same program, the user needs to be prepared for the fact that interaction from the certificate security plugin can interrupt the normal flow of operation.
 
Ideally, all requests to the user will have some timeout, so that the underlying operation is not blocked for prolonged periods of time. Currently, not all user requests are timed in this way. However, no problem should normally arise, because successful operation without the certificate security requests is not possible anyway, and all consumers have an automatic reconnection mechanism, meaning that even if their internal timeout causes the connection to fail while the user has not yet provided the required response, the connection will be made in the end, after the user finishes the response.
 
=== Console ===
For getting the local certificates, the user is shown a list of default certificates, and is allowed to either accept the default list, or specify a name of the file where the local certificate to be used is stored, as in the example output below. Current limitations: Only one certificate file can be specified. Querying a certificate store is not supported.
<pre>
Local certificates for: MQTT client connection to mqtts://test.mosquitto.org (MqttNet)
Supply local certificate(s) for authentication to mqtts://test.mosquitto.org .
There are 0 default certificates.
Certificate file name (Enter=use default certificates)? client.crt
Loaded certificate: OU=Software Engineering, S=PM, O="CODE Consulting and Development, s.r.o.", L=Plzen, CN=opclabs.com, C=CZ
</pre>
For validation of a remote certificate, the user is shown information related to the operation, together with information about the certificate. The user accepts or rejects the certificate by pressing a corresponding key.
 
<pre>
Validate remote certificate for: MQTT client connection to mqtts://test.mosquitto.org (MqttNet)
The identity of the remote computer cannot be verified. Do you want to connect anyway?
The remote computer could not be authenticated due to problems with its security certificate. It may be unsafe to proceed.
Information:
  Target: mqtts://test.mosquitto.org
  Associated status: Certificate chain errors.
 
  Subject: CN=test.mosquitto.org, OU=Public server, O=Mosquitto, L=Derby, S=United Kingdom, C=GB
  Issuer: E=roger@atchoo.org, CN=mosquitto.org, OU=CA, O=Mosquitto, L=Derby, S=United Kingdom, C=GB
  Valid from: 3/20/2019 3:21:39 PM
  Valid to: 3/16/2032 3:21:39 PM
  Thumbprint: E62D6F0D957ED20B74B1D55D404EEF992CE482F0
 
Do you want to accept the certificate anyway? [y/N]: Y
</pre>
When not redirected to a file, the console output is colorized.
 
=== Windows Forms ===
Getting local certificate is not currently supported.
For validation of a remote certificate, the user is presented a notifier window with information related to the operation, together with information about the certificate. The user accepts or rejects the certificate by pressing a corresponding button.
 
= Usage =
The plugin usage depends on its host.
== In code ==
In order to obtain or modify the settings of the Certificate security plugin, you need to obtain its parameters object (of type {{Style=Identifier|CertificateSecurityParameters}}).
How precisely you retrieve the {{Style=Identifier|CertificateSecurityParameters}} depends on the hosting software. In QuickOPC (with {{Style=Identifier|EasyUASubscriber}} object), you can use following code:
<pre>
CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();
</pre>
If you need to modify the settings, remembers that some of the parameters must be set soon enough - before the static activation of the component takes place.
 
Example: Publish over secure MQTT connection (with UADP message mapping), accepting any remote certificate.
<pre>
CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();
certificateSecurityParameters.StaticCertificateSecurityParameters.RemoteCertificateAcceptancePolicy.AcceptAnyCertificate = true;
</pre>
Example: Publish over secure MQTT connection (with UADP message mapping), allowing the user to specify the local certificate (by disabling the static certificate security provider).
<pre>
CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();
certificateSecurityParameters.AllowStatic = false;
</pre>
 
== In command-line tools ==
In some command-line tools such as [[:Category:OpcCmd Utility|OpcCmd Utility]] or [[:Category:UADemoPublisher|UADemoPublisher]], the Certificate security plugin is already set up and enabled.
=== UADemoPublisher ===
The Certificate security plugin integrates itself with the command-line options and commands. Options are made available that allow you to configure most of the Certificate security provider aspects from the command line.
 
The option short names for Certificate security plugin start with "-x-cs-", the long names start with "--X-CertificateSecurity-". Below is a listing of options and parameters values as available in the UADemoPublisher.


<pre>
<pre>
Options:
Options:
   -x-cs-ai|--X-CertificateSecurity-AllowInteraction <bool>                   Certificate security: Allow interaction (default True)
   -x-cs-ai|--X-CertificateSecurity-AllowInteraction <bool>             Certificate security: Allow interaction (default True)
   -x-cs-as|--X-CertificateSecurity-AllowStatic <bool>                         Certificate security: Allow static (default True)
   -x-cs-as|--X-CertificateSecurity-AllowStatic <bool>                   Certificate security: Allow static (default True)
   -x-cs-lcfn|--X-CertificateSecurity-LocalCertsFileName <string>              Certificate security: Local certs: File name (*)
   -x-cs-lcf|--X-CertificateSecurity-LocalCertFile <string>              Certificate security: Local certificate from file (*)
   -x-cs-lcfv|--X-CertificateSecurity-LocalCertsFindValue <string>            Certificate security: Local certs: Find value
   -x-cs-lcps|--X-CertificateSecurity-LocalCertPkiStore <pkiStoreQuery>  Certificate security: Local certificate from PKI store (*)
  -x-cs-lcsl|--X-CertificateSecurity-LocalCertsStoreLocation <storeLocation>  Certificate security: Local certs: Store location (default CurrentUser)
   -x-cs-rpaa|--X-CertificateSecurity-RemotePolicyAcceptAny <bool>       Certificate security: Remote policy: Accept any certificate
  -x-cs-lcsn|--X-CertificateSecurity-LocalCertsStoreName <storeName>          Certificate security: Local certs: Store name (default My)
  -x-cs-lcft|--X-CertificateSecurity-LocalCertsFindType <findType>            Certificate security: Local certs: Find type (default FindByThumbprint)
  -x-cs-lcst|--X-CertificateSecurity-LocalCertsSourceTypes <sourceTypes>      Certificate security: Local certs: Source types
   -x-cs-rpaa|--X-CertificateSecurity-RemotePolicyAcceptAny <bool>             Certificate security: Remote policy: Accept any certificate


Parameter values:
Parameter values:
   <findType>       FindByThumbprint/FindBySubjectName/FindBySubjectDistinguishedName/FindByIssuerName/FindByIssuerDistinguishedName/FindBySerialNumber/FindByTimeValid/FindByTimeNotYetValid/FindByTimeExpired/FindByTemplateName/FindByApplicationPolicy/FindByCertificatePolicy/FindByExtension/FindByKeyUsage/FindBySubjectKeyIdentifier
   <findType>               FindByThumbprint|FindBySubjectName|FindBySubjectDistinguishedName|FindByIssuerName|FindByIssuerDistinguishedName|FindBySerialNumber|FindByTimeValid|FindByTimeNotYetValid|FindByTimeExpired|FindByTemplateName|FindByApplicationPolicy|FindByCertificatePolicy|FindByExtension|FindByKeyUsage|FindBySubjectKeyIdentifier
   <sourceTypes>     None/File/PkiStore[,None/File/PkiStore]...
   <pkiStoreQuery>          <storeLocation>\<storeName>?<findType>:<string>
   <storeLocation>   CurrentUser/LocalMachine
   <storeLocation>         CurrentUser|LocalMachine
   <storeName>       AddressBook/AuthRoot/CertificateAuthority/Disallowed/My/Root/TrustedPeople/TrustedPublisher
   <storeName>             AddressBook|AuthRoot|CertificateAuthority|Disallowed|My|Root|TrustedPeople|TrustedPublisher
</pre>
</pre>
When you set a parameter in the {{Style=Identifier|LocalCertificatesQuery}} from command line, the {{Style=Identifier|SourceType}} is automatically set to include the source that corresponds to the parameter. For example, if you use the --X-CertificateSecurity-LocalCertFile option, the {{Style=Identifier|SourceType}} is automatically set to {{Style=Identifier|File}}, or if you use the --X-CertificateSecurity-LocalCertPkiStore option, the {{Style=Identifier|SourceType}} is automatically set to {{Style=Identifier|PkiStore}}.
The local certificate query is specified in a single formatted string that contains the store location, store name, the find type and the find value. The syntax can be seen from the "parameter values" listing above.
Example: Publish over secure MQTT connection (with UADP message mapping), specifying a local certificate from the specified certificate store and with a given thumbprint.
<pre>UADemoPublisher -muts -x-cs-lcps CurrentUser\My?FindByThumbprint:B488B2274EF93104C37F4F25B2AF8D1333C33696</pre>
Example: Publish over secure MQTT connection (with UADP message mapping), accepting any remote certificate.
<pre>UADemoPublisher -muts -x-cs-rpaa True</pre>
Example: Publish over secure MQTT connection (with UADP message mapping), allowing the user to specify the local certificate (by disabling the static certificate security provider).
<pre>UADemoPublisher -muts -x-cs-as False</pre>
=== OpcCmd Utility ===
Use commands (such as <code>get <key></code> or <code>set <key> <typedValue></code> under <code>uaSubscriber manage plugins configuration part CertificateSecurityParameters</code> to work with the Certificate security plugin configuration.

Latest revision as of 07:18, 19 September 2024


Concepts

The certificate security plugin extends its host by operations related to secure communications made with help of PKI (Public Key Infrastructure) certificates.

Warning-icon.png

Warning: The Certificate security plugin is not used with OPC UA Client-Server certificates, because of the special needs of OPC UA Client-Server security. Its use is for other purposes, such as secured MQTT communications in OPC UA PubSub.

Operations

There are three operations provided by the certificate security plugin, explained below.

Get local certificates

Gets the local PKI (X.509) certificates used for authentication. As an input, the information about the consumer, and the target server is given. This operation returns a list of local certificates to be used for establishing the connection.

Select local certificate

Currently not used by any of the consumers.

Validate remote certificate

Verifies the remote PKI (X.509) certificate used for authentication. As an input, the information about the consumer, and the target server is given, as well as the certificate used to authenticate by the remote party, the chain of certificate authorities associated with the remote certificate, and possible transport (SSL) errors associated with the remote certificate. The specified certificate is either accepted or rejected for authentication by this operation.

Certificate security providers

The Certificate security plugin is based on concept of Certificate security providers. Each of the providers is capable of performing the security operations in certain way. The Certificate security plugin then composes the individual providers into a single one. Seen from the outside, the Certificate security plugin behavior is as described for the "Composed" provider below. The descriptions for the individual providers then follow.

Composed

The composed certificate security provider, as defined by the Certificate security plugin, takes each of the allowed constituent providers in the order listed in the table below, and asks it to perform the requested operation. The constituent provider can either:

  • Perform and finalize the operation. In this case, the subsequent constituent providers will not be involved in the operation.
  • Ignore the operation (pass it over). In this case, the composed provider will ask the next constituent provider to perform the operation, and so on.

The overall behavior can be influenced by allowing or disallowing the constituent providers, and parameterizing them as needed.

Order Enabled by Enabled default Parameterized by Description
1 AllowStatic True StaticCertificateSecurityParameters Configuration settings determine how the security choices will be made.
2 AllowHandler True - A code written by the developer and hooked to event handlers makes the security choices.
3 AllowInteraction True - The security choices are made by the end user interactively.

In order to make it clearer what is the effect of various combinations, the table below lists the resulting behavior for various combinations of AllowXXXX settings. For simplicity, it is assumed that there is no custom code attached by the Handler certificate security provider (or that this provider is disabled). The "consumer" is the part of the software that has requested the certificate security operation. In might be e.g. one of the MQTT communication packages.

AllowStatic setting AllowInteraction setting Get local certificates Validate remote certificate
False False The consumer will use its default behavior for obtaining local certificates. The consumer will use its default behavior for validating the remote certificate.
False True The user is allowed to supply the local certificates (depending on the capabilities of the interaction provider), or use the provided defaults. The default local certificates for the interaction are given by the StaticCertificateSecurityParameters.LocalCertificatesQuery setting (even though AllowStatic is set False). The user is allowed to accept or reject the remote certificate.
True False Local certificates are obtained according to StaticCertificateSecurityParameters.LocalCertificatesQuery setting (certificates can be read from certificate files, and/or looked up according to specified criteria in a certificate store). The default LocalCertificatesQuery returns no local certificates. The remote certificate is accepted if it complies with the StaticCertificateSecurityParameters.RemoteCertificateAcceptancePolicy setting.
True True The remote certificate is accepted if it complies with the StaticCertificateSecurityParameters.RemoteCertificateAcceptancePolicy setting. Otherwise, the user is allowed to accept or reject the remote certificate.

Static

The Static certificate security provider does not distinguish between (ignores) the different purposes/consumers of the operation (such as that the local certificates may be provided for MQTT, or for AMQP), and also different targets (for which server are the local certificates intended, or from which server the remote certificate came). If you need that level of granularity, use the Handler certificate security provider (and make the distinction in your code), or the Interaction certificate security provider (and let the end user make the decisions).

Local certificate queries

The parameters in the LocalCertificatesQueries specify queries for supplying local certificates. Each query returns a certificates located in the file system or in a specified certificate store. The SourceType property in the CertificatesQuery determines where the certificates will come from.

Certificates located in the file system are specified using the FileName property. Use an absolute path (recommended), or a path relative to the current directory.

Certificates located in a PKI certificate store are specified using a combination of following properties:

  • FindValue: Specifies one or more sources of security certificates.
  • StoreLocation: Specifies the location of the PKI certificate store.[1]
  • StoreName: Specifies the name of the PKI certificate store.[2]
  • PkiFindType: Specifies the type of value to search for in PKI certificate store.[3]

A typical query might specify to find certificates with certain subject name, or certain template name.

Remote certificate acceptance policy

The certificate acceptance policy has following properties:

  • AcceptAnyCertificate: Determines whether any certificate will be accepted, even if a certificate validation error occurs. Note: When this property is True, it effectively bypasses an important security feature. Use this value only for testing and development purposes, or if your application does not require the certificate check.

Handler

With the Handler certificate security provider, you achieve the highest level of control over the certificate security operations - at the expense of having to write the code the handles them. When the AllowHandler property in the Certificate security plugin is True (the default), the plugin places an ICertificateSecurityHandler service into the service container of the plugin host. You can can retrieve the ICertificateSecurityHandler service from the host, and hook your own event handlers to it. The ICertificateSecurityHandler service exposes following events:

  • GetLocalCertificates: Raised to supply the local certificates used for authentication.
  • ValidateRemoteCertificate: Raised to verify the remote certificate used for authentication.

The events have event arguments that contain all inputs needed for the operation, and also provide a place for your code to place the result. When getting local certificates, your code needs to fill in the GetCertificatesEventArgs.CertificatesResult property (a value result with collection of certificates obtained). When validating the remote certificate, your code needs to fill in the GetCertificatesEventArgs.ValidationResult property (a Boolean - determines whether the specified certificate is accepted for authentication).

How precisely you retrieve the ICertificateSecurityHandler depends on the hosting software. In QuickOPC (with EasyUASubscriber object), you can use following code:

ICertificateSecurityHandler certificateSecurityHandler = EasyUASubscriber.SharedServiceProvider.GetService<ICertificateSecurityHandler>();

Interaction

The Interaction certificate security provider allows the end user to make the security choices (to certain degree).

How the interaction actually looks like depends on the technology used by your application, Currently, two types of interaction are possible:

  • Console
  • Windows Forms (on Windows only)

Which interaction type will actually take place is dynamically decided at run time by the plugin, automatically. The Windows Forms interaction is internally implemented using the Windows Forms technology, but (despite its name) is suitable for almost any kind of windowed user interface on Windows.

User responses are memoized for the lifetime of the process (application domain in .NET Framework). That is, the user will not be asked the same question for the same combination of inputs (e.g. validating the same remote certificate for the same purpose and from the same server).

Since the requests for certificate security operations come at generally unpredictable times (such as when the secured connection is being opened), and the user interaction mechanism is largely unaware of other user interface activities that are going on in the same program, the user needs to be prepared for the fact that interaction from the certificate security plugin can interrupt the normal flow of operation.

Ideally, all requests to the user will have some timeout, so that the underlying operation is not blocked for prolonged periods of time. Currently, not all user requests are timed in this way. However, no problem should normally arise, because successful operation without the certificate security requests is not possible anyway, and all consumers have an automatic reconnection mechanism, meaning that even if their internal timeout causes the connection to fail while the user has not yet provided the required response, the connection will be made in the end, after the user finishes the response.

Console

For getting the local certificates, the user is shown a list of default certificates, and is allowed to either accept the default list, or specify a name of the file where the local certificate to be used is stored, as in the example output below. Current limitations: Only one certificate file can be specified. Querying a certificate store is not supported.

Local certificates for: MQTT client connection to mqtts://test.mosquitto.org (MqttNet)
Supply local certificate(s) for authentication to mqtts://test.mosquitto.org .
There are 0 default certificates.
Certificate file name (Enter=use default certificates)? client.crt
Loaded certificate: OU=Software Engineering, S=PM, O="CODE Consulting and Development, s.r.o.", L=Plzen, CN=opclabs.com, C=CZ

For validation of a remote certificate, the user is shown information related to the operation, together with information about the certificate. The user accepts or rejects the certificate by pressing a corresponding key.

Validate remote certificate for: MQTT client connection to mqtts://test.mosquitto.org (MqttNet)
The identity of the remote computer cannot be verified. Do you want to connect anyway?
The remote computer could not be authenticated due to problems with its security certificate. It may be unsafe to proceed.
Information:
  Target: mqtts://test.mosquitto.org
  Associated status: Certificate chain errors.
  
  Subject: CN=test.mosquitto.org, OU=Public server, O=Mosquitto, L=Derby, S=United Kingdom, C=GB
  Issuer: E=roger@atchoo.org, CN=mosquitto.org, OU=CA, O=Mosquitto, L=Derby, S=United Kingdom, C=GB
  Valid from: 3/20/2019 3:21:39 PM
  Valid to: 3/16/2032 3:21:39 PM
  Thumbprint: E62D6F0D957ED20B74B1D55D404EEF992CE482F0

Do you want to accept the certificate anyway? [y/N]: Y

When not redirected to a file, the console output is colorized.

Windows Forms

Getting local certificate is not currently supported. For validation of a remote certificate, the user is presented a notifier window with information related to the operation, together with information about the certificate. The user accepts or rejects the certificate by pressing a corresponding button.

Usage

The plugin usage depends on its host.

In code

In order to obtain or modify the settings of the Certificate security plugin, you need to obtain its parameters object (of type CertificateSecurityParameters). How precisely you retrieve the CertificateSecurityParameters depends on the hosting software. In QuickOPC (with EasyUASubscriber object), you can use following code:

CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();

If you need to modify the settings, remembers that some of the parameters must be set soon enough - before the static activation of the component takes place.

Example: Publish over secure MQTT connection (with UADP message mapping), accepting any remote certificate.

CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();
certificateSecurityParameters.StaticCertificateSecurityParameters.RemoteCertificateAcceptancePolicy.AcceptAnyCertificate = true;

Example: Publish over secure MQTT connection (with UADP message mapping), allowing the user to specify the local certificate (by disabling the static certificate security provider).

CertificateSecurityParameters certificateSecurityParameters = EasyUASubscriber.SharedParameters.PluginConfigurations.Find<CertificateSecurityParameters>();
certificateSecurityParameters.AllowStatic = false;

In command-line tools

In some command-line tools such as OpcCmd Utility or UADemoPublisher, the Certificate security plugin is already set up and enabled.

UADemoPublisher

The Certificate security plugin integrates itself with the command-line options and commands. Options are made available that allow you to configure most of the Certificate security provider aspects from the command line.

The option short names for Certificate security plugin start with "-x-cs-", the long names start with "--X-CertificateSecurity-". Below is a listing of options and parameters values as available in the UADemoPublisher.

Options:
  -x-cs-ai|--X-CertificateSecurity-AllowInteraction <bool>              Certificate security: Allow interaction (default True)
  -x-cs-as|--X-CertificateSecurity-AllowStatic <bool>                   Certificate security: Allow static (default True)
  -x-cs-lcf|--X-CertificateSecurity-LocalCertFile <string>              Certificate security: Local certificate from file (*)
  -x-cs-lcps|--X-CertificateSecurity-LocalCertPkiStore <pkiStoreQuery>  Certificate security: Local certificate from PKI store (*)
  -x-cs-rpaa|--X-CertificateSecurity-RemotePolicyAcceptAny <bool>       Certificate security: Remote policy: Accept any certificate

Parameter values:
  <findType>               FindByThumbprint|FindBySubjectName|FindBySubjectDistinguishedName|FindByIssuerName|FindByIssuerDistinguishedName|FindBySerialNumber|FindByTimeValid|FindByTimeNotYetValid|FindByTimeExpired|FindByTemplateName|FindByApplicationPolicy|FindByCertificatePolicy|FindByExtension|FindByKeyUsage|FindBySubjectKeyIdentifier
  <pkiStoreQuery>          <storeLocation>\<storeName>?<findType>:<string>
  <storeLocation>          CurrentUser|LocalMachine
  <storeName>              AddressBook|AuthRoot|CertificateAuthority|Disallowed|My|Root|TrustedPeople|TrustedPublisher

When you set a parameter in the LocalCertificatesQuery from command line, the SourceType is automatically set to include the source that corresponds to the parameter. For example, if you use the --X-CertificateSecurity-LocalCertFile option, the SourceType is automatically set to File, or if you use the --X-CertificateSecurity-LocalCertPkiStore option, the SourceType is automatically set to PkiStore.

The local certificate query is specified in a single formatted string that contains the store location, store name, the find type and the find value. The syntax can be seen from the "parameter values" listing above.

Example: Publish over secure MQTT connection (with UADP message mapping), specifying a local certificate from the specified certificate store and with a given thumbprint.

UADemoPublisher -muts -x-cs-lcps CurrentUser\My?FindByThumbprint:B488B2274EF93104C37F4F25B2AF8D1333C33696

Example: Publish over secure MQTT connection (with UADP message mapping), accepting any remote certificate.

UADemoPublisher -muts -x-cs-rpaa True

Example: Publish over secure MQTT connection (with UADP message mapping), allowing the user to specify the local certificate (by disabling the static certificate security provider).

UADemoPublisher -muts -x-cs-as False

OpcCmd Utility

Use commands (such as get <key> or set <key> <typedValue> under uaSubscriber manage plugins configuration part CertificateSecurityParameters to work with the Certificate security plugin configuration.