feat(common.opcua): Add support for secret-store secrets (#12863)
This commit is contained in:
parent
1ccad43d6b
commit
bd5f6b7c7c
|
|
@ -24,8 +24,8 @@ type OpcUAClientConfig struct {
|
||||||
SecurityMode string `toml:"security_mode"`
|
SecurityMode string `toml:"security_mode"`
|
||||||
Certificate string `toml:"certificate"`
|
Certificate string `toml:"certificate"`
|
||||||
PrivateKey string `toml:"private_key"`
|
PrivateKey string `toml:"private_key"`
|
||||||
Username string `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password string `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
AuthMethod string `toml:"auth_method"`
|
AuthMethod string `toml:"auth_method"`
|
||||||
ConnectTimeout config.Duration `toml:"connect_timeout"`
|
ConnectTimeout config.Duration `toml:"connect_timeout"`
|
||||||
RequestTimeout config.Duration `toml:"request_timeout"`
|
RequestTimeout config.Duration `toml:"request_timeout"`
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"github.com/gopcua/opcua"
|
"github.com/gopcua/opcua"
|
||||||
"github.com/gopcua/opcua/debug"
|
"github.com/gopcua/opcua/debug"
|
||||||
"github.com/gopcua/opcua/ua"
|
"github.com/gopcua/opcua/ua"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SELF SIGNED CERT FUNCTIONS
|
// SELF SIGNED CERT FUNCTIONS
|
||||||
|
|
@ -288,42 +289,42 @@ func (o *OpcUAClient) generateClientOpts(endpoints []*ua.EndpointDescription) ([
|
||||||
return opts, nil
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OpcUAClient) generateAuth(a string, cert []byte, un, pw string) (ua.UserTokenType, opcua.Option, error) {
|
func (o *OpcUAClient) generateAuth(a string, cert []byte, user, passwd config.Secret) (ua.UserTokenType, opcua.Option, error) {
|
||||||
var err error
|
|
||||||
|
|
||||||
var authMode ua.UserTokenType
|
var authMode ua.UserTokenType
|
||||||
var authOption opcua.Option
|
var authOption opcua.Option
|
||||||
switch strings.ToLower(a) {
|
switch strings.ToLower(a) {
|
||||||
case "anonymous":
|
case "anonymous":
|
||||||
authMode = ua.UserTokenTypeAnonymous
|
authMode = ua.UserTokenTypeAnonymous
|
||||||
authOption = opcua.AuthAnonymous()
|
authOption = opcua.AuthAnonymous()
|
||||||
|
|
||||||
case "username":
|
case "username":
|
||||||
authMode = ua.UserTokenTypeUserName
|
authMode = ua.UserTokenTypeUserName
|
||||||
|
|
||||||
if un == "" {
|
var username, password []byte
|
||||||
|
if !user.Empty() {
|
||||||
|
var err error
|
||||||
|
username, err = user.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("error reading the username input: %w", err)
|
return 0, nil, fmt.Errorf("error reading the username input: %w", err)
|
||||||
}
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pw == "" {
|
if !passwd.Empty() {
|
||||||
|
var err error
|
||||||
|
password, err = passwd.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, fmt.Errorf("error reading the password input: %w", err)
|
return 0, nil, fmt.Errorf("error reading the password input: %w", err)
|
||||||
}
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
}
|
}
|
||||||
|
authOption = opcua.AuthUsername(string(username), string(password))
|
||||||
authOption = opcua.AuthUsername(un, pw)
|
|
||||||
|
|
||||||
case "certificate":
|
case "certificate":
|
||||||
authMode = ua.UserTokenTypeCertificate
|
authMode = ua.UserTokenTypeCertificate
|
||||||
authOption = opcua.AuthCertificate(cert)
|
authOption = opcua.AuthCertificate(cert)
|
||||||
|
|
||||||
case "issuedtoken":
|
case "issuedtoken":
|
||||||
// todo: this is unsupported, fail here or fail in the opcua package?
|
// todo: this is unsupported, fail here or fail in the opcua package?
|
||||||
authMode = ua.UserTokenTypeIssuedToken
|
authMode = ua.UserTokenTypeIssuedToken
|
||||||
authOption = opcua.AuthIssuedToken([]byte(nil))
|
authOption = opcua.AuthIssuedToken([]byte(nil))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
o.Log.Warnf("unknown auth-mode, defaulting to Anonymous")
|
o.Log.Warnf("unknown auth-mode, defaulting to Anonymous")
|
||||||
authMode = ua.UserTokenTypeAnonymous
|
authMode = ua.UserTokenTypeAnonymous
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,15 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
|
|
||||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||||
|
|
||||||
|
## Secret-store support
|
||||||
|
|
||||||
|
This plugin supports secrets from secret-stores for the `username` and
|
||||||
|
`password` option.
|
||||||
|
See the [secret-store documentation][SECRETSTORE] for more details on how
|
||||||
|
to use them.
|
||||||
|
|
||||||
|
[SECRETSTORE]: ../../../docs/CONFIGURATION.md#secret-store-secrets
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
```toml @sample.conf
|
```toml @sample.conf
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,6 @@ func TestGetDataBadNodeContainerIntegration(t *testing.T) {
|
||||||
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
||||||
SecurityPolicy: "None",
|
SecurityPolicy: "None",
|
||||||
SecurityMode: "None",
|
SecurityMode: "None",
|
||||||
Certificate: "",
|
|
||||||
PrivateKey: "",
|
|
||||||
Username: "",
|
|
||||||
Password: "",
|
|
||||||
AuthMethod: "Anonymous",
|
AuthMethod: "Anonymous",
|
||||||
ConnectTimeout: config.Duration(10 * time.Second),
|
ConnectTimeout: config.Duration(10 * time.Second),
|
||||||
RequestTimeout: config.Duration(1 * time.Second),
|
RequestTimeout: config.Duration(1 * time.Second),
|
||||||
|
|
@ -128,10 +124,6 @@ func TestReadClientIntegration(t *testing.T) {
|
||||||
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
||||||
SecurityPolicy: "None",
|
SecurityPolicy: "None",
|
||||||
SecurityMode: "None",
|
SecurityMode: "None",
|
||||||
Certificate: "",
|
|
||||||
PrivateKey: "",
|
|
||||||
Username: "",
|
|
||||||
Password: "",
|
|
||||||
AuthMethod: "Anonymous",
|
AuthMethod: "Anonymous",
|
||||||
ConnectTimeout: config.Duration(10 * time.Second),
|
ConnectTimeout: config.Duration(10 * time.Second),
|
||||||
RequestTimeout: config.Duration(1 * time.Second),
|
RequestTimeout: config.Duration(1 * time.Second),
|
||||||
|
|
@ -188,8 +180,8 @@ func TestReadClientIntegrationWithPasswordAuth(t *testing.T) {
|
||||||
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
Endpoint: fmt.Sprintf("opc.tcp://%s:%s", container.Address, container.Ports[servicePort]),
|
||||||
SecurityPolicy: "None",
|
SecurityPolicy: "None",
|
||||||
SecurityMode: "None",
|
SecurityMode: "None",
|
||||||
Username: "peter",
|
Username: config.NewSecret([]byte("peter")),
|
||||||
Password: "peter123",
|
Password: config.NewSecret([]byte("peter123")),
|
||||||
AuthMethod: "UserName",
|
AuthMethod: "UserName",
|
||||||
ConnectTimeout: config.Duration(10 * time.Second),
|
ConnectTimeout: config.Duration(10 * time.Second),
|
||||||
RequestTimeout: config.Duration(1 * time.Second),
|
RequestTimeout: config.Duration(1 * time.Second),
|
||||||
|
|
@ -293,8 +285,8 @@ use_unregistered_reads = true
|
||||||
require.Equal(t, "/etc/telegraf/cert.pem", o.ReadClientConfig.Certificate)
|
require.Equal(t, "/etc/telegraf/cert.pem", o.ReadClientConfig.Certificate)
|
||||||
require.Equal(t, "/etc/telegraf/key.pem", o.ReadClientConfig.PrivateKey)
|
require.Equal(t, "/etc/telegraf/key.pem", o.ReadClientConfig.PrivateKey)
|
||||||
require.Equal(t, "Anonymous", o.ReadClientConfig.AuthMethod)
|
require.Equal(t, "Anonymous", o.ReadClientConfig.AuthMethod)
|
||||||
require.Equal(t, "", o.ReadClientConfig.Username)
|
require.True(t, o.ReadClientConfig.Username.Empty())
|
||||||
require.Equal(t, "", o.ReadClientConfig.Password)
|
require.True(t, o.ReadClientConfig.Password.Empty())
|
||||||
require.Equal(t, []input.NodeSettings{
|
require.Equal(t, []input.NodeSettings{
|
||||||
{
|
{
|
||||||
FieldName: "name",
|
FieldName: "name",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,15 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
|
|
||||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||||
|
|
||||||
|
## Secret-store support
|
||||||
|
|
||||||
|
This plugin supports secrets from secret-stores for the `username` and
|
||||||
|
`password` option.
|
||||||
|
See the [secret-store documentation][SECRETSTORE] for more details on how
|
||||||
|
to use them.
|
||||||
|
|
||||||
|
[SECRETSTORE]: ../../../docs/CONFIGURATION.md#secret-store-secrets
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
```toml @sample.conf
|
```toml @sample.conf
|
||||||
|
|
|
||||||
|
|
@ -205,8 +205,8 @@ additional_valid_status_codes = ["0xC0"]
|
||||||
require.Equal(t, "/etc/telegraf/cert.pem", o.SubscribeClientConfig.Certificate)
|
require.Equal(t, "/etc/telegraf/cert.pem", o.SubscribeClientConfig.Certificate)
|
||||||
require.Equal(t, "/etc/telegraf/key.pem", o.SubscribeClientConfig.PrivateKey)
|
require.Equal(t, "/etc/telegraf/key.pem", o.SubscribeClientConfig.PrivateKey)
|
||||||
require.Equal(t, "Anonymous", o.SubscribeClientConfig.AuthMethod)
|
require.Equal(t, "Anonymous", o.SubscribeClientConfig.AuthMethod)
|
||||||
require.Equal(t, "", o.SubscribeClientConfig.Username)
|
require.True(t, o.SubscribeClientConfig.Username.Empty())
|
||||||
require.Equal(t, "", o.SubscribeClientConfig.Password)
|
require.True(t, o.SubscribeClientConfig.Password.Empty())
|
||||||
require.Equal(t, []input.NodeSettings{
|
require.Equal(t, []input.NodeSettings{
|
||||||
{
|
{
|
||||||
FieldName: "name",
|
FieldName: "name",
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ func (o *SubscribeClient) processReceivedNotifications() {
|
||||||
i := int(monitoredItemNotif.ClientHandle)
|
i := int(monitoredItemNotif.ClientHandle)
|
||||||
oldValue := o.LastReceivedData[i].Value
|
oldValue := o.LastReceivedData[i].Value
|
||||||
o.UpdateNodeValue(i, monitoredItemNotif.Value)
|
o.UpdateNodeValue(i, monitoredItemNotif.Value)
|
||||||
o.Log.Debugf("Data change notification: node %q value changed from %f to %f",
|
o.Log.Debugf("Data change notification: node %q value changed from %v to %v",
|
||||||
o.NodeIDs[i].String(), oldValue, o.LastReceivedData[i].Value)
|
o.NodeIDs[i].String(), oldValue, o.LastReceivedData[i].Value)
|
||||||
o.metrics <- o.MetricForNode(i)
|
o.metrics <- o.MetricForNode(i)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue