mirror of
https://github.com/hashicorp/vault.git
synced 2026-06-06 07:13:04 -04:00
Fix AWS auth renewals (#8991)
* fix aws auth renewals * Update builtin/credential/aws/path_login.go Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com> * debug log missing account_ids * strip tests and related changes Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com>
This commit is contained in:
parent
b5ba59b757
commit
ac880b0079
1 changed files with 57 additions and 33 deletions
|
|
@ -842,6 +842,11 @@ func (b *backend) pathLoginUpdateEc2(ctx context.Context, req *logical.Request,
|
|||
Alias: &logical.Alias{
|
||||
Name: identityAlias,
|
||||
},
|
||||
InternalData: map[string]interface{}{
|
||||
"instance_id": identityDocParsed.InstanceID,
|
||||
"region": identityDocParsed.Region,
|
||||
"account_id": identityDocParsed.AccountID,
|
||||
},
|
||||
}
|
||||
roleEntry.PopulateTokenAuth(auth)
|
||||
if err := identityConfigEntry.EC2AuthMetadataHandler.PopulateDesiredMetadata(auth, map[string]string{
|
||||
|
|
@ -963,9 +968,9 @@ func (b *backend) pathLoginRenew(ctx context.Context, req *logical.Request, data
|
|||
}
|
||||
|
||||
func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
canonicalArn := req.Auth.Metadata["canonical_arn"]
|
||||
if canonicalArn == "" {
|
||||
return nil, fmt.Errorf("unable to retrieve canonical ARN from metadata during renewal")
|
||||
canonicalArn, err := getMetadataValue(req.Auth, "canonical_arn")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
roleName := ""
|
||||
|
|
@ -996,16 +1001,19 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
|
|||
// renew existing tokens.
|
||||
if roleEntry.InferredEntityType != "" {
|
||||
if roleEntry.InferredEntityType == ec2EntityType {
|
||||
instanceID, ok := req.Auth.Metadata["inferred_entity_id"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no inferred entity ID in auth metadata")
|
||||
}
|
||||
instanceRegion, ok := req.Auth.Metadata["inferred_aws_region"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no inferred AWS region in auth metadata")
|
||||
}
|
||||
_, err := b.validateInstance(ctx, req.Storage, instanceID, instanceRegion, req.Auth.Metadata["account_id"])
|
||||
instanceID, err := getMetadataValue(req.Auth, "inferred_entity_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
instanceRegion, err := getMetadataValue(req.Auth, "inferred_aws_region")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accountID, err := getMetadataValue(req.Auth, "account_id")
|
||||
if err != nil {
|
||||
b.Logger().Debug("account_id not present during iam renewal attempt, continuing to attempt validation")
|
||||
}
|
||||
if _, err := b.validateInstance(ctx, req.Storage, instanceID, instanceRegion, accountID); err != nil {
|
||||
return nil, errwrap.Wrapf(fmt.Sprintf("failed to verify instance ID %q: {{err}}", instanceID), err)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1027,9 +1035,9 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
|
|||
// implies that roleEntry.ResolveAWSUniqueIDs is true)
|
||||
// 2: roleEntry.ResolveAWSUniqueIDs is false and canonical_arn is in roleEntry.BoundIamPrincipalARNs
|
||||
// 3: Full ARN matches one of the wildcard globs in roleEntry.BoundIamPrincipalARNs
|
||||
clientUserId, ok := req.Auth.Metadata["client_user_id"]
|
||||
clientUserId, err := getMetadataValue(req.Auth, "client_user_id")
|
||||
switch {
|
||||
case ok && strutil.StrListContains(roleEntry.BoundIamPrincipalIDs, clientUserId): // check 1 passed
|
||||
case err == nil && strutil.StrListContains(roleEntry.BoundIamPrincipalIDs, clientUserId): // check 1 passed
|
||||
case !roleEntry.ResolveAWSUniqueIDs && strutil.StrListContains(roleEntry.BoundIamPrincipalARNs, canonicalArn): // check 2 passed
|
||||
default:
|
||||
// check 3 is a bit more complex, so we do it last
|
||||
|
|
@ -1070,28 +1078,22 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathLoginRenewEc2(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
instanceID := req.Auth.Metadata["instance_id"]
|
||||
if instanceID == "" {
|
||||
return nil, fmt.Errorf("unable to fetch instance ID from metadata during renewal")
|
||||
func (b *backend) pathLoginRenewEc2(ctx context.Context, req *logical.Request, _ *framework.FieldData) (*logical.Response, error) {
|
||||
instanceID, err := getMetadataValue(req.Auth, "instance_id")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region := req.Auth.Metadata["region"]
|
||||
if region == "" {
|
||||
return nil, fmt.Errorf("unable to fetch region from metadata during renewal")
|
||||
region, err := getMetadataValue(req.Auth, "region")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure backwards compatibility for older clients without account_id saved in metadata
|
||||
accountID, ok := req.Auth.Metadata["account_id"]
|
||||
if ok {
|
||||
if accountID == "" {
|
||||
return nil, fmt.Errorf("unable to fetch account_id from metadata during renewal")
|
||||
}
|
||||
accountID, err := getMetadataValue(req.Auth, "account_id")
|
||||
if err != nil {
|
||||
b.Logger().Debug("account_id not present during ec2 renewal attempt, continuing to attempt validation")
|
||||
}
|
||||
|
||||
// Cross check that the instance is still in 'running' state
|
||||
_, err := b.validateInstance(ctx, req.Storage, instanceID, region, accountID)
|
||||
if err != nil {
|
||||
if _, err := b.validateInstance(ctx, req.Storage, instanceID, region, accountID); err != nil {
|
||||
return nil, errwrap.Wrapf(fmt.Sprintf("failed to verify instance ID %q: {{err}}", instanceID), err)
|
||||
}
|
||||
|
||||
|
|
@ -1360,8 +1362,13 @@ func (b *backend) pathLoginUpdateIam(ctx context.Context, req *logical.Request,
|
|||
"role_id": roleEntry.RoleID,
|
||||
},
|
||||
InternalData: map[string]interface{}{
|
||||
"role_name": roleName,
|
||||
"role_id": roleEntry.RoleID,
|
||||
"role_name": roleName,
|
||||
"role_id": roleEntry.RoleID,
|
||||
"canonical_arn": entity.canonicalArn(),
|
||||
"client_user_id": callerUniqueId,
|
||||
"inferred_entity_id": inferredEntityID,
|
||||
"inferred_aws_region": roleEntry.InferredAWSRegion,
|
||||
"account_id": entity.AccountNumber,
|
||||
},
|
||||
DisplayName: entity.FriendlyName,
|
||||
Alias: &logical.Alias{
|
||||
|
|
@ -1709,6 +1716,23 @@ func (b *backend) fullArn(ctx context.Context, e *iamEntity, s logical.Storage)
|
|||
}
|
||||
}
|
||||
|
||||
// getMetadataValue attempts to get a metadata key from
|
||||
// auth.InternalData and if unset, auth.Metadata. If not
|
||||
// found, returns "".
|
||||
func getMetadataValue(fromAuth *logical.Auth, forKey string) (string, error) {
|
||||
if raw, ok := fromAuth.InternalData[forKey]; ok {
|
||||
if val, ok := raw.(string); ok {
|
||||
return val, nil
|
||||
} else {
|
||||
return "", fmt.Errorf("unable to fetch %q from auth metadata due to type of %T", forKey, raw)
|
||||
}
|
||||
}
|
||||
if val, ok := fromAuth.Metadata[forKey]; ok {
|
||||
return val, nil
|
||||
}
|
||||
return "", fmt.Errorf("%q not found in auth metadata", forKey)
|
||||
}
|
||||
|
||||
const iamServerIdHeader = "X-Vault-AWS-IAM-Server-ID"
|
||||
|
||||
const pathLoginSyn = `
|
||||
|
|
|
|||
Loading…
Reference in a new issue