fix(secrets): Minimize secret holding time (#13002)

This commit is contained in:
Sven Rebhan 2023-04-03 15:28:41 +02:00 committed by GitHub
parent edcd28650c
commit 83b4056985
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 86 additions and 71 deletions

View File

@ -32,14 +32,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)
} }
defer config.ReleaseSecret(username) cfg.Net.SASL.User = string(username)
config.ReleaseSecret(username)
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)
} }
defer config.ReleaseSecret(password)
cfg.Net.SASL.User = string(username)
cfg.Net.SASL.Password = string(password) cfg.Net.SASL.Password = string(password)
config.ReleaseSecret(password)
if k.SASLMechanism != "" { if k.SASLMechanism != "" {
cfg.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism) cfg.Net.SASL.Mechanism = sarama.SASLMechanism(k.SASLMechanism)

View File

@ -399,6 +399,10 @@ func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
} }
func (h *HTTPResponse) setRequestAuth(request *http.Request) error { func (h *HTTPResponse) setRequestAuth(request *http.Request) error {
if h.Username.Empty() || h.Password.Empty() {
return nil
}
username, err := h.Username.Get() username, err := h.Username.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting username failed: %w", err) return fmt.Errorf("getting username failed: %w", err)
@ -409,9 +413,8 @@ func (h *HTTPResponse) setRequestAuth(request *http.Request) error {
return fmt.Errorf("getting password failed: %w", err) return fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password) defer config.ReleaseSecret(password)
if len(username) != 0 || len(password) != 0 { request.SetBasicAuth(string(username), string(password))
request.SetBasicAuth(string(username), string(password))
}
return nil return nil
} }

View File

@ -105,12 +105,12 @@ func (m *Mysql) Init() error {
// Adapt the DSN string // Adapt the DSN string
for i, server := range m.Servers { for i, server := range m.Servers {
s, err := server.Get() dsnSecret, err := server.Get()
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(s) dsn := string(dsnSecret)
config.ReleaseSecret(s) config.ReleaseSecret(dsnSecret)
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)
@ -415,12 +415,12 @@ const (
) )
func (m *Mysql) gatherServer(server *config.Secret, acc telegraf.Accumulator) error { func (m *Mysql) gatherServer(server *config.Secret, acc telegraf.Accumulator) error {
s, err := server.Get() dsnSecret, err := server.Get()
if err != nil { if err != nil {
return err return err
} }
dsn := string(s) dsn := string(dsnSecret)
config.ReleaseSecret(s) config.ReleaseSecret(dsnSecret)
servtag := getDSNTag(dsn) servtag := getDSNTag(dsn)
db, err := sql.Open("mysql", dsn) db, err := sql.Open("mysql", dsn)

View File

@ -109,18 +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 config.ReleaseSecret(username)
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 config.ReleaseSecret(password)
clientConfig := opensearch.Config{ clientConfig := opensearch.Config{
Addresses: o.URLs, Addresses: o.URLs,
Username: string(username), Username: string(username),
Password: string(password), Password: string(password),
} }
config.ReleaseSecret(username)
config.ReleaseSecret(password)
if o.InsecureSkipVerify { if o.InsecureSkipVerify {
clientConfig.Transport = &http.Transport{ clientConfig.Transport = &http.Transport{

View File

@ -102,18 +102,21 @@ var socketRegexp = regexp.MustCompile(`/\.s\.PGSQL\.\d+$`)
// Start starts the ServiceInput's service, whatever that may be // Start starts the ServiceInput's service, whatever that may be
func (p *Service) Start(telegraf.Accumulator) (err error) { func (p *Service) Start(telegraf.Accumulator) (err error) {
addr, err := p.Address.Get() addrSecret, err := p.Address.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting address failed: %w", err) return fmt.Errorf("getting address failed: %w", err)
} }
defer config.ReleaseSecret(addr) addr := string(addrSecret)
defer config.ReleaseSecret(addrSecret)
if p.Address.Empty() || string(addr) == "localhost" { if p.Address.Empty() || addr == "localhost" {
addr = []byte("host=localhost sslmode=disable") addr = "host=localhost sslmode=disable"
p.Address = config.NewSecret(addr) if err := p.Address.Set([]byte(addr)); err != nil {
return err
}
} }
connConfig, err := pgx.ParseConfig(string(addr)) connConfig, err := pgx.ParseConfig(addr)
if err != nil { if err != nil {
return err return err
} }

View File

@ -171,28 +171,34 @@ func (s *SnmpTrap) Start(acc telegraf.Accumulator) error {
return fmt.Errorf("unknown privacy protocol %q", s.PrivProtocol) return fmt.Errorf("unknown privacy protocol %q", s.PrivProtocol)
} }
secname, err := s.SecName.Get() secnameSecret, err := s.SecName.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting secname failed: %w", err) return fmt.Errorf("getting secname failed: %w", err)
} }
privPasswd, err := s.PrivPassword.Get() secname := string(secnameSecret)
config.ReleaseSecret(secnameSecret)
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)
} }
authPasswd, err := s.AuthPassword.Get() privPasswd := string(privPasswdSecret)
config.ReleaseSecret(privPasswdSecret)
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)
config.ReleaseSecret(authPasswdSecret)
s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{ s.listener.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: string(secname), UserName: secname,
PrivacyProtocol: privacyProtocol, PrivacyProtocol: privacyProtocol,
PrivacyPassphrase: string(privPasswd), PrivacyPassphrase: privPasswd,
AuthenticationPassphrase: string(authPasswd), AuthenticationPassphrase: authPasswd,
AuthenticationProtocol: authenticationProtocol, AuthenticationProtocol: authenticationProtocol,
} }
config.ReleaseSecret(secname)
config.ReleaseSecret(privPasswd)
config.ReleaseSecret(authPasswd)
} }
// wrap the handler, used in unit tests // wrap the handler, used in unit tests

View File

@ -358,13 +358,14 @@ func (s *SQL) Start(_ telegraf.Accumulator) error {
var err error var err error
// Connect to the database server // Connect to the database server
dsn, err := s.Dsn.Get() dsnSecret, err := s.Dsn.Get()
if err != nil { if err != nil {
return fmt.Errorf("getting DSN failed: %w", err) return fmt.Errorf("getting DSN failed: %w", err)
} }
defer config.ReleaseSecret(dsn) dsn := string(dsnSecret)
config.ReleaseSecret(dsnSecret)
s.Log.Debug("Connecting...") s.Log.Debug("Connecting...")
s.db, err = dbsql.Open(s.driverName, string(dsn)) s.db, err = dbsql.Open(s.driverName, dsn)
if err != nil { if err != nil {
return err return err
} }
@ -472,12 +473,7 @@ func (s *SQL) executeQuery(ctx context.Context, acc telegraf.Accumulator, q Quer
} }
func (s *SQL) checkDSN() error { func (s *SQL) checkDSN() error {
dsn, err := s.Dsn.Get() if s.Dsn.Empty() {
if err != nil {
return fmt.Errorf("getting DSN failed: %w", err)
}
defer config.ReleaseSecret(dsn)
if len(dsn) == 0 {
return errors.New("missing data source name (DSN) option") return errors.New("missing data source name (DSN) option")
} }
return nil return nil

View File

@ -202,26 +202,28 @@ func (s *SQLServer) Gather(acc telegraf.Accumulator) error {
var healthMetrics = make(map[string]*HealthMetric) var healthMetrics = make(map[string]*HealthMetric)
for i, pool := range s.pools { for i, pool := range s.pools {
dnsSecret, err := s.Servers[i].Get()
if err != nil {
acc.AddError(err)
continue
}
dsn := string(dnsSecret)
config.ReleaseSecret(dnsSecret)
for _, query := range s.queries { for _, query := range s.queries {
wg.Add(1) wg.Add(1)
go func(pool *sql.DB, query Query, serverIndex int) { go func(pool *sql.DB, query Query, dsn string) {
defer wg.Done() defer wg.Done()
dsn, err := s.Servers[serverIndex].Get() queryError := s.gatherServer(pool, query, acc, dsn)
if err != nil {
acc.AddError(err)
return
}
defer config.ReleaseSecret(dsn)
queryError := s.gatherServer(pool, query, acc, string(dsn))
if s.HealthMetric { if s.HealthMetric {
mutex.Lock() mutex.Lock()
s.gatherHealth(healthMetrics, string(dsn), queryError) s.gatherHealth(healthMetrics, dsn, queryError)
mutex.Unlock() mutex.Unlock()
} }
acc.AddError(queryError) acc.AddError(queryError)
}(pool, query, i) }(pool, query, dsn)
} }
} }

View File

@ -141,13 +141,14 @@ func NewClient(ctx context.Context, vSphereURL *url.URL, vs *VSphere) (*Client,
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)
password, err := vs.Password.Get() password, err := vs.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username)
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password)
vSphereURL.User = url.UserPassword(string(username), string(password)) vSphereURL.User = url.UserPassword(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
} }
vs.Log.Debugf("Creating client: %s", vSphereURL.Host) vs.Log.Debugf("Creating client: %s", vSphereURL.Host)

View File

@ -470,14 +470,14 @@ func (a *Elasticsearch) getAuthOptions() ([]elastic.ClientOptionFunc, 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)
password, err := a.Password.Get() password, err := a.Password.Get()
if err != nil { if err != nil {
config.ReleaseSecret(username)
return nil, fmt.Errorf("getting password failed: %w", err) return nil, fmt.Errorf("getting password failed: %w", err)
} }
defer config.ReleaseSecret(password)
fns = append(fns, elastic.SetBasicAuth(string(username), string(password))) fns = append(fns, elastic.SetBasicAuth(string(username), string(password)))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
} }
if !a.AuthBearerToken.Empty() { if !a.AuthBearerToken.Empty() {
@ -485,10 +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)
} }
defer config.ReleaseSecret(token)
auth := []string{"Bearer " + string(token)} auth := []string{"Bearer " + string(token)}
fns = append(fns, elastic.SetHeaders(http.Header{"Authorization": auth})) fns = append(fns, elastic.SetHeaders(http.Header{"Authorization": auth}))
config.ReleaseSecret(token)
} }
return fns, nil return fns, nil
} }

View File

@ -77,12 +77,11 @@ func (g *Groundwork) Init() 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)
password, err := g.Password.Get() password, err := g.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 config.ReleaseSecret(password)
g.client = clients.GWClient{ g.client = clients.GWClient{
AppName: "telegraf", AppName: "telegraf",
AppType: g.DefaultAppType, AppType: g.DefaultAppType,
@ -93,6 +92,8 @@ func (g *Groundwork) Init() error {
IsDynamicInventory: true, IsDynamicInventory: true,
}, },
} }
config.ReleaseSecret(username)
config.ReleaseSecret(password)
logper.SetLogger( logper.SetLogger(
func(fields interface{}, format string, a ...interface{}) { func(fields interface{}, format string, a ...interface{}) {

View File

@ -183,14 +183,14 @@ func (h *HTTP) writeMetric(reqBody []byte) 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)
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)
} }
defer config.ReleaseSecret(password)
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
} }
// google api auth // google api auth

View File

@ -494,14 +494,14 @@ func (c *httpClient) addHeaders(req *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)
password, err := c.config.Password.Get() password, err := c.config.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 config.ReleaseSecret(password)
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(string(username), string(password))
config.ReleaseSecret(username)
config.ReleaseSecret(password)
} }
for header, value := range c.config.Headers { for header, value := range c.config.Headers {

View File

@ -165,13 +165,14 @@ func (i *Instrumental) Write(metrics []telegraf.Metric) error {
} }
func (i *Instrumental) authenticate(conn net.Conn) error { func (i *Instrumental) authenticate(conn net.Conn) error {
token, err := i.APIToken.Get() tokenSecret, 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)
} }
defer config.ReleaseSecret(token) token := string(tokenSecret)
config.ReleaseSecret(tokenSecret)
if _, err := fmt.Fprintf(conn, HandshakeFormat, string(token)); err != nil { if _, err := fmt.Fprintf(conn, HandshakeFormat, token); err != nil {
return err return err
} }

View File

@ -83,18 +83,20 @@ func (s *IoTDB) 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)
password, err := s.Password.Get() password, err := s.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 config.ReleaseSecret(password)
sessionConf := &client.Config{ sessionConf := &client.Config{
Host: s.Host, Host: s.Host,
Port: s.Port, Port: s.Port,
UserName: string(username), UserName: string(username),
Password: string(password), Password: string(password),
} }
config.ReleaseSecret(username)
config.ReleaseSecret(password)
var ss = client.NewSession(sessionConf) var ss = client.NewSession(sessionConf)
s.session = &ss s.session = &ss
timeoutInMs := int(time.Duration(s.Timeout).Milliseconds()) timeoutInMs := int(time.Duration(s.Timeout).Milliseconds())

View File

@ -158,14 +158,14 @@ func (l *Loki) writeMetrics(s Streams) 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)
password, err := l.Password.Get() password, err := l.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 config.ReleaseSecret(password)
req.SetBasicAuth(string(username), string(password)) req.SetBasicAuth(string(username), string(password))
config.ReleaseSecret(password)
config.ReleaseSecret(username)
} }
for k, v := range l.Headers { for k, v := range l.Headers {