chore(secrets): Abstract secret implementation (#13953)

This commit is contained in:
Sven Rebhan 2023-09-25 22:37:04 +02:00 committed by GitHub
parent ac79964226
commit e2c4e10650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 484 additions and 358 deletions

View File

@ -8,10 +8,9 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/awnumar/memguard"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"golang.org/x/term" "golang.org/x/term"
"github.com/influxdata/telegraf/config"
) )
func processFilterOnlySecretStoreFlags(ctx *cli.Context) Filters { func processFilterOnlySecretStoreFlags(ctx *cli.Context) Filters {
@ -119,7 +118,7 @@ To also reveal the actual secret, i.e. the value, you can pass the
} }
} }
_, _ = fmt.Printf(" %-30s %s\n", k, string(v)) _, _ = fmt.Printf(" %-30s %s\n", k, string(v))
config.ReleaseSecret(v) memguard.WipeBytes(v)
} }
} }

View File

@ -6,8 +6,6 @@ import (
"strings" "strings"
"sync/atomic" "sync/atomic"
"github.com/awnumar/memguard"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
) )
@ -26,17 +24,67 @@ var secretStorePattern = regexp.MustCompile(`^\w+$`)
// in a secret-store. // in a secret-store.
var secretPattern = regexp.MustCompile(`@\{(\w+:\w+)\}`) var secretPattern = regexp.MustCompile(`@\{(\w+:\w+)\}`)
// secretCount is the number of secrets use in Telegraf
var secretCount atomic.Int64 var secretCount atomic.Int64
// selectedImpl is the configured implementation for secrets
var selectedImpl secretImpl = &protectedSecretImpl{}
// secretImpl represents an abstraction for different implementations of secrets
type secretImpl interface {
Container(secret []byte) secretContainer
EmptyBuffer() SecretBuffer
Wipe(secret []byte)
}
// secretContainer represents an abstraction of the container holding the
// actual secret value
type secretContainer interface {
Destroy()
Equals(ref []byte) (bool, error)
Buffer() (SecretBuffer, error)
AsBuffer(secret []byte) SecretBuffer
Replace(secret []byte)
}
// SecretBuffer allows to access the content of the secret
type SecretBuffer interface {
// Size returns the length of the buffer content
Size() int
// Grow will grow the capacity of the underlying buffer to the given size
Grow(capacity int)
// Bytes returns the content of the buffer as bytes.
// NOTE: The returned bytes shall NOT be accessed after destroying the
// buffer using 'Destroy()' as the underlying the memory area might be
// wiped and invalid.
Bytes() []byte
// TemporaryString returns the content of the buffer as a string.
// NOTE: The returned String shall NOT be accessed after destroying the
// buffer using 'Destroy()' as the underlying the memory area might be
// wiped and invalid.
TemporaryString() string
// String returns a copy of the underlying buffer's content as string.
// It is safe to use the returned value after destroying the buffer.
String() string
// Destroy will wipe the buffer's content and destroy the underlying
// buffer. Do not access the buffer after destroying it.
Destroy()
}
// Secret safely stores sensitive data such as a password or token // Secret safely stores sensitive data such as a password or token
type Secret struct { type Secret struct {
enclave *memguard.Enclave // container is the implementation for holding the secret. It can be
// protected or not depending on the concrete implementation.
container secretContainer
// resolvers are the functions for resolving a given secret-id (key)
resolvers map[string]telegraf.ResolveFunc resolvers map[string]telegraf.ResolveFunc
// unlinked contains all references in the secret that are not yet // unlinked contains all references in the secret that are not yet
// linked to the corresponding secret store. // linked to the corresponding secret store.
unlinked []string unlinked []string
// Denotes if the secret is completely empty // notempty denotes if the secret is completely empty
notempty bool notempty bool
} }
@ -71,10 +119,10 @@ func (s *Secret) init(secret []byte) {
// Find all parts that need to be resolved and return them // Find all parts that need to be resolved and return them
s.unlinked = secretPattern.FindAllString(string(secret), -1) s.unlinked = secretPattern.FindAllString(string(secret), -1)
// Setup the enclave
s.enclave = memguard.NewEnclave(secret)
s.resolvers = nil s.resolvers = nil
// Setup the container implementation
s.container = selectedImpl.Container(secret)
} }
// Destroy the secret content // Destroy the secret content
@ -83,17 +131,11 @@ func (s *Secret) Destroy() {
s.unlinked = nil s.unlinked = nil
s.notempty = false s.notempty = false
if s.enclave == nil { if s.container != nil {
return s.container.Destroy()
s.container = nil
} }
// Wipe the secret from memory
lockbuf, err := s.enclave.Open()
if err == nil {
lockbuf.Destroy()
}
s.enclave = nil
// Keep track of the number of secrets... // Keep track of the number of secrets...
secretCount.Add(-1) secretCount.Add(-1)
} }
@ -105,7 +147,7 @@ func (s *Secret) Empty() bool {
// EqualTo performs a constant-time comparison of the secret to the given reference // EqualTo performs a constant-time comparison of the secret to the given reference
func (s *Secret) EqualTo(ref []byte) (bool, error) { func (s *Secret) EqualTo(ref []byte) (bool, error) {
if s.enclave == nil { if s.container == nil {
return false, nil return false, nil
} }
@ -113,20 +155,13 @@ func (s *Secret) EqualTo(ref []byte) (bool, error) {
return false, fmt.Errorf("unlinked parts in secret: %v", strings.Join(s.unlinked, ";")) return false, fmt.Errorf("unlinked parts in secret: %v", strings.Join(s.unlinked, ";"))
} }
// Get a locked-buffer of the secret to perform the comparison return s.container.Equals(ref)
lockbuf, err := s.enclave.Open()
if err != nil {
return false, fmt.Errorf("opening enclave failed: %w", err)
}
defer lockbuf.Destroy()
return lockbuf.EqualTo(ref), nil
} }
// Get return the string representation of the secret // Get return the string representation of the secret
func (s *Secret) Get() ([]byte, error) { func (s *Secret) Get() (SecretBuffer, error) {
if s.enclave == nil { if s.container == nil {
return nil, nil return selectedImpl.EmptyBuffer(), nil
} }
if len(s.unlinked) > 0 { if len(s.unlinked) > 0 {
@ -134,22 +169,19 @@ func (s *Secret) Get() ([]byte, error) {
} }
// Decrypt the secret so we can return it // Decrypt the secret so we can return it
lockbuf, err := s.enclave.Open() buffer, err := s.container.Buffer()
if err != nil { if err != nil {
return nil, fmt.Errorf("opening enclave failed: %w", err) return nil, err
} }
defer lockbuf.Destroy()
secret := lockbuf.Bytes()
// We've got a static secret so simply return the buffer
if len(s.resolvers) == 0 { if len(s.resolvers) == 0 {
// Make a copy as we cannot access lockbuf after Destroy, i.e. return buffer, nil
// after this function finishes.
newsecret := append([]byte{}, secret...)
return newsecret, protect(newsecret)
} }
defer buffer.Destroy()
replaceErrs := make([]string, 0) replaceErrs := make([]string, 0)
newsecret := secretPattern.ReplaceAllFunc(secret, func(match []byte) []byte { newsecret := secretPattern.ReplaceAllFunc(buffer.Bytes(), func(match []byte) []byte {
resolver, found := s.resolvers[string(match)] resolver, found := s.resolvers[string(match)]
if !found { if !found {
replaceErrs = append(replaceErrs, fmt.Sprintf("no resolver for %q", match)) replaceErrs = append(replaceErrs, fmt.Sprintf("no resolver for %q", match))
@ -164,11 +196,11 @@ func (s *Secret) Get() ([]byte, error) {
return replacement return replacement
}) })
if len(replaceErrs) > 0 { if len(replaceErrs) > 0 {
memguard.WipeBytes(newsecret) selectedImpl.Wipe(newsecret)
return nil, fmt.Errorf("replacing secrets failed: %s", strings.Join(replaceErrs, ";")) return nil, fmt.Errorf("replacing secrets failed: %s", strings.Join(replaceErrs, ";"))
} }
return newsecret, protect(newsecret) return s.container.AsBuffer(newsecret), nil
} }
// Set overwrites the secret's value with a new one. Please note, the secret // Set overwrites the secret's value with a new one. Please note, the secret
@ -182,7 +214,7 @@ func (s *Secret) Set(value []byte) error {
} }
// Set the new secret // Set the new secret
s.enclave = memguard.NewEnclave(secret) s.container.Replace(secret)
s.resolvers = res s.resolvers = res
s.notempty = len(value) > 0 s.notempty = len(value) > 0
@ -198,27 +230,26 @@ func (s *Secret) GetUnlinked() []string {
// secret-store resolvers. // secret-store resolvers.
func (s *Secret) Link(resolvers map[string]telegraf.ResolveFunc) error { func (s *Secret) Link(resolvers map[string]telegraf.ResolveFunc) error {
// Decrypt the secret so we can return it // Decrypt the secret so we can return it
if s.enclave == nil { if s.container == nil {
return nil return nil
} }
lockbuf, err := s.enclave.Open() buffer, err := s.container.Buffer()
if err != nil { if err != nil {
return fmt.Errorf("opening enclave failed: %w", err) return err
} }
defer lockbuf.Destroy() defer buffer.Destroy()
secret := lockbuf.Bytes()
// Iterate through the parts and try to resolve them. For static parts // Iterate through the parts and try to resolve them. For static parts
// we directly replace them, while for dynamic ones we store the resolver. // we directly replace them, while for dynamic ones we store the resolver.
newsecret, res, replaceErrs := resolve(secret, resolvers) newsecret, res, replaceErrs := resolve(buffer.Bytes(), resolvers)
if len(replaceErrs) > 0 { if len(replaceErrs) > 0 {
return fmt.Errorf("linking secrets failed: %s", strings.Join(replaceErrs, ";")) return fmt.Errorf("linking secrets failed: %s", strings.Join(replaceErrs, ";"))
} }
s.resolvers = res s.resolvers = res
// Store the secret if it has changed // Store the secret if it has changed
if string(secret) != string(newsecret) { if buffer.TemporaryString() != string(newsecret) {
s.enclave = memguard.NewEnclave(newsecret) s.container.Replace(newsecret)
} }
// All linked now // All linked now

131
config/secret_protected.go Normal file
View File

@ -0,0 +1,131 @@
package config
import (
"fmt"
"github.com/awnumar/memguard"
)
type protectedSecretImpl struct{}
func (*protectedSecretImpl) Container(secret []byte) secretContainer {
return &protectedSecretContainer{
enclave: memguard.NewEnclave(secret),
}
}
func (*protectedSecretImpl) EmptyBuffer() SecretBuffer {
return &lockedBuffer{}
}
func (*protectedSecretImpl) Wipe(secret []byte) {
memguard.WipeBytes(secret)
}
type lockedBuffer struct {
buf *memguard.LockedBuffer
}
func (lb *lockedBuffer) Size() int {
if lb.buf == nil {
return 0
}
return lb.buf.Size()
}
func (lb *lockedBuffer) Grow(capacity int) {
size := lb.Size()
if capacity <= size {
return
}
buf := memguard.NewBuffer(capacity)
if lb.buf != nil {
buf.Copy(lb.buf.Bytes())
}
lb.buf.Destroy()
lb.buf = buf
}
func (lb *lockedBuffer) Bytes() []byte {
if lb.buf == nil {
return nil
}
return lb.buf.Bytes()
}
func (lb *lockedBuffer) TemporaryString() string {
if lb.buf == nil {
return ""
}
return lb.buf.String()
}
func (lb *lockedBuffer) String() string {
if lb.buf == nil {
return ""
}
return string(lb.buf.Bytes())
}
func (lb *lockedBuffer) Destroy() {
if lb.buf == nil {
return
}
lb.buf.Destroy()
lb.buf = nil
}
type protectedSecretContainer struct {
enclave *memguard.Enclave
}
func (c *protectedSecretContainer) Destroy() {
if c.enclave == nil {
return
}
// Wipe the secret from memory
lockbuf, err := c.enclave.Open()
if err == nil {
lockbuf.Destroy()
}
c.enclave = nil
}
func (c *protectedSecretContainer) Equals(ref []byte) (bool, error) {
if c.enclave == nil {
return false, nil
}
// Get a locked-buffer of the secret to perform the comparison
lockbuf, err := c.enclave.Open()
if err != nil {
return false, fmt.Errorf("opening enclave failed: %w", err)
}
defer lockbuf.Destroy()
return lockbuf.EqualTo(ref), nil
}
func (c *protectedSecretContainer) Buffer() (SecretBuffer, error) {
if c.enclave == nil {
return &lockedBuffer{}, nil
}
// Get a locked-buffer of the secret to perform the comparison
lockbuf, err := c.enclave.Open()
if err != nil {
return nil, fmt.Errorf("opening enclave failed: %w", err)
}
return &lockedBuffer{lockbuf}, nil
}
func (c *protectedSecretContainer) AsBuffer(secret []byte) SecretBuffer {
return &lockedBuffer{memguard.NewBufferFromBytes(secret)}
}
func (c *protectedSecretContainer) Replace(secret []byte) {
c.enclave = memguard.NewEnclave(secret)
}

View File

@ -19,8 +19,8 @@ func TestSecretConstantManually(t *testing.T) {
defer s.Destroy() defer s.Destroy()
retrieved, err := s.Get() retrieved, err := s.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(retrieved) defer retrieved.Destroy()
require.EqualValues(t, mysecret, retrieved) require.EqualValues(t, mysecret, retrieved.TemporaryString())
} }
func TestLinking(t *testing.T) { func TestLinking(t *testing.T) {
@ -35,8 +35,8 @@ func TestLinking(t *testing.T) {
require.NoError(t, s.Link(resolvers)) require.NoError(t, s.Link(resolvers))
retrieved, err := s.Get() retrieved, err := s.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(retrieved) defer retrieved.Destroy()
require.EqualValues(t, "a resolved secret", retrieved) require.EqualValues(t, "a resolved secret", retrieved.TemporaryString())
} }
func TestLinkingResolverError(t *testing.T) { func TestLinkingResolverError(t *testing.T) {
@ -96,8 +96,8 @@ func TestUninitializedEnclave(t *testing.T) {
require.NoError(t, s.Link(map[string]telegraf.ResolveFunc{})) require.NoError(t, s.Link(map[string]telegraf.ResolveFunc{}))
retrieved, err := s.Get() retrieved, err := s.Get()
require.NoError(t, err) require.NoError(t, err)
require.Empty(t, retrieved) defer retrieved.Destroy()
ReleaseSecret(retrieved) require.Empty(t, retrieved.Bytes())
} }
func TestEnclaveOpenError(t *testing.T) { func TestEnclaveOpenError(t *testing.T) {
@ -162,9 +162,9 @@ func TestSecretConstant(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin) plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, tt.expected, string(secret)) require.EqualValues(t, tt.expected, secret.TemporaryString())
}) })
} }
} }
@ -313,9 +313,9 @@ func TestSecretUnquote(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin) plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, plugin.Expected, string(secret)) require.EqualValues(t, plugin.Expected, secret.TemporaryString())
}) })
} }
} }
@ -343,9 +343,9 @@ func TestSecretEnvironmentVariable(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin) plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, "an env secret", secret) require.EqualValues(t, "an env secret", secret.TemporaryString())
} }
func TestSecretStoreStatic(t *testing.T) { func TestSecretStoreStatic(t *testing.T) {
@ -384,8 +384,8 @@ func TestSecretStoreStatic(t *testing.T) {
plugin := input.Input.(*MockupSecretPlugin) plugin := input.Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, expected[i], secret) require.EqualValues(t, expected[i], secret.TemporaryString())
ReleaseSecret(secret) secret.Destroy()
} }
} }
@ -430,8 +430,8 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
plugin := input.Input.(*MockupSecretPlugin) plugin := input.Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, expected[i], secret) require.EqualValues(t, expected[i], secret.TemporaryString())
ReleaseSecret(secret) secret.Destroy()
} }
} }
@ -507,9 +507,9 @@ func TestSecretStoreStaticChanging(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin) plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, "Ood Bnar", secret) require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
for _, v := range sequence { for _, v := range sequence {
store.Secrets["secret"] = []byte(v) store.Secrets["secret"] = []byte(v)
@ -517,8 +517,8 @@ func TestSecretStoreStaticChanging(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// The secret should not change as the store is marked non-dyamic! // The secret should not change as the store is marked non-dyamic!
require.EqualValues(t, "Ood Bnar", secret) require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
ReleaseSecret(secret) secret.Destroy()
} }
} }
@ -553,8 +553,8 @@ func TestSecretStoreDynamic(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// The secret should not change as the store is marked non-dynamic! // The secret should not change as the store is marked non-dynamic!
require.EqualValues(t, v, secret) require.EqualValues(t, v, secret.TemporaryString())
ReleaseSecret(secret) secret.Destroy()
} }
} }
@ -620,14 +620,14 @@ func TestSecretSet(t *testing.T) {
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, "a secret", string(secret)) require.EqualValues(t, "a secret", secret.TemporaryString())
require.NoError(t, plugin.Secret.Set([]byte("another secret"))) require.NoError(t, plugin.Secret.Set([]byte("another secret")))
newsecret, err := plugin.Secret.Get() newsecret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(newsecret) defer newsecret.Destroy()
require.EqualValues(t, "another secret", string(newsecret)) require.EqualValues(t, "another secret", newsecret.TemporaryString())
} }
func TestSecretSetResolve(t *testing.T) { func TestSecretSetResolve(t *testing.T) {
@ -654,14 +654,14 @@ func TestSecretSetResolve(t *testing.T) {
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, "Ood Bnar", string(secret)) require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
require.NoError(t, plugin.Secret.Set([]byte("@{mock:secret} is cool"))) require.NoError(t, plugin.Secret.Set([]byte("@{mock:secret} is cool")))
newsecret, err := plugin.Secret.Get() newsecret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(newsecret) defer newsecret.Destroy()
require.EqualValues(t, "Ood Bnar is cool", string(newsecret)) require.EqualValues(t, "Ood Bnar is cool", newsecret.TemporaryString())
} }
func TestSecretSetResolveInvalid(t *testing.T) { func TestSecretSetResolveInvalid(t *testing.T) {
@ -688,8 +688,8 @@ func TestSecretSetResolveInvalid(t *testing.T) {
secret, err := plugin.Secret.Get() secret, err := plugin.Secret.Get()
require.NoError(t, err) require.NoError(t, err)
defer ReleaseSecret(secret) defer secret.Destroy()
require.EqualValues(t, "Ood Bnar", string(secret)) require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
err = plugin.Secret.Set([]byte("@{mock:another_secret}")) err = plugin.Secret.Set([]byte("@{mock:another_secret}"))
require.ErrorContains(t, err, `linking new secrets failed: unlinked part "@{mock:another_secret}"`) require.ErrorContains(t, err, `linking new secrets failed: unlinked part "@{mock:another_secret}"`)

View File

@ -1,20 +0,0 @@
//go:build linux
package config
import (
"syscall"
"github.com/awnumar/memguard"
)
func protect(secret []byte) error {
return syscall.Mlock(secret)
}
func ReleaseSecret(secret []byte) {
memguard.WipeBytes(secret)
if err := syscall.Munlock(secret); err != nil {
panic(err)
}
}

View File

@ -1,15 +0,0 @@
//go:build !linux
package config
import (
"github.com/awnumar/memguard"
)
func protect(_ []byte) error {
return nil
}
func ReleaseSecret(secret []byte) {
memguard.WipeBytes(secret)
}

View File

@ -33,14 +33,14 @@ func (k *SASLAuth) SetSASLConfig(cfg *sarama.Config) error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
cfg.Net.SASL.User = string(username) cfg.Net.SASL.User = username.String()
config.ReleaseSecret(username) username.Destroy()
password, err := k.SASLPassword.Get() password, err := k.SASLPassword.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
cfg.Net.SASL.Password = string(password) cfg.Net.SASL.Password = password.String()
config.ReleaseSecret(password) password.Destroy()
if k.SASLMechanism != "" { if k.SASLMechanism != "" {
cfg.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism) cfg.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism)
@ -58,8 +58,8 @@ func (k *SASLAuth) SetSASLConfig(cfg *sarama.Config) error {
case sarama.SASLTypeGSSAPI: case sarama.SASLTypeGSSAPI:
cfg.Net.SASL.GSSAPI.ServiceName = k.SASLGSSAPIServiceName cfg.Net.SASL.GSSAPI.ServiceName = k.SASLGSSAPIServiceName
cfg.Net.SASL.GSSAPI.AuthType = gssapiAuthType(k.SASLGSSAPIAuthType) cfg.Net.SASL.GSSAPI.AuthType = gssapiAuthType(k.SASLGSSAPIAuthType)
cfg.Net.SASL.GSSAPI.Username = string(username) cfg.Net.SASL.GSSAPI.Username = username.String()
cfg.Net.SASL.GSSAPI.Password = string(password) cfg.Net.SASL.GSSAPI.Password = password.String()
cfg.Net.SASL.GSSAPI.DisablePAFXFAST = k.SASLGSSAPIDisablePAFXFAST cfg.Net.SASL.GSSAPI.DisablePAFXFAST = k.SASLGSSAPIDisablePAFXFAST
cfg.Net.SASL.GSSAPI.KerberosConfigPath = k.SASLGSSAPIKerberosConfigPath cfg.Net.SASL.GSSAPI.KerberosConfigPath = k.SASLGSSAPIKerberosConfigPath
cfg.Net.SASL.GSSAPI.KeyTabPath = k.SASLGSSAPIKeyTabPath cfg.Net.SASL.GSSAPI.KeyTabPath = k.SASLGSSAPIKeyTabPath
@ -71,7 +71,7 @@ func (k *SASLAuth) SetSASLConfig(cfg *sarama.Config) error {
} }
} }
if len(username) > 0 || k.SASLMechanism != "" { if !k.SASLUsername.Empty() || k.SASLMechanism != "" {
cfg.Net.SASL.Enable = true cfg.Net.SASL.Enable = true
version, err := SASLVersion(cfg.Version, k.SASLVersion) version, err := SASLVersion(cfg.Version, k.SASLVersion)
@ -89,9 +89,9 @@ func (k *SASLAuth) Token() (*sarama.AccessToken, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err) return nil, fmt.Errorf("getting token failed: %w", err)
} }
defer config.ReleaseSecret(token) defer token.Destroy()
return &sarama.AccessToken{ return &sarama.AccessToken{
Token: string(token), Token: token.String(),
Extensions: k.SASLExtentions, Extensions: k.SASLExtentions,
}, nil }, nil
} }

View File

@ -6,7 +6,6 @@ import (
mqttv3 "github.com/eclipse/paho.mqtt.golang" // Library that supports v3.1.1 mqttv3 "github.com/eclipse/paho.mqtt.golang" // Library that supports v3.1.1
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/internal" "github.com/influxdata/telegraf/internal"
) )
@ -54,16 +53,16 @@ func NewMQTTv311Client(cfg *MqttConfig) (*mqttv311Client, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err) return nil, fmt.Errorf("getting username failed: %w", err)
} }
opts.SetUsername(string(user)) opts.SetUsername(user.String())
config.ReleaseSecret(user) user.Destroy()
} }
if !cfg.Password.Empty() { if !cfg.Password.Empty() {
password, err := cfg.Password.Get() password, err := cfg.Password.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
opts.SetPassword(string(password)) opts.SetPassword(password.String())
config.ReleaseSecret(password) password.Destroy()
} }
servers, err := parseServers(cfg.Servers) servers, err := parseServers(cfg.Servers)

View File

@ -17,6 +17,8 @@ import (
type mqttv5Client struct { type mqttv5Client struct {
client *mqttv5auto.ConnectionManager client *mqttv5auto.ConnectionManager
options mqttv5auto.ClientConfig options mqttv5auto.ClientConfig
username config.Secret
password config.Secret
timeout time.Duration timeout time.Duration
qos int qos int
retain bool retain bool
@ -47,19 +49,6 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, error) {
opts.ClientID = "Telegraf-Output-" + id opts.ClientID = "Telegraf-Output-" + id
} }
user, err := cfg.Username.Get()
if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err)
}
pass, err := cfg.Password.Get()
if err != nil {
config.ReleaseSecret(user)
return nil, fmt.Errorf("getting password failed: %w", err)
}
opts.SetUsernamePassword(string(user), pass)
config.ReleaseSecret(user)
config.ReleaseSecret(pass)
tlsCfg, err := cfg.ClientConfig.TLSConfig() tlsCfg, err := cfg.ClientConfig.TLSConfig()
if err != nil { if err != nil {
return nil, err return nil, err
@ -107,6 +96,8 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, error) {
return &mqttv5Client{ return &mqttv5Client{
options: opts, options: opts,
timeout: time.Duration(cfg.Timeout), timeout: time.Duration(cfg.Timeout),
username: cfg.Username,
password: config.Password,
qos: cfg.QoS, qos: cfg.QoS,
retain: cfg.Retain, retain: cfg.Retain,
properties: properties, properties: properties,
@ -114,6 +105,18 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, error) {
} }
func (m *mqttv5Client) Connect() (bool, error) { func (m *mqttv5Client) Connect() (bool, error) {
user, err := m.username.Get()
if err != nil {
return false, fmt.Errorf("getting username failed: %w", err)
}
defer user.Destroy()
pass, err := m.password.Get()
if err != nil {
return false, fmt.Errorf("getting password failed: %w", err)
}
defer pass.Destroy()
m.options.SetUsernamePassword(user.TemporaryString(), pass.Bytes())
client, err := mqttv5auto.NewConnection(context.Background(), m.options) client, err := mqttv5auto.NewConnection(context.Background(), m.options)
if err != nil { if err != nil {
return false, err return false, err

View File

@ -301,21 +301,21 @@ func (o *OpcUAClient) generateAuth(a string, cert []byte, user, passwd config.Se
var username, password []byte var username, password []byte
if !user.Empty() { if !user.Empty() {
var err error usecret, err := user.Get()
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) defer usecret.Destroy()
username = usecret.Bytes()
} }
if !passwd.Empty() { if !passwd.Empty() {
var err error psecret, err := passwd.Get()
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) defer psecret.Destroy()
password = psecret.Bytes()
} }
authOption = opcua.AuthUsername(string(username), string(password)) authOption = opcua.AuthUsername(string(username), string(password))
case "certificate": case "certificate":

View File

@ -289,17 +289,18 @@ func (c *CtrlXDataLayer) Start(acc telegraf.Accumulator) error {
password, err := c.Password.Get() password, err := c.Password.Get()
if err != nil { if err != nil {
username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
c.tokenManager = token.TokenManager{ c.tokenManager = token.TokenManager{
Url: c.url, Url: c.url,
Username: string(username), Username: username.String(),
Password: string(password), Password: password.String(),
Connection: c.connection, Connection: c.connection,
} }
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
c.acc = acc c.acc = acc

View File

@ -73,7 +73,7 @@ func (m *Example) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
// Initialze your internal states // Initialze your internal states
m.count = 1 m.count = 1

View File

@ -112,10 +112,7 @@ func (h *HTTP) SetParserFunc(fn telegraf.ParserFunc) {
// Returns: // Returns:
// //
// error: Any error that may have occurred // error: Any error that may have occurred
func (h *HTTP) gatherURL( func (h *HTTP) gatherURL(acc telegraf.Accumulator, url string) error {
acc telegraf.Accumulator,
url string,
) error {
body := makeRequestBodyReader(h.ContentEncoding, h.Body) body := makeRequestBodyReader(h.ContentEncoding, h.Body)
request, err := http.NewRequest(h.Method, url, body) request, err := http.NewRequest(h.Method, url, body)
if err != nil { if err != nil {
@ -127,7 +124,8 @@ func (h *HTTP) gatherURL(
if err != nil { if err != nil {
return err return err
} }
bearer := "Bearer " + strings.TrimSpace(string(token)) bearer := "Bearer " + strings.TrimSpace(token.String())
token.Destroy()
request.Header.Set("Authorization", bearer) request.Header.Set("Authorization", bearer)
} else if h.TokenFile != "" { } else if h.TokenFile != "" {
token, err := os.ReadFile(h.BearerToken) token, err := os.ReadFile(h.BearerToken)
@ -209,15 +207,15 @@ func (h *HTTP) setRequestAuth(request *http.Request) error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := h.Password.Get() password, err := h.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
request.SetBasicAuth(string(username), string(password)) request.SetBasicAuth(username.String(), password.String())
return nil return nil
} }

View File

@ -407,13 +407,13 @@ func (h *HTTPResponse) setRequestAuth(request *http.Request) error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := h.Password.Get() password, err := h.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
request.SetBasicAuth(string(username), string(password)) request.SetBasicAuth(username.String(), password.String())
return nil return nil
} }

View File

@ -370,8 +370,8 @@ func (m *MQTTConsumer) createOpts() (*mqtt.ClientOptions, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err) return nil, fmt.Errorf("getting username failed: %w", err)
} }
opts.SetUsername(string(user)) opts.SetUsername(user.String())
config.ReleaseSecret(user) user.Destroy()
} }
if !m.Password.Empty() { if !m.Password.Empty() {
@ -379,8 +379,8 @@ func (m *MQTTConsumer) createOpts() (*mqtt.ClientOptions, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
opts.SetPassword(string(password)) opts.SetPassword(password.String())
config.ReleaseSecret(password) password.Destroy()
} }
if len(m.Servers) == 0 { if len(m.Servers) == 0 {
return opts, fmt.Errorf("could not get host information") return opts, fmt.Errorf("could not get host information")

View File

@ -109,8 +109,8 @@ func (m *Mysql) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("getting server %d failed: %w", i, err) return fmt.Errorf("getting server %d failed: %w", i, err)
} }
dsn := string(dsnSecret) dsn := dsnSecret.String()
config.ReleaseSecret(dsnSecret) dsnSecret.Destroy()
conf, err := mysql.ParseDSN(dsn) conf, err := mysql.ParseDSN(dsn)
if err != nil { if err != nil {
return fmt.Errorf("parsing %q failed: %w", dsn, err) return fmt.Errorf("parsing %q failed: %w", dsn, err)
@ -419,8 +419,8 @@ func (m *Mysql) gatherServer(server *config.Secret, acc telegraf.Accumulator) er
if err != nil { if err != nil {
return err return err
} }
dsn := string(dsnSecret) dsn := dsnSecret.String()
config.ReleaseSecret(dsnSecret) dsnSecret.Destroy()
servtag := getDSNTag(dsn) servtag := getDSNTag(dsn)
db, err := sql.Open("mysql", dsn) db, err := sql.Open("mysql", dsn)

View File

@ -109,19 +109,19 @@ func (o *OpensearchQuery) newClient() error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer username.Destroy()
password, err := o.Password.Get() password, err := o.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username)
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer password.Destroy()
clientConfig := opensearch.Config{ clientConfig := opensearch.Config{
Addresses: o.URLs, Addresses: o.URLs,
Username: string(username), Username: username.String(),
Password: string(password), Password: password.String(),
} }
config.ReleaseSecret(username)
config.ReleaseSecret(password)
if o.InsecureSkipVerify { if o.InsecureSkipVerify {
clientConfig.Transport = &http.Transport{ clientConfig.Transport = &http.Transport{

View File

@ -1,7 +1,6 @@
package postgresql package postgresql
import ( import (
"bytes"
"database/sql" "database/sql"
"fmt" "fmt"
"net" "net"
@ -106,8 +105,8 @@ func (p *Service) Start(telegraf.Accumulator) (err error) {
if err != nil { if err != nil {
return fmt.Errorf("getting address failed: %w", err) return fmt.Errorf("getting address failed: %w", err)
} }
addr := string(addrSecret) addr := addrSecret.String()
defer config.ReleaseSecret(addrSecret) defer addrSecret.Destroy()
if p.Address.Empty() || addr == "localhost" { if p.Address.Empty() || addr == "localhost" {
addr = "host=localhost sslmode=disable" addr = "host=localhost sslmode=disable"
@ -161,15 +160,15 @@ func (p *Service) SanitizedAddress() (sanitizedAddress string, err error) {
if err != nil { if err != nil {
return sanitizedAddress, fmt.Errorf("getting address for sanitization failed: %w", err) return sanitizedAddress, fmt.Errorf("getting address for sanitization failed: %w", err)
} }
defer config.ReleaseSecret(addr) defer addr.Destroy()
var canonicalizedAddress string var canonicalizedAddress string
if bytes.HasPrefix(addr, []byte("postgres://")) || bytes.HasPrefix(addr, []byte("postgresql://")) { if strings.HasPrefix(addr.TemporaryString(), "postgres://") || strings.HasPrefix(addr.TemporaryString(), "postgresql://") {
if canonicalizedAddress, err = parseURL(string(addr)); err != nil { if canonicalizedAddress, err = parseURL(addr.String()); err != nil {
return sanitizedAddress, err return sanitizedAddress, err
} }
} else { } else {
canonicalizedAddress = string(addr) canonicalizedAddress = addr.String()
} }
return kvMatcher.ReplaceAllString(canonicalizedAddress, ""), nil return kvMatcher.ReplaceAllString(canonicalizedAddress, ""), nil

View File

@ -75,28 +75,35 @@ func (r *Radius) pollServer(acc telegraf.Accumulator, server string) error {
if err != nil { if err != nil {
return fmt.Errorf("getting secret failed: %w", err) return fmt.Errorf("getting secret failed: %w", err)
} }
defer config.ReleaseSecret(secret) defer secret.Destroy()
username, err := r.Username.Get() username, err := r.Username.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := r.Password.Get() password, err := r.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
// Create the radius packet with PAP authentication // Create the radius packet with PAP authentication
packet := radius.New(radius.CodeAccessRequest, secret) packet := radius.New(radius.CodeAccessRequest, secret.Bytes())
err = rfc2865.UserName_Set(packet, username) if err := rfc2865.UserName_Set(packet, username.Bytes()); err != nil {
if err != nil {
return fmt.Errorf("setting username for radius auth failed: %w", err) return fmt.Errorf("setting username for radius auth failed: %w", err)
} }
err = rfc2865.UserPassword_Set(packet, password)
if err != nil { // The radius client requires the password in a buffer with capacity being
// a multiple of 16 for internal operations. To not expose the password we
// grow the (potentially protected) buffer to the required capacity.
capacity := password.Size()
if capacity%16 != 0 {
password.Grow(capacity + 16 - capacity%16)
}
if err := rfc2865.UserPassword_Set(packet, password.Bytes()[:capacity]); err != nil {
return fmt.Errorf("setting password for radius auth failed: %w", err) return fmt.Errorf("setting password for radius auth failed: %w", err)
} }

View File

@ -192,22 +192,22 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error {
if err != nil { if err != nil {
return fmt.Errorf("getting secname failed: %w", err) return fmt.Errorf("getting secname failed: %w", err)
} }
secname := string(secnameSecret) secname := secnameSecret.String()
config.ReleaseSecret(secnameSecret) secnameSecret.Destroy()
privPasswdSecret, err := s.PrivPassword.Get() privPasswdSecret, err := s.PrivPassword.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting secname failed: %w", err) return fmt.Errorf("getting secname failed: %w", err)
} }
privPasswd := string(privPasswdSecret) privPasswd := privPasswdSecret.String()
config.ReleaseSecret(privPasswdSecret) privPasswdSecret.Destroy()
authPasswdSecret, err := s.AuthPassword.Get() authPasswdSecret, err := s.AuthPassword.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting secname failed: %w", err) return fmt.Errorf("getting secname failed: %w", err)
} }
authPasswd := string(authPasswdSecret) authPasswd := authPasswdSecret.String()
config.ReleaseSecret(authPasswdSecret) authPasswdSecret.Destroy()
s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{ s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: secname, UserName: secname,

View File

@ -372,8 +372,8 @@ func (s *SQL) setupConnection() error {
if err != nil { if err != nil {
return fmt.Errorf("getting DSN failed: %w", err) return fmt.Errorf("getting DSN failed: %w", err)
} }
dsn := string(dsnSecret) dsn := dsnSecret.String()
config.ReleaseSecret(dsnSecret) dsnSecret.Destroy()
s.Log.Debug("Connecting...") s.Log.Debug("Connecting...")
s.db, err = dbsql.Open(s.driverName, dsn) s.db, err = dbsql.Open(s.driverName, dsn)

View File

@ -218,8 +218,8 @@ func (s *SQLServer) Gather(acc telegraf.Accumulator) error {
acc.AddError(err) acc.AddError(err)
continue continue
} }
dsn := string(dnsSecret) dsn := dnsSecret.String()
config.ReleaseSecret(dnsSecret) dnsSecret.Destroy()
for _, query := range s.queries { for _, query := range s.queries {
wg.Add(1) wg.Add(1)
@ -272,8 +272,8 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
// 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.
pool, err = sql.Open("mssql", string(dsn)) pool, err = sql.Open("mssql", dsn.String())
config.ReleaseSecret(dsn) dsn.Destroy()
if err != nil { if err != nil {
acc.AddError(err) acc.AddError(err)
continue continue
@ -300,8 +300,8 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
acc.AddError(err) acc.AddError(err)
continue continue
} }
connector, err := mssql.NewAccessTokenConnector(string(dsn), tokenProvider) connector, err := mssql.NewAccessTokenConnector(dsn.String(), tokenProvider)
config.ReleaseSecret(dsn) dsn.Destroy()
if err != nil { if err != nil {
acc.AddError(fmt.Errorf("error creating the SQL connector: %w", err)) acc.AddError(fmt.Errorf("error creating the SQL connector: %w", err))
continue continue

View File

@ -120,21 +120,21 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
if err != nil { if err != nil {
return fmt.Errorf("getting secret failed: %w", err) return fmt.Errorf("getting secret failed: %w", err)
} }
defer config.ReleaseSecret(secret) defer secret.Destroy()
client.ConnConfig.Secret = secret client.ConnConfig.Secret = secret.Bytes()
username, err := t.Username.Get() username, err := t.Username.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := t.Password.Get() password, err := t.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
ctx := context.Background() ctx := context.Background()
if t.ResponseTimeout > 0 { if t.ResponseTimeout > 0 {
@ -162,7 +162,7 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
return nil return nil
} }
reply, err = session.Continue(ctx, string(username)) reply, err = session.Continue(ctx, username.String())
if err != nil { if err != nil {
if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, os.ErrDeadlineExceeded) { if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, os.ErrDeadlineExceeded) {
return fmt.Errorf("error on tacacs authentication continue username request to %s : %w", client.Addr, err) return fmt.Errorf("error on tacacs authentication continue username request to %s : %w", client.Addr, err)
@ -179,7 +179,7 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
return nil return nil
} }
reply, err = session.Continue(ctx, string(password)) reply, err = session.Continue(ctx, password.String())
if err != nil { if err != nil {
if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, os.ErrDeadlineExceeded) { if !errors.Is(err, context.DeadlineExceeded) && !errors.Is(err, os.ErrDeadlineExceeded) {
return fmt.Errorf("error on tacacs authentication continue password request to %s : %w", client.Addr, err) return fmt.Errorf("error on tacacs authentication continue password request to %s : %w", client.Addr, err)

View File

@ -21,7 +21,6 @@ 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
@ -106,13 +105,13 @@ func (cf *ClientFactory) testClient(ctx context.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := cf.parent.Password.Get() password, err := cf.parent.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
auth := url.UserPassword(string(username), string(password)) auth := url.UserPassword(username.String(), password.String())
if err := cf.client.Client.SessionManager.Login(ctx2, auth); err != nil { if err := cf.client.Client.SessionManager.Login(ctx2, auth); err != nil {
return fmt.Errorf("renewing authentication failed: %w", err) return fmt.Errorf("renewing authentication failed: %w", err)
@ -143,12 +142,12 @@ func NewClient(ctx context.Context, vSphereURL *url.URL, vs *VSphere) (*Client,
} }
password, err := vs.Password.Get() password, err := vs.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
vSphereURL.User = url.UserPassword(string(username), string(password)) vSphereURL.User = url.UserPassword(username.String(), password.String())
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
} }
vs.Log.Debugf("Creating client: %s", vSphereURL.Host) vs.Log.Debugf("Creating client: %s", vSphereURL.Host)

View File

@ -301,16 +301,16 @@ func (q *AMQP) makeClientConfig() (*ClientConfig, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err) return nil, fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := q.Password.Get() password, err := q.Password.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
auth = []amqp.Authentication{ auth = []amqp.Authentication{
&amqp.PlainAuth{ &amqp.PlainAuth{
Username: string(username), Username: username.String(),
Password: string(password), Password: password.String(),
}, },
} }
} }

View File

@ -64,12 +64,12 @@ func (c *Clarify) Init() error {
} }
password, err := c.Password.Get() password, err := c.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
creds := clarify.BasicAuthCredentials(string(username), string(password)) creds := clarify.BasicAuthCredentials(username.String(), password.String())
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
c.client = creds.Client(ctx) c.client = creds.Client(ctx)
return nil return nil
} }

View File

@ -156,8 +156,8 @@ func (d *Dynatrace) send(msg string) error {
if err != nil { if err != nil {
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
req.Header.Add("Authorization", "Api-Token "+string(token)) req.Header.Add("Authorization", "Api-Token "+token.String())
config.ReleaseSecret(token) token.Destroy()
} }
// add user-agent header to identify metric source // add user-agent header to identify metric source
req.Header.Add("User-Agent", "telegraf") req.Header.Add("User-Agent", "telegraf")

View File

@ -472,12 +472,12 @@ func (a *Elasticsearch) getAuthOptions() ([]elastic.ClientOptionFunc, error) {
} }
password, err := a.Password.Get() password, err := a.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
fns = append(fns, elastic.SetBasicAuth(string(username), string(password))) fns = append(fns, elastic.SetBasicAuth(username.String(), password.String()))
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
} }
if !a.AuthBearerToken.Empty() { if !a.AuthBearerToken.Empty() {
@ -485,9 +485,9 @@ func (a *Elasticsearch) getAuthOptions() ([]elastic.ClientOptionFunc, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err) return nil, fmt.Errorf("getting token failed: %w", err)
} }
auth := []string{"Bearer " + string(token)} auth := []string{"Bearer " + token.String()}
fns = append(fns, elastic.SetHeaders(http.Header{"Authorization": auth})) fns = append(fns, elastic.SetHeaders(http.Header{"Authorization": auth}))
config.ReleaseSecret(token) token.Destroy()
} }
return fns, nil return fns, nil
} }

View File

@ -79,7 +79,7 @@ func (g *Groundwork) Init() error {
} }
password, err := g.Password.Get() password, err := g.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
g.client = clients.GWClient{ g.client = clients.GWClient{
@ -87,13 +87,13 @@ func (g *Groundwork) Init() error {
AppType: g.DefaultAppType, AppType: g.DefaultAppType,
GWConnection: &clients.GWConnection{ GWConnection: &clients.GWConnection{
HostName: g.Server, HostName: g.Server,
UserName: string(username), UserName: username.String(),
Password: string(password), Password: password.String(),
IsDynamicInventory: true, IsDynamicInventory: true,
}, },
} }
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
logper.SetLogger( logper.SetLogger(
func(fields interface{}, format string, a ...interface{}) { func(fields interface{}, format string, a ...interface{}) {

View File

@ -105,11 +105,8 @@ func (h *HTTP) Close() error {
} }
func (h *HTTP) Write(metrics []telegraf.Metric) error { func (h *HTTP) Write(metrics []telegraf.Metric) error {
var reqBody []byte
if h.UseBatchFormat { if h.UseBatchFormat {
var err error reqBody, err := h.serializer.SerializeBatch(metrics)
reqBody, err = h.serializer.SerializeBatch(metrics)
if err != nil { if err != nil {
return err return err
} }
@ -118,8 +115,7 @@ func (h *HTTP) Write(metrics []telegraf.Metric) error {
} }
for _, metric := range metrics { for _, metric := range metrics {
var err error reqBody, err := h.serializer.Serialize(metric)
reqBody, err = h.serializer.Serialize(metric)
if err != nil { if err != nil {
return err return err
} }
@ -185,12 +181,12 @@ func (h *HTTP) writeMetric(reqBody []byte) error {
} }
password, err := h.Password.Get() password, err := h.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(username.String(), password.String())
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
} }
// google api auth // google api auth

View File

@ -500,12 +500,12 @@ func (c *httpClient) addHeaders(req *http.Request) error {
} }
password, err := c.config.Password.Get() password, err := c.config.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(username.String(), password.String())
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
} }
for header, value := range c.config.Headers { for header, value := range c.config.Headers {

View File

@ -100,9 +100,8 @@ func NewHTTPClient(cfg *HTTPConfig) (*httpClient, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err) return nil, fmt.Errorf("getting token failed: %w", err)
} }
headers["Authorization"] = "Token " + string(token) headers["Authorization"] = "Token " + token.String()
config.ReleaseSecret(token) token.Destroy()
for k, v := range cfg.Headers { for k, v := range cfg.Headers {
headers[k] = v headers[k] = v
} }

View File

@ -177,14 +177,13 @@ func (i *Instrumental) Write(metrics []telegraf.Metric) error {
} }
func (i *Instrumental) authenticate(conn net.Conn) error { func (i *Instrumental) authenticate(conn net.Conn) error {
tokenSecret, err := i.APIToken.Get() token, err := i.APIToken.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
token := string(tokenSecret) defer token.Destroy()
config.ReleaseSecret(tokenSecret)
if _, err := fmt.Fprintf(conn, HandshakeFormat, token); err != nil { if _, err := fmt.Fprintf(conn, HandshakeFormat, token.TemporaryString()); err != nil {
return err return err
} }

View File

@ -85,17 +85,18 @@ func (s *IoTDB) Connect() error {
} }
password, err := s.Password.Get() password, err := s.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer password.Destroy()
sessionConf := &client.Config{ sessionConf := &client.Config{
Host: s.Host, Host: s.Host,
Port: s.Port, Port: s.Port,
UserName: string(username), UserName: username.String(),
Password: string(password), Password: password.String(),
} }
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
var ss = client.NewSession(sessionConf) var ss = client.NewSession(sessionConf)
s.session = &ss s.session = &ss

View File

@ -149,12 +149,12 @@ func (l *Librato) writeBatch(start int, sizeBatch int, metricCounter int, tempGa
} }
token, err := l.APIToken.Get() token, err := l.APIToken.Get()
if err != nil { if err != nil {
config.ReleaseSecret(user) user.Destroy()
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
req.SetBasicAuth(string(user), string(token)) req.SetBasicAuth(user.String(), token.String())
config.ReleaseSecret(user) user.Destroy()
config.ReleaseSecret(token) token.Destroy()
resp, err := l.client.Do(req) resp, err := l.client.Do(req)
if err != nil { if err != nil {

View File

@ -145,9 +145,9 @@ func (l *Logzio) authURL() (string, error) {
if err != nil { if err != nil {
return "", fmt.Errorf("getting token failed: %w", err) return "", fmt.Errorf("getting token failed: %w", err)
} }
defer config.ReleaseSecret(token) defer token.Destroy()
return fmt.Sprintf("%s/?token=%s", l.URL, string(token)), nil return fmt.Sprintf("%s/?token=%s", l.URL, token.TemporaryString()), nil
} }
func (l *Logzio) parseMetric(metric telegraf.Metric) *Metric { func (l *Logzio) parseMetric(metric telegraf.Metric) *Metric {

View File

@ -163,12 +163,12 @@ func (l *Loki) writeMetrics(s Streams) error {
} }
password, err := l.Password.Get() password, err := l.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(username.String(), password.String())
config.ReleaseSecret(password) username.Destroy()
config.ReleaseSecret(username) password.Destroy()
} }
for k, v := range l.Headers { for k, v := range l.Headers {

View File

@ -107,16 +107,16 @@ func (s *MongoDB) Init() error {
} }
password, err := s.Password.Get() password, err := s.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
credential := options.Credential{ credential := options.Credential{
AuthMechanism: "SCRAM-SHA-256", AuthMechanism: "SCRAM-SHA-256",
Username: string(username), Username: username.String(),
Password: string(password), Password: password.String(),
} }
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
s.clientOptions.SetAuth(credential) s.clientOptions.SetAuth(credential)
case "X509": case "X509":
//format connection string to include tls/x509 options //format connection string to include tls/x509 options

View File

@ -58,12 +58,12 @@ func (n *NATS) Connect() error {
} }
password, err := n.Password.Get() password, err := n.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username) username.Destroy()
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
opts = append(opts, nats.UserInfo(string(username), string(password))) opts = append(opts, nats.UserInfo(username.String(), password.String()))
config.ReleaseSecret(username) username.Destroy()
config.ReleaseSecret(password) password.Destroy()
} }
if n.Credentials != "" { if n.Credentials != "" {

View File

@ -140,14 +140,14 @@ func (p *PrometheusClient) Init() error {
ipRange = append(ipRange, ipNet) ipRange = append(ipRange, ipNet)
} }
password, err := p.BasicPassword.Get() psecret, err := p.BasicPassword.Get()
if err != nil { if err != nil {
return err return err
} }
passwordStr := string(password) password := psecret.String()
defer config.ReleaseSecret(password) psecret.Destroy()
authHandler := internal.BasicAuthHandler(p.BasicUsername, passwordStr, "prometheus", onAuthError) authHandler := internal.BasicAuthHandler(p.BasicUsername, password, "prometheus", onAuthError)
rangeHandler := internal.IPRangeHandler(ipRange, onError) rangeHandler := internal.IPRangeHandler(ipRange, onError)
promHandler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}) promHandler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError})
landingPageHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { landingPageHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -36,18 +36,18 @@ func (r *RedisTimeSeries) Connect() error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := r.Password.Get() password, err := r.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
r.client = redis.NewClient(&redis.Options{ r.client = redis.NewClient(&redis.Options{
Addr: r.Address, Addr: r.Address,
Username: string(username), Username: username.String(),
Password: string(password), Password: password.String(),
DB: r.Database, DB: r.Database,
}) })
return r.client.Ping().Err() return r.client.Ping().Err()

View File

@ -86,8 +86,8 @@ func (s *SignalFx) Connect() error {
if err != nil { if err != nil {
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
client.AuthToken = string(token) client.AuthToken = token.String()
config.ReleaseSecret(token) token.Destroy()
if s.IngestURL != "" { if s.IngestURL != "" {
client.DatapointEndpoint = datapointEndpointForIngestURL(s.IngestURL) client.DatapointEndpoint = datapointEndpointForIngestURL(s.IngestURL)

View File

@ -101,13 +101,13 @@ func (q *STOMP) getAuthOption() (func(*stomp.Conn) error, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting username failed: %w", err) return nil, fmt.Errorf("getting username failed: %w", err)
} }
defer config.ReleaseSecret(username) defer username.Destroy()
password, err := q.Password.Get() password, err := q.Password.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer password.Destroy()
return stomp.ConnOpt.Login(string(username), string(password)), nil return stomp.ConnOpt.Login(username.String(), password.String()), nil
} }
func init() { func init() {

View File

@ -131,8 +131,8 @@ func (w *Warp10) Write(metrics []telegraf.Metric) error {
if err != nil { if err != nil {
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
req.Header.Set("X-Warp10-Token", string(token)) req.Header.Set("X-Warp10-Token", token.String())
config.ReleaseSecret(token) token.Destroy()
resp, err := w.client.Do(req) resp, err := w.client.Do(req)
if err != nil { if err != nil {

View File

@ -320,12 +320,12 @@ func (w *Wavefront) Close() error {
func (w *Wavefront) makeAuthOptions() ([]wavefront.Option, error) { func (w *Wavefront) makeAuthOptions() ([]wavefront.Option, error) {
if !w.Token.Empty() { if !w.Token.Empty() {
b, err := w.Token.Get() tsecret, err := w.Token.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse token value: %w", err) return nil, fmt.Errorf("failed to parse token value: %w", err)
} }
token := string(b) token := tsecret.String()
config.ReleaseSecret(b) tsecret.Destroy()
return []wavefront.Option{ return []wavefront.Option{
wavefront.APIToken(token), wavefront.APIToken(token),
@ -333,31 +333,31 @@ func (w *Wavefront) makeAuthOptions() ([]wavefront.Option, error) {
} }
if !w.AuthCSPAPIToken.Empty() { if !w.AuthCSPAPIToken.Empty() {
b, err := w.AuthCSPAPIToken.Get() tsecret, err := w.AuthCSPAPIToken.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to CSP API token value: %w", err) return nil, fmt.Errorf("failed to CSP API token value: %w", err)
} }
apiToken := string(b) apiToken := tsecret.String()
config.ReleaseSecret(b) tsecret.Destroy()
return []wavefront.Option{ return []wavefront.Option{
wavefront.CSPAPIToken(apiToken, wavefront.CSPBaseURL(w.CSPBaseURL)), wavefront.CSPAPIToken(apiToken, wavefront.CSPBaseURL(w.CSPBaseURL)),
}, nil }, nil
} }
if w.AuthCSPClientCredentials != nil { if w.AuthCSPClientCredentials != nil {
appIDBytes, err := w.AuthCSPClientCredentials.AppID.Get() appIDSecret, err := w.AuthCSPClientCredentials.AppID.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse Client Credentials App ID value: %w", err) return nil, fmt.Errorf("failed to parse Client Credentials App ID value: %w", err)
} }
appID := string(appIDBytes) appID := appIDSecret.String()
config.ReleaseSecret(appIDBytes) appIDSecret.Destroy()
appSecretBytes, err := w.AuthCSPClientCredentials.AppSecret.Get() appSecret, err := w.AuthCSPClientCredentials.AppSecret.Get()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse Client Credentials App Secret value: %w", err) return nil, fmt.Errorf("failed to parse Client Credentials App Secret value: %w", err)
} }
cspAppSecret := string(appSecretBytes) cspAppSecret := appSecret.String()
config.ReleaseSecret(appSecretBytes) appSecret.Destroy()
options := []wavefront.CSPOption{ options := []wavefront.CSPOption{
wavefront.CSPBaseURL(w.CSPBaseURL), wavefront.CSPBaseURL(w.CSPBaseURL),

View File

@ -96,12 +96,12 @@ func (a *AesEncryptor) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("getting key failed: %w", err) return fmt.Errorf("getting key failed: %w", err)
} }
key := make([]byte, hex.DecodedLen(len(encodedKey))) key := make([]byte, hex.DecodedLen(len(encodedKey.Bytes())))
if _, err := hex.Decode(key, encodedKey); err != nil { _, err = hex.Decode(key, encodedKey.Bytes())
config.ReleaseSecret(encodedKey) encodedKey.Destroy()
if err != nil {
return fmt.Errorf("decoding key failed: %w", err) return fmt.Errorf("decoding key failed: %w", err)
} }
config.ReleaseSecret(encodedKey)
actuallen := len(key) actuallen := len(key)
memguard.WipeBytes(key) memguard.WipeBytes(key)
@ -118,8 +118,8 @@ func (a *AesEncryptor) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("getting IV failed: %w", err) return fmt.Errorf("getting IV failed: %w", err)
} }
ivlen := len(encodedIV) ivlen := len(encodedIV.Bytes())
config.ReleaseSecret(encodedIV) encodedIV.Destroy()
if ivlen != 2*aes.BlockSize { if ivlen != 2*aes.BlockSize {
return errors.New("init vector size must match block size") return errors.New("init vector size must match block size")
} }
@ -140,12 +140,12 @@ func (a *AesEncryptor) Decrypt(data []byte) ([]byte, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting key failed: %w", err) return nil, fmt.Errorf("getting key failed: %w", err)
} }
key := make([]byte, hex.DecodedLen(len(encodedKey))) key := make([]byte, hex.DecodedLen(len(encodedKey.Bytes())))
if _, err := hex.Decode(key, encodedKey); err != nil { _, err = hex.Decode(key, encodedKey.Bytes())
config.ReleaseSecret(encodedKey) encodedKey.Destroy()
if err != nil {
return nil, fmt.Errorf("decoding key failed: %w", err) return nil, fmt.Errorf("decoding key failed: %w", err)
} }
config.ReleaseSecret(encodedKey)
// Setup AES // Setup AES
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
@ -158,9 +158,9 @@ func (a *AesEncryptor) Decrypt(data []byte) ([]byte, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("getting initialization-vector failed: %w", err) return nil, fmt.Errorf("getting initialization-vector failed: %w", err)
} }
iv := make([]byte, hex.DecodedLen(len(encodedIV))) iv := make([]byte, hex.DecodedLen(len(encodedIV.Bytes())))
_, err = hex.Decode(iv, encodedIV) _, err = hex.Decode(iv, encodedIV.Bytes())
config.ReleaseSecret(encodedIV) encodedIV.Destroy()
if err != nil { if err != nil {
memguard.WipeBytes(iv) memguard.WipeBytes(iv)
return nil, fmt.Errorf("decoding init vector failed: %w", err) return nil, fmt.Errorf("decoding init vector failed: %w", err)

View File

@ -201,14 +201,13 @@ func (h *HTTP) setRequestAuth(request *http.Request) error {
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
} }
defer username.Destroy()
password, err := h.Password.Get() password, err := h.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username)
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
request.SetBasicAuth(string(username), string(password)) defer password.Destroy()
config.ReleaseSecret(username) request.SetBasicAuth(username.String(), password.String())
config.ReleaseSecret(password)
} }
if !h.Token.Empty() { if !h.Token.Empty() {
@ -216,8 +215,8 @@ func (h *HTTP) setRequestAuth(request *http.Request) error {
if err != nil { if err != nil {
return fmt.Errorf("getting token failed: %w", err) return fmt.Errorf("getting token failed: %w", err)
} }
bearer := "Bearer " + strings.TrimSpace(string(token)) defer token.Destroy()
config.ReleaseSecret(token) bearer := "Bearer " + strings.TrimSpace(token.String())
request.Header.Set("Authorization", bearer) request.Header.Set("Authorization", bearer)
} }

View File

@ -39,15 +39,15 @@ func (k *KDFConfig) generatePBKDF2HMAC(hf hashFunc, keylen int) (config.Secret,
if err != nil { if err != nil {
return config.Secret{}, config.Secret{}, fmt.Errorf("getting password failed: %w", err) return config.Secret{}, config.Secret{}, fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(passwd) defer passwd.Destroy()
salt, err := k.Salt.Get() salt, err := k.Salt.Get()
if err != nil { if err != nil {
return config.Secret{}, config.Secret{}, fmt.Errorf("getting salt failed: %w", err) return config.Secret{}, config.Secret{}, fmt.Errorf("getting salt failed: %w", err)
} }
defer config.ReleaseSecret(salt) defer salt.Destroy()
rawkey := pbkdf2.Key(passwd, salt, k.Iterations, keylen, hf) rawkey := pbkdf2.Key(passwd.Bytes(), salt.Bytes(), k.Iterations, keylen, hf)
key := config.NewSecret([]byte(hex.EncodeToString(rawkey))) key := config.NewSecret([]byte(hex.EncodeToString(rawkey)))
return key, config.Secret{}, nil return key, config.Secret{}, nil
} }

View File

@ -41,12 +41,14 @@ func TestKDF(t *testing.T) {
key, err := skey.Get() key, err := skey.Get()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tt.key, string(key)) defer key.Destroy()
require.Equal(t, tt.key, key.TemporaryString())
if tt.iv != "" { if tt.iv != "" {
iv, err := siv.Get() iv, err := siv.Get()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, tt.iv, string(iv)) defer iv.Destroy()
require.Equal(t, tt.iv, iv.TemporaryString())
} else { } else {
require.True(t, siv.Empty()) require.True(t, siv.Empty())
} }

View File

@ -47,15 +47,15 @@ func (j *Jose) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(passwd) defer passwd.Destroy()
promptFunc = keyring.FixedStringPrompt(string(passwd)) promptFunc = keyring.FixedStringPrompt(passwd.String())
} else if !config.Password.Empty() { } else if !config.Password.Empty() {
passwd, err := config.Password.Get() passwd, err := config.Password.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting global password failed: %w", err) return fmt.Errorf("getting global password failed: %w", err)
} }
defer config.ReleaseSecret(passwd) defer passwd.Destroy()
promptFunc = keyring.FixedStringPrompt(string(passwd)) promptFunc = keyring.FixedStringPrompt(passwd.String())
} }
// Setup the actual keyring // Setup the actual keyring

View File

@ -120,19 +120,20 @@ func (o *OAuth2) Init() error {
csecret, err := c.ClientSecret.Get() csecret, err := c.ClientSecret.Get()
if err != nil { if err != nil {
cid.Destroy()
return fmt.Errorf("getting client secret for %q failed: %w", c.Key, err) return fmt.Errorf("getting client secret for %q failed: %w", c.Key, err)
} }
// Setup the configuration // Setup the configuration
cfg := &clientcredentials.Config{ cfg := &clientcredentials.Config{
ClientID: string(cid), ClientID: cid.String(),
ClientSecret: string(csecret), ClientSecret: csecret.String(),
TokenURL: endpoint.TokenURL, TokenURL: endpoint.TokenURL,
Scopes: c.Scopes, Scopes: c.Scopes,
AuthStyle: endpoint.AuthStyle, AuthStyle: endpoint.AuthStyle,
} }
config.ReleaseSecret(cid) cid.Destroy()
config.ReleaseSecret(csecret) csecret.Destroy()
// Add the parameters if any // Add the parameters if any
for k, v := range c.Params { for k, v := range c.Params {

View File

@ -6,21 +6,18 @@ import (
"fmt" "fmt"
"github.com/99designs/keyring" "github.com/99designs/keyring"
"github.com/influxdata/telegraf/config"
) )
func (o *OS) createKeyringConfig() (keyring.Config, error) { func (o *OS) createKeyringConfig() (keyring.Config, error) {
passwd, err := o.Password.Get()
if err != nil {
return keyring.Config{}, fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(passwd)
// Create the prompt-function in case we need it // Create the prompt-function in case we need it
promptFunc := keyring.TerminalPrompt promptFunc := keyring.TerminalPrompt
if len(passwd) != 0 { if !o.Password.Empty() {
promptFunc = keyring.FixedStringPrompt(string(passwd)) passwd, err := o.Password.Get()
if err != nil {
return keyring.Config{}, fmt.Errorf("getting password failed: %w", err)
}
promptFunc = keyring.FixedStringPrompt(passwd.String())
passwd.Destroy()
} }
return keyring.Config{ return keyring.Config{