Просмотр исходного кода

fix(aws): redact credentials in aws auth config logs (#6683)

* fix(aws): redact credentials in aws auth config logs

The AWS auth code logged the resolved aws.CredentialsProvider object at
info level:

    log.Info("using aws config", ..., "credentials", cfg.Credentials)

When auth comes from a static secretRef (e.g. the ECRAuthorizationToken
generator), that provider is a credentials.StaticCredentialsProvider,
and serializing it dumps AccessKeyID and SecretAccessKey in plaintext to
the logs at the default info log level.

Log a non-sensitive type descriptor of the credentials provider instead,
via a new credentialsProviderName helper, at both call sites. Region and
external-id fields are unchanged, so debugging which auth path was taken
is preserved without leaking secrets.

Signed-off-by: Chen Xi <xichen0425@gmail.com>

* use plainly synthetic strings

Signed-off-by: Chen Xi <xichen0425@gmail.com>

---------

Signed-off-by: Chen Xi <xichen0425@gmail.com>
Co-authored-by: Gergely Bräutigam <gergely.brautigam@sap.com>
Chen Xi 3 недель назад
Родитель
Сommit
708b60e82a
2 измененных файлов с 40 добавлено и 2 удалено
  1. 15 2
      providers/v1/aws/auth/auth.go
  2. 25 0
      providers/v1/aws/auth/auth_test.go

+ 15 - 2
providers/v1/aws/auth/auth.go

@@ -129,11 +129,24 @@ func createConfiguration(prov *esv1.AWSProvider, assumeRoler STSProvider, loadCf
 			cfg.Credentials = stscreds.NewAssumeRoleProvider(stsclient, prov.Role)
 		}
 	}
-	log.Info("using aws config", "region", cfg.Region, "external id", sessExtID, "credentials", cfg.Credentials)
+	log.Info("using aws config", "region", cfg.Region, "external id", sessExtID, "credentials", credentialsProviderName(cfg.Credentials))
 
 	return &cfg, nil
 }
 
+// credentialsProviderName returns a non-sensitive identifier for the given
+// credentials provider, suitable for logging. It deliberately avoids
+// serializing the provider itself: some implementations (most notably
+// credentials.StaticCredentialsProvider, used for secretRef auth) embed the raw
+// access key ID and secret access key, which would otherwise be written to logs
+// in plaintext.
+func credentialsProviderName(creds aws.CredentialsProvider) string {
+	if creds == nil {
+		return "<nil>"
+	}
+	return fmt.Sprintf("%T", creds)
+}
+
 func setAssumeRoleOptionFn(sessExtID string, sessTags []stsTypes.Tag, sessTransitiveTagKeys []string) func(p *stscreds.AssumeRoleOptions) {
 	return func(p *stscreds.AssumeRoleOptions) {
 		if sessExtID != "" {
@@ -218,7 +231,7 @@ func NewGeneratorSession(
 		stsclient := assumeRoler(&awscfg)
 		awscfg.Credentials = stscreds.NewAssumeRoleProvider(stsclient, role)
 	}
-	log.Info("using aws config", "region", awscfg.Region, "credentials", awscfg.Credentials)
+	log.Info("using aws config", "region", awscfg.Region, "credentials", credentialsProviderName(awscfg.Credentials))
 	return &awscfg, nil
 }
 

+ 25 - 0
providers/v1/aws/auth/auth_test.go

@@ -23,6 +23,7 @@ import (
 	"time"
 
 	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/credentials"
 	"github.com/aws/aws-sdk-go-v2/service/sts"
 	ststypes "github.com/aws/aws-sdk-go-v2/service/sts/types"
 	"github.com/stretchr/testify/assert"
@@ -829,3 +830,27 @@ func TestNewGeneratorSession_DefaultCredentialChainFallback(t *testing.T) {
 	assert.NotEmpty(t, creds.AccessKeyID)
 	assert.NotEmpty(t, creds.SecretAccessKey)
 }
+
+func TestCredentialsProviderName(t *testing.T) {
+	const (
+		accessKeyID     = "test-access-key-id"
+		secretAccessKey = "test-secret-access-key"
+	)
+
+	t.Run("nil provider", func(t *testing.T) {
+		assert.Equal(t, "<nil>", credentialsProviderName(nil))
+	})
+
+	t.Run("does not leak static credentials", func(t *testing.T) {
+		// StaticCredentialsProvider embeds the raw access key ID and secret
+		// access key. Serializing it (as the logger did previously) would dump
+		// them in plaintext, so the descriptor must reference neither.
+		provider := credentials.NewStaticCredentialsProvider(accessKeyID, secretAccessKey, "")
+
+		name := credentialsProviderName(provider)
+
+		assert.NotContains(t, name, accessKeyID)
+		assert.NotContains(t, name, secretAccessKey)
+		assert.Contains(t, name, "StaticCredentialsProvider")
+	})
+}