Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport 1.6.0: Improve errors for aws login with an unbound ARN (#10036) #10213

Merged
merged 1 commit into from
Oct 22, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions builtin/credential/aws/path_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,18 +1047,23 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
case !roleEntry.ResolveAWSUniqueIDs && strutil.StrListContains(roleEntry.BoundIamPrincipalARNs, canonicalArn): // check 2 passed
default:
// check 3 is a bit more complex, so we do it last
// only try to look up full ARNs if there's a wildcard ARN in BoundIamPrincipalIDs.
if !hasWildcardBind(roleEntry.BoundIamPrincipalARNs) {
return nil, fmt.Errorf("role %q no longer bound to ARN %q", roleName, canonicalArn)
}

fullArn := b.getCachedUserId(clientUserId)
if fullArn == "" {
entity, err := parseIamArn(canonicalArn)
if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("error parsing ARN %q: {{err}}", canonicalArn), err)
return nil, errwrap.Wrapf(fmt.Sprintf("error parsing ARN %q when updating login for role %q: {{err}}", canonicalArn, roleName), err)
}
fullArn, err = b.fullArn(ctx, entity, req.Storage)
if err != nil {
return nil, errwrap.Wrapf(fmt.Sprintf("error looking up full ARN of entity %v: {{err}}", entity), err)
return nil, errwrap.Wrapf(fmt.Sprintf("error looking up full ARN of entity %v when updating login for role %q: {{err}}", entity, roleName), err)
}
if fullArn == "" {
return nil, fmt.Errorf("got empty string back when looking up full ARN of entity %v", entity)
return nil, fmt.Errorf("got empty string back when looking up full ARN of entity %v when updating login for role %q", entity, roleName)
}
if clientUserId != "" {
b.setCachedUserId(clientUserId, fullArn)
Expand All @@ -1072,7 +1077,7 @@ func (b *backend) pathLoginRenewIam(ctx context.Context, req *logical.Request, d
}
}
if !matchedWildcardBind {
return nil, fmt.Errorf("role no longer bound to ARN %q", canonicalArn)
return nil, fmt.Errorf("role %q no longer bound to ARN %q", roleName, canonicalArn)
}
}
}
Expand Down Expand Up @@ -1317,15 +1322,19 @@ func (b *backend) pathLoginUpdateIam(ctx context.Context, req *logical.Request,
case strutil.StrListContains(roleEntry.BoundIamPrincipalIDs, callerUniqueId): // check 1 passed
case !roleEntry.ResolveAWSUniqueIDs && strutil.StrListContains(roleEntry.BoundIamPrincipalARNs, entity.canonicalArn()): // check 2 passed
default:
// evaluate check 3
// evaluate check 3 -- only try to look up full ARNs if there's a wildcard ARN in BoundIamPrincipalIDs.
if !hasWildcardBind(roleEntry.BoundIamPrincipalARNs) {
return logical.ErrorResponse("IAM Principal %q does not belong to the role %q", callerID.Arn, roleName), nil
}

fullArn := b.getCachedUserId(callerUniqueId)
if fullArn == "" {
fullArn, err = b.fullArn(ctx, entity, req.Storage)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf("error looking up full ARN of entity %v: %v", entity, err)), nil
return logical.ErrorResponse("error looking up full ARN of entity %v when attempting login for role %q: %v", entity, roleName, err), nil
}
if fullArn == "" {
return logical.ErrorResponse(fmt.Sprintf("got empty string back when looking up full ARN of entity %v", entity)), nil
return logical.ErrorResponse("got empty string back when looking up full ARN of entity %v when attempting login for role %q", entity, roleName), nil
}
b.setCachedUserId(callerUniqueId, fullArn)
}
Expand All @@ -1337,7 +1346,7 @@ func (b *backend) pathLoginUpdateIam(ctx context.Context, req *logical.Request,
}
}
if !matchedWildcardBind {
return logical.ErrorResponse(fmt.Sprintf("IAM Principal %q does not belong to the role %q", callerID.Arn, roleName)), nil
return logical.ErrorResponse("IAM Principal %q does not belong to the role %q", callerID.Arn, roleName), nil
}
}
}
Expand Down Expand Up @@ -1409,6 +1418,15 @@ func (b *backend) pathLoginUpdateIam(ctx context.Context, req *logical.Request,
}, nil
}

func hasWildcardBind(boundIamPrincipalARNs []string) bool {
for _, principalARN := range boundIamPrincipalARNs {
if strings.HasSuffix(principalARN, "*") {
return true
}
}
return false
}

// Validate that the iam_request_body passed is valid for the STS request
func validateLoginIamRequestBody(body string) error {
qs, err := url.ParseQuery(body)
Expand Down