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"
"strings"
"github.com/awnumar/memguard"
"github.com/urfave/cli/v2"
"golang.org/x/term"
"github.com/influxdata/telegraf/config"
)
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))
config.ReleaseSecret(v)
memguard.WipeBytes(v)
}
}

View File

@ -6,8 +6,6 @@ import (
"strings"
"sync/atomic"
"github.com/awnumar/memguard"
"github.com/influxdata/telegraf"
)
@ -26,17 +24,67 @@ var secretStorePattern = regexp.MustCompile(`^\w+$`)
// in a secret-store.
var secretPattern = regexp.MustCompile(`@\{(\w+:\w+)\}`)
// secretCount is the number of secrets use in Telegraf
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
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
// unlinked contains all references in the secret that are not yet
// linked to the corresponding secret store.
unlinked []string
// Denotes if the secret is completely empty
// notempty denotes if the secret is completely empty
notempty bool
}
@ -71,10 +119,10 @@ func (s *Secret) init(secret []byte) {
// Find all parts that need to be resolved and return them
s.unlinked = secretPattern.FindAllString(string(secret), -1)
// Setup the enclave
s.enclave = memguard.NewEnclave(secret)
s.resolvers = nil
// Setup the container implementation
s.container = selectedImpl.Container(secret)
}
// Destroy the secret content
@ -83,17 +131,11 @@ func (s *Secret) Destroy() {
s.unlinked = nil
s.notempty = false
if s.enclave == nil {
return
if s.container != nil {
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...
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
func (s *Secret) EqualTo(ref []byte) (bool, error) {
if s.enclave == nil {
if s.container == 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, ";"))
}
// Get a locked-buffer of the secret to perform the comparison
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
return s.container.Equals(ref)
}
// Get return the string representation of the secret
func (s *Secret) Get() ([]byte, error) {
if s.enclave == nil {
return nil, nil
func (s *Secret) Get() (SecretBuffer, error) {
if s.container == nil {
return selectedImpl.EmptyBuffer(), nil
}
if len(s.unlinked) > 0 {
@ -134,22 +169,19 @@ func (s *Secret) Get() ([]byte, error) {
}
// Decrypt the secret so we can return it
lockbuf, err := s.enclave.Open()
buffer, err := s.container.Buffer()
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 {
// Make a copy as we cannot access lockbuf after Destroy, i.e.
// after this function finishes.
newsecret := append([]byte{}, secret...)
return newsecret, protect(newsecret)
return buffer, nil
}
defer buffer.Destroy()
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)]
if !found {
replaceErrs = append(replaceErrs, fmt.Sprintf("no resolver for %q", match))
@ -164,11 +196,11 @@ func (s *Secret) Get() ([]byte, error) {
return replacement
})
if len(replaceErrs) > 0 {
memguard.WipeBytes(newsecret)
selectedImpl.Wipe(newsecret)
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
@ -182,7 +214,7 @@ func (s *Secret) Set(value []byte) error {
}
// Set the new secret
s.enclave = memguard.NewEnclave(secret)
s.container.Replace(secret)
s.resolvers = res
s.notempty = len(value) > 0
@ -198,27 +230,26 @@ func (s *Secret) GetUnlinked() []string {
// secret-store resolvers.
func (s *Secret) Link(resolvers map[string]telegraf.ResolveFunc) error {
// Decrypt the secret so we can return it
if s.enclave == nil {
if s.container == nil {
return nil
}
lockbuf, err := s.enclave.Open()
buffer, err := s.container.Buffer()
if err != nil {
return fmt.Errorf("opening enclave failed: %w", err)
return err
}
defer lockbuf.Destroy()
secret := lockbuf.Bytes()
defer buffer.Destroy()
// Iterate through the parts and try to resolve them. For static parts
// 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 {
return fmt.Errorf("linking secrets failed: %s", strings.Join(replaceErrs, ";"))
}
s.resolvers = res
// Store the secret if it has changed
if string(secret) != string(newsecret) {
s.enclave = memguard.NewEnclave(newsecret)
if buffer.TemporaryString() != string(newsecret) {
s.container.Replace(newsecret)
}
// 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()
retrieved, err := s.Get()
require.NoError(t, err)
defer ReleaseSecret(retrieved)
require.EqualValues(t, mysecret, retrieved)
defer retrieved.Destroy()
require.EqualValues(t, mysecret, retrieved.TemporaryString())
}
func TestLinking(t *testing.T) {
@ -35,8 +35,8 @@ func TestLinking(t *testing.T) {
require.NoError(t, s.Link(resolvers))
retrieved, err := s.Get()
require.NoError(t, err)
defer ReleaseSecret(retrieved)
require.EqualValues(t, "a resolved secret", retrieved)
defer retrieved.Destroy()
require.EqualValues(t, "a resolved secret", retrieved.TemporaryString())
}
func TestLinkingResolverError(t *testing.T) {
@ -96,8 +96,8 @@ func TestUninitializedEnclave(t *testing.T) {
require.NoError(t, s.Link(map[string]telegraf.ResolveFunc{}))
retrieved, err := s.Get()
require.NoError(t, err)
require.Empty(t, retrieved)
ReleaseSecret(retrieved)
defer retrieved.Destroy()
require.Empty(t, retrieved.Bytes())
}
func TestEnclaveOpenError(t *testing.T) {
@ -162,9 +162,9 @@ func TestSecretConstant(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get()
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)
secret, err := plugin.Secret.Get()
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)
secret, err := plugin.Secret.Get()
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) {
@ -384,8 +384,8 @@ func TestSecretStoreStatic(t *testing.T) {
plugin := input.Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get()
require.NoError(t, err)
require.EqualValues(t, expected[i], secret)
ReleaseSecret(secret)
require.EqualValues(t, expected[i], secret.TemporaryString())
secret.Destroy()
}
}
@ -430,8 +430,8 @@ func TestSecretStoreInvalidKeys(t *testing.T) {
plugin := input.Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get()
require.NoError(t, err)
require.EqualValues(t, expected[i], secret)
ReleaseSecret(secret)
require.EqualValues(t, expected[i], secret.TemporaryString())
secret.Destroy()
}
}
@ -507,9 +507,9 @@ func TestSecretStoreStaticChanging(t *testing.T) {
plugin := c.Inputs[0].Input.(*MockupSecretPlugin)
secret, err := plugin.Secret.Get()
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 {
store.Secrets["secret"] = []byte(v)
@ -517,8 +517,8 @@ func TestSecretStoreStaticChanging(t *testing.T) {
require.NoError(t, err)
// The secret should not change as the store is marked non-dyamic!
require.EqualValues(t, "Ood Bnar", secret)
ReleaseSecret(secret)
require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
secret.Destroy()
}
}
@ -553,8 +553,8 @@ func TestSecretStoreDynamic(t *testing.T) {
require.NoError(t, err)
// The secret should not change as the store is marked non-dynamic!
require.EqualValues(t, v, secret)
ReleaseSecret(secret)
require.EqualValues(t, v, secret.TemporaryString())
secret.Destroy()
}
}
@ -620,14 +620,14 @@ func TestSecretSet(t *testing.T) {
secret, err := plugin.Secret.Get()
require.NoError(t, err)
defer ReleaseSecret(secret)
require.EqualValues(t, "a secret", string(secret))
defer secret.Destroy()
require.EqualValues(t, "a secret", secret.TemporaryString())
require.NoError(t, plugin.Secret.Set([]byte("another secret")))
newsecret, err := plugin.Secret.Get()
require.NoError(t, err)
defer ReleaseSecret(newsecret)
require.EqualValues(t, "another secret", string(newsecret))
defer newsecret.Destroy()
require.EqualValues(t, "another secret", newsecret.TemporaryString())
}
func TestSecretSetResolve(t *testing.T) {
@ -654,14 +654,14 @@ func TestSecretSetResolve(t *testing.T) {
secret, err := plugin.Secret.Get()
require.NoError(t, err)
defer ReleaseSecret(secret)
require.EqualValues(t, "Ood Bnar", string(secret))
defer secret.Destroy()
require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
require.NoError(t, plugin.Secret.Set([]byte("@{mock:secret} is cool")))
newsecret, err := plugin.Secret.Get()
require.NoError(t, err)
defer ReleaseSecret(newsecret)
require.EqualValues(t, "Ood Bnar is cool", string(newsecret))
defer newsecret.Destroy()
require.EqualValues(t, "Ood Bnar is cool", newsecret.TemporaryString())
}
func TestSecretSetResolveInvalid(t *testing.T) {
@ -688,8 +688,8 @@ func TestSecretSetResolveInvalid(t *testing.T) {
secret, err := plugin.Secret.Get()
require.NoError(t, err)
defer ReleaseSecret(secret)
require.EqualValues(t, "Ood Bnar", string(secret))
defer secret.Destroy()
require.EqualValues(t, "Ood Bnar", secret.TemporaryString())
err = plugin.Secret.Set([]byte("@{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 {
return fmt.Errorf("getting username failed: %w", err)
}
cfg.Net.SASL.User = string(username)
config.ReleaseSecret(username)
cfg.Net.SASL.User = username.String()
username.Destroy()
password, err := k.SASLPassword.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
cfg.Net.SASL.Password = string(password)
config.ReleaseSecret(password)
cfg.Net.SASL.Password = password.String()
password.Destroy()
if 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:
cfg.Net.SASL.GSSAPI.ServiceName = k.SASLGSSAPIServiceName
cfg.Net.SASL.GSSAPI.AuthType = gssapiAuthType(k.SASLGSSAPIAuthType)
cfg.Net.SASL.GSSAPI.Username = string(username)
cfg.Net.SASL.GSSAPI.Password = string(password)
cfg.Net.SASL.GSSAPI.Username = username.String()
cfg.Net.SASL.GSSAPI.Password = password.String()
cfg.Net.SASL.GSSAPI.DisablePAFXFAST = k.SASLGSSAPIDisablePAFXFAST
cfg.Net.SASL.GSSAPI.KerberosConfigPath = k.SASLGSSAPIKerberosConfigPath
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
version, err := SASLVersion(cfg.Version, k.SASLVersion)
@ -89,9 +89,9 @@ func (k *SASLAuth) Token() (*sarama.AccessToken, error) {
if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err)
}
defer config.ReleaseSecret(token)
defer token.Destroy()
return &sarama.AccessToken{
Token: string(token),
Token: token.String(),
Extensions: k.SASLExtentions,
}, nil
}

View File

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

View File

@ -17,6 +17,8 @@ import (
type mqttv5Client struct {
client *mqttv5auto.ConnectionManager
options mqttv5auto.ClientConfig
username config.Secret
password config.Secret
timeout time.Duration
qos int
retain bool
@ -47,19 +49,6 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, error) {
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()
if err != nil {
return nil, err
@ -107,6 +96,8 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, error) {
return &mqttv5Client{
options: opts,
timeout: time.Duration(cfg.Timeout),
username: cfg.Username,
password: config.Password,
qos: cfg.QoS,
retain: cfg.Retain,
properties: properties,
@ -114,6 +105,18 @@ func NewMQTTv5Client(cfg *MqttConfig) (*mqttv5Client, 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)
if err != nil {
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
if !user.Empty() {
var err error
username, err = user.Get()
usecret, err := user.Get()
if err != nil {
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() {
var err error
password, err = passwd.Get()
psecret, err := passwd.Get()
if err != nil {
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))
case "certificate":

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -109,8 +109,8 @@ func (m *Mysql) Init() error {
if err != nil {
return fmt.Errorf("getting server %d failed: %w", i, err)
}
dsn := string(dsnSecret)
config.ReleaseSecret(dsnSecret)
dsn := dsnSecret.String()
dsnSecret.Destroy()
conf, err := mysql.ParseDSN(dsn)
if err != nil {
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 {
return err
}
dsn := string(dsnSecret)
config.ReleaseSecret(dsnSecret)
dsn := dsnSecret.String()
dsnSecret.Destroy()
servtag := getDSNTag(dsn)
db, err := sql.Open("mysql", dsn)

View File

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

View File

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

View File

@ -75,28 +75,35 @@ func (r *Radius) pollServer(acc telegraf.Accumulator, server string) error {
if err != nil {
return fmt.Errorf("getting secret failed: %w", err)
}
defer config.ReleaseSecret(secret)
defer secret.Destroy()
username, err := r.Username.Get()
if err != nil {
return fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
defer username.Destroy()
password, err := r.Password.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
defer password.Destroy()
// Create the radius packet with PAP authentication
packet := radius.New(radius.CodeAccessRequest, secret)
err = rfc2865.UserName_Set(packet, username)
if err != nil {
packet := radius.New(radius.CodeAccessRequest, secret.Bytes())
if err := rfc2865.UserName_Set(packet, username.Bytes()); err != nil {
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)
}

View File

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

View File

@ -372,8 +372,8 @@ func (s *SQL) setupConnection() error {
if err != nil {
return fmt.Errorf("getting DSN failed: %w", err)
}
dsn := string(dsnSecret)
config.ReleaseSecret(dsnSecret)
dsn := dsnSecret.String()
dsnSecret.Destroy()
s.Log.Debug("Connecting...")
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)
continue
}
dsn := string(dnsSecret)
config.ReleaseSecret(dnsSecret)
dsn := dnsSecret.String()
dnsSecret.Destroy()
for _, query := range s.queries {
wg.Add(1)
@ -272,8 +272,8 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
// Use the DSN (connection string) directly. In this case,
// empty username/password causes use of Windows
// integrated authentication.
pool, err = sql.Open("mssql", string(dsn))
config.ReleaseSecret(dsn)
pool, err = sql.Open("mssql", dsn.String())
dsn.Destroy()
if err != nil {
acc.AddError(err)
continue
@ -300,8 +300,8 @@ func (s *SQLServer) Start(acc telegraf.Accumulator) error {
acc.AddError(err)
continue
}
connector, err := mssql.NewAccessTokenConnector(string(dsn), tokenProvider)
config.ReleaseSecret(dsn)
connector, err := mssql.NewAccessTokenConnector(dsn.String(), tokenProvider)
dsn.Destroy()
if err != nil {
acc.AddError(fmt.Errorf("error creating the SQL connector: %w", err))
continue

View File

@ -120,21 +120,21 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
if err != nil {
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()
if err != nil {
return fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
defer username.Destroy()
password, err := t.Password.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
defer password.Destroy()
ctx := context.Background()
if t.ResponseTimeout > 0 {
@ -162,7 +162,7 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
return nil
}
reply, err = session.Continue(ctx, string(username))
reply, err = session.Continue(ctx, username.String())
if err != nil {
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)
@ -179,7 +179,7 @@ func (t *Tacacs) pollServer(acc telegraf.Accumulator, client *tacplus.Client) er
return nil
}
reply, err = session.Continue(ctx, string(password))
reply, err = session.Continue(ctx, password.String())
if err != nil {
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)

View File

@ -21,7 +21,6 @@ import (
"github.com/vmware/govmomi/vim25/types"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
)
// 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 {
return fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
defer username.Destroy()
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))
defer password.Destroy()
auth := url.UserPassword(username.String(), password.String())
if err := cf.client.Client.SessionManager.Login(ctx2, auth); err != nil {
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()
if err != nil {
config.ReleaseSecret(username)
username.Destroy()
return nil, fmt.Errorf("getting password failed: %w", err)
}
vSphereURL.User = url.UserPassword(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
vSphereURL.User = url.UserPassword(username.String(), password.String())
username.Destroy()
password.Destroy()
}
vs.Log.Debugf("Creating client: %s", vSphereURL.Host)

View File

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

View File

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

View File

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

View File

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

View File

@ -79,7 +79,7 @@ func (g *Groundwork) Init() error {
}
password, err := g.Password.Get()
if err != nil {
config.ReleaseSecret(username)
username.Destroy()
return fmt.Errorf("getting password failed: %w", err)
}
g.client = clients.GWClient{
@ -87,13 +87,13 @@ func (g *Groundwork) Init() error {
AppType: g.DefaultAppType,
GWConnection: &clients.GWConnection{
HostName: g.Server,
UserName: string(username),
Password: string(password),
UserName: username.String(),
Password: password.String(),
IsDynamicInventory: true,
},
}
config.ReleaseSecret(username)
config.ReleaseSecret(password)
username.Destroy()
password.Destroy()
logper.SetLogger(
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 {
var reqBody []byte
if h.UseBatchFormat {
var err error
reqBody, err = h.serializer.SerializeBatch(metrics)
reqBody, err := h.serializer.SerializeBatch(metrics)
if err != nil {
return err
}
@ -118,8 +115,7 @@ func (h *HTTP) Write(metrics []telegraf.Metric) error {
}
for _, metric := range metrics {
var err error
reqBody, err = h.serializer.Serialize(metric)
reqBody, err := h.serializer.Serialize(metric)
if err != nil {
return err
}
@ -185,12 +181,12 @@ func (h *HTTP) writeMetric(reqBody []byte) error {
}
password, err := h.Password.Get()
if err != nil {
config.ReleaseSecret(username)
username.Destroy()
return fmt.Errorf("getting password failed: %w", err)
}
req.SetBasicAuth(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
req.SetBasicAuth(username.String(), password.String())
username.Destroy()
password.Destroy()
}
// google api auth

View File

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

View File

@ -100,9 +100,8 @@ func NewHTTPClient(cfg *HTTPConfig) (*httpClient, error) {
if err != nil {
return nil, fmt.Errorf("getting token failed: %w", err)
}
headers["Authorization"] = "Token " + string(token)
config.ReleaseSecret(token)
headers["Authorization"] = "Token " + token.String()
token.Destroy()
for k, v := range cfg.Headers {
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 {
tokenSecret, err := i.APIToken.Get()
token, err := i.APIToken.Get()
if err != nil {
return fmt.Errorf("getting token failed: %w", err)
}
token := string(tokenSecret)
config.ReleaseSecret(tokenSecret)
defer token.Destroy()
if _, err := fmt.Fprintf(conn, HandshakeFormat, token); err != nil {
if _, err := fmt.Fprintf(conn, HandshakeFormat, token.TemporaryString()); err != nil {
return err
}

View File

@ -85,17 +85,18 @@ func (s *IoTDB) Connect() error {
}
password, err := s.Password.Get()
if err != nil {
config.ReleaseSecret(username)
username.Destroy()
return fmt.Errorf("getting password failed: %w", err)
}
defer password.Destroy()
sessionConf := &client.Config{
Host: s.Host,
Port: s.Port,
UserName: string(username),
Password: string(password),
UserName: username.String(),
Password: password.String(),
}
config.ReleaseSecret(username)
config.ReleaseSecret(password)
username.Destroy()
password.Destroy()
var ss = client.NewSession(sessionConf)
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()
if err != nil {
config.ReleaseSecret(user)
user.Destroy()
return fmt.Errorf("getting token failed: %w", err)
}
req.SetBasicAuth(string(user), string(token))
config.ReleaseSecret(user)
config.ReleaseSecret(token)
req.SetBasicAuth(user.String(), token.String())
user.Destroy()
token.Destroy()
resp, err := l.client.Do(req)
if err != nil {

View File

@ -145,9 +145,9 @@ func (l *Logzio) authURL() (string, error) {
if err != nil {
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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -86,8 +86,8 @@ func (s *SignalFx) Connect() error {
if err != nil {
return fmt.Errorf("getting token failed: %w", err)
}
client.AuthToken = string(token)
config.ReleaseSecret(token)
client.AuthToken = token.String()
token.Destroy()
if 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 {
return nil, fmt.Errorf("getting username failed: %w", err)
}
defer config.ReleaseSecret(username)
defer username.Destroy()
password, err := q.Password.Get()
if err != nil {
return nil, fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(password)
return stomp.ConnOpt.Login(string(username), string(password)), nil
defer password.Destroy()
return stomp.ConnOpt.Login(username.String(), password.String()), nil
}
func init() {

View File

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

View File

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

View File

@ -96,12 +96,12 @@ func (a *AesEncryptor) Init() error {
if err != nil {
return fmt.Errorf("getting key failed: %w", err)
}
key := make([]byte, hex.DecodedLen(len(encodedKey)))
if _, err := hex.Decode(key, encodedKey); err != nil {
config.ReleaseSecret(encodedKey)
key := make([]byte, hex.DecodedLen(len(encodedKey.Bytes())))
_, err = hex.Decode(key, encodedKey.Bytes())
encodedKey.Destroy()
if err != nil {
return fmt.Errorf("decoding key failed: %w", err)
}
config.ReleaseSecret(encodedKey)
actuallen := len(key)
memguard.WipeBytes(key)
@ -118,8 +118,8 @@ func (a *AesEncryptor) Init() error {
if err != nil {
return fmt.Errorf("getting IV failed: %w", err)
}
ivlen := len(encodedIV)
config.ReleaseSecret(encodedIV)
ivlen := len(encodedIV.Bytes())
encodedIV.Destroy()
if ivlen != 2*aes.BlockSize {
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 {
return nil, fmt.Errorf("getting key failed: %w", err)
}
key := make([]byte, hex.DecodedLen(len(encodedKey)))
if _, err := hex.Decode(key, encodedKey); err != nil {
config.ReleaseSecret(encodedKey)
key := make([]byte, hex.DecodedLen(len(encodedKey.Bytes())))
_, err = hex.Decode(key, encodedKey.Bytes())
encodedKey.Destroy()
if err != nil {
return nil, fmt.Errorf("decoding key failed: %w", err)
}
config.ReleaseSecret(encodedKey)
// Setup AES
block, err := aes.NewCipher(key)
@ -158,9 +158,9 @@ func (a *AesEncryptor) Decrypt(data []byte) ([]byte, error) {
if err != nil {
return nil, fmt.Errorf("getting initialization-vector failed: %w", err)
}
iv := make([]byte, hex.DecodedLen(len(encodedIV)))
_, err = hex.Decode(iv, encodedIV)
config.ReleaseSecret(encodedIV)
iv := make([]byte, hex.DecodedLen(len(encodedIV.Bytes())))
_, err = hex.Decode(iv, encodedIV.Bytes())
encodedIV.Destroy()
if err != nil {
memguard.WipeBytes(iv)
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 {
return fmt.Errorf("getting username failed: %w", err)
}
defer username.Destroy()
password, err := h.Password.Get()
if err != nil {
config.ReleaseSecret(username)
return fmt.Errorf("getting password failed: %w", err)
}
request.SetBasicAuth(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
defer password.Destroy()
request.SetBasicAuth(username.String(), password.String())
}
if !h.Token.Empty() {
@ -216,8 +215,8 @@ func (h *HTTP) setRequestAuth(request *http.Request) error {
if err != nil {
return fmt.Errorf("getting token failed: %w", err)
}
bearer := "Bearer " + strings.TrimSpace(string(token))
config.ReleaseSecret(token)
defer token.Destroy()
bearer := "Bearer " + strings.TrimSpace(token.String())
request.Header.Set("Authorization", bearer)
}

View File

@ -39,15 +39,15 @@ func (k *KDFConfig) generatePBKDF2HMAC(hf hashFunc, keylen int) (config.Secret,
if err != nil {
return config.Secret{}, config.Secret{}, fmt.Errorf("getting password failed: %w", err)
}
defer config.ReleaseSecret(passwd)
defer passwd.Destroy()
salt, err := k.Salt.Get()
if err != nil {
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)))
return key, config.Secret{}, nil
}

View File

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

View File

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

View File

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

View File

@ -6,21 +6,18 @@ import (
"fmt"
"github.com/99designs/keyring"
"github.com/influxdata/telegraf/config"
)
func (o *OS) createKeyringConfig() (keyring.Config, error) {
// Create the prompt-function in case we need it
promptFunc := keyring.TerminalPrompt
if !o.Password.Empty() {
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
promptFunc := keyring.TerminalPrompt
if len(passwd) != 0 {
promptFunc = keyring.FixedStringPrompt(string(passwd))
promptFunc = keyring.FixedStringPrompt(passwd.String())
passwd.Destroy()
}
return keyring.Config{