Skip to content

Commit

Permalink
provider/aws: Make account ID validation work in EC2 instances
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Apr 3, 2016
1 parent 6b67dfd commit 9bca9db
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
19 changes: 18 additions & 1 deletion builtin/providers/aws/auth_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,24 @@ import (
)

func GetAccountId(iamconn *iam.IAM, authProviderName string) (string, error) {
// Try IAM GetUser
// If we have creds from instance profile, we can use metadata API
if authProviderName == ec2rolecreds.ProviderName {
log.Println("[DEBUG] Trying to get account ID via AWS Metadata API")

cfg := &aws.Config{}
setOptionalEndpoint(cfg)
metadataClient := ec2metadata.New(session.New(cfg))
info, err := metadataClient.IAMInfo()
if err != nil {
// This can be triggered when no IAM Role is assigned
// or AWS just happens to return invalid response
return "", fmt.Errorf("Failed getting EC2 IAM info: %s", err)
}

return parseAccountIdFromArn(info.InstanceProfileArn)
}

// Then try IAM GetUser
log.Println("[DEBUG] Trying to get account ID via iam:GetUser")
outUser, err := iamconn.GetUser(nil)
if err == nil {
Expand Down
54 changes: 54 additions & 0 deletions builtin/providers/aws/auth_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,60 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
awsCredentials "github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
)

func TestAWSGetAccountId_shouldBeValid_fromEC2Role(t *testing.T) {
resetEnv := unsetEnv(t)
defer resetEnv()
// capture the test server's close method, to call after the test returns
awsTs := awsEnv(t)
defer awsTs()

iamEndpoints := []*iamEndpoint{}
ts, iamConn := getMockedAwsIamApi(iamEndpoints)
defer ts()

id, err := GetAccountId(iamConn, ec2rolecreds.ProviderName)
if err != nil {
t.Fatalf("Getting account ID from EC2 metadata API failed: %s", err)
}

expectedAccountId := "123456789013"
if id != expectedAccountId {
t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
}
}

func TestAWSGetAccountId_shouldBeValid_EC2RoleHasPriority(t *testing.T) {
resetEnv := unsetEnv(t)
defer resetEnv()
// capture the test server's close method, to call after the test returns
awsTs := awsEnv(t)
defer awsTs()

iamEndpoints := []*iamEndpoint{
&iamEndpoint{
Request: &iamRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
Response: &iamResponse{200, iamResponse_GetUser_valid, "text/xml"},
},
}
ts, iamConn := getMockedAwsIamApi(iamEndpoints)
defer ts()

id, err := GetAccountId(iamConn, ec2rolecreds.ProviderName)
if err != nil {
t.Fatalf("Getting account ID from EC2 metadata API failed: %s", err)
}

expectedAccountId := "123456789013"
if id != expectedAccountId {
t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
}
}

func TestAWSGetAccountId_shouldBeValid_fromIamUser(t *testing.T) {
iamEndpoints := []*iamEndpoint{
&iamEndpoint{
Expand Down Expand Up @@ -610,6 +660,10 @@ const metadataApiRoutes = `
"uri": "/latest/meta-data/instance-id",
"body": "mock-instance-id"
},
{
"uri": "/latest/meta-data/iam/info",
"body": "{\"Code\": \"Success\",\"LastUpdated\": \"2016-03-17T12:27:32Z\",\"InstanceProfileArn\": \"arn:aws:iam::123456789013:instance-profile/my-instance-profile\",\"InstanceProfileId\": \"AIPAABCDEFGHIJKLMN123\"}"
},
{
"uri": "/latest/meta-data/iam/security-credentials",
"body": "test_role"
Expand Down

0 comments on commit 9bca9db

Please sign in to comment.