diff --git a/pkg/storage/chunk/client/aws/config.go b/pkg/storage/chunk/client/aws/config.go index 5512d0645f4d2..918beecd4490b 100644 --- a/pkg/storage/chunk/client/aws/config.go +++ b/pkg/storage/chunk/client/aws/config.go @@ -16,7 +16,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/dynamodb" - "github.com/pkg/errors" ) // DynamoConfigFromURL returns AWS config from given URL. It expects escaped @@ -73,15 +72,17 @@ func DynamoConfigFromURL(awsURL *url.URL) (*dynamodb.Options, error) { return &config, nil } -func CredentialsFromURL(awsURL *url.URL) (key, secret, session string, err error) { +func CredentialsFromURL(awsURL *url.URL) (key, secret, session string) { if awsURL.User != nil { username := awsURL.User.Username() password, _ := awsURL.User.Password() // We request at least the username or password being set to enable the static credentials. if username != "" || password != "" { - return username, password, "", nil + return username, password, "" } } - return "", "", "", errors.New("Unable to build AWS credentials from URL") + // Return empty credentials instead of error to allow AWS SDK to use default credential chain + // (environment variables, IAM roles, etc.) + return "", "", "" } diff --git a/pkg/storage/chunk/client/aws/config_test.go b/pkg/storage/chunk/client/aws/config_test.go new file mode 100644 index 0000000000000..ce016592cc1f9 --- /dev/null +++ b/pkg/storage/chunk/client/aws/config_test.go @@ -0,0 +1,59 @@ +package aws + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCredentialsFromURL(t *testing.T) { + tests := []struct { + name string + urlStr string + expectedKey string + expectedSecret string + expectedSession string + }{ + { + name: "URL with username and password", + urlStr: "s3://mykey:mysecret@us-east-1", + expectedKey: "mykey", + expectedSecret: "mysecret", + expectedSession: "", + }, + { + name: "URL with only username", + urlStr: "s3://mykey@us-east-1", + expectedKey: "mykey", + expectedSecret: "", + expectedSession: "", + }, + { + name: "URL without credentials (should not error)", + urlStr: "s3://us-east-1", + expectedKey: "", + expectedSecret: "", + expectedSession: "", + }, + { + name: "URL with endpoint without credentials", + urlStr: "s3://s3.amazonaws.com", + expectedKey: "", + expectedSecret: "", + expectedSession: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u, err := url.Parse(tt.urlStr) + require.NoError(t, err) + + key, secret, session := CredentialsFromURL(u) + require.Equal(t, tt.expectedKey, key) + require.Equal(t, tt.expectedSecret, secret) + require.Equal(t, tt.expectedSession, session) + }) + } +} diff --git a/pkg/storage/chunk/client/aws/s3_storage_client.go b/pkg/storage/chunk/client/aws/s3_storage_client.go index 317b5d91aed3e..45efcebe80939 100644 --- a/pkg/storage/chunk/client/aws/s3_storage_client.go +++ b/pkg/storage/chunk/client/aws/s3_storage_client.go @@ -215,11 +215,13 @@ func buildS3Client(cfg S3Config, hedgingCfg hedging.Config, hedging bool) (*s3.C // if an s3 url is passed use it to initialize the s3Config and then override with any additional params if cfg.S3.URL != nil { - key, secret, session, err := CredentialsFromURL(cfg.S3.URL) - if err != nil { - return nil, err + key, secret, session := CredentialsFromURL(cfg.S3.URL) + + // Only set credentials if they were provided in the URL + // Otherwise, let AWS SDK use the default credential chain + if key != "" || secret != "" { + s3Options.Credentials = credentials.NewStaticCredentialsProvider(key, secret, session) } - s3Options.Credentials = credentials.NewStaticCredentialsProvider(key, secret, session) } else { s3Options.Region = "dummy" }