diff --git a/builtin/credential/aws/backend_test.go b/builtin/credential/aws/backend_test.go index 2d546fcc19fd..98446029fdcb 100644 --- a/builtin/credential/aws/backend_test.go +++ b/builtin/credential/aws/backend_test.go @@ -1428,7 +1428,7 @@ func TestBackendAcc_LoginWithCallerIdentity(t *testing.T) { t.Fatalf("bad: failed to create role; resp:%#v\nerr:%v", resp, err) } - fakeArn := "arn:aws:iam::123456789012:role/FakeRole" + fakeArn := "arn:aws:iam::123456789012:role/somePath/FakeRole" fakeArnResolver := func(s logical.Storage, arn string) (string, error) { if arn == fakeArn { return fmt.Sprintf("FakeUniqueIdFor%s", fakeArn), nil @@ -1535,6 +1535,9 @@ func TestBackendAcc_LoginWithCallerIdentity(t *testing.T) { renewReq.Auth.LeaseOptions = resp.Auth.LeaseOptions renewReq.Auth.Policies = resp.Auth.Policies renewReq.Auth.IssueTime = time.Now() + // dump a fake ARN into the metadata to ensure that we ONLY look + // at the unique ID that has been generated + renewReq.Auth.Metadata["canonical_arn"] = "fake_arn" // ensure we can renew resp, err = b.pathLoginRenew(renewReq, empty_login_fd) if err != nil { diff --git a/builtin/credential/aws/path_login.go b/builtin/credential/aws/path_login.go index 64a707d70919..99edadb74f35 100644 --- a/builtin/credential/aws/path_login.go +++ b/builtin/credential/aws/path_login.go @@ -918,7 +918,7 @@ func (b *backend) pathLoginRenewIam( if !ok { return nil, fmt.Errorf("no inferred AWS region in auth metadata") } - _, err := b.validateInstance(req.Storage, instanceID, instanceRegion, req.Auth.Metadata["accountID"]) + _, err := b.validateInstance(req.Storage, instanceID, instanceRegion, req.Auth.Metadata["account_id"]) if err != nil { return nil, fmt.Errorf("failed to verify instance ID %q: %v", instanceID, err) } @@ -927,30 +927,22 @@ func (b *backend) pathLoginRenewIam( } } - // The role may have been specified with only bindings on the inferred entity. The - // creation/modification of roles ensures that there is always at least one valid binding, and - // those bindings are either with a bound_iam_principal_arn or bindings on the inferred enttity. - // If the bound_iam_principal_arn is set to "", then that means all the bindings were set on the - // inferred entity type and already checked, so we don't need to check bound_iam_principal_arn. - if roleEntry.BoundIamPrincipalARN != "" && roleEntry.BoundIamPrincipalARN != canonicalArn { - return nil, fmt.Errorf("role no longer bound to arn %q", canonicalArn) - } - // Need to hanndle the case where an auth token was generated before we put client_user_id in the metadata - // Basic goal here is: - // 1. If no client_user_id metadata exists, then skip the check (it might be nice to fill it in later, but - // could be complicated) - // 2. If role is not bound to an ID, that means that checking the unique ID has been disabled, so skip the - // check - // 3. Otherwise, ensure that the stored client_user_id matches the bound IAM principal ID. If an IAM user - // or role is deleted and recreated, then existing clients will NOT be able to renew and they'll need - // to reauthenticate to Vault with updated IAM credentials - originalUserId, ok := req.Auth.Metadata["client_user_id"] - if ok && roleEntry.BoundIamPrincipalID != "" && roleEntry.BoundIamPrincipalID != req.Auth.Metadata["client_user_id"] { - return nil, fmt.Errorf("role no longer bound to ID %q", originalUserId) + if roleEntry.BoundIamPrincipalARN != "" { + // We might not get here if all bindings were on the inferred entity, which we've already validated + // above + clientUserId, ok := req.Auth.Metadata["client_user_id"] + if ok && roleEntry.BoundIamPrincipalID != "" { + // Resolving unique IDs is enabled and the auth metadata contains the unique ID, so checking the + // unique ID is authoritative at this stage + if roleEntry.BoundIamPrincipalID != clientUserId { + return nil, fmt.Errorf("role no longer bound to ID %q", clientUserId) + } + } else if roleEntry.BoundIamPrincipalARN != canonicalArn { + return nil, fmt.Errorf("role no longer bound to arn %q", canonicalArn) + } } return framework.LeaseExtend(roleEntry.TTL, roleEntry.MaxTTL, b.System())(req, data) - } func (b *backend) pathLoginRenewEc2(