Skip to content

Commit 2a92ca5

Browse files
Merge pull request #314389 from dominicbetts/aio-opcua-fixes
AIO: OPC UA updates and fixes
2 parents 573a947 + d5c8819 commit 2a92ca5

5 files changed

Lines changed: 224 additions & 11 deletions

File tree

articles/iot-operations/discover-manage-assets/howto-configure-opc-ua-certificates-infrastructure.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,52 @@ Like the previous examples, you use a dedicated Kubernetes secret to store the c
295295
```
296296
297297
Now that the connector for OPC UA uses the enterprise certificate, don't forget to add the new certificate's public key to the trusted certificate lists of all OPC UA servers it needs to connect to.
298+
299+
## Configure certificate subject alternative names
300+
301+
The connector's self-signed certificate automatically includes the application URI and the local hostname in the Subject Alternative Name (SAN) extension. If OPC UA servers access the connector through other hostnames or IP addresses, you need to add those identities to the SAN. To learn more about SAN and when you need custom entries, see [Certificate subject alternative name](overview-opc-ua-connector-certificates-management.md#certificate-subject-alternative-name).
302+
303+
> [!NOTE]
304+
> This configuration only applies to the connector's self-generated certificate. If you use an enterprise grade certificate, configure the SAN entries when you generate that certificate externally. For more information, see [Configure an enterprise grade application instance certificate](#configure-an-enterprise-grade-application-instance-certificate).
305+
306+
To add custom DNS names, IP addresses, or both, add the `SubjectAlternativeDnsNames` and `SubjectAlternativeIpAddresses` properties to the connector's `SecurityPki` configuration in the `additionalConfiguration` field of the connector's deployment:
307+
308+
```json
309+
{
310+
"SecurityPki": {
311+
"SubjectName": "CN=aio-opc-opcuabroker",
312+
"ApplicationUri": "urn:microsoft.com:aio:opc:ua:broker",
313+
"SubjectAlternativeDnsNames": "opcua-connector.iot-ops.svc.cluster.local,opcua.contoso.com",
314+
"SubjectAlternativeIpAddresses": "192.168.1.100,10.0.0.50"
315+
}
316+
}
317+
```
318+
319+
The resulting certificate SAN includes the application URI, all specified DNS names and IP addresses, and the local hostname that the connector adds automatically.
320+
321+
### Regenerate the certificate with new SAN entries
322+
323+
If you change the SAN configuration on a running connector, regenerate the certificate to apply the new entries:
324+
325+
1. Update the configuration with the new SAN values.
326+
1. Delete the existing certificate from the PKI store:
327+
328+
```bash
329+
rm -rf -- /tmp/opcuabroker/pki/own/certs/* /tmp/opcuabroker/pki/own/private/*
330+
```
331+
332+
1. Restart the connector pod. The connector automatically generates a new certificate with the updated SAN entries.
333+
334+
To verify the new certificate contains the expected SAN entries, run the following command:
335+
336+
```bash
337+
openssl x509 -in /tmp/opcuabroker/pki/own/certs/your-cert-file.der -inform DER -text -noout | grep -A 10 "Subject Alternative Name"
338+
```
339+
340+
### Troubleshoot SAN validation failures
341+
342+
If an OPC UA server rejects connections with certificate hostname or IP validation errors:
343+
344+
1. Check the server's error message for the hostname or IP address it validated against.
345+
1. Add that hostname or IP address to the appropriate SAN configuration property (`SubjectAlternativeDnsNames` or `SubjectAlternativeIpAddresses`).
346+
1. Regenerate the certificate as described in the previous section.

articles/iot-operations/discover-manage-assets/howto-configure-opc-ua.md

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ Now you can define the events associated with the event group. To add OPC UA eve
435435

436436
# [Azure CLI](#tab/cli)
437437

438-
To add an event group and events to an existing asset, use the `az iot ops ns asset opcua event-group` and `az iot ops ns asset custom event` commands:
438+
To add an event group and events to an existing asset, use the `az iot ops ns asset opcua event-group` and `az iot ops ns asset opcua event` commands:
439439

440440
```azurecli
441441
# Add an event group to the thermostat asset
@@ -444,17 +444,17 @@ az iot ops ns asset opcua event-group add \
444444
--asset thermostat \
445445
--instance {your instance name} \
446446
-g {your resource group name} \
447-
--name alerts
447+
--name alerts \
448+
--dest topic="azure-iot-operations/events/test-thermostat-cli" retain=Never qos=Qos1 ttl=3600
448449
449450
# Add an event to the event group
450-
az iot ops ns asset custom event add \
451+
az iot ops ns asset opcua event add \
451452
--asset thermostat \
452453
--instance {your instance name} \
453454
-g {your resource group name} \
454455
--event-group alerts \
455456
--name serverObjectNotifier \
456-
--data-source "ns=0;i=2253" \
457-
--dest topic="azure-iot-operations/events/test-thermostat-cli" retain=Never qos=Qos1 ttl=3600
457+
--data-source "ns=0;i=2253"
458458
459459
# List the event groups for the asset
460460
az iot ops ns asset opcua event-group list \
@@ -469,7 +469,7 @@ When you add an event group by using the Azure CLI, you can configure:
469469
- Publishing interval and queue size
470470
- Event destinations (MQTT topic, QoS, retain, TTL)
471471

472-
To add individual events to an event group, use the `az iot ops ns asset custom event add` command with the `--event-group` parameter.
472+
To add individual events to an event group, use the `az iot ops ns asset opcua event add` command with the `--event-group` parameter.
473473

474474
To remove an event group, use the `az iot ops ns asset opcua event-group remove` command.
475475

@@ -542,14 +542,13 @@ The following screenshot shows an example event filter:
542542
The following command updates an existing event definition to include an event filter by using the `config` parameter:
543543

544544
```azurecli
545-
az iot ops ns asset custom event add \
545+
az iot ops ns asset opcua event add \
546546
--asset thermostat \
547547
--instance {your instance name} \
548548
-g {your resource group name} \
549549
--event-group alerts \
550550
--name serverObjectNotifier \
551551
--data-source "ns=0;i=2253" \
552-
--dest topic="azure-iot-operations/events/test-thermostat-cli" retain=Never qos=Qos1 ttl=3600 \
553552
--replace true \
554553
--config "{\"eventFilter\":{\"selectClauses\":[{\"browsePath\":\"EventId\",\"typeDefinitionId\":\"ns=0;i=2041\",\"fieldId\":\"myEventId\"},{\"browsePath\":\"EventType\",\"typeDefinitionId\":\"ns=0;i=2041\",\"fieldId\":\"EventType\"},{\"browsePath\":\"SourceName\",\"typeDefinitionId\":\"\",\"fieldId\":\"mySourceName\"},{\"browsePath\":\"Severity\",\"typeDefinitionId\":\"\",\"fieldId\":\"Severity\"}]}}"
555554
```
@@ -875,6 +874,72 @@ To delete individual resources by using Bicep, see [Deployment stacks](/azure/az
875874

876875
---
877876

877+
878+
## Configure a shared endpoint
879+
880+
By default, each asset opens its own dedicated OPC UA session. You can configure a *shared* endpoint so that the connector uses a single session for all assets that reference the endpoint. To learn more about shared endpoints and when to use them, see [Shared endpoint mode](overview-opc-ua-connector.md#shared-endpoint-mode).
881+
882+
To enable shared mode, set `"shared": true` in the `additionalConfiguration` JSON of a device inbound endpoint:
883+
884+
```json
885+
{
886+
"properties": {
887+
"endpoints": {
888+
"inbound": {
889+
"my-opcua-endpoint": {
890+
"address": "opc.tcp://my-plc.my-namespace:4840",
891+
"endpointType": "Microsoft.OpcUa",
892+
"authentication": {
893+
"method": "Anonymous"
894+
},
895+
"additionalConfiguration": "{\"shared\": true}"
896+
}
897+
}
898+
}
899+
}
900+
}
901+
```
902+
903+
If you omit the `shared` property from `additionalConfiguration`, the default value is `false` and each asset opens its own dedicated OPC UA session.
904+
905+
The `shared` flag is also supported on legacy `AssetEndpointProfile` resources. However, for new deployments, use the device/asset (namespaced) resource model.
906+
907+
Multiple assets can then reference the same shared endpoint:
908+
909+
```yaml
910+
apiVersion: namespaces.deviceregistry.microsoft.com/v1
911+
kind: Asset
912+
metadata:
913+
name: asset-temperature
914+
namespace: azure-iot-operations
915+
spec:
916+
deviceRef:
917+
deviceName: my-shared-plc
918+
endpointName: my-opcua-endpoint
919+
datasets:
920+
- name: temperature-data
921+
dataPoints:
922+
- name: temperature
923+
dataSource: "ns=2;i=1001"
924+
---
925+
apiVersion: namespaces.deviceregistry.microsoft.com/v1
926+
kind: Asset
927+
metadata:
928+
name: asset-pressure
929+
namespace: azure-iot-operations
930+
spec:
931+
deviceRef:
932+
deviceName: my-shared-plc
933+
endpointName: my-opcua-endpoint
934+
datasets:
935+
- name: pressure-data
936+
dataPoints:
937+
- name: pressure
938+
dataSource: "ns=2;i=1002"
939+
```
940+
941+
Both `asset-temperature` and `asset-pressure` reuse the single OPC UA session that the connector established for `my-opcua-endpoint`.
942+
878943
## Related content
879944

880945
- [Manage asset and device configurations](howto-use-operations-experience.md)

articles/iot-operations/discover-manage-assets/howto-control-opc-ua.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ The response to a successfully executed request is a message that contains all t
376376

377377
Endpoint operations are process control calls that work on an inbound endpoint only. They don't need an asset.
378378

379-
For example, to dump the address space of an OPC UA server, send a message to the topic `azure-iot-operations/endpoint-operations/{InboundEndpointName}/browse`.
379+
For example, to dump the address space of an OPC UA server, send a message to the topic `azure-iot-operations/endpoint-operations/{DeviceName}/{EndpointName}/{ActionName}`.
380380

381381
If the payload contains an empty JSON object, the entire address space is returned.
382382

articles/iot-operations/discover-manage-assets/overview-opc-ua-connector-certificates-management.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ The following diagram shows the sequence of events that occur when the connector
2828

2929
:::image type="content" source="media/overview-opc-ua-connector-certificates-management/mutual-trust.svg" alt-text="Diagram that summarizes the OPC UA connector connection handshake." border="false":::
3030

31-
<!-- ```mermaid
31+
<!--
32+
mermaid
3233
sequenceDiagram
3334
participant Connector as Connector for OPC UA
3435
participant OPCUA as OPC UA server
@@ -40,7 +41,7 @@ sequenceDiagram
4041
OPCUA->>Connector: Presents OPC UA server application instance certificate
4142
4243
Connector->>Connector: Validate OPC UA server certificate against<br>connector for OPC UA trusted certificates list<br>or trusted issuers list.
43-
``` -->
44+
-->
4445

4546
## Connector for OPC UA application instance certificate
4647

@@ -89,6 +90,42 @@ The default name for the `SecretProviderClass` custom resource that handles the
8990

9091
To learn how to manage the issuer certificates list, see [Configure the issuer certificates list](howto-configure-opc-ua-certificates-infrastructure.md#configure-the-issuer-certificates-list).
9192

93+
## Certificate subject alternative name
94+
95+
Subject Alternative Name (SAN) is an X.509 certificate extension that specifies additional identities for a certificate beyond the subject field. For OPC UA certificates, the SAN typically includes:
96+
97+
- **URI entries**: The OPC UA application URI, required by the OPC UA specification.
98+
- **DNS entries**: Hostnames and FQDNs where the application can be reached.
99+
- **IP entries**: IP addresses where the application can be reached.
100+
101+
The connector's self-signed certificate automatically includes the application URI and the local hostname. OPC UA servers validate that the client's certificate SAN contains the hostname or IP address used for the connection. If the SAN doesn't match, the server rejects the connection.
102+
103+
### When to configure custom SAN entries
104+
105+
Configure custom SAN entries when:
106+
107+
- The connector is accessed through multiple hostnames, for example `opcua.local` and `broker.contoso.com`.
108+
- The connector has multiple IP addresses across different network interfaces.
109+
- You use Kubernetes services or ingress that expose different DNS names.
110+
- You connect through a load balancer or proxy.
111+
- OPC UA servers reject connections because of a hostname or IP mismatch.
112+
113+
### SAN configuration properties
114+
115+
Add the following properties to the `SecurityPki` configuration section:
116+
117+
| Property | Type | Description |
118+
|----------|------|-------------|
119+
| `SubjectAlternativeDnsNames` | string | Comma-separated list of DNS names to include in the certificate SAN. |
120+
| `SubjectAlternativeIpAddresses` | string | Comma-separated list of IP addresses to include in the certificate SAN. |
121+
122+
DNS names can be hostnames, FQDNs, or Kubernetes service names and are case-insensitive. IP addresses must be valid IPv4 or IPv6 addresses. The connector automatically trims whitespace and removes empty entries.
123+
124+
> [!IMPORTANT]
125+
> Custom SAN entries only apply to self-generated certificates. If you provide a custom certificate through the `ApplicationCert` secret or specify an existing certificate through `Thumbprint`, the certificate already exists and its SAN can't be modified. Wildcard DNS names aren't supported in OPC UA certificates.
126+
127+
To learn how to configure custom SAN entries and regenerate the connector certificate, see [Configure certificate subject alternative names](howto-configure-opc-ua-certificates-infrastructure.md#configure-certificate-subject-alternative-names).
128+
92129
## Features supported
93130

94131
The following table shows the feature support level for authentication in the current version of the connector for OPC UA:

articles/iot-operations/discover-manage-assets/overview-opc-ua-connector.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ The connector for OPC UA supports the following features as part of Azure IoT Op
5555
| Payload compression | Yes | Supports `gzip` and `brotli` |
5656
| [Dynamic node resolution](#resolve-nodes-dynamically-by-using-browse-paths) | Yes | Using `TranslateBrowsePathToNodeId` service |
5757
| State store synchronization | Yes | Sync OPC UA node properties to distributed state store |
58+
| [Shared endpoint mode](#shared-endpoint-mode) | Yes | Multiple assets share a single OPC UA session |
5859
| [Key frame generation](#understand-key-frames-for-opc-ua-data-points) | Yes | Enables downstream services to recover state more quickly |
5960

6061
## How it works
@@ -97,6 +98,67 @@ To configure this behavior, select **Sync properties into state store** when you
9798

9899
You can also force a synchronization of all properties by making an MQTT RPC call to the `azure-iot-operation/asset-operations/{AssetName}/builtin/syncProperties` topic. A payload `{}` forces a synchronization without observing `ModelChange` events. A payload `{"observeModelChanges": true}` forces a synchronization that observes `ModelChange` events.
99100

101+
## Shared endpoint mode
102+
103+
By default, each asset that connects to an OPC UA server opens its own independent OPC UA session. This default behavior is called *dedicated* mode.
104+
105+
When you set the `shared` flag to `true` on a device's inbound endpoint, the connector establishes a single OPC UA session for the endpoint and reuses it across all assets that reference that endpoint. This behavior is called *shared* mode.
106+
107+
```
108+
Dedicated mode (default) Shared mode
109+
───────────────────────── ─────────────────────────
110+
Asset A → Session A Asset A ─┐
111+
Asset B → Session B Asset B ──┼─→ Session (shared)
112+
Asset C → Session C Asset C ─┘
113+
(3 sessions to the server) (1 session to the server)
114+
```
115+
116+
### When to use shared mode
117+
118+
Use shared mode when:
119+
120+
- The OPC UA server enforces a low session limit, for example a PLC that allows only a few simultaneous connections.
121+
- You have many assets pointing to the same server and want to minimize the connection footprint.
122+
- You want to reduce resource consumption (memory, TCP connections, licensing) on the OPC UA server.
123+
124+
The `shared` flag is independent of the authentication method. The single shared session uses whichever authentication method you configure on the endpoint. Telemetry payload, topic structure, and message schema are identical regardless of session mode.
125+
126+
You can mix shared and dedicated assets on the same device. Create separate endpoints, for example `my-opcua-endpoint-shared` and `my-opcua-endpoint-dedicated`, each with its own `shared` flag. Assets reference a specific endpoint by name through `deviceRef.endpointName`.
127+
128+
### Constraints and trade-offs
129+
130+
| Aspect | Dedicated mode | Shared mode |
131+
|---|---|---|
132+
| Sessions to server | One per asset | One per endpoint |
133+
| Server session limit impact | High | Low |
134+
| Isolation between assets | Full (each asset has its own session) | None (all assets share the same session) |
135+
| Session disconnect impact | Only the affected asset reconnects | All assets on the endpoint are affected |
136+
| Certificate update | Each asset reconnects independently | The single shared session is recreated; all assets on the endpoint are briefly interrupted |
137+
138+
> [!IMPORTANT]
139+
> When the shared OPC UA session disconnects because of a network failure, server restart, or certificate rotation, all assets that reference the endpoint temporarily lose telemetry until the session is reestablished.
140+
141+
### Shared endpoint lifecycle
142+
143+
1. When you create or update a device resource, the connector reads the `shared` flag.
144+
1. If `shared` is `true`, the connector opens one OPC UA session before any asset connects. The endpoint transitions to the `Shared` state.
145+
1. When an asset connects, its `ConnectedAsset` record links to the existing session—no second session opens.
146+
1. When you remove an asset, the OPC UA session stays open for other assets. Only the removed asset's subscriptions are torn down.
147+
1. When you delete or update the device, the shared session disconnects and all linked assets are requeued.
148+
149+
If you change `shared` from `true` to `false` on a running device, the connector disconnects the shared session and requeues all affected assets. Each asset then establishes its own dedicated session. Expect a brief interruption in telemetry.
150+
151+
### Health states for shared endpoints
152+
153+
- The **InboundEndpoint** health state reports `Available` or `Unavailable` for the single shared session.
154+
- Each **Asset** health state also reports `Available` or `Unavailable`. Because all assets share the same session, a session drop marks all linked assets as `Unavailable` simultaneously.
155+
156+
### Certificate rotation for shared endpoints
157+
158+
When the connector's application certificate is renewed, it recreates the secure channel of the shared session once. All assets on the endpoint are briefly interrupted, then automatically recover without requiring individual reconnects.
159+
160+
To learn how to configure a shared endpoint, see [Configure a shared endpoint](howto-configure-opc-ua.md#configure-a-shared-endpoint).
161+
100162
## Connector for OPC UA message format
101163

102164
The connector for OPC UA publishes messages from OPC UA servers to the MQTT broker as JSON. Each message has a payload and a collection of properties that are part of the MQTT user properties section. The payload contains the messages from the OPC UA server, and the properties provide metadata.

0 commit comments

Comments
 (0)