Connect to a secured OPC UA server
Most production OPC UA servers refuse anonymous, unencrypted sessions. tedge-dot connects to them with an application certificate of its own, and it only talks to a server whose certificate it trusts. Nothing is trusted implicitly.
What you’ll build: a device that connects to the demo’s secured OPC UA simulator
(opcua-secure-sim, Basic256Sha256 with sign_and_encrypt, user operator). You’ll see its first
connection get refused because the server’s certificate is unknown. Then you’ll trust that
certificate with tedge-dot pki and watch the device connect, with no restart.
You need a Linux host with thin-edge.io and a tedge-dot package installed (Install), and Docker for the simulator. Both packages support OPC UA security with the same PKI layout and trust rules.
Try it with the demo
Section titled “Try it with the demo”-
Start the secured simulator. It is opt-in (compose profile
secure) and listens on127.0.0.1:4841:Terminal window docker compose -f /usr/share/tedge-dot/demo/docker-compose.yaml --profile secure up -d opcua-secure-simFrom a checkout, use
demo/docker-compose.yamlinstead. -
Add the secured device. Copy the demo OPC UA config into place:
Terminal window sudo cp /usr/share/tedge-dot/demo/opcua.toml /etc/tedge/plugins/ot/opcua.tomlThen uncomment the
opc-securedevice at the end of the file:View/etc/tedge/plugins/ot/opcua.toml (uncomment) # [[device]]# name = "opc-secure"# protocol_address = { endpoint = "opc.tcp://127.0.0.1:4841/", security_policy = "Basic256Sha256", security_mode = "sign_and_encrypt", user = "operator", password = "demo-password" }# default_mode = "typed"# points_from = ["demo-sim"]demo/config/opcua.tomlon GitHubThe service applies the change within a few seconds. The first time a secured device is configured, the connector generates its application certificate in
/var/lib/tedge-dot/opcua/pki. -
Watch the link status. Each device publishes its link status, retained, on
te/device/<device>/ot/<protocol>/status/link:Terminal window tedge mqtt sub 'te/device/opc-secure/ot/opcua/status/link'The device is
disconnected, with a reason starting withcertificate untrusted:. The reason names the server certificate’s thumbprint and subject, and the command that trusts it. The connector has also copied the certificate torejected/certsfor you to review. -
Review and trust the server certificate.
Terminal window sudo tedge-dot pki list rejectedsudo tedge-dot pki trust <first 8 digits of the thumbprint>The trust lists are read again on every connection attempt, so the device connects on its next attempt. You don’t need to reload or restart anything. The link status changes to
connected, and itsinfoshows"server_certificate": "trusted"and the server’s thumbprint.
How the configuration works
Section titled “How the configuration works”Security is set per device in protocol_address, with defaults in [connection]. The demo
connection defaults to no security, and the secured device overrides it:
[connection]application_name = "tedge-dot"security_policy = "None"security_mode = "none"connect_timeout_s = 10demo/config/opcua.toml on GitHub- Policy and mode.
security_policytakes the policy name (Basic256Sha256,Aes128_Sha256_RsaOaep,Aes256_Sha256_RsaPss, …) andsecurity_modetakesnone,signorsign_and_encrypt. If a device sets a policy but no mode, it gets that policy’s default mode (sign_and_encrypt). TheNonepolicy requires the modenone. The deprecatedBasic128Rsa15andBasic256policies needallow_deprecated_security = true. - Identity. Each device uses exactly one identity: anonymous (no identity keys),
userwithpasswordorpassword_file, or an X.509 user (user_certificateanduser_private_key). Apassword_filekeeps the secret out of a file that management commands may rewrite. - Plaintext passwords are refused. A password that would travel unprotected, for example on a
channel with no message security, fails with
plaintext password refused:unless you setallow_plaintext_password = true. - The endpoint is dialled as configured. The connector discovers the server’s endpoints and
picks the one that matches the device’s policy, mode and identity. It then always connects to
the host and port in
endpoint, whatever URL the server advertises, which helps with servers behind NAT or in containers.
The full key tables are in the OPC UA connector reference.
The PKI directory
Section titled “The PKI directory”The connector keeps its certificates in /var/lib/tedge-dot/opcua/pki (set pki_dir in
[connection] to change it):
| Directory | Holds |
|---|---|
own/ | The application certificate (own/certs/cert.der) and its private key |
trusted/certs/, trusted/crl/ | Pinned server certificates and trusted CAs, with the CAs’ CRLs |
issuers/certs/, issuers/crl/ | Intermediate CAs. They complete a chain but are never trusted on their own |
rejected/certs/ | Server certificates that failed validation, for you to review |
A server certificate is trusted in one of two ways:
Trust exactly this certificate. This suits a single server with a self-signed certificate, as in the demo:
sudo tedge-dot pki trust <thumbprint> # a rejected certificate, by thumbprintsudo tedge-dot pki trust ./server-cert.der # or import a certificate fileTrust every server certificate that a CA issued. A CA is only usable with a CRL, so add one (an empty CRL if the CA has revoked nothing):
sudo tedge-dot pki trust ./site-ca.pem # the root CA, as trustedsudo tedge-dot pki add-issuer ./intermediate.pem # intermediates, if anysudo tedge-dot pki add-crl ./site-ca.crl # each CA's CRLIf a CRL is missing, the device is refused with certificate revoked: and the reason says
“revocation unknown”. To stop trusting one certificate from a trusted CA, revoke it in that
CA’s CRL.
Servers often need to trust your certificate too. Export it (never the key) and give it to the server’s administrator:
tedge-dot pki show # subject, thumbprint, validity, application URItedge-dot pki export --pem -o tedge-dot.pemtedge-dot pki at a glance
Section titled “tedge-dot pki at a glance”tedge-dot pki works offline (no broker, no server). It uses the PKI directory from --pki-dir,
or else from the pki_dir of --config, or else from /etc/tedge/plugins/ot/opcua.toml. Add
--json for machine-readable output.
| Command | Does |
|---|---|
show | Shows the application certificate |
export [--pem] [-o FILE] | Writes the application certificate (never the key) |
create [--application-uri URI] [--hostname NAME]... [--days N] [--force] | Generates the application certificate. --force replaces an existing one and keeps the old one |
list [trusted|issuers|rejected] | Lists the certificates, with the CAs’ CRL status |
trust <thumbprint|file> | Trusts a rejected certificate, or imports a file as trusted |
reject <thumbprint> | Moves a trusted certificate to rejected/ |
remove <thumbprint> [--group G] | Deletes a certificate |
add-issuer <file> | Imports intermediate CAs |
add-crl <file> | Stores a CRL next to the CA that issued it |
A thumbprint can be a prefix of at least 8 hex digits. See the reference for the JSON fields and exit codes.
When a device stays disconnected
Section titled “When a device stays disconnected”The reason in the link status starts with a fixed prefix. Match on the prefix; the text after it
is written for people:
| Prefix | What to do |
|---|---|
certificate untrusted: | Trust the server certificate, or its CA (see above). |
application certificate rejected: | The server refused your certificate. Run tedge-dot pki export and have the server trust it. |
certificate invalid: | The certificate is expired, its host name or application URI does not match, or its key is too short for the policy. Fix the server’s certificate; trusting it won’t help. |
certificate revoked: | It is revoked, or a CA’s CRL is missing (“revocation unknown”). Add the CRL. |
no matching endpoint: | The server offers no endpoint with this policy and mode. The reason lists what it does offer. |
identity rejected: / identity unsupported: | Wrong user or password, or the endpoint doesn’t accept this kind of identity. |
plaintext password refused: | Use a signed and encrypted mode, or allow plaintext passwords explicitly. |
application certificate: | Your own certificate could not be loaded or created, or it has expired. |
Unsecured devices keep working while a secured device is refused. The full rules are in Reasons (link status).