-
Notifications
You must be signed in to change notification settings - Fork 12
Configure OPC UA certificates infrastructure for the connector for OPC UA
Use the az iot ops connector opcua
command to configure trusted list certificates, issuer list certificates and enterprise grade application instance certificate. Addition commands will help you create Azure keyvault secret and then add the secret reference to secretproviderclass opc-ua-connector and corresponding secretsync.
❗ NOTE secret sync must be enabled before proceed the command, and make sure you have Key Vault Secrets Officer access for your Azure key vault.
Add a trusted certificate to the OPC UA Broker's trusted certificate list. The certificate file extension must be .der or .crt. Azure resource secretproviderclass 'opc-ua-connector' and secretsync 'aio-opc-ua-broker-trust-list' will be created if not found.
az iot ops connector opcua trust add --instance <instance> --resource-group <instanceresourcegroup>
--certificate-file "<certificate>.der"
Add an issuer certificate to the OPC UA Broker's issuer certificate list. The certificate file extension must be .der, .crt or .crl. When adding a .crl file, a .der or .crt file with same file name must be added first. Azure resource secretproviderclass 'opc-ua-connector'and secretsync 'aio-opc-ua-broker-issuer-list' will be created if not found.
az iot ops connector opcua issuer add --instance <instance> --resource-group <instanceresourcegroup>
--certificate-file "<certificate>.der"
Add an enterprise grade client application instance certificate. The public key file extension must be .der and private key file extension must be .pem. Please make sure to use same filename for public key and private key file. Azure resource secretproviderclass 'opc-ua-connector' and secretsync 'aio-opc-ua-broker-client-certificate' will be created if not found.
az iot ops connector opcua client add --instance <instance> --resource-group <instanceresourcegroup>
--public-key-file "<newopc>.der" --private-key-file "<newopc>.pem" --subject-name <aio-opc-opcuabroker>
--application-uri <application-uri>
Remove trusted certificate(s) from the OPC UA Broker's trusted certificate list.
Remove trusted certificates called 'testcert1.der' and 'testcert2.crt' from trusted certificate list. Removing all trusted certificates from the OPC UA Broker's trusted certificate list will trigger deletion of the secretsync resource 'aio-opc-ua-broker-trust-list'.
Note: Add space-separated certificate names to remove using --certificate-names
input, the names can be found under the corresponding secretsync resource property targetKey
.
az iot ops connector opcua trust remove --instance instance --resource-group instanceresourcegroup --certificate-names testcert1.der testcert2.crt
Remove issuer certificate(s) from the OPC UA Broker's issuer certificate list. Remove issuer certificates and its revocation list with .crl extension from issuer certificate list. Removing all issuer certificates from the OPC UA Broker's issuer certificate list will trigger deletion of the secretsync resource 'aio-opc-ua-broker-issuer-list'. Please make sure to remove corresponding .crl if exist when removing .der/.crt certificate to avoid orphaned secret.
az iot ops connector opcua issuer remove --instance instance --resource-group instanceresourcegroup --certificate-names testcert.der testcert.crl
Remove client application instance certificate from the OPC UA Broker. Remove client certificates from the OPC UA Broker's client certificate store. Removing all certificates from the OPC UA Broker's client certificate store will trigger deletion of the secretsync resource 'aio-opc-ua-broker-client-certificate'. And this operation will trigger the fallback to default (cert-manager based) certificate. This fallback requires an aio extension update. Please make sure to remove both public(.der) and private(.pem) key certificate pair to avoid orphaned secret.
az iot ops connector opcua client remove --instance instance --resource-group instanceresourcegroup --certificate-names testcert.der testcert.pem
Show details of secretsync resource 'aio-opc-ua-broker-trust-list'.
az iot ops connector opcua trust show --instance instance --resource-group instanceresourcegroup
Show details of secretsync resource 'aio-opc-ua-broker-issuer-list'.
az iot ops connector opcua issuer show --instance instance --resource-group instanceresourcegroup
Show details of secretsync resource 'aio-opc-ua-broker-client-certificate'.
az iot ops connector opcua client show --instance instance --resource-group instanceresourcegroup
Configure certificate secret with custom name
Add a trusted certificate to the OPC UA Broker's trusted certificate list with custom secret name.
az iot ops connector opcua trust add --instance <instance> --resource-group <instanceresourcegroup>
--certificate-file "<certificate>.crt" --secret-name <custom-secret-name>
Add an issuer certificate to the OPC UA Broker's issuer certificate list with custom secret name.
az iot ops connector opcua issuer add --instance <instance> --resource-group <instanceresourcegroup>
--certificate-file "<certificate>.crt" --secret-name <custom-secret-name>
Add an enterprise grade client application instance certificate with custom public and private key secret name.
az iot ops connector opcua client add --instance <instance> --resource-group <instanceresourcegroup>
--public-key-file "<newopc>.der" --private-key-file "<newopc>.pem" --subject-name <aio-opc-opcuabroker>
--application-uri <application-uri> --public-key-secret-name <public-secret-name> --private-key-secret-name <private-secret-name>
Configure certificate secret and skip the overwrite confirmation prompt when the secret already exists. Add a trusted certificate to the trusted certificate list and skip the overwrite confirmation prompt when the secret already exists.
az iot ops connector opcua trust add --instance instance --resource-group instanceresourcegroup --certificate-file "certificate.der" --overwrite-secret
Remove certificates including remove related keyvault secret. Remove trusted certificates from trusted certificate list, including remove related keyvault secret.
az iot ops connector opcua trust remove --instance instance --resource-group instanceresourcegroup --certificate-names testcert1.der testcert2.crt --include-secrets
Test trusted certificate list
-
Deploy the OPC PLC simulator
-
Extract the OPC PLC application instance certificate and add it to the OPC UA connector trust list
kubectl -n azure-iot-operations get secret opc-plc-default-application-cert -o jsonpath='{.data.tls\.crt}' | base64 -d > opcplc.crt
- Add extracted certificate to trusted certificate list
az iot ops connector opcua trust add --instance $AIO_INSTANCE_NAME --resource-group $RESOURCE_GROUP --certificate-file "./opcplc.crt"
-
Verify secret got created in Azure Key Vault.
-
Verify kubernetes secret got created
You can also verify if data flows by following quickstart steps
-
Add AIO Connector certificate to PLC Simulator Trust list
# Extract the OPC UA connector application instance certificate and add it to the OPC PLC trust list
kubectl -n azure-iot-operations get secret aio-opc-opcuabroker-default-application-cert -o jsonpath='{.data.tls\.crt}' | base64 -d > opcuabroker.crt
data=$(kubectl create secret generic temp --from-file=opcuabroker.crt=./opcuabroker.crt --dry-run=client -o jsonpath='{.data}')
kubectl patch secret opc-plc-trust-list -n azure-iot-operations -p "{\"data\": $data}"
rm ./opcuabroker.crt
- Follow rest of quickstart to set up end to end and make sure Connector and connect to PLC.
Test enterprise grade application instance certificate
Steps:
- Save following helm charts as opc-plc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: opc-plc-000000
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: opcplc-000000
template:
metadata:
labels:
app.kubernetes.io/component: opcplc-000000
spec:
containers:
- name: opc-plc
image: mcr.microsoft.com/iotedge/opc-plc:latest
args:
- "--ph=opcplc-000000"
- "--cdn=opcplc-000000"
- "--ut"
- "--sph"
- "--sn=5"
- "--sr=10"
- "--fn=10"
- "--ftl=212"
- "--ftu=273"
- "--ftr=True"
- "--veryfastrate=1000"
- "--gn=1"
- "--pn=50000"
- "--at=FlatDirectory"
- "--drurs"
ports:
- containerPort: 50000
volumeMounts:
- name: opc-plc-default-application-cert
mountPath: /app/pki/own
- name: opc-plc-trust-list
mountPath: /app/pki/trusted
volumes:
- name: opc-plc-default-application-cert
secret:
secretName: opc-plc-default-application-cert
- name: opc-plc-trust-list
secret:
secretName: opc-plc-trust-list
serviceAccountName: opcplc-000000-service-account
---
apiVersion: v1
kind: Service
metadata:
name: opcplc-000000
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
spec:
type: ClusterIP
selector:
app.kubernetes.io/component: opcplc-000000
ports:
- port: 50000
protocol: TCP
targetPort: 50000
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: opc-plc-self-signed-issuer
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: opc-plc-default-application-cert
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
spec:
secretName: opc-plc-default-application-cert
duration: 2160h # 90d
renewBefore: 360h # 15d
issuerRef:
name: opc-plc-self-signed-issuer
kind: Issuer
commonName: OpcPlc
dnsNames:
- opcplc-000000
- opcplc-000000.azure-iot-operations.svc.cluster.local
- opcplc-000000.azure-iot-operations
uris:
- urn:OpcPlc:opcplc-000000
usages:
- digital signature
- key encipherment
- data encipherment
- server auth
- client auth
privateKey:
algorithm: RSA
size: 2048
encodeUsagesInRequest: true
isCA: false
---
apiVersion: v1
kind: Secret
metadata:
name: opc-plc-trust-list
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
data: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: opcplc-000000-service-account
namespace: azure-iot-operations
labels:
app.kubernetes.io/component: opcplc-000000
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: opc-plc-000000-secret-access-role
namespace: azure-iot-operations
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: opc-plc-000000-secret-access-rolebinding
namespace: azure-iot-operations
subjects:
- kind: ServiceAccount
name: opcplc-000000-service-account
namespace: azure-iot-operations
roleRef:
kind: Role
name: opc-plc-000000-secret-access-role
apiGroup: rbac.authorization.k8s.io
- connect to the cluster that has AIO deployment and run
kubectl apply -f <path-to-file>\opc-plc.yaml
You should see following output:
deployment.apps/opc-plc-000000 created
service/opcplc-000000 created
issuer.cert-manager.io/opc-plc-self-signed-issuer created
certificate.cert-manager.io/opc-plc-default-application-cert created
secret/opc-plc-trust-list created
serviceaccount/opcplc-000000-service-account created
role.rbac.authorization.k8s.io/opc-plc-000000-secret-access-role created
rolebinding.rbac.authorization.k8s.io/opc-plc-000000-secret-access-rolebinding created
- Create asset endpoint profile use
az iot ops asset endpoint create opcua --name myprofile -g myresourcegroup --instance myinstance --target-address opc.tcp://opcplc-000000:50000
- Create asset using asset endpoint profile just created
az iot ops asset create
az iot ops asset create --name myasset -g testjiacjucc0407-120422770 --endpoint-profile myprofile --instance myinstance0407 --tags NodeID="ns=2;s=Channel1.Device1.Tag1" TagName="Tag1"
- Validate the created asset CR
kubectl get assets myasset -n azure-iot-operations -o yaml
and you should see an untrusted certificate issue, this means the server is connected, but failed due to the certificate not trusted
apiVersion: deviceregistry.microsoft.com/v1
kind: Asset
metadata:
annotations:
management.azure.com/apiVersion: "2024-11-01"
management.azure.com/bridgeLocation: EastUS2
management.azure.com/cloudEnvironment: AzureCloud
management.azure.com/correlationId: 2fe48616-7ab0-4bea-97d0-1d61c3e95538
…
status:
errors:
- code: 400
message: '{"title":"Disconnected","detail":"Session creation failure","lastTransitionTime":"2025-04-07T23:12:57.7108905Z","reasons":{"StatusCode":"BadCertificateUntrusted","SimbolicId":"BadCertificateUntrusted","Message":"Certificate
is not trusted.","RejectedCertificate":"…'
- Get self-signed client certificates using public key:
kubectl -n azure-iot-operations get secret opc-plc-default-application-cert -o jsonpath='{.data.tls\.crt}' | base64 -d > opcuabroker.crt
openssl x509 -outform der -in opcuabroker.crt -out opcuabroker.der
private key:
kubectl -n azure-iot-operations get secret opc-plc-default-application-cert -o jsonpath='{.data.tls\.key}' | base64 -d > opcuabroker.pem
- Configure client certificate using
az iot ops connector opcua client add --instance myinstance --resource-group resourcegroup --public-key-file "<path-to-file>\opcuabroker.der" --private-key-file "<path-to-file>\opcuabroker.pem"
now the error code in asset should change to:
status:
errors:
- code: 200
message: '{"title":"Connected","lastTransitionTime":"2025-04-07T23:55:45.7913102Z"}'
this means you are now connected!
Note
For CA signed enterprise grade certificate, please Save the CA certificate and the CRL in the aio-opc-ua-broker-issuer-list
secret before proceeding client add
# Append CA certificate to the issuer list secret as a new entry
az iot ops connector opcua issuer add --instance <your instance name> --resource-group <your resource group> --certificate-file "./my-server-ca.der"
# Append the CRL to the issuer list secret as a new entry
az iot ops connector opcua issuer add --instance <your instance name> --resource-group <your resource group> --certificate-file "./my-server-ca.crl"
For a PEM encoded certificate in a file such as ./my-server-ca.crt, run the following commands:
# Append CA certificate to the issuer list secret as a new entry
az iot ops connector opcua issuer add --instance <your instance name> --resource-group <your resource group> --certificate-file "./my-server-ca.crt"
# Append the CRL to the issuer list secret as a new entry
az iot ops connector opcua issuer add --instance <your instance name> --resource-group <your resource group> --certificate-file "./my-server-ca.crl"