feat(secretstores): add support for additional input plugins (#12067)

This commit is contained in:
Sven Rebhan 2023-01-09 17:17:23 +01:00 committed by GitHub
parent aa2b6947ff
commit 63ab159481
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 357 additions and 201 deletions

View File

@ -2,15 +2,17 @@ package kafka
import ( import (
"errors" "errors"
"fmt"
"github.com/Shopify/sarama" "github.com/Shopify/sarama"
"github.com/influxdata/telegraf/config"
) )
type SASLAuth struct { type SASLAuth struct {
SASLUsername string `toml:"sasl_username"` SASLUsername config.Secret `toml:"sasl_username"`
SASLPassword string `toml:"sasl_password"` SASLPassword config.Secret `toml:"sasl_password"`
SASLMechanism string `toml:"sasl_mechanism"` SASLMechanism string `toml:"sasl_mechanism"`
SASLVersion *int `toml:"sasl_version"` SASLVersion *int `toml:"sasl_version"`
// GSSAPI config // GSSAPI config
SASLGSSAPIServiceName string `toml:"sasl_gssapi_service_name"` SASLGSSAPIServiceName string `toml:"sasl_gssapi_service_name"`
@ -21,36 +23,46 @@ type SASLAuth struct {
SASLGSSAPIRealm string `toml:"sasl_gssapi_realm"` SASLGSSAPIRealm string `toml:"sasl_gssapi_realm"`
// OAUTHBEARER config. experimental. undoubtedly this is not good enough. // OAUTHBEARER config. experimental. undoubtedly this is not good enough.
SASLAccessToken string `toml:"sasl_access_token"` SASLAccessToken config.Secret `toml:"sasl_access_token"`
} }
// SetSASLConfig configures SASL for kafka (sarama) // SetSASLConfig configures SASL for kafka (sarama)
func (k *SASLAuth) SetSASLConfig(config *sarama.Config) error { func (k *SASLAuth) SetSASLConfig(cfg *sarama.Config) error {
config.Net.SASL.User = k.SASLUsername username, err := k.SASLUsername.Get()
config.Net.SASL.Password = k.SASLPassword if err != nil {
return fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
password, err := k.SASLPassword.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
cfg.Net.SASL.User = string(username)
cfg.Net.SASL.Password = string(password)
if k.SASLMechanism != "" { if k.SASLMechanism != "" {
config.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism) cfg.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism)
switch config.Net.SASL.Mechanism { switch cfg.Net.SASL.Mechanism {
case sarama.SASLTypeSCRAMSHA256: case sarama.SASLTypeSCRAMSHA256:
config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { cfg.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient {
return &XDGSCRAMClient{HashGeneratorFcn: SHA256} return &XDGSCRAMClient{HashGeneratorFcn: SHA256}
} }
case sarama.SASLTypeSCRAMSHA512: case sarama.SASLTypeSCRAMSHA512:
config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { cfg.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient {
return &XDGSCRAMClient{HashGeneratorFcn: SHA512} return &XDGSCRAMClient{HashGeneratorFcn: SHA512}
} }
case sarama.SASLTypeOAuth: case sarama.SASLTypeOAuth:
config.Net.SASL.TokenProvider = k // use self as token provider. cfg.Net.SASL.TokenProvider = k // use self as token provider.
case sarama.SASLTypeGSSAPI: case sarama.SASLTypeGSSAPI:
config.Net.SASL.GSSAPI.ServiceName = k.SASLGSSAPIServiceName cfg.Net.SASL.GSSAPI.ServiceName = k.SASLGSSAPIServiceName
config.Net.SASL.GSSAPI.AuthType = gssapiAuthType(k.SASLGSSAPIAuthType) cfg.Net.SASL.GSSAPI.AuthType = gssapiAuthType(k.SASLGSSAPIAuthType)
config.Net.SASL.GSSAPI.Username = k.SASLUsername cfg.Net.SASL.GSSAPI.Username = string(username)
config.Net.SASL.GSSAPI.Password = k.SASLPassword cfg.Net.SASL.GSSAPI.Password = string(password)
config.Net.SASL.GSSAPI.DisablePAFXFAST = k.SASLGSSAPIDisablePAFXFAST cfg.Net.SASL.GSSAPI.DisablePAFXFAST = k.SASLGSSAPIDisablePAFXFAST
config.Net.SASL.GSSAPI.KerberosConfigPath = k.SASLGSSAPIKerberosConfigPath cfg.Net.SASL.GSSAPI.KerberosConfigPath = k.SASLGSSAPIKerberosConfigPath
config.Net.SASL.GSSAPI.KeyTabPath = k.SASLGSSAPIKeyTabPath cfg.Net.SASL.GSSAPI.KeyTabPath = k.SASLGSSAPIKeyTabPath
config.Net.SASL.GSSAPI.Realm = k.SASLGSSAPIRealm cfg.Net.SASL.GSSAPI.Realm = k.SASLGSSAPIRealm
case sarama.SASLTypePlaintext: case sarama.SASLTypePlaintext:
// nothing. // nothing.
@ -58,22 +70,27 @@ func (k *SASLAuth) SetSASLConfig(config *sarama.Config) error {
} }
} }
if k.SASLUsername != "" || k.SASLMechanism != "" { if len(username) > 0 || k.SASLMechanism != "" {
config.Net.SASL.Enable = true cfg.Net.SASL.Enable = true
version, err := SASLVersion(config.Version, k.SASLVersion) version, err := SASLVersion(cfg.Version, k.SASLVersion)
if err != nil { if err != nil {
return err return err
} }
config.Net.SASL.Version = version cfg.Net.SASL.Version = version
} }
return nil return nil
} }
// Token does nothing smart, it just grabs a hard-coded token from config. // Token does nothing smart, it just grabs a hard-coded token from config.
func (k *SASLAuth) Token() (*sarama.AccessToken, error) { func (k *SASLAuth) Token() (*sarama.AccessToken, error) {
token, err := k.SASLAccessToken.Get()
if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err)
}
defer config.ReleaseSecret(token)
return &sarama.AccessToken{ return &sarama.AccessToken{
Token: k.SASLAccessToken, Token: string(token),
Extensions: map[string]string{}, Extensions: map[string]string{},
}, nil }, nil
} }

View File

@ -51,8 +51,8 @@ type HTTPResponse struct {
ResponseStatusCode int ResponseStatusCode int
Interface string Interface string
// HTTP Basic Auth Credentials // HTTP Basic Auth Credentials
Username string `toml:"username"` Username config.Secret `toml:"username"`
Password string `toml:"password"` Password config.Secret `toml:"password"`
tls.ClientConfig tls.ClientConfig
Log telegraf.Logger Log telegraf.Logger
@ -219,8 +219,8 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
} }
} }
if h.Username != "" || h.Password != "" { if err := h.setRequestAuth(request); err != nil {
request.SetBasicAuth(h.Username, h.Password) return nil, nil, err
} }
// Start Timer // Start Timer
@ -398,6 +398,23 @@ func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
return nil return nil
} }
func (h *HTTPResponse) setRequestAuth(request *http.Request) error {
username, err := h.Username.Get()
if err != nil {
return fmt.Errorf("getting username failed: %v", err)
}
defer config.ReleaseSecret(username)
password, err := h.Password.Get()
if err != nil {
return fmt.Errorf("getting password failed: %v", err)
}
defer config.ReleaseSecret(password)
if len(username) != 0 || len(password) != 0 {
request.SetBasicAuth(string(username), string(password))
}
return nil
}
func init() { func init() {
inputs.Add("http_response", func() telegraf.Input { inputs.Add("http_response", func() telegraf.Input {
return &HTTPResponse{} return &HTTPResponse{}

View File

@ -1115,8 +1115,8 @@ func TestBasicAuth(t *testing.T) {
Body: "{ 'test': 'data'}", Body: "{ 'test': 'data'}",
Method: "GET", Method: "GET",
ResponseTimeout: config.Duration(time.Second * 20), ResponseTimeout: config.Duration(time.Second * 20),
Username: "me", Username: config.NewSecret([]byte("me")),
Password: "mypassword", Password: config.NewSecret([]byte("mypassword")),
Headers: map[string]string{ Headers: map[string]string{
"Content-Type": "application/json", "Content-Type": "application/json",
}, },

View File

@ -65,8 +65,8 @@ type MQTTConsumer struct {
Topics []string `toml:"topics"` Topics []string `toml:"topics"`
TopicTag *string `toml:"topic_tag"` TopicTag *string `toml:"topic_tag"`
TopicParsing []TopicParsingConfig `toml:"topic_parsing"` TopicParsing []TopicParsingConfig `toml:"topic_parsing"`
Username string `toml:"username"` Username config.Secret `toml:"username"`
Password string `toml:"password"` Password config.Secret `toml:"password"`
QoS int `toml:"qos"` QoS int `toml:"qos"`
ConnectionTimeout config.Duration `toml:"connection_timeout"` ConnectionTimeout config.Duration `toml:"connection_timeout"`
MaxUndeliveredMessages int `toml:"max_undelivered_messages"` MaxUndeliveredMessages int `toml:"max_undelivered_messages"`
@ -331,16 +331,25 @@ func (m *MQTTConsumer) createOpts() (*mqtt.ClientOptions, error) {
if tlsCfg != nil { if tlsCfg != nil {
opts.SetTLSConfig(tlsCfg) opts.SetTLSConfig(tlsCfg)
} }
user := m.Username if !m.Username.Empty() {
if user != "" { user, err := m.Username.Get()
opts.SetUsername(user) if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err)
}
opts.SetUsername(string(user))
config.ReleaseSecret(user)
} }
password := m.Password
if password != "" { if !m.Password.Empty() {
opts.SetPassword(password) password, err := m.Password.Get()
if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err)
}
opts.SetPassword(string(password))
config.ReleaseSecret(password)
} }
if len(m.Servers) == 0 { if len(m.Servers) == 0 {
return opts, fmt.Errorf("could not get host informations") return opts, fmt.Errorf("could not get host information")
} }
for _, server := range m.Servers { for _, server := range m.Servers {
// Preserve support for host:port style servers; deprecated in Telegraf 1.4.4 // Preserve support for host:port style servers; deprecated in Telegraf 1.4.4

View File

@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait" "github.com/testcontainers/testcontainers-go/wait"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/inputs/postgresql" "github.com/influxdata/telegraf/plugins/inputs/postgresql"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
) )
@ -48,13 +49,15 @@ func TestPgBouncerGeneratesMetricsIntegration(t *testing.T) {
require.NoError(t, err, "failed to start container") require.NoError(t, err, "failed to start container")
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s user=pgbouncer password=pgbouncer dbname=pgbouncer port=%s sslmode=disable",
container.Address,
container.Ports[pgBouncerServicePort],
)
p := &PgBouncer{ p := &PgBouncer{
Service: postgresql.Service{ Service: postgresql.Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s user=pgbouncer password=pgbouncer dbname=pgbouncer port=%s sslmode=disable",
container.Address,
container.Ports[pgBouncerServicePort],
),
IsPgBouncer: true, IsPgBouncer: true,
}, },
} }

View File

@ -31,6 +31,7 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## to grab metrics for. ## to grab metrics for.
## ##
address = "host=localhost user=postgres sslmode=disable" address = "host=localhost user=postgres sslmode=disable"
## A custom name for the database that will be used as the "server" tag in the ## A custom name for the database that will be used as the "server" tag in the
## measurement output. If not specified, a default one generated from ## measurement output. If not specified, a default one generated from
## the connection address is used. ## the connection address is used.

View File

@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait" "github.com/testcontainers/testcontainers-go/wait"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
) )
@ -42,13 +43,15 @@ func TestPostgresqlGeneratesMetricsIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
IsPgBouncer: false, IsPgBouncer: false,
}, },
Databases: []string{"postgres"}, Databases: []string{"postgres"},
@ -131,13 +134,15 @@ func TestPostgresqlTagsMetricsWithDatabaseNameIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
}, },
Databases: []string{"postgres"}, Databases: []string{"postgres"},
} }
@ -161,13 +166,15 @@ func TestPostgresqlDefaultsToAllDatabasesIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
}, },
} }
@ -198,13 +205,15 @@ func TestPostgresqlIgnoresUnwantedColumnsIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
}, },
} }
@ -225,13 +234,15 @@ func TestPostgresqlDatabaseWhitelistTestIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
}, },
Databases: []string{"template0"}, Databases: []string{"template0"},
} }
@ -269,13 +280,15 @@ func TestPostgresqlDatabaseBlacklistTestIntegration(t *testing.T) {
container := launchTestContainer(t) container := launchTestContainer(t)
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Service: Service{ Service: Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
}, },
IgnoredDatabases: []string{"template0"}, IgnoredDatabases: []string{"template0"},
} }

View File

@ -13,6 +13,7 @@
## to grab metrics for. ## to grab metrics for.
## ##
address = "host=localhost user=postgres sslmode=disable" address = "host=localhost user=postgres sslmode=disable"
## A custom name for the database that will be used as the "server" tag in the ## A custom name for the database that will be used as the "server" tag in the
## measurement output. If not specified, a default one generated from ## measurement output. If not specified, a default one generated from
## the connection address is used. ## the connection address is used.

View File

@ -1,6 +1,7 @@
package postgresql package postgresql
import ( import (
"bytes"
"database/sql" "database/sql"
"fmt" "fmt"
"net" "net"
@ -88,26 +89,31 @@ func parseURL(uri string) (string, error) {
// Service common functionality shared between the postgresql and postgresql_extensible // Service common functionality shared between the postgresql and postgresql_extensible
// packages. // packages.
type Service struct { type Service struct {
Address string Address config.Secret `toml:"address"`
OutputAddress string OutputAddress string `toml:"outputaddress"`
MaxIdle int MaxIdle int `toml:"max_idle"`
MaxOpen int MaxOpen int `toml:"max_open"`
MaxLifetime config.Duration MaxLifetime config.Duration `toml:"max_lifetime"`
IsPgBouncer bool `toml:"-"`
DB *sql.DB DB *sql.DB
IsPgBouncer bool `toml:"-"`
} }
var socketRegexp = regexp.MustCompile(`/\.s\.PGSQL\.\d+$`) var socketRegexp = regexp.MustCompile(`/\.s\.PGSQL\.\d+$`)
// Start starts the ServiceInput's service, whatever that may be // Start starts the ServiceInput's service, whatever that may be
func (p *Service) Start(telegraf.Accumulator) (err error) { func (p *Service) Start(telegraf.Accumulator) (err error) {
const localhost = "host=localhost sslmode=disable" addr, err := p.Address.Get()
if err != nil {
return fmt.Errorf("getting address failed: %v", err)
}
defer config.ReleaseSecret(addr)
if p.Address == "" || p.Address == "localhost" { if p.Address.Empty() || string(addr) == "localhost" {
p.Address = localhost addr = []byte("host=localhost sslmode=disable")
p.Address = config.NewSecret(addr)
} }
connConfig, err := pgx.ParseConfig(p.Address) connConfig, err := pgx.ParseConfig(string(addr))
if err != nil { if err != nil {
return err return err
} }
@ -146,23 +152,24 @@ var kvMatcher, _ = regexp.Compile(`(password|sslcert|sslkey|sslmode|sslrootcert)
// SanitizedAddress utility function to strip sensitive information from the connection string. // SanitizedAddress utility function to strip sensitive information from the connection string.
func (p *Service) SanitizedAddress() (sanitizedAddress string, err error) { func (p *Service) SanitizedAddress() (sanitizedAddress string, err error) {
var (
canonicalizedAddress string
)
if p.OutputAddress != "" { if p.OutputAddress != "" {
return p.OutputAddress, nil return p.OutputAddress, nil
} }
if strings.HasPrefix(p.Address, "postgres://") || strings.HasPrefix(p.Address, "postgresql://") { addr, err := p.Address.Get()
if canonicalizedAddress, err = parseURL(p.Address); err != nil { if err != nil {
return sanitizedAddress, fmt.Errorf("getting address for sanitization failed: %v", err)
}
defer config.ReleaseSecret(addr)
var canonicalizedAddress string
if bytes.HasPrefix(addr, []byte("postgres://")) || bytes.HasPrefix(addr, []byte("postgresql://")) {
if canonicalizedAddress, err = parseURL(string(addr)); err != nil {
return sanitizedAddress, err return sanitizedAddress, err
} }
} else { } else {
canonicalizedAddress = p.Address canonicalizedAddress = string(addr)
} }
sanitizedAddress = kvMatcher.ReplaceAllString(canonicalizedAddress, "") return kvMatcher.ReplaceAllString(canonicalizedAddress, ""), nil
return sanitizedAddress, err
} }

View File

@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait" "github.com/testcontainers/testcontainers-go/wait"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/inputs/postgresql" "github.com/influxdata/telegraf/plugins/inputs/postgresql"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
) )
@ -32,14 +33,16 @@ func queryRunner(t *testing.T, q query) *testutil.Accumulator {
require.NoError(t, err, "failed to start container") require.NoError(t, err, "failed to start container")
defer container.Terminate() defer container.Terminate()
addr := fmt.Sprintf(
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
)
p := &Postgresql{ p := &Postgresql{
Log: testutil.Logger{}, Log: testutil.Logger{},
Service: postgresql.Service{ Service: postgresql.Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s port=%s user=postgres sslmode=disable",
container.Address,
container.Ports[servicePort],
),
IsPgBouncer: false, IsPgBouncer: false,
}, },
Databases: []string{"postgres"}, Databases: []string{"postgres"},
@ -239,13 +242,16 @@ func TestPostgresqlSqlScript(t *testing.T) {
Withdbname: false, Withdbname: false,
Tagvalue: "", Tagvalue: "",
}} }}
addr := fmt.Sprintf(
"host=%s user=postgres sslmode=disable",
testutil.GetLocalHost(),
)
p := &Postgresql{ p := &Postgresql{
Log: testutil.Logger{}, Log: testutil.Logger{},
Service: postgresql.Service{ Service: postgresql.Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s user=postgres sslmode=disable",
testutil.GetLocalHost(),
),
IsPgBouncer: false, IsPgBouncer: false,
}, },
Databases: []string{"postgres"}, Databases: []string{"postgres"},
@ -263,13 +269,15 @@ func TestPostgresqlIgnoresUnwantedColumnsIntegration(t *testing.T) {
t.Skip("Skipping integration test in short mode") t.Skip("Skipping integration test in short mode")
} }
addr := fmt.Sprintf(
"host=%s user=postgres sslmode=disable",
testutil.GetLocalHost(),
)
p := &Postgresql{ p := &Postgresql{
Log: testutil.Logger{}, Log: testutil.Logger{},
Service: postgresql.Service{ Service: postgresql.Service{
Address: fmt.Sprintf( Address: config.NewSecret([]byte(addr)),
"host=%s user=postgres sslmode=disable",
testutil.GetLocalHost(),
),
}, },
} }

View File

@ -109,5 +109,7 @@ snmp_trap,mib=SNMPv2-MIB,name=coldStart,oid=.1.3.6.1.6.3.1.1.5.1,source=192.168.
snmp_trap,mib=NET-SNMP-AGENT-MIB,name=nsNotifyShutdown,oid=.1.3.6.1.4.1.8072.4.0.2,source=192.168.122.102,version=2c,community=public sysUpTimeInstance=5803i,snmpTrapEnterprise.0="netSnmpNotificationPrefix" 1574109186555115459 snmp_trap,mib=NET-SNMP-AGENT-MIB,name=nsNotifyShutdown,oid=.1.3.6.1.4.1.8072.4.0.2,source=192.168.122.102,version=2c,community=public sysUpTimeInstance=5803i,snmpTrapEnterprise.0="netSnmpNotificationPrefix" 1574109186555115459
``` ```
[net-snmp]: http://www.net-snmp.org/ ## References
[man snmpcmd]: http://net-snmp.sourceforge.net/docs/man/snmpcmd.html#lbAK
- [net-snmp project home](http://www.net-snmp.org)
- [`snmpcmd` man-page](http://net-snmp.sourceforge.net/docs/man/snmpcmd.html)

View File

@ -35,14 +35,14 @@ type SnmpTrap struct {
// Settings for version 3 // Settings for version 3
// Values: "noAuthNoPriv", "authNoPriv", "authPriv" // Values: "noAuthNoPriv", "authNoPriv", "authPriv"
SecLevel string `toml:"sec_level"` SecLevel string `toml:"sec_level"`
SecName string `toml:"sec_name"` SecName config.Secret `toml:"sec_name"`
// Values: "MD5", "SHA", "". Default: "" // Values: "MD5", "SHA", "". Default: ""
AuthProtocol string `toml:"auth_protocol"` AuthProtocol string `toml:"auth_protocol"`
AuthPassword string `toml:"auth_password"` AuthPassword config.Secret `toml:"auth_password"`
// Values: "DES", "AES", "". Default: "" // Values: "DES", "AES", "". Default: ""
PrivProtocol string `toml:"priv_protocol"` PrivProtocol string `toml:"priv_protocol"`
PrivPassword string `toml:"priv_password"` PrivPassword config.Secret `toml:"priv_password"`
acc telegraf.Accumulator acc telegraf.Accumulator
listener *gosnmp.TrapListener listener *gosnmp.TrapListener
@ -171,13 +171,28 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error {
return fmt.Errorf("unknown privacy protocol '%s'", s.PrivProtocol) return fmt.Errorf("unknown privacy protocol '%s'", s.PrivProtocol)
} }
secname, err := s.SecName.Get()
if err != nil {
return fmt.Errorf("getting secname failed: %v", err)
}
privPasswd, err := s.PrivPassword.Get()
if err != nil {
return fmt.Errorf("getting secname failed: %v", err)
}
authPasswd, err := s.AuthPassword.Get()
if err != nil {
return fmt.Errorf("getting secname failed: %v", err)
}
s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{ s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: s.SecName, UserName: string(secname),
PrivacyProtocol: privacyProtocol, PrivacyProtocol: privacyProtocol,
PrivacyPassphrase: s.PrivPassword, PrivacyPassphrase: string(privPasswd),
AuthenticationPassphrase: s.AuthPassword, AuthenticationPassphrase: string(authPasswd),
AuthenticationProtocol: authenticationProtocol, AuthenticationProtocol: authenticationProtocol,
} }
config.ReleaseSecret(secname)
config.ReleaseSecret(privPasswd)
config.ReleaseSecret(authPasswd)
} }
// wrap the handler, used in unit tests // wrap the handler, used in unit tests

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/internal/snmp" "github.com/influxdata/telegraf/internal/snmp"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
) )
@ -1274,12 +1275,12 @@ func TestReceiveTrap(t *testing.T) {
//if cold start be answer otherwise err //if cold start be answer otherwise err
Log: testutil.Logger{}, Log: testutil.Logger{},
Version: tt.version.String(), Version: tt.version.String(),
SecName: tt.secName, SecName: config.NewSecret([]byte(tt.secName)),
SecLevel: tt.secLevel, SecLevel: tt.secLevel,
AuthProtocol: tt.authProto, AuthProtocol: tt.authProto,
AuthPassword: tt.authPass, AuthPassword: config.NewSecret([]byte(tt.authPass)),
PrivProtocol: tt.privProto, PrivProtocol: tt.privProto,
PrivPassword: tt.privPass, PrivPassword: config.NewSecret([]byte(tt.privPass)),
Translator: "netsnmp", Translator: "netsnmp",
} }

View File

@ -146,7 +146,6 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## "database_type" enables a specific set of queries depending on the database type. If specified, it replaces azuredb = true/false and query_version = 2 ## "database_type" enables a specific set of queries depending on the database type. If specified, it replaces azuredb = true/false and query_version = 2
## In the config file, the sql server plugin section should be repeated each with a set of servers for a specific database_type. ## In the config file, the sql server plugin section should be repeated each with a set of servers for a specific database_type.
## Possible values for database_type are - "SQLServer" or "AzureSQLDB" or "AzureSQLManagedInstance" or "AzureSQLPool" ## Possible values for database_type are - "SQLServer" or "AzureSQLDB" or "AzureSQLManagedInstance" or "AzureSQLPool"
database_type = "SQLServer" database_type = "SQLServer"
## A list of queries to include. If not specified, all the below listed queries are used. ## A list of queries to include. If not specified, all the below listed queries are used.

View File

@ -4,8 +4,10 @@ import (
"os" "os"
"testing" "testing"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil"
) )
func TestAzureSQLIntegration_Database_ResourceStats_Query(t *testing.T) { func TestAzureSQLIntegration_Database_ResourceStats_Query(t *testing.T) {
@ -18,9 +20,10 @@ func TestAzureSQLIntegration_Database_ResourceStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBResourceStats"}, IncludeQuery: []string{"AzureSQLDBResourceStats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -63,9 +66,10 @@ func TestAzureSQLIntegration_Database_ResourceGovernance_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBResourceGovernance"}, IncludeQuery: []string{"AzureSQLDBResourceGovernance"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -124,9 +128,10 @@ func TestAzureSQLIntegration_Database_WaitStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBWaitStats"}, IncludeQuery: []string{"AzureSQLDBWaitStats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -161,9 +166,10 @@ func TestAzureSQLIntegration_Database_DatabaseIO_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBDatabaseIO"}, IncludeQuery: []string{"AzureSQLDBDatabaseIO"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -207,9 +213,10 @@ func TestAzureSQLIntegration_Database_ServerProperties_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBServerProperties"}, IncludeQuery: []string{"AzureSQLDBServerProperties"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -248,9 +255,10 @@ func TestAzureSQLIntegration_Database_OsWaitstats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBOsWaitstats"}, IncludeQuery: []string{"AzureSQLDBOsWaitstats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -286,9 +294,10 @@ func TestAzureSQLIntegration_Database_MemoryClerks_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBMemoryClerks"}, IncludeQuery: []string{"AzureSQLDBMemoryClerks"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -319,9 +328,10 @@ func TestAzureSQLIntegration_Database_PerformanceCounters_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBPerformanceCounters"}, IncludeQuery: []string{"AzureSQLDBPerformanceCounters"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -355,9 +365,10 @@ func TestAzureSQLIntegration_Database_Requests_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBRequests"}, IncludeQuery: []string{"AzureSQLDBRequests"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
@ -413,9 +424,10 @@ func TestAzureSQLIntegration_Database_Schedulers_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_DB_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLDBSchedulers"}, IncludeQuery: []string{"AzureSQLDBSchedulers"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",

View File

@ -4,6 +4,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -18,9 +19,10 @@ func TestAzureSQLIntegration_Managed_ResourceStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIResourceStats"}, IncludeQuery: []string{"AzureSQLMIResourceStats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -51,9 +53,10 @@ func TestAzureSQLIntegration_Managed_ResourceGovernance_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIResourceGovernance"}, IncludeQuery: []string{"AzureSQLMIResourceGovernance"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -92,9 +95,10 @@ func TestAzureSQLIntegration_Managed_DatabaseIO_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIDatabaseIO"}, IncludeQuery: []string{"AzureSQLMIDatabaseIO"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -134,9 +138,10 @@ func TestAzureSQLIntegration_Managed_ServerProperties_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIServerProperties"}, IncludeQuery: []string{"AzureSQLMIServerProperties"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -181,9 +186,10 @@ func TestAzureSQLIntegration_Managed_OsWaitStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIOsWaitstats"}, IncludeQuery: []string{"AzureSQLMIOsWaitstats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -218,9 +224,10 @@ func TestAzureSQLIntegration_Managed_MemoryClerks_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIMemoryClerks"}, IncludeQuery: []string{"AzureSQLMIMemoryClerks"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -250,9 +257,10 @@ func TestAzureSQLIntegration_Managed_PerformanceCounters_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIPerformanceCounters"}, IncludeQuery: []string{"AzureSQLMIPerformanceCounters"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -285,9 +293,10 @@ func TestAzureSQLIntegration_Managed_Requests_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMIRequests"}, IncludeQuery: []string{"AzureSQLMIRequests"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",
@ -343,9 +352,10 @@ func TestAzureSQLIntegration_Managed_Schedulers_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_MI_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLMISchedulers"}, IncludeQuery: []string{"AzureSQLMISchedulers"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLManagedInstance", DatabaseType: "AzureSQLManagedInstance",

View File

@ -4,6 +4,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -18,9 +19,10 @@ func TestAzureSQLIntegration_ElasticPool_ResourceStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolResourceStats"}, IncludeQuery: []string{"AzureSQLPoolResourceStats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -60,9 +62,10 @@ func TestAzureSQLIntegration_ElasticPool_ResourceGovernance_Query(t *testing.T)
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolResourceGovernance"}, IncludeQuery: []string{"AzureSQLPoolResourceGovernance"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -123,9 +126,10 @@ func TestAzureSQLIntegration_ElasticPool_DatabaseIO_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolDatabaseIO"}, IncludeQuery: []string{"AzureSQLPoolDatabaseIO"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -167,9 +171,10 @@ func TestAzureSQLIntegration_ElasticPool_OsWaitStats_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolOsWaitStats"}, IncludeQuery: []string{"AzureSQLPoolOsWaitStats"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -204,9 +209,10 @@ func TestAzureSQLIntegration_ElasticPool_MemoryClerks_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolMemoryClerks"}, IncludeQuery: []string{"AzureSQLPoolMemoryClerks"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -236,9 +242,10 @@ func TestAzureSQLIntegration_ElasticPool_PerformanceCounters_Query(t *testing.T)
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolPerformanceCounters"}, IncludeQuery: []string{"AzureSQLPoolPerformanceCounters"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",
@ -270,9 +277,10 @@ func TestAzureSQLIntegration_ElasticPool_Schedulers_Query(t *testing.T) {
} }
connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") connectionString := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
serversList := []config.Secret{config.NewSecret([]byte(connectionString))}
server := &SQLServer{ server := &SQLServer{
Servers: []string{connectionString}, Servers: serversList,
IncludeQuery: []string{"AzureSQLPoolSchedulers"}, IncludeQuery: []string{"AzureSQLPoolSchedulers"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
DatabaseType: "AzureSQLPool", DatabaseType: "AzureSQLPool",

View File

@ -23,7 +23,6 @@
## "database_type" enables a specific set of queries depending on the database type. If specified, it replaces azuredb = true/false and query_version = 2 ## "database_type" enables a specific set of queries depending on the database type. If specified, it replaces azuredb = true/false and query_version = 2
## In the config file, the sql server plugin section should be repeated each with a set of servers for a specific database_type. ## In the config file, the sql server plugin section should be repeated each with a set of servers for a specific database_type.
## Possible values for database_type are - "SQLServer" or "AzureSQLDB" or "AzureSQLManagedInstance" or "AzureSQLPool" ## Possible values for database_type are - "SQLServer" or "AzureSQLDB" or "AzureSQLManagedInstance" or "AzureSQLPool"
database_type = "SQLServer" database_type = "SQLServer"
## A list of queries to include. If not specified, all the below listed queries are used. ## A list of queries to include. If not specified, all the below listed queries are used.

View File

@ -25,7 +25,7 @@ var sampleConfig string
// SQLServer struct // SQLServer struct
type SQLServer struct { type SQLServer struct {
Servers []string `toml:"servers"` Servers []config.Secret `toml:"servers"`
QueryTimeout config.Duration `toml:"query_timeout"` QueryTimeout config.Duration `toml:"query_timeout"`
AuthMethod string `toml:"auth_method"` AuthMethod string `toml:"auth_method"`
QueryVersion int `toml:"query_version" deprecated:"1.16.0;use 'database_type' instead"` QueryVersion int `toml:"query_version" deprecated:"1.16.0;use 'database_type' instead"`
@ -206,12 +206,17 @@ func (s *SQLServer) Gather(acc telegraf.Accumulator) error {
wg.Add(1) wg.Add(1)
go func(pool *sql.DB, query Query, serverIndex int) { go func(pool *sql.DB, query Query, serverIndex int) {
defer wg.Done() defer wg.Done()
connectionString := s.Servers[serverIndex] dsn, err := s.Servers[serverIndex].Get()
queryError := s.gatherServer(pool, query, acc, connectionString) if err != nil {
acc.AddError(err)
return
}
defer config.ReleaseSecret(dsn)
queryError := s.gatherServer(pool, query, acc, string(dsn))
if s.HealthMetric { if s.HealthMetric {
mutex.Lock() mutex.Lock()
s.gatherHealth(healthMetrics, connectionString, queryError) s.gatherHealth(healthMetrics, string(dsn), queryError)
mutex.Unlock() mutex.Unlock()
} }
@ -244,19 +249,24 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
switch strings.ToLower(s.AuthMethod) { switch strings.ToLower(s.AuthMethod) {
case "connection_string": case "connection_string":
// Get the connection string potentially containing secrets
dsn, err := serv.Get()
if err != nil {
acc.AddError(err)
continue
}
// Use the DSN (connection string) directly. In this case, // Use the DSN (connection string) directly. In this case,
// empty username/password causes use of Windows // empty username/password causes use of Windows
// integrated authentication. // integrated authentication.
var err error pool, err = sql.Open("mssql", string(dsn))
pool, err = sql.Open("mssql", serv) config.ReleaseSecret(dsn)
if err != nil { if err != nil {
acc.AddError(err) acc.AddError(err)
continue continue
} }
case "aad": case "aad":
// AAD Auth with system-assigned managed identity (MSI) // AAD Auth with system-assigned managed identity (MSI)
// AAD Auth is only supported for Azure SQL Database or Azure SQL Managed Instance // AAD Auth is only supported for Azure SQL Database or Azure SQL Managed Instance
if s.DatabaseType == "SQLServer" { if s.DatabaseType == "SQLServer" {
err := errors.New("database connection failed : AAD auth is not supported for SQL VM i.e. DatabaseType=SQLServer") err := errors.New("database connection failed : AAD auth is not supported for SQL VM i.e. DatabaseType=SQLServer")
@ -271,7 +281,14 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
continue continue
} }
connector, err := mssql.NewAccessTokenConnector(serv, tokenProvider) // Get the connection string potentially containing secrets
dsn, err := serv.Get()
if err != nil {
acc.AddError(err)
continue
}
connector, err := mssql.NewAccessTokenConnector(string(dsn), tokenProvider)
config.ReleaseSecret(dsn)
if err != nil { if err != nil {
acc.AddError(fmt.Errorf("error creating the SQL connector : %s", err.Error())) acc.AddError(fmt.Errorf("error creating the SQL connector : %s", err.Error()))
continue continue
@ -529,7 +546,7 @@ func (s *SQLServer) refreshToken() (*adal.Token, error) {
func init() { func init() {
inputs.Add("sqlserver", func() telegraf.Input { inputs.Add("sqlserver", func() telegraf.Input {
return &SQLServer{ return &SQLServer{
Servers: []string{defaultServer}, Servers: []config.Secret{config.NewSecret([]byte(defaultServer))},
AuthMethod: "connection_string", AuthMethod: "connection_string",
} }
}) })

View File

@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil" "github.com/influxdata/telegraf/testutil"
) )
@ -116,12 +117,12 @@ func TestSqlServerIntegration_MultipleInstance(t *testing.T) {
testServer := "Server=127.0.0.1;Port=1433;User Id=SA;Password=ABCabc01;app name=telegraf;log=1" testServer := "Server=127.0.0.1;Port=1433;User Id=SA;Password=ABCabc01;app name=telegraf;log=1"
s := &SQLServer{ s := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
ExcludeQuery: []string{"MemoryClerk"}, ExcludeQuery: []string{"MemoryClerk"},
Log: testutil.Logger{}, Log: testutil.Logger{},
} }
s2 := &SQLServer{ s2 := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
ExcludeQuery: []string{"DatabaseSize"}, ExcludeQuery: []string{"DatabaseSize"},
Log: testutil.Logger{}, Log: testutil.Logger{},
} }
@ -153,12 +154,12 @@ func TestSqlServerIntegration_MultipleInstanceWithHealthMetric(t *testing.T) {
testServer := "Server=127.0.0.1;Port=1433;User Id=SA;Password=ABCabc01;app name=telegraf;log=1" testServer := "Server=127.0.0.1;Port=1433;User Id=SA;Password=ABCabc01;app name=telegraf;log=1"
s := &SQLServer{ s := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
ExcludeQuery: []string{"MemoryClerk"}, ExcludeQuery: []string{"MemoryClerk"},
Log: testutil.Logger{}, Log: testutil.Logger{},
} }
s2 := &SQLServer{ s2 := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
ExcludeQuery: []string{"DatabaseSize"}, ExcludeQuery: []string{"DatabaseSize"},
HealthMetric: true, HealthMetric: true,
Log: testutil.Logger{}, Log: testutil.Logger{},
@ -194,7 +195,10 @@ func TestSqlServer_HealthMetric(t *testing.T) {
fakeServer2 := "localhost\\fakeinstance2;Database=fakedb2;Password=ABCabc01;" fakeServer2 := "localhost\\fakeinstance2;Database=fakedb2;Password=ABCabc01;"
s1 := &SQLServer{ s1 := &SQLServer{
Servers: []string{fakeServer1, fakeServer2}, Servers: []config.Secret{
config.NewSecret([]byte(fakeServer1)),
config.NewSecret([]byte(fakeServer2)),
},
IncludeQuery: []string{"DatabaseSize", "MemoryClerk"}, IncludeQuery: []string{"DatabaseSize", "MemoryClerk"},
HealthMetric: true, HealthMetric: true,
AuthMethod: "connection_string", AuthMethod: "connection_string",
@ -202,7 +206,7 @@ func TestSqlServer_HealthMetric(t *testing.T) {
} }
s2 := &SQLServer{ s2 := &SQLServer{
Servers: []string{fakeServer1}, Servers: []config.Secret{config.NewSecret([]byte(fakeServer1))},
IncludeQuery: []string{"DatabaseSize"}, IncludeQuery: []string{"DatabaseSize"},
AuthMethod: "connection_string", AuthMethod: "connection_string",
Log: testutil.Logger{}, Log: testutil.Logger{},
@ -344,13 +348,13 @@ func TestSqlServerIntegration_AGQueriesApplicableForDatabaseTypeSQLServer(t *tes
testServer := os.Getenv("AZURESQL_POOL_CONNECTION_STRING") testServer := os.Getenv("AZURESQL_POOL_CONNECTION_STRING")
s := &SQLServer{ s := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
DatabaseType: "SQLServer", DatabaseType: "SQLServer",
IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"}, IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"},
Log: testutil.Logger{}, Log: testutil.Logger{},
} }
s2 := &SQLServer{ s2 := &SQLServer{
Servers: []string{testServer}, Servers: []config.Secret{config.NewSecret([]byte(testServer))},
DatabaseType: "AzureSQLDB", DatabaseType: "AzureSQLDB",
IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"}, IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"},
Log: testutil.Logger{}, Log: testutil.Logger{},
@ -395,13 +399,13 @@ func TestSqlServerIntegration_AGQueryFieldsOutputBasedOnSQLServerVersion(t *test
testServer2012 := os.Getenv("AZURESQL_POOL_CONNECTION_STRING_2012") testServer2012 := os.Getenv("AZURESQL_POOL_CONNECTION_STRING_2012")
s2019 := &SQLServer{ s2019 := &SQLServer{
Servers: []string{testServer2019}, Servers: []config.Secret{config.NewSecret([]byte(testServer2019))},
DatabaseType: "SQLServer", DatabaseType: "SQLServer",
IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"}, IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"},
Log: testutil.Logger{}, Log: testutil.Logger{},
} }
s2012 := &SQLServer{ s2012 := &SQLServer{
Servers: []string{testServer2012}, Servers: []config.Secret{config.NewSecret([]byte(testServer2012))},
DatabaseType: "SQLServer", DatabaseType: "SQLServer",
IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"}, IncludeQuery: []string{"SQLServerAvailabilityReplicaStates", "SQLServerDatabaseReplicaStates"},
Log: testutil.Logger{}, Log: testutil.Logger{},

View File

@ -21,6 +21,7 @@ import (
"github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/types"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
) )
// The highest number of metrics we can query for, no matter what settings // The highest number of metrics we can query for, no matter what settings
@ -99,9 +100,24 @@ func (cf *ClientFactory) testClient(ctx context.Context) error {
cf.parent.Log.Info("Client session seems to have time out. Reauthenticating!") cf.parent.Log.Info("Client session seems to have time out. Reauthenticating!")
ctx2, cancel2 := context.WithTimeout(ctx, time.Duration(cf.parent.Timeout)) ctx2, cancel2 := context.WithTimeout(ctx, time.Duration(cf.parent.Timeout))
defer cancel2() defer cancel2()
if err := cf.client.Client.SessionManager.Login(ctx2, url.UserPassword(cf.parent.Username, cf.parent.Password)); err != nil {
return fmt.Errorf("renewing authentication failed: %s", err.Error()) // Resolving the secrets and construct the authentication info
username, err := cf.parent.Username.Get()
if err != nil {
return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username)
password, err := cf.parent.Password.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
auth := url.UserPassword(string(username), string(password))
if err := cf.client.Client.SessionManager.Login(ctx2, auth); err != nil {
return fmt.Errorf("renewing authentication failed: %w", err)
}
} }
return nil return nil
@ -120,8 +136,19 @@ func NewClient(ctx context.Context, vSphereURL *url.URL, vs *VSphere) (*Client,
if tlsCfg == nil { if tlsCfg == nil {
tlsCfg = &tls.Config{} tlsCfg = &tls.Config{}
} }
if vs.Username != "" { if !vs.Username.Empty() {
vSphereURL.User = url.UserPassword(vs.Username, vs.Password) // Resolving the secrets and construct the authentication info
username, err := vs.Username.Get()
if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
password, err := vs.Password.Get()
if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
vSphereURL.User = url.UserPassword(string(username), string(password))
} }
vs.Log.Debugf("Creating client: %s", vSphereURL.Host) vs.Log.Debugf("Creating client: %s", vSphereURL.Host)

View File

@ -22,8 +22,8 @@ var sampleConfig string
// and a list of connected vSphere endpoints // and a list of connected vSphere endpoints
type VSphere struct { type VSphere struct {
Vcenters []string Vcenters []string
Username string Username config.Secret `toml:"username"`
Password string Password config.Secret `toml:"password"`
DatacenterInstances bool DatacenterInstances bool
DatacenterMetricInclude []string DatacenterMetricInclude []string
DatacenterMetricExclude []string DatacenterMetricExclude []string

View File

@ -225,9 +225,7 @@ func TestMaxQuery(t *testing.T) {
return return
} }
m, s, err := createSim(0) m, s, err := createSim(0)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
defer m.Remove() defer m.Remove()
defer s.Close() defer s.Close()
@ -235,9 +233,7 @@ func TestMaxQuery(t *testing.T) {
v.MaxQueryMetrics = 256 v.MaxQueryMetrics = 256
ctx := context.Background() ctx := context.Background()
c, err := NewClient(ctx, s.URL, v) c, err := NewClient(ctx, s.URL, v)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
require.Equal(t, 256, v.MaxQueryMetrics) require.Equal(t, 256, v.MaxQueryMetrics)
om := object.NewOptionManager(c.Client.Client, *c.Client.Client.ServiceContent.Setting) om := object.NewOptionManager(c.Client.Client, *c.Client.Client.ServiceContent.Setting)
@ -245,16 +241,12 @@ func TestMaxQuery(t *testing.T) {
Key: "config.vpxd.stats.maxQueryMetrics", Key: "config.vpxd.stats.maxQueryMetrics",
Value: "42", Value: "42",
}}) }})
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
v.MaxQueryMetrics = 256 v.MaxQueryMetrics = 256
ctx = context.Background() ctx = context.Background()
c2, err := NewClient(ctx, s.URL, v) c2, err := NewClient(ctx, s.URL, v)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
require.Equal(t, 42, v.MaxQueryMetrics) require.Equal(t, 42, v.MaxQueryMetrics)
c.close() c.close()
c2.close() c2.close()
@ -287,9 +279,7 @@ func TestFinder(t *testing.T) {
} }
m, s, err := createSim(0) m, s, err := createSim(0)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
defer m.Remove() defer m.Remove()
defer s.Close() defer s.Close()
@ -413,9 +403,7 @@ func TestFolders(t *testing.T) {
} }
m, s, err := createSim(1) m, s, err := createSim(1)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
defer m.Remove() defer m.Remove()
defer s.Close() defer s.Close()
@ -477,8 +465,8 @@ func testCollection(t *testing.T, excludeClusters bool) {
v := defaultVSphere() v := defaultVSphere()
if vCenter != "" { if vCenter != "" {
v.Vcenters = []string{vCenter} v.Vcenters = []string{vCenter}
v.Username = username v.Username = config.NewSecret([]byte(username))
v.Password = password v.Password = config.NewSecret([]byte(password))
} else { } else {
// Don't run test on 32-bit machines due to bug in simulator. // Don't run test on 32-bit machines due to bug in simulator.
// https://github.com/vmware/govmomi/issues/1330 // https://github.com/vmware/govmomi/issues/1330
@ -488,9 +476,7 @@ func testCollection(t *testing.T, excludeClusters bool) {
} }
m, s, err := createSim(0) m, s, err := createSim(0)
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
defer m.Remove() defer m.Remove()
defer s.Close() defer s.Close()
v.Vcenters = []string{s.URL.String()} v.Vcenters = []string{s.URL.String()}