Skip to content

Conversation

@skartikey
Copy link
Contributor

Summary

Add support for explicitly trusting server certificates when connecting to OPC UA servers with self-signed certificates. This resolves connection failures with "StatusBadSecurityChecksFailed" error when using SignAndEncrypt security mode.

The new configuration option allows users to specify a path to the server's certificate file, enabling secure connections to OPC UA servers that use self-signed certificates without manual OS-level certificate trust configuration.

Example configuration:

[[inputs.opcua]]
   endpoint = "opc.tcp://192.168.1.100:4840"
   security_policy = "Basic256Sha256"
   security_mode = "SignAndEncrypt"
   
   # Client certificates
   certificate = "/etc/telegraf/opcua_client_cert.pem"
   private_key = "/etc/telegraf/opcua_client_key.pem"

   # Server certificate to trust (new feature)
   server_certificate = "/etc/telegraf/opcua_server_cert.pem"

Checklist

  • No AI generated code was used in this PR

Related issues

resolves #17608

Add support for explicitly trusting server certificates when connecting to OPC UA servers with self-signed certificates. This resolves connection failures with "StatusBadSecurityChecksFailed" error when using SignAndEncrypt security mode.
@telegraf-tiger telegraf-tiger bot added area/opcua feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins labels Oct 14, 2025
Copy link
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @skartikey for the PR! Some small comments in the code, the biggest being the naming of the option...

skartikey and others added 3 commits October 22, 2025 18:04
Co-authored-by: Sven Rebhan <36194019+srebhan@users.noreply.github.com>
  Rename configuration option from server_certificate to remote_certificate
  for improved clarity, especially for opcua_listener plugin. Also restructure
  README to make "Server Certificate Trust" a subsection under Configuration.
  - Rename config option for clarity across opcua and opcua_listener plugins
  - Simplify documentation: remove third-party specifics and example configs
  - Fix race condition: read certificate content immediately after validation
  - Simplify test assertions to inline require statements
  - Update coding guidelines with review learnings
@telegraf-tiger
Copy link
Contributor

Copy link
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update @skartikey! I think we should get rid of the additional checks as none of them will guarantee the certificate handling to succeed. So removing all the magic and just provide the remote-certificate-file option is as good as doing all those checks IMO. The library will fail if it cannot load the file and we can pass that on to the user...

Comment on lines +142 to +150
// Validate remote certificate file exists if provided (regardless of security mode)
if o.RemoteCertificate != "" {
if _, err := os.Stat(o.RemoteCertificate); err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("%w: remote certificate file does not exist: %s", ErrInvalidConfiguration, o.RemoteCertificate)
}
return fmt.Errorf("%w: cannot access remote certificate file: %s: %w", ErrInvalidConfiguration, o.RemoteCertificate, err)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this check? Can't this be handled in the CreateClient function when actually reading the certificate? My reasoning is that this check is actually useless because the file permissions can be changed or the file can be removed between here and the actual read call, so why check it here if it doesn't prevent an error in the read location?

if o.RemoteCertificate != "" {
cert, err := os.ReadFile(o.RemoteCertificate)
if err != nil {
return nil, fmt.Errorf("%w: failed to read remote certificate file %s: %w", ErrInvalidConfiguration, o.RemoteCertificate, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the ErrInvalidConfiguration for checks down below? If so, please add a comment so people don't remove it later. If you don't need it, please remove that part to shorten the error. Furthermore, this actually isn't an invalid configuration but maybe just a permission issue... ;-)

Comment on lines +351 to +357

// If a remote certificate is explicitly configured, use it to override
// the certificate from the endpoint. This allows trusting self-signed certificates.
if len(o.remoteCertificate) > 0 {
o.Log.Debugf("Using explicitly configured remote certificate from %s", o.Config.RemoteCertificate)
opts = append(opts, opcua.RemoteCertificate(o.remoteCertificate))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So reading of the above, I think you should remove all those checks above and just use the opcua.RemoteCertificateFile (or whatever it was) call here and leave the error handling to the library!

Comment on lines +289 to +290
#### Obtaining the Server Certificate

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove this caption and put it in the text, but that's just a matter of taste not a must.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/opcua feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegraf OPC UA self-signed server cert trust issue

3 participants