Skip to content

Commit

Permalink
Support reading AWS token from the filesystem
Browse files Browse the repository at this point in the history
Signed-off-by: Curtis Maddalozzo <cmaddalozzo@bloomberg.net>
  • Loading branch information
cmaddalozzo committed Sep 5, 2024
1 parent 3c2fc5d commit bed1043
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
20 changes: 15 additions & 5 deletions plugins/rest/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ const (
ec2DefaultTokenPath = "http://169.254.169.254/latest/api/token"

// ref. https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html
ecsDefaultCredServicePath = "http://169.254.170.2"
ecsRelativePathEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
ecsFullPathEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
ecsAuthorizationTokenEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
ecsDefaultCredServicePath = "http://169.254.170.2"
ecsRelativePathEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
ecsFullPathEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
ecsAuthorizationTokenEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
ecsAuthorizationTokenFileEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE"

// ref. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html
stsDefaultDomain = "amazonaws.com"
Expand Down Expand Up @@ -278,8 +279,17 @@ func (cs *awsMetadataCredentialService) refreshFromService(ctx context.Context)
// to the request
if _, useFullPath := os.LookupEnv(ecsFullPathEnvVar); useFullPath {
token, tokenExists := os.LookupEnv(ecsAuthorizationTokenEnvVar)
// If token doesn't exist as an env var check if it exists on the file system (e.g. for pod identities)
if !tokenExists {
return errors.New("unable to get ECS metadata authorization token")
tokenFilePath, tokenFilePathExists := os.LookupEnv(ecsAuthorizationTokenFileEnvVar)
if !tokenFilePathExists {
return errors.New("unable to get ECS metadata authorization token")
}
tokenBytes, err := os.ReadFile(tokenFilePath)
if err != nil {
return errors.New("failed to read ECS metadata authorization token from file: " + err.Error())
}
token = string(tokenBytes)
}
req.Header.Set("Authorization", token)
}
Expand Down
43 changes: 43 additions & 0 deletions plugins/rest/aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,16 @@ func TestMetadataCredentialService(t *testing.T) {
assertErr("unable to get ECS metadata authorization token", err, t)
os.Unsetenv(ecsFullPathEnvVar)

test.WithTempFS(nil, func(path string) {
// wrong path: bad file token
t.Setenv(ecsFullPathEnvVar, "fullPath")
os.Setenv(ecsAuthorizationTokenFileEnvVar, filepath.Join(path, "bad-file"))
_, err = cs.credentials(context.Background())
assertErr("failed to read ECS metadata authorization token from file", err, t)
os.Unsetenv(ecsFullPathEnvVar)
os.Unsetenv(ecsAuthorizationTokenFileEnvVar)
})

// wrong path: creds not found
cs = awsMetadataCredentialService{
RoleName: "not_my_iam_role", // not present
Expand Down Expand Up @@ -525,6 +535,39 @@ func TestMetadataCredentialService(t *testing.T) {
assertEq(creds.SessionToken, ts.payload.Token, t)
os.Unsetenv(ecsFullPathEnvVar)
os.Unsetenv(ecsAuthorizationTokenEnvVar)

// happy path: credentials fetched from full path var using token from filesystem
files := map[string]string{
"good_token_file": "THIS_IS_A_GOOD_TOKEN",
}
test.WithTempFS(files, func(path string) {
// happy path: credentials fetched from full path var
cs = awsMetadataCredentialService{
RegionName: "us-east-1",
credServicePath: "", // not set as we want to test env var resolution
logger: logging.Get(),
}
ts.payload = metadataPayload{
AccessKeyID: "MYAWSACCESSKEYGOESHERE",
SecretAccessKey: "MYAWSSECRETACCESSKEYGOESHERE",
Code: "Success",
Token: "MYAWSSECURITYTOKENGOESHERE",
Expiration: time.Now().UTC().Add(time.Minute * 2)} // short time
t.Setenv(ecsFullPathEnvVar, ts.server.URL+"/fullPath")
t.Setenv(ecsAuthorizationTokenFileEnvVar, filepath.Join(path, "good_token_file"))
creds, err = cs.credentials(context.Background())
if err != nil {
// Cannot proceed with test if unable to fetch credentials.
t.Fatal(err)
}

assertEq(creds.AccessKey, ts.payload.AccessKeyID, t)
assertEq(creds.SecretKey, ts.payload.SecretAccessKey, t)
assertEq(creds.RegionName, cs.RegionName, t)
assertEq(creds.SessionToken, ts.payload.Token, t)
os.Unsetenv(ecsFullPathEnvVar)
os.Unsetenv(ecsAuthorizationTokenFileEnvVar)
})
}

func TestMetadataServiceErrorHandled(t *testing.T) {
Expand Down

0 comments on commit bed1043

Please sign in to comment.