Skip to content

Commit 1d56540

Browse files
mbamberPettitWesley
authored andcommitted
Add new role-arn endpoint
It is sometimes applicable to assume a role in a different account in line with some recommended AWS account structures (identity account structure). This adds support for a `role-arn` endpoint to the `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` environment variable which accepts a full role ARN. Fixes #36
1 parent 301457d commit 1d56540

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

local-container-endpoints/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ const (
6565
// RoleCredentialsPathWithSlash adds a trailing slash
6666
RoleCredentialsPathWithSlash = RoleCredentialsPath + "/"
6767

68+
//RoleArnCredentialsPath is the path for obtaining credentials from a role ARN
69+
RoleArnCredentialsPath = "/role-arn/{roleArn}/{roleName}"
70+
// RoleArnCredentialsPathWithSlash adds a trailing slash
71+
RoleArnCredentialsPathWithSlash = RoleArnCredentialsPath + "/"
72+
6873
// TempCredentialsPath is the path for obtaining temp creds from sts:GetSessionsToken
6974
TempCredentialsPath = "/creds"
7075
// TempCredentialsPathWithSlash adds a trailing slash

local-container-endpoints/handlers/credentials_handler.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func NewCredentialService() (*CredentialService, error) {
7979

8080
sess, err := session.NewSessionWithOptions(session.Options{
8181
Config: aws.Config{
82-
EndpointResolver: endpoints.ResolverFunc(customResolverFn),
82+
EndpointResolver: endpoints.ResolverFunc(customResolverFn),
8383
CredentialsChainVerboseErrors: aws.Bool(true),
8484
},
8585
SharedConfigState: session.SharedConfigEnable,
@@ -109,6 +109,9 @@ func (service *CredentialService) SetupRoutes(router *mux.Router) {
109109
router.HandleFunc(config.RoleCredentialsPath, ServeHTTP(service.getRoleHandler()))
110110
router.HandleFunc(config.RoleCredentialsPathWithSlash, ServeHTTP(service.getRoleHandler()))
111111

112+
router.HandleFunc(config.RoleArnCredentialsPath, ServeHTTP(service.getRoleArnHandler()))
113+
router.HandleFunc(config.RoleArnCredentialsPathWithSlash, ServeHTTP(service.getRoleArnHandler()))
114+
112115
router.HandleFunc(config.TempCredentialsPath, ServeHTTP(service.getTemporaryCredentialHandler()))
113116
router.HandleFunc(config.TempCredentialsPathWithSlash, ServeHTTP(service.getTemporaryCredentialHandler()))
114117
}
@@ -137,6 +140,31 @@ func (service *CredentialService) getRoleHandler() func(w http.ResponseWriter, r
137140
}
138141
}
139142

143+
// GetRoleArnHandler returns the Task IAM Role handler for complete role ARNs
144+
func (service *CredentialService) getRoleArnHandler() func(w http.ResponseWriter, r *http.Request) error {
145+
return func(w http.ResponseWriter, r *http.Request) error {
146+
logrus.Debug("Received role credentials request using ARN")
147+
148+
vars := mux.Vars(r)
149+
roleName := vars["roleName"]
150+
roleArn := fmt.Sprintf("%s/%s", vars["roleArn"], roleName)
151+
if roleArn == "" {
152+
return HTTPError{
153+
Code: http.StatusBadRequest,
154+
Err: fmt.Errorf("Invalid URL path %s; expected '/role-arn/<IAM Role ARN>", r.URL.Path),
155+
}
156+
}
157+
158+
response, err := service.getRoleCredentialsFromArn(roleArn, roleName)
159+
if err != nil {
160+
return err
161+
}
162+
163+
writeJSONResponse(w, response)
164+
return nil
165+
}
166+
}
167+
140168
func (service *CredentialService) getRoleCredentials(roleName string) (*CredentialResponse, error) {
141169
logrus.Debugf("Requesting credentials for %s", roleName)
142170

@@ -147,8 +175,14 @@ func (service *CredentialService) getRoleCredentials(roleName string) (*Credenti
147175
return nil, err
148176
}
149177

178+
return service.getRoleCredentialsFromArn(aws.StringValue(output.Role.Arn), roleName)
179+
}
180+
181+
func (service *CredentialService) getRoleCredentialsFromArn(roleArn, roleName string) (*CredentialResponse, error) {
182+
logrus.Debugf("Requesting credentials for role with ARN %s", roleArn)
183+
150184
creds, err := service.stsClient.AssumeRole(&sts.AssumeRoleInput{
151-
RoleArn: output.Role.Arn,
185+
RoleArn: aws.String(roleArn),
152186
DurationSeconds: aws.Int64(temporaryCredentialsDurationInS),
153187
RoleSessionName: aws.String(utils.Truncate(fmt.Sprintf("ecs-local-%s", roleName), roleSessionNameLength)),
154188
})
@@ -160,7 +194,7 @@ func (service *CredentialService) getRoleCredentials(roleName string) (*Credenti
160194
return &CredentialResponse{
161195
AccessKeyID: aws.StringValue(creds.Credentials.AccessKeyId),
162196
SecretAccessKey: aws.StringValue(creds.Credentials.SecretAccessKey),
163-
RoleArn: aws.StringValue(output.Role.Arn),
197+
RoleArn: roleArn,
164198
Token: aws.StringValue(creds.Credentials.SessionToken),
165199
Expiration: creds.Credentials.Expiration.Format(CredentialExpirationTimeFormat),
166200
}, nil

0 commit comments

Comments
 (0)