mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
feat(aws): add ability to provide a role session name when generating STS credentials (#11345)
* feat(aws): add ability to provide a sessionName to sts credentials Co-authored-by: Brad Vernon <bvernon@nvidia.com> Co-authored-by: Jim Kalafut <jim@kalafut.net> Co-authored-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
@@ -32,6 +32,10 @@ func pathUser(b *backend) *framework.Path {
|
|||||||
Description: "Lifetime of the returned credentials in seconds",
|
Description: "Lifetime of the returned credentials in seconds",
|
||||||
Default: 3600,
|
Default: 3600,
|
||||||
},
|
},
|
||||||
|
"role_session_name": &framework.FieldSchema{
|
||||||
|
Type: framework.TypeString,
|
||||||
|
Description: "Session name to use when assuming role. Max chars: 64",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||||
@@ -80,6 +84,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
|
|||||||
}
|
}
|
||||||
|
|
||||||
roleArn := d.Get("role_arn").(string)
|
roleArn := d.Get("role_arn").(string)
|
||||||
|
roleSessionName := d.Get("role_session_name").(string)
|
||||||
|
|
||||||
var credentialType string
|
var credentialType string
|
||||||
switch {
|
switch {
|
||||||
@@ -125,7 +130,7 @@ func (b *backend) pathCredsRead(ctx context.Context, req *logical.Request, d *fr
|
|||||||
case !strutil.StrListContains(role.RoleArns, roleArn):
|
case !strutil.StrListContains(role.RoleArns, roleArn):
|
||||||
return logical.ErrorResponse(fmt.Sprintf("role_arn %q not in allowed role arns for Vault role %q", roleArn, roleName)), nil
|
return logical.ErrorResponse(fmt.Sprintf("role_arn %q not in allowed role arns for Vault role %q", roleArn, roleName)), nil
|
||||||
}
|
}
|
||||||
return b.assumeRole(ctx, req.Storage, req.DisplayName, roleName, roleArn, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl)
|
return b.assumeRole(ctx, req.Storage, req.DisplayName, roleName, roleArn, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl, roleSessionName)
|
||||||
case federationTokenCred:
|
case federationTokenCred:
|
||||||
return b.getFederationToken(ctx, req.Storage, req.DisplayName, roleName, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl)
|
return b.getFederationToken(ctx, req.Storage, req.DisplayName, roleName, role.PolicyDocument, role.PolicyArns, role.IAMGroups, ttl)
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ func (b *backend) getFederationToken(ctx context.Context, s logical.Storage,
|
|||||||
|
|
||||||
func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
|
func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
|
||||||
displayName, roleName, roleArn, policy string, policyARNs []string,
|
displayName, roleName, roleArn, policy string, policyARNs []string,
|
||||||
iamGroups []string, lifeTimeInSeconds int64) (*logical.Response, error) {
|
iamGroups []string, lifeTimeInSeconds int64, roleSessionName string) (*logical.Response, error) {
|
||||||
|
|
||||||
// grab any IAM group policies associated with the vault role, both inline
|
// grab any IAM group policies associated with the vault role, both inline
|
||||||
// and managed
|
// and managed
|
||||||
@@ -165,10 +165,19 @@ func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
|
|||||||
return logical.ErrorResponse(err.Error()), nil
|
return logical.ErrorResponse(err.Error()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
username, usernameWarning := genUsername(displayName, roleName, "iam_user")
|
roleSessionNameWarning := ""
|
||||||
|
if roleSessionName == "" {
|
||||||
|
roleSessionName, roleSessionNameWarning = genUsername(displayName, roleName, "iam_user")
|
||||||
|
} else {
|
||||||
|
roleSessionName = normalizeDisplayName(roleSessionName)
|
||||||
|
if len(roleSessionName) > 64 {
|
||||||
|
roleSessionName = roleSessionName[0:64]
|
||||||
|
roleSessionNameWarning = "the role session name was truncated to 64 characters to fit within IAM session name length limits"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assumeRoleInput := &sts.AssumeRoleInput{
|
assumeRoleInput := &sts.AssumeRoleInput{
|
||||||
RoleSessionName: aws.String(username),
|
RoleSessionName: aws.String(roleSessionName),
|
||||||
RoleArn: aws.String(roleArn),
|
RoleArn: aws.String(roleArn),
|
||||||
DurationSeconds: &lifeTimeInSeconds,
|
DurationSeconds: &lifeTimeInSeconds,
|
||||||
}
|
}
|
||||||
@@ -187,8 +196,9 @@ func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
|
|||||||
"access_key": *tokenResp.Credentials.AccessKeyId,
|
"access_key": *tokenResp.Credentials.AccessKeyId,
|
||||||
"secret_key": *tokenResp.Credentials.SecretAccessKey,
|
"secret_key": *tokenResp.Credentials.SecretAccessKey,
|
||||||
"security_token": *tokenResp.Credentials.SessionToken,
|
"security_token": *tokenResp.Credentials.SessionToken,
|
||||||
|
"arn": *tokenResp.AssumedRoleUser.Arn,
|
||||||
}, map[string]interface{}{
|
}, map[string]interface{}{
|
||||||
"username": username,
|
"username": roleSessionName,
|
||||||
"policy": roleArn,
|
"policy": roleArn,
|
||||||
"is_sts": true,
|
"is_sts": true,
|
||||||
})
|
})
|
||||||
@@ -199,8 +209,8 @@ func (b *backend) assumeRole(ctx context.Context, s logical.Storage,
|
|||||||
// STS are purposefully short-lived and aren't renewable
|
// STS are purposefully short-lived and aren't renewable
|
||||||
resp.Secret.Renewable = false
|
resp.Secret.Renewable = false
|
||||||
|
|
||||||
if usernameWarning != "" {
|
if roleSessionNameWarning != "" {
|
||||||
resp.AddWarning(usernameWarning)
|
resp.AddWarning(roleSessionNameWarning)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
|||||||
3
changelog/11345.txt
Normal file
3
changelog/11345.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
```release-note:improvement
|
||||||
|
secrets/aws: add ability to provide a role session name when generating STS credentials
|
||||||
|
```
|
||||||
@@ -523,6 +523,10 @@ credentials retrieved through `/aws/creds` must be of the `iam_user` type.
|
|||||||
the Vault role is `assumed_role`. Must match one of the allowed role ARNs in
|
the Vault role is `assumed_role`. Must match one of the allowed role ARNs in
|
||||||
the Vault role. Optional if the Vault role only allows a single AWS role ARN;
|
the Vault role. Optional if the Vault role only allows a single AWS role ARN;
|
||||||
required otherwise.
|
required otherwise.
|
||||||
|
- `role_session_name` `(string)` - The role session name to attach to the assumed role ARN.
|
||||||
|
`role_session_name` is limited to 64 characters; if exceeded, the `role_session_name` in the
|
||||||
|
assumed role ARN will be truncated to 64 characters. If `role_session_name` is not provided,
|
||||||
|
then it will be generated dynamically by default.
|
||||||
- `ttl` `(string: "3600s")` – Specifies the TTL for the use of the STS token.
|
- `ttl` `(string: "3600s")` – Specifies the TTL for the use of the STS token.
|
||||||
This is specified as a string with a duration suffix. Valid only when
|
This is specified as a string with a duration suffix. Valid only when
|
||||||
`credential_type` is `assumed_role` or `federation_token`. When not specified,
|
`credential_type` is `assumed_role` or `federation_token`. When not specified,
|
||||||
@@ -550,7 +554,8 @@ $ curl \
|
|||||||
"data": {
|
"data": {
|
||||||
"access_key": "AKIA...",
|
"access_key": "AKIA...",
|
||||||
"secret_key": "xlCs...",
|
"secret_key": "xlCs...",
|
||||||
"security_token": null
|
"security_token": null,
|
||||||
|
"arn": "arn:aws:sts::123456789012:assumed-role/DeveloperRole/some-user-supplied-role-session-name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user