Support reading AWS token from the filesystem

Signed-off-by: Curtis Maddalozzo <cmaddalozzo@bloomberg.net>
This commit is contained in:
Curtis Maddalozzo
2024-09-09 15:12:21 -07:00
committed by GitHub
parent d250ea485e
commit cdd09e5966
2 changed files with 64 additions and 7 deletions
+21 -7
View File
@@ -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"
@@ -277,9 +278,22 @@ func (cs *awsMetadataCredentialService) refreshFromService(ctx context.Context)
// if using the AWS_CONTAINER_CREDENTIALS_FULL_URI variable, we need to associate the token
// to the request
if _, useFullPath := os.LookupEnv(ecsFullPathEnvVar); useFullPath {
token, tokenExists := os.LookupEnv(ecsAuthorizationTokenEnvVar)
if !tokenExists {
return errors.New("unable to get ECS metadata authorization token")
var token string
tokenFilePath, tokenFilePathExists := os.LookupEnv(ecsAuthorizationTokenFileEnvVar)
if tokenFilePathExists {
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)
// If token doesn't exist as a file check if it exists as an environment variable
} else {
var tokenExists bool
token, tokenExists = os.LookupEnv(ecsAuthorizationTokenEnvVar)
if !tokenExists {
return errors.New("unable to get ECS metadata authorization token")
}
}
req.Header.Set("Authorization", token)
}
+43
View File
@@ -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
@@ -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) {