Allow non-prefix-matched IAM role and instance profile ARNs in AWS auth backend (#4071)

* Update aws auth docs with new semantics

Moving away from implicitly globbed bound_iam_role_arn and
bound_iam_instance_profile_arn variables to make them explicit

* Refactor tests to reduce duplication

auth/aws EC2 login tests had the same flow duplicated a few times, so
refactoring to reduce duplication

* Add tests for aws auth explicit wildcard constraints

* Remove implicit prefix matching from AWS auth backend

In the aws auth backend, bound_iam_role_arn and
bound_iam_instance_profile_arn were ALWAYS prefix matched, and there was
no way to opt out of this implicit prefix matching. This now makes the
implicit prefix matching an explicit opt-in feature by requiring users
to specify a * at the end of an ARN if they want the prefix matching.
This commit is contained in:
Joel Thompson
2018-03-17 19:24:49 -06:00
committed by Jeff Mitchell
parent aabccd5fd2
commit 29551c0b1b
5 changed files with 120 additions and 64 deletions

View File

@@ -1084,12 +1084,12 @@ func TestBackendAcc_LoginWithInstanceIdentityDocAndWhitelistIdentity(t *testing.
Data: loginInput,
}
// Place the wrong AMI ID in the role data.
// Baseline role data that should succeed permit login
data := map[string]interface{}{
"auth_type": "ec2",
"policies": "root",
"max_ttl": "120s",
"bound_ami_id": []string{"wrong_ami_id", "wrong_ami_id2"},
"bound_ami_id": []string{"wrong_ami_id", amiID, "wrong_ami_id2"},
"bound_account_id": accountID,
"bound_iam_role_arn": iamARN,
"bound_ec2_instance_id": []string{parsedIdentityDoc.InstanceID, "i-1234567"},
@@ -1102,63 +1102,64 @@ func TestBackendAcc_LoginWithInstanceIdentityDocAndWhitelistIdentity(t *testing.
Data: data,
}
// Save the role with wrong AMI ID
resp, err := b.HandleRequest(context.Background(), roleReq)
if err != nil && (resp != nil && resp.IsError()) {
t.Fatalf("bad: resp: %#v\nerr:%v", resp, err)
updateRoleExpectLoginFail := func(roleRequest, loginRequest *logical.Request) error {
resp, err := b.HandleRequest(context.Background(), roleRequest)
if err != nil || (resp != nil && resp.IsError()) {
return fmt.Errorf("bad: failed to create role: resp:%#v\nerr:%v", resp, err)
}
resp, err = b.HandleRequest(context.Background(), loginRequest)
if err != nil || resp == nil || (resp != nil && !resp.IsError()) {
return fmt.Errorf("bad: expected login failure: resp:%#v\nerr:%v", resp, err)
}
return nil
}
// Expect failure when tried to login with wrong AMI ID
resp, err = b.HandleRequest(context.Background(), loginRequest)
if err != nil || resp == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad: expected error response: resp:%#v\nerr:%v", resp, err)
// Test a role with the wrong AMI ID
data["bound_ami_id"] = []string{"ami-1234567", "ami-7654321"}
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// Place the correct AMI ID in one of the values, but make the AccountID wrong
roleReq.Operation = logical.UpdateOperation
// Place the correct AMI ID in one of the values, but make the AccountID wrong
data["bound_ami_id"] = []string{"wrong_ami_id_1", amiID, "wrong_ami_id_2"}
data["bound_account_id"] = []string{"wrong-account-id", "wrong-account-id-2"}
resp, err = b.HandleRequest(context.Background(), roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: failed to create role: resp:%#v\nerr:%v", resp, err)
}
// Expect failure when tried to login with incorrect AccountID
resp, err = b.HandleRequest(context.Background(), loginRequest)
if err != nil || resp == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad: expected error response: resp:%#v\nerr:%v", resp, err)
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// Place the correct AccountID in one of the values, but make the wrong IAMRoleARN
data["bound_account_id"] = []string{"wrong-account-id-1", accountID, "wrong-account-id-2"}
data["bound_iam_role_arn"] = []string{"wrong_iam_role_arn", "wrong_iam_role_arn_2"}
resp, err = b.HandleRequest(context.Background(), roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: failed to create role: resp:%#v\nerr:%v", resp, err)
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// Attempt to login and expect a fail because IAM Role ARN is wrong
resp, err = b.HandleRequest(context.Background(), loginRequest)
if err != nil || resp == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad: expected error response: resp:%#v\nerr:%v", resp, err)
}
// place a correct IAM role ARN
// Place correct IAM role ARN, but incorrect instance ID
data["bound_iam_role_arn"] = []string{"wrong_iam_role_arn_1", iamARN, "wrong_iam_role_arn_2"}
data["bound_ec2_instance_id"] = "i-1234567"
resp, err = b.HandleRequest(context.Background(), roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: failed to create role: resp:%#v\nerr:%v", resp, err)
}
// Attempt to login and expect a fail because instance ID is wrong
resp, err = b.HandleRequest(context.Background(), loginRequest)
if err != nil || resp == nil || (resp != nil && !resp.IsError()) {
t.Fatalf("bad: expected error response: resp:%#v\nerr:%v", resp, err)
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// place a correct EC2 Instance ID
// Place correct instance ID, but substring of the IAM role ARN
data["bound_ec2_instance_id"] = []string{parsedIdentityDoc.InstanceID, "i-1234567"}
resp, err = b.HandleRequest(context.Background(), roleReq)
data["bound_iam_role_arn"] = []string{"wrong_iam_role_arn", iamARN[:len(iamARN)-2], "wrong_iam_role_arn_2"}
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// place a wildcard in the middle of the role ARN
// The :31 gets arn:aws:iam::123456789012:role/
// This test relies on the role name having at least two characters
data["bound_iam_role_arn"] = []string{"wrong_iam_role_arn", fmt.Sprintf("%s*%s", iamARN[:31], iamARN[32:])}
if err := updateRoleExpectLoginFail(roleReq, loginRequest); err != nil {
t.Fatal(err)
}
// globbed IAM role ARN
data["bound_iam_role_arn"] = []string{"wrong_iam_role_arn_1", fmt.Sprintf("%s*", iamARN[:len(iamARN)-2]), "wrong_iam_role_arn_2"}
resp, err := b.HandleRequest(context.Background(), roleReq)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("bad: failed to create role: resp:%#v\nerr:%v", resp, err)
}