Credentials
Three identity flavours: anonymous, username/password, X.509. Plus a client certificate the channel itself needs when security is on. Flags for all four, environment patterns for production.
OPC UA has two independent identity axes:
- Application identity — proved by the client certificate.
Needed whenever the channel uses any non-
Nonesecurity policy. - User identity — proved by username/password or by an X.509 user certificate. Configured per session.
The CLI flags cover both.
The flags
| Flag | Purpose |
|---|---|
--cert=<path> |
Client (application) certificate, PEM |
--key=<path> |
Client (application) private key, PEM |
--ca=<path> |
CA bundle for chain validation |
-u, --username=<user> |
Username for session-level identity |
-p, --password=<pass> |
Password for session-level identity |
The CLI does not currently have a flag for user X.509 certificate — that path is library-only.
Anonymous (default)
The default. No --username / --password flags.
opcua-cli browse opc.tcp://plc.local:4840 \
-s Basic256Sha256 \
-m SignAndEncrypt \
--cert=/etc/opcua/client.pem \
--key=/etc/opcua/client.key
The channel is secured (cert + key) but the session is anonymous. Most servers allow anonymous reads on published metrics; writes typically require a real identity.
Username / password
Add -u and -p:
opcua-cli write opc.tcp://plc.local:4840 "ns=2;s=PLC/Setpoint" 42.5 \
-s Basic256Sha256 \
-m SignAndEncrypt \
--cert=/etc/opcua/client.pem \
--key=/etc/opcua/client.key \
-u operator \
-p "$OPCUA_PASSWORD"
The password is encrypted under the channel's asymmetric keys
before transit — using whichever SecurityPolicy is active on
the relevant UserTokenPolicy (the server publishes it via
discovery). Cleartext never crosses the wire when the channel is
Sign or SignAndEncrypt.
Warning
Username over a -s None channel transmits the password in
cleartext. The CLI does not prevent the combination but it
is unsafe. If your server requires username auth, also require
at least Sign mode.
Sourcing secrets
Three options, from worst to best:
| Source | Notes |
|---|---|
-p literalvalue on the command line |
Visible in ps/top/shell history. Use only for ad-hoc one-offs |
-p "$OPCUA_PASSWORD" from environment |
Not visible in ps; visible in printenv and the shell's exported env |
| Read from a file at invocation time | Cleanest: --password "$(cat /etc/opcua/secret)" |
In CI, prefer secrets injected as environment variables (GitHub Actions secrets, GitLab masked variables, Vault sidecar injection). Avoid checking literals into command lines in scripts that go to source control.
Client certificate
Required whenever --security-policy is anything other than
None. PEM-formatted certificate and matching private key.
opcua-cli browse opc.tcp://plc.local:4840 \
-s Basic256Sha256 \
-m SignAndEncrypt \
--cert=/etc/opcua/client.pem \
--key=/etc/opcua/client.key
The cert is the client application's identity; the server's trust store decides whether to accept it.
Generating a client certificate
A minimal RSA client cert with OpenSSL:
# 1. Generate the private key
openssl genpkey -algorithm RSA -out client.key -pkeyopt rsa_keygen_bits:2048
# 2. Generate the certificate (self-signed, 1 year validity)
openssl req -new -x509 \
-key client.key \
-out client.pem \
-days 365 \
-subj "/CN=opcua-cli/O=YourOrg" \
-addext "subjectAltName=URI:urn:opcua-cli"
The URI:urn:opcua-cli Subject Alternative Name (SAN) is what
OPC UA uses as the Application URI — the server's audit log
references it. Pick something meaningful per environment.
For full certificate generation patterns (CA-signed, ECC, …),
see opcua-client — security.
You must supply your own certificate
The CLI does not auto-generate a client certificate. If you
configure a non-None security policy without --cert and
--key, the underlying opcua-client library refuses to bring
up the secure channel and the connection fails with a security
error.
Generate the cert once with the OpenSSL snippet above (or your
PKI's normal client-cert workflow), persist it, and pass it on
every invocation. For longer-form patterns — CA-issued certs,
ECC keys, per-environment Application URIs — see
opcua-client · trust store and client identity.
CA bundle (--ca)
When the server expects full chain validation on the client cert (rare in OPC UA, common in HTTP-like protocols), supply the CA bundle:
opcua-cli browse opc.tcp://plc.local:4840 \
-s Basic256Sha256 -m SignAndEncrypt \
--cert=/etc/opcua/client.pem \
--key=/etc/opcua/client.key \
--ca=/etc/opcua/ca-bundle.pem
Most OPC UA servers do not require this — the trust model on
the OPC UA side is typically per-certificate trust, not chain-
based. Use --ca only when the server documentation says so.
Worked combinations
| Server requires | CLI flags |
|---|---|
| Unsecured anonymous | (none) |
| Sign + anonymous | -s Basic256Sha256 -m Sign --cert=... --key=... |
| SignAndEncrypt + anonymous | -s Basic256Sha256 -m SignAndEncrypt --cert=... --key=... |
| SignAndEncrypt + username | -s Basic256Sha256 -m SignAndEncrypt --cert=... --key=... -u user -p pass |
| SignAndEncrypt + X.509 user identity | Library-only (no CLI flag yet) |
| Internal CA chain validation | Add --ca=... |
Common pitfalls
--certwithout--key(or vice versa). Both must be on the command line for the CLI to wire a client certificate; if one is missing, the CLI silently skips thesetClientCertificate()call. With any non-Nonesecurity policy the channel will then fail to open insideopcua-client, typically asBadCertificateInvalidor a security exception from OpenSSL.- Mismatched cert and key. The library refuses to load the
pair. Verify with
openssl x509 -modulus -in client.pem | openssl md5andopenssl rsa -modulus -in client.key | openssl md5— the two MD5s must match. - Cert expired. Most servers refuse expired certs with
BadCertificateTimeInvalid. Generate a fresh one. - Spaces in paths on Windows.
cmd.exeneeds the path in quotes:--cert="C:\Program Files\opcua\client.pem". - Forgetting to
chmod 600the key file. Not enforced by the CLI, but the standard secret-handling discipline applies.