github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/auth_helpers_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"testing"
    12  
    13  	"github.com/aws/aws-sdk-go/aws/awserr"
    14  	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
    15  	"github.com/aws/aws-sdk-go/service/iam"
    16  	"github.com/aws/aws-sdk-go/service/sts"
    17  )
    18  
    19  func TestAWSGetAccountInfo_shouldBeValid_fromEC2Role(t *testing.T) {
    20  	resetEnv := unsetEnv(t)
    21  	defer resetEnv()
    22  	// capture the test server's close method, to call after the test returns
    23  	awsTs := awsEnv(t)
    24  	defer awsTs()
    25  
    26  	closeEmpty, emptySess, err := getMockedAwsApiSession("zero", []*awsMockEndpoint{})
    27  	defer closeEmpty()
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	iamConn := iam.New(emptySess)
    33  	stsConn := sts.New(emptySess)
    34  
    35  	part, id, err := GetAccountInfo(iamConn, stsConn, ec2rolecreds.ProviderName)
    36  	if err != nil {
    37  		t.Fatalf("Getting account ID from EC2 metadata API failed: %s", err)
    38  	}
    39  
    40  	expectedPart := "aws"
    41  	if part != expectedPart {
    42  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
    43  	}
    44  
    45  	expectedAccountId := "123456789013"
    46  	if id != expectedAccountId {
    47  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
    48  	}
    49  }
    50  
    51  func TestAWSGetAccountInfo_shouldBeValid_EC2RoleHasPriority(t *testing.T) {
    52  	resetEnv := unsetEnv(t)
    53  	defer resetEnv()
    54  	// capture the test server's close method, to call after the test returns
    55  	awsTs := awsEnv(t)
    56  	defer awsTs()
    57  
    58  	iamEndpoints := []*awsMockEndpoint{
    59  		{
    60  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
    61  			Response: &awsMockResponse{200, iamResponse_GetUser_valid, "text/xml"},
    62  		},
    63  	}
    64  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
    65  	defer closeIam()
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	iamConn := iam.New(iamSess)
    70  	closeSts, stsSess, err := getMockedAwsApiSession("STS", []*awsMockEndpoint{})
    71  	defer closeSts()
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	stsConn := sts.New(stsSess)
    76  
    77  	part, id, err := GetAccountInfo(iamConn, stsConn, ec2rolecreds.ProviderName)
    78  	if err != nil {
    79  		t.Fatalf("Getting account ID from EC2 metadata API failed: %s", err)
    80  	}
    81  
    82  	expectedPart := "aws"
    83  	if part != expectedPart {
    84  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
    85  	}
    86  
    87  	expectedAccountId := "123456789013"
    88  	if id != expectedAccountId {
    89  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
    90  	}
    91  }
    92  
    93  func TestAWSGetAccountInfo_shouldBeValid_fromIamUser(t *testing.T) {
    94  	iamEndpoints := []*awsMockEndpoint{
    95  		{
    96  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
    97  			Response: &awsMockResponse{200, iamResponse_GetUser_valid, "text/xml"},
    98  		},
    99  	}
   100  
   101  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
   102  	defer closeIam()
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	closeSts, stsSess, err := getMockedAwsApiSession("STS", []*awsMockEndpoint{})
   107  	defer closeSts()
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	iamConn := iam.New(iamSess)
   113  	stsConn := sts.New(stsSess)
   114  
   115  	part, id, err := GetAccountInfo(iamConn, stsConn, "")
   116  	if err != nil {
   117  		t.Fatalf("Getting account ID via GetUser failed: %s", err)
   118  	}
   119  
   120  	expectedPart := "aws"
   121  	if part != expectedPart {
   122  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
   123  	}
   124  
   125  	expectedAccountId := "123456789012"
   126  	if id != expectedAccountId {
   127  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
   128  	}
   129  }
   130  
   131  func TestAWSGetAccountInfo_shouldBeValid_fromGetCallerIdentity(t *testing.T) {
   132  	iamEndpoints := []*awsMockEndpoint{
   133  		{
   134  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
   135  			Response: &awsMockResponse{403, iamResponse_GetUser_unauthorized, "text/xml"},
   136  		},
   137  	}
   138  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
   139  	defer closeIam()
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	stsEndpoints := []*awsMockEndpoint{
   145  		{
   146  			Request:  &awsMockRequest{"POST", "/", "Action=GetCallerIdentity&Version=2011-06-15"},
   147  			Response: &awsMockResponse{200, stsResponse_GetCallerIdentity_valid, "text/xml"},
   148  		},
   149  	}
   150  	closeSts, stsSess, err := getMockedAwsApiSession("STS", stsEndpoints)
   151  	defer closeSts()
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	iamConn := iam.New(iamSess)
   157  	stsConn := sts.New(stsSess)
   158  
   159  	part, id, err := GetAccountInfo(iamConn, stsConn, "")
   160  	if err != nil {
   161  		t.Fatalf("Getting account ID via GetUser failed: %s", err)
   162  	}
   163  
   164  	expectedPart := "aws"
   165  	if part != expectedPart {
   166  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
   167  	}
   168  
   169  	expectedAccountId := "123456789012"
   170  	if id != expectedAccountId {
   171  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
   172  	}
   173  }
   174  
   175  func TestAWSGetAccountInfo_shouldBeValid_fromIamListRoles(t *testing.T) {
   176  	iamEndpoints := []*awsMockEndpoint{
   177  		{
   178  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
   179  			Response: &awsMockResponse{403, iamResponse_GetUser_unauthorized, "text/xml"},
   180  		},
   181  		{
   182  			Request:  &awsMockRequest{"POST", "/", "Action=ListRoles&MaxItems=1&Version=2010-05-08"},
   183  			Response: &awsMockResponse{200, iamResponse_ListRoles_valid, "text/xml"},
   184  		},
   185  	}
   186  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
   187  	defer closeIam()
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  
   192  	stsEndpoints := []*awsMockEndpoint{
   193  		{
   194  			Request:  &awsMockRequest{"POST", "/", "Action=GetCallerIdentity&Version=2011-06-15"},
   195  			Response: &awsMockResponse{403, stsResponse_GetCallerIdentity_unauthorized, "text/xml"},
   196  		},
   197  	}
   198  	closeSts, stsSess, err := getMockedAwsApiSession("STS", stsEndpoints)
   199  	defer closeSts()
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	iamConn := iam.New(iamSess)
   205  	stsConn := sts.New(stsSess)
   206  
   207  	part, id, err := GetAccountInfo(iamConn, stsConn, "")
   208  	if err != nil {
   209  		t.Fatalf("Getting account ID via ListRoles failed: %s", err)
   210  	}
   211  
   212  	expectedPart := "aws"
   213  	if part != expectedPart {
   214  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
   215  	}
   216  
   217  	expectedAccountId := "123456789012"
   218  	if id != expectedAccountId {
   219  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
   220  	}
   221  }
   222  
   223  func TestAWSGetAccountInfo_shouldBeValid_federatedRole(t *testing.T) {
   224  	iamEndpoints := []*awsMockEndpoint{
   225  		{
   226  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
   227  			Response: &awsMockResponse{400, iamResponse_GetUser_federatedFailure, "text/xml"},
   228  		},
   229  		{
   230  			Request:  &awsMockRequest{"POST", "/", "Action=ListRoles&MaxItems=1&Version=2010-05-08"},
   231  			Response: &awsMockResponse{200, iamResponse_ListRoles_valid, "text/xml"},
   232  		},
   233  	}
   234  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
   235  	defer closeIam()
   236  	if err != nil {
   237  		t.Fatal(err)
   238  	}
   239  
   240  	closeSts, stsSess, err := getMockedAwsApiSession("STS", []*awsMockEndpoint{})
   241  	defer closeSts()
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	iamConn := iam.New(iamSess)
   247  	stsConn := sts.New(stsSess)
   248  
   249  	part, id, err := GetAccountInfo(iamConn, stsConn, "")
   250  	if err != nil {
   251  		t.Fatalf("Getting account ID via ListRoles failed: %s", err)
   252  	}
   253  
   254  	expectedPart := "aws"
   255  	if part != expectedPart {
   256  		t.Fatalf("Expected partition: %s, given: %s", expectedPart, part)
   257  	}
   258  
   259  	expectedAccountId := "123456789012"
   260  	if id != expectedAccountId {
   261  		t.Fatalf("Expected account ID: %s, given: %s", expectedAccountId, id)
   262  	}
   263  }
   264  
   265  func TestAWSGetAccountInfo_shouldError_unauthorizedFromIam(t *testing.T) {
   266  	iamEndpoints := []*awsMockEndpoint{
   267  		{
   268  			Request:  &awsMockRequest{"POST", "/", "Action=GetUser&Version=2010-05-08"},
   269  			Response: &awsMockResponse{403, iamResponse_GetUser_unauthorized, "text/xml"},
   270  		},
   271  		{
   272  			Request:  &awsMockRequest{"POST", "/", "Action=ListRoles&MaxItems=1&Version=2010-05-08"},
   273  			Response: &awsMockResponse{403, iamResponse_ListRoles_unauthorized, "text/xml"},
   274  		},
   275  	}
   276  	closeIam, iamSess, err := getMockedAwsApiSession("IAM", iamEndpoints)
   277  	defer closeIam()
   278  	if err != nil {
   279  		t.Fatal(err)
   280  	}
   281  
   282  	closeSts, stsSess, err := getMockedAwsApiSession("STS", []*awsMockEndpoint{})
   283  	defer closeSts()
   284  	if err != nil {
   285  		t.Fatal(err)
   286  	}
   287  
   288  	iamConn := iam.New(iamSess)
   289  	stsConn := sts.New(stsSess)
   290  
   291  	part, id, err := GetAccountInfo(iamConn, stsConn, "")
   292  	if err == nil {
   293  		t.Fatal("Expected error when getting account ID")
   294  	}
   295  
   296  	if part != "" {
   297  		t.Fatalf("Expected no partition, given: %s", part)
   298  	}
   299  
   300  	if id != "" {
   301  		t.Fatalf("Expected no account ID, given: %s", id)
   302  	}
   303  }
   304  
   305  func TestAWSParseAccountInfoFromArn(t *testing.T) {
   306  	validArn := "arn:aws:iam::101636750127:instance-profile/aws-elasticbeanstalk-ec2-role"
   307  	expectedPart := "aws"
   308  	expectedId := "101636750127"
   309  	part, id, err := parseAccountInfoFromArn(validArn)
   310  	if err != nil {
   311  		t.Fatalf("Expected no error when parsing valid ARN: %s", err)
   312  	}
   313  	if part != expectedPart {
   314  		t.Fatalf("Parsed part doesn't match with expected (%q != %q)", part, expectedPart)
   315  	}
   316  	if id != expectedId {
   317  		t.Fatalf("Parsed id doesn't match with expected (%q != %q)", id, expectedId)
   318  	}
   319  
   320  	invalidArn := "blablah"
   321  	part, id, err = parseAccountInfoFromArn(invalidArn)
   322  	if err == nil {
   323  		t.Fatalf("Expected error when parsing invalid ARN (%q)", invalidArn)
   324  	}
   325  }
   326  
   327  func TestAWSGetCredentials_shouldError(t *testing.T) {
   328  	resetEnv := unsetEnv(t)
   329  	defer resetEnv()
   330  	cfg := Config{}
   331  
   332  	c, err := GetCredentials(&cfg)
   333  	if awsErr, ok := err.(awserr.Error); ok {
   334  		if awsErr.Code() != "NoCredentialProviders" {
   335  			t.Fatal("Expected NoCredentialProviders error")
   336  		}
   337  	}
   338  	_, err = c.Get()
   339  	if awsErr, ok := err.(awserr.Error); ok {
   340  		if awsErr.Code() != "NoCredentialProviders" {
   341  			t.Fatal("Expected NoCredentialProviders error")
   342  		}
   343  	}
   344  	if err == nil {
   345  		t.Fatal("Expected an error with empty env, keys, and IAM in AWS Config")
   346  	}
   347  }
   348  
   349  func TestAWSGetCredentials_shouldBeStatic(t *testing.T) {
   350  	simple := []struct {
   351  		Key, Secret, Token string
   352  	}{
   353  		{
   354  			Key:    "test",
   355  			Secret: "secret",
   356  		}, {
   357  			Key:    "test",
   358  			Secret: "test",
   359  			Token:  "test",
   360  		},
   361  	}
   362  
   363  	for _, c := range simple {
   364  		cfg := Config{
   365  			AccessKey: c.Key,
   366  			SecretKey: c.Secret,
   367  			Token:     c.Token,
   368  		}
   369  
   370  		creds, err := GetCredentials(&cfg)
   371  		if err != nil {
   372  			t.Fatalf("Error gettings creds: %s", err)
   373  		}
   374  		if creds == nil {
   375  			t.Fatal("Expected a static creds provider to be returned")
   376  		}
   377  
   378  		v, err := creds.Get()
   379  		if err != nil {
   380  			t.Fatalf("Error gettings creds: %s", err)
   381  		}
   382  
   383  		if v.AccessKeyID != c.Key {
   384  			t.Fatalf("AccessKeyID mismatch, expected: (%s), got (%s)", c.Key, v.AccessKeyID)
   385  		}
   386  		if v.SecretAccessKey != c.Secret {
   387  			t.Fatalf("SecretAccessKey mismatch, expected: (%s), got (%s)", c.Secret, v.SecretAccessKey)
   388  		}
   389  		if v.SessionToken != c.Token {
   390  			t.Fatalf("SessionToken mismatch, expected: (%s), got (%s)", c.Token, v.SessionToken)
   391  		}
   392  	}
   393  }
   394  
   395  // TestAWSGetCredentials_shouldIAM is designed to test the scenario of running Terraform
   396  // from an EC2 instance, without environment variables or manually supplied
   397  // credentials.
   398  func TestAWSGetCredentials_shouldIAM(t *testing.T) {
   399  	// clear AWS_* environment variables
   400  	resetEnv := unsetEnv(t)
   401  	defer resetEnv()
   402  
   403  	// capture the test server's close method, to call after the test returns
   404  	ts := awsEnv(t)
   405  	defer ts()
   406  
   407  	// An empty config, no key supplied
   408  	cfg := Config{}
   409  
   410  	creds, err := GetCredentials(&cfg)
   411  	if err != nil {
   412  		t.Fatalf("Error gettings creds: %s", err)
   413  	}
   414  	if creds == nil {
   415  		t.Fatal("Expected a static creds provider to be returned")
   416  	}
   417  
   418  	v, err := creds.Get()
   419  	if err != nil {
   420  		t.Fatalf("Error gettings creds: %s", err)
   421  	}
   422  	if v.AccessKeyID != "somekey" {
   423  		t.Fatalf("AccessKeyID mismatch, expected: (somekey), got (%s)", v.AccessKeyID)
   424  	}
   425  	if v.SecretAccessKey != "somesecret" {
   426  		t.Fatalf("SecretAccessKey mismatch, expected: (somesecret), got (%s)", v.SecretAccessKey)
   427  	}
   428  	if v.SessionToken != "sometoken" {
   429  		t.Fatalf("SessionToken mismatch, expected: (sometoken), got (%s)", v.SessionToken)
   430  	}
   431  }
   432  
   433  // TestAWSGetCredentials_shouldIAM is designed to test the scenario of running Terraform
   434  // from an EC2 instance, without environment variables or manually supplied
   435  // credentials.
   436  func TestAWSGetCredentials_shouldIgnoreIAM(t *testing.T) {
   437  	resetEnv := unsetEnv(t)
   438  	defer resetEnv()
   439  	// capture the test server's close method, to call after the test returns
   440  	ts := awsEnv(t)
   441  	defer ts()
   442  	simple := []struct {
   443  		Key, Secret, Token string
   444  	}{
   445  		{
   446  			Key:    "test",
   447  			Secret: "secret",
   448  		}, {
   449  			Key:    "test",
   450  			Secret: "test",
   451  			Token:  "test",
   452  		},
   453  	}
   454  
   455  	for _, c := range simple {
   456  		cfg := Config{
   457  			AccessKey: c.Key,
   458  			SecretKey: c.Secret,
   459  			Token:     c.Token,
   460  		}
   461  
   462  		creds, err := GetCredentials(&cfg)
   463  		if err != nil {
   464  			t.Fatalf("Error gettings creds: %s", err)
   465  		}
   466  		if creds == nil {
   467  			t.Fatal("Expected a static creds provider to be returned")
   468  		}
   469  
   470  		v, err := creds.Get()
   471  		if err != nil {
   472  			t.Fatalf("Error gettings creds: %s", err)
   473  		}
   474  		if v.AccessKeyID != c.Key {
   475  			t.Fatalf("AccessKeyID mismatch, expected: (%s), got (%s)", c.Key, v.AccessKeyID)
   476  		}
   477  		if v.SecretAccessKey != c.Secret {
   478  			t.Fatalf("SecretAccessKey mismatch, expected: (%s), got (%s)", c.Secret, v.SecretAccessKey)
   479  		}
   480  		if v.SessionToken != c.Token {
   481  			t.Fatalf("SessionToken mismatch, expected: (%s), got (%s)", c.Token, v.SessionToken)
   482  		}
   483  	}
   484  }
   485  
   486  func TestAWSGetCredentials_shouldErrorWithInvalidEndpoint(t *testing.T) {
   487  	resetEnv := unsetEnv(t)
   488  	defer resetEnv()
   489  	// capture the test server's close method, to call after the test returns
   490  	ts := invalidAwsEnv(t)
   491  	defer ts()
   492  
   493  	creds, err := GetCredentials(&Config{})
   494  	if err != nil {
   495  		t.Fatalf("Error gettings creds: %s", err)
   496  	}
   497  	if creds == nil {
   498  		t.Fatal("Expected a static creds provider to be returned")
   499  	}
   500  
   501  	v, err := creds.Get()
   502  	if err == nil {
   503  		t.Fatal("Expected error returned when getting creds w/ invalid EC2 endpoint")
   504  	}
   505  
   506  	if v.ProviderName != "" {
   507  		t.Fatalf("Expected provider name to be empty, %q given", v.ProviderName)
   508  	}
   509  }
   510  
   511  func TestAWSGetCredentials_shouldIgnoreInvalidEndpoint(t *testing.T) {
   512  	resetEnv := unsetEnv(t)
   513  	defer resetEnv()
   514  	// capture the test server's close method, to call after the test returns
   515  	ts := invalidAwsEnv(t)
   516  	defer ts()
   517  
   518  	creds, err := GetCredentials(&Config{AccessKey: "accessKey", SecretKey: "secretKey"})
   519  	if err != nil {
   520  		t.Fatalf("Error gettings creds: %s", err)
   521  	}
   522  	v, err := creds.Get()
   523  	if err != nil {
   524  		t.Fatalf("Getting static credentials w/ invalid EC2 endpoint failed: %s", err)
   525  	}
   526  	if creds == nil {
   527  		t.Fatal("Expected a static creds provider to be returned")
   528  	}
   529  
   530  	if v.ProviderName != "StaticProvider" {
   531  		t.Fatalf("Expected provider name to be %q, %q given", "StaticProvider", v.ProviderName)
   532  	}
   533  
   534  	if v.AccessKeyID != "accessKey" {
   535  		t.Fatalf("Static Access Key %q doesn't match: %s", "accessKey", v.AccessKeyID)
   536  	}
   537  
   538  	if v.SecretAccessKey != "secretKey" {
   539  		t.Fatalf("Static Secret Key %q doesn't match: %s", "secretKey", v.SecretAccessKey)
   540  	}
   541  }
   542  
   543  func TestAWSGetCredentials_shouldCatchEC2RoleProvider(t *testing.T) {
   544  	resetEnv := unsetEnv(t)
   545  	defer resetEnv()
   546  	// capture the test server's close method, to call after the test returns
   547  	ts := awsEnv(t)
   548  	defer ts()
   549  
   550  	creds, err := GetCredentials(&Config{})
   551  	if err != nil {
   552  		t.Fatalf("Error gettings creds: %s", err)
   553  	}
   554  	if creds == nil {
   555  		t.Fatal("Expected an EC2Role creds provider to be returned")
   556  	}
   557  
   558  	v, err := creds.Get()
   559  	if err != nil {
   560  		t.Fatalf("Expected no error when getting creds: %s", err)
   561  	}
   562  	expectedProvider := "EC2RoleProvider"
   563  	if v.ProviderName != expectedProvider {
   564  		t.Fatalf("Expected provider name to be %q, %q given",
   565  			expectedProvider, v.ProviderName)
   566  	}
   567  }
   568  
   569  var credentialsFileContents = `[myprofile]
   570  aws_access_key_id = accesskey
   571  aws_secret_access_key = secretkey
   572  `
   573  
   574  func TestAWSGetCredentials_shouldBeShared(t *testing.T) {
   575  	file, err := ioutil.TempFile(os.TempDir(), "terraform_aws_cred")
   576  	if err != nil {
   577  		t.Fatalf("Error writing temporary credentials file: %s", err)
   578  	}
   579  	_, err = file.WriteString(credentialsFileContents)
   580  	if err != nil {
   581  		t.Fatalf("Error writing temporary credentials to file: %s", err)
   582  	}
   583  	err = file.Close()
   584  	if err != nil {
   585  		t.Fatalf("Error closing temporary credentials file: %s", err)
   586  	}
   587  
   588  	defer os.Remove(file.Name())
   589  
   590  	resetEnv := unsetEnv(t)
   591  	defer resetEnv()
   592  
   593  	if err := os.Setenv("AWS_PROFILE", "myprofile"); err != nil {
   594  		t.Fatalf("Error resetting env var AWS_PROFILE: %s", err)
   595  	}
   596  	if err := os.Setenv("AWS_SHARED_CREDENTIALS_FILE", file.Name()); err != nil {
   597  		t.Fatalf("Error resetting env var AWS_SHARED_CREDENTIALS_FILE: %s", err)
   598  	}
   599  
   600  	creds, err := GetCredentials(&Config{Profile: "myprofile", CredsFilename: file.Name()})
   601  	if err != nil {
   602  		t.Fatalf("Error gettings creds: %s", err)
   603  	}
   604  	if creds == nil {
   605  		t.Fatal("Expected a provider chain to be returned")
   606  	}
   607  
   608  	v, err := creds.Get()
   609  	if err != nil {
   610  		t.Fatalf("Error gettings creds: %s", err)
   611  	}
   612  
   613  	if v.AccessKeyID != "accesskey" {
   614  		t.Fatalf("AccessKeyID mismatch, expected (%s), got (%s)", "accesskey", v.AccessKeyID)
   615  	}
   616  
   617  	if v.SecretAccessKey != "secretkey" {
   618  		t.Fatalf("SecretAccessKey mismatch, expected (%s), got (%s)", "accesskey", v.AccessKeyID)
   619  	}
   620  }
   621  
   622  func TestAWSGetCredentials_shouldBeENV(t *testing.T) {
   623  	// need to set the environment variables to a dummy string, as we don't know
   624  	// what they may be at runtime without hardcoding here
   625  	s := "some_env"
   626  	resetEnv := setEnv(s, t)
   627  
   628  	defer resetEnv()
   629  
   630  	cfg := Config{}
   631  	creds, err := GetCredentials(&cfg)
   632  	if err != nil {
   633  		t.Fatalf("Error gettings creds: %s", err)
   634  	}
   635  	if creds == nil {
   636  		t.Fatalf("Expected a static creds provider to be returned")
   637  	}
   638  
   639  	v, err := creds.Get()
   640  	if err != nil {
   641  		t.Fatalf("Error gettings creds: %s", err)
   642  	}
   643  	if v.AccessKeyID != s {
   644  		t.Fatalf("AccessKeyID mismatch, expected: (%s), got (%s)", s, v.AccessKeyID)
   645  	}
   646  	if v.SecretAccessKey != s {
   647  		t.Fatalf("SecretAccessKey mismatch, expected: (%s), got (%s)", s, v.SecretAccessKey)
   648  	}
   649  	if v.SessionToken != s {
   650  		t.Fatalf("SessionToken mismatch, expected: (%s), got (%s)", s, v.SessionToken)
   651  	}
   652  }
   653  
   654  // unsetEnv unsets environment variables for testing a "clean slate" with no
   655  // credentials in the environment
   656  func unsetEnv(t *testing.T) func() {
   657  	// Grab any existing AWS keys and preserve. In some tests we'll unset these, so
   658  	// we need to have them and restore them after
   659  	e := getEnv()
   660  	if err := os.Unsetenv("AWS_ACCESS_KEY_ID"); err != nil {
   661  		t.Fatalf("Error unsetting env var AWS_ACCESS_KEY_ID: %s", err)
   662  	}
   663  	if err := os.Unsetenv("AWS_SECRET_ACCESS_KEY"); err != nil {
   664  		t.Fatalf("Error unsetting env var AWS_SECRET_ACCESS_KEY: %s", err)
   665  	}
   666  	if err := os.Unsetenv("AWS_SESSION_TOKEN"); err != nil {
   667  		t.Fatalf("Error unsetting env var AWS_SESSION_TOKEN: %s", err)
   668  	}
   669  	if err := os.Unsetenv("AWS_PROFILE"); err != nil {
   670  		t.Fatalf("Error unsetting env var AWS_PROFILE: %s", err)
   671  	}
   672  	if err := os.Unsetenv("AWS_SHARED_CREDENTIALS_FILE"); err != nil {
   673  		t.Fatalf("Error unsetting env var AWS_SHARED_CREDENTIALS_FILE: %s", err)
   674  	}
   675  
   676  	return func() {
   677  		// re-set all the envs we unset above
   678  		if err := os.Setenv("AWS_ACCESS_KEY_ID", e.Key); err != nil {
   679  			t.Fatalf("Error resetting env var AWS_ACCESS_KEY_ID: %s", err)
   680  		}
   681  		if err := os.Setenv("AWS_SECRET_ACCESS_KEY", e.Secret); err != nil {
   682  			t.Fatalf("Error resetting env var AWS_SECRET_ACCESS_KEY: %s", err)
   683  		}
   684  		if err := os.Setenv("AWS_SESSION_TOKEN", e.Token); err != nil {
   685  			t.Fatalf("Error resetting env var AWS_SESSION_TOKEN: %s", err)
   686  		}
   687  		if err := os.Setenv("AWS_PROFILE", e.Profile); err != nil {
   688  			t.Fatalf("Error resetting env var AWS_PROFILE: %s", err)
   689  		}
   690  		if err := os.Setenv("AWS_SHARED_CREDENTIALS_FILE", e.CredsFilename); err != nil {
   691  			t.Fatalf("Error resetting env var AWS_SHARED_CREDENTIALS_FILE: %s", err)
   692  		}
   693  	}
   694  }
   695  
   696  func setEnv(s string, t *testing.T) func() {
   697  	e := getEnv()
   698  	// Set all the envs to a dummy value
   699  	if err := os.Setenv("AWS_ACCESS_KEY_ID", s); err != nil {
   700  		t.Fatalf("Error setting env var AWS_ACCESS_KEY_ID: %s", err)
   701  	}
   702  	if err := os.Setenv("AWS_SECRET_ACCESS_KEY", s); err != nil {
   703  		t.Fatalf("Error setting env var AWS_SECRET_ACCESS_KEY: %s", err)
   704  	}
   705  	if err := os.Setenv("AWS_SESSION_TOKEN", s); err != nil {
   706  		t.Fatalf("Error setting env var AWS_SESSION_TOKEN: %s", err)
   707  	}
   708  	if err := os.Setenv("AWS_PROFILE", s); err != nil {
   709  		t.Fatalf("Error setting env var AWS_PROFILE: %s", err)
   710  	}
   711  	if err := os.Setenv("AWS_SHARED_CREDENTIALS_FILE", s); err != nil {
   712  		t.Fatalf("Error setting env var AWS_SHARED_CREDENTIALS_FLE: %s", err)
   713  	}
   714  
   715  	return func() {
   716  		// re-set all the envs we unset above
   717  		if err := os.Setenv("AWS_ACCESS_KEY_ID", e.Key); err != nil {
   718  			t.Fatalf("Error resetting env var AWS_ACCESS_KEY_ID: %s", err)
   719  		}
   720  		if err := os.Setenv("AWS_SECRET_ACCESS_KEY", e.Secret); err != nil {
   721  			t.Fatalf("Error resetting env var AWS_SECRET_ACCESS_KEY: %s", err)
   722  		}
   723  		if err := os.Setenv("AWS_SESSION_TOKEN", e.Token); err != nil {
   724  			t.Fatalf("Error resetting env var AWS_SESSION_TOKEN: %s", err)
   725  		}
   726  		if err := os.Setenv("AWS_PROFILE", e.Profile); err != nil {
   727  			t.Fatalf("Error setting env var AWS_PROFILE: %s", err)
   728  		}
   729  		if err := os.Setenv("AWS_SHARED_CREDENTIALS_FILE", s); err != nil {
   730  			t.Fatalf("Error setting env var AWS_SHARED_CREDENTIALS_FLE: %s", err)
   731  		}
   732  	}
   733  }
   734  
   735  // awsEnv establishes a httptest server to mock out the internal AWS Metadata
   736  // service. IAM Credentials are retrieved by the EC2RoleProvider, which makes
   737  // API calls to this internal URL. By replacing the server with a test server,
   738  // we can simulate an AWS environment
   739  func awsEnv(t *testing.T) func() {
   740  	routes := routes{}
   741  	if err := json.Unmarshal([]byte(metadataApiRoutes), &routes); err != nil {
   742  		t.Fatalf("Failed to unmarshal JSON in AWS ENV test: %s", err)
   743  	}
   744  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   745  		w.Header().Set("Content-Type", "text/plain")
   746  		w.Header().Add("Server", "MockEC2")
   747  		log.Printf("[DEBUG] Mocker server received request to %q", r.RequestURI)
   748  		for _, e := range routes.Endpoints {
   749  			if r.RequestURI == e.Uri {
   750  				fmt.Fprintln(w, e.Body)
   751  				w.WriteHeader(200)
   752  				return
   753  			}
   754  		}
   755  		w.WriteHeader(400)
   756  	}))
   757  
   758  	os.Setenv("AWS_METADATA_URL", ts.URL+"/latest")
   759  	return ts.Close
   760  }
   761  
   762  // invalidAwsEnv establishes a httptest server to simulate behaviour
   763  // when endpoint doesn't respond as expected
   764  func invalidAwsEnv(t *testing.T) func() {
   765  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   766  		w.WriteHeader(400)
   767  	}))
   768  
   769  	os.Setenv("AWS_METADATA_URL", ts.URL+"/latest")
   770  	return ts.Close
   771  }
   772  
   773  func getEnv() *currentEnv {
   774  	// Grab any existing AWS keys and preserve. In some tests we'll unset these, so
   775  	// we need to have them and restore them after
   776  	return &currentEnv{
   777  		Key:           os.Getenv("AWS_ACCESS_KEY_ID"),
   778  		Secret:        os.Getenv("AWS_SECRET_ACCESS_KEY"),
   779  		Token:         os.Getenv("AWS_SESSION_TOKEN"),
   780  		Profile:       os.Getenv("AWS_PROFILE"),
   781  		CredsFilename: os.Getenv("AWS_SHARED_CREDENTIALS_FILE"),
   782  	}
   783  }
   784  
   785  // struct to preserve the current environment
   786  type currentEnv struct {
   787  	Key, Secret, Token, Profile, CredsFilename string
   788  }
   789  
   790  type routes struct {
   791  	Endpoints []*endpoint `json:"endpoints"`
   792  }
   793  type endpoint struct {
   794  	Uri  string `json:"uri"`
   795  	Body string `json:"body"`
   796  }
   797  
   798  const metadataApiRoutes = `
   799  {
   800    "endpoints": [
   801      {
   802        "uri": "/latest/meta-data/instance-id",
   803        "body": "mock-instance-id"
   804      },
   805      {
   806        "uri": "/latest/meta-data/iam/info",
   807        "body": "{\"Code\": \"Success\",\"LastUpdated\": \"2016-03-17T12:27:32Z\",\"InstanceProfileArn\": \"arn:aws:iam::123456789013:instance-profile/my-instance-profile\",\"InstanceProfileId\": \"AIPAABCDEFGHIJKLMN123\"}"
   808      },
   809      {
   810        "uri": "/latest/meta-data/iam/security-credentials",
   811        "body": "test_role"
   812      },
   813      {
   814        "uri": "/latest/meta-data/iam/security-credentials/test_role",
   815        "body": "{\"Code\":\"Success\",\"LastUpdated\":\"2015-12-11T17:17:25Z\",\"Type\":\"AWS-HMAC\",\"AccessKeyId\":\"somekey\",\"SecretAccessKey\":\"somesecret\",\"Token\":\"sometoken\"}"
   816      }
   817    ]
   818  }
   819  `
   820  
   821  const iamResponse_GetUser_valid = `<GetUserResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
   822    <GetUserResult>
   823      <User>
   824        <UserId>AIDACKCEVSQ6C2EXAMPLE</UserId>
   825        <Path>/division_abc/subdivision_xyz/</Path>
   826        <UserName>Bob</UserName>
   827        <Arn>arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob</Arn>
   828        <CreateDate>2013-10-02T17:01:44Z</CreateDate>
   829        <PasswordLastUsed>2014-10-10T14:37:51Z</PasswordLastUsed>
   830      </User>
   831    </GetUserResult>
   832    <ResponseMetadata>
   833      <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   834    </ResponseMetadata>
   835  </GetUserResponse>`
   836  
   837  const iamResponse_GetUser_unauthorized = `<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
   838    <Error>
   839      <Type>Sender</Type>
   840      <Code>AccessDenied</Code>
   841      <Message>User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: iam:GetUser on resource: arn:aws:iam::123456789012:user/Bob</Message>
   842    </Error>
   843    <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   844  </ErrorResponse>`
   845  
   846  const stsResponse_GetCallerIdentity_valid = `<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
   847    <GetCallerIdentityResult>
   848     <Arn>arn:aws:iam::123456789012:user/Alice</Arn>
   849      <UserId>AKIAI44QH8DHBEXAMPLE</UserId>
   850      <Account>123456789012</Account>
   851    </GetCallerIdentityResult>
   852    <ResponseMetadata>
   853      <RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
   854    </ResponseMetadata>
   855  </GetCallerIdentityResponse>`
   856  
   857  const stsResponse_GetCallerIdentity_unauthorized = `<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
   858    <Error>
   859      <Type>Sender</Type>
   860      <Code>AccessDenied</Code>
   861      <Message>User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: sts:GetCallerIdentity</Message>
   862    </Error>
   863    <RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
   864  </ErrorResponse>`
   865  
   866  const iamResponse_GetUser_federatedFailure = `<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
   867    <Error>
   868      <Type>Sender</Type>
   869      <Code>ValidationError</Code>
   870      <Message>Must specify userName when calling with non-User credentials</Message>
   871    </Error>
   872    <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   873  </ErrorResponse>`
   874  
   875  const iamResponse_ListRoles_valid = `<ListRolesResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
   876    <ListRolesResult>
   877      <IsTruncated>true</IsTruncated>
   878      <Marker>AWceSSsKsazQ4IEplT9o4hURCzBs00iavlEvEXAMPLE</Marker>
   879      <Roles>
   880        <member>
   881          <Path>/</Path>
   882          <AssumeRolePolicyDocument>%7B%22Version%22%3A%222008-10-17%22%2C%22Statement%22%3A%5B%7B%22Sid%22%3A%22%22%2C%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22ec2.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D</AssumeRolePolicyDocument>
   883          <RoleId>AROACKCEVSQ6C2EXAMPLE</RoleId>
   884          <RoleName>elasticbeanstalk-role</RoleName>
   885          <Arn>arn:aws:iam::123456789012:role/elasticbeanstalk-role</Arn>
   886          <CreateDate>2013-10-02T17:01:44Z</CreateDate>
   887        </member>
   888      </Roles>
   889    </ListRolesResult>
   890    <ResponseMetadata>
   891      <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   892    </ResponseMetadata>
   893  </ListRolesResponse>`
   894  
   895  const iamResponse_ListRoles_unauthorized = `<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
   896    <Error>
   897      <Type>Sender</Type>
   898      <Code>AccessDenied</Code>
   899      <Message>User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: iam:ListRoles on resource: arn:aws:iam::123456789012:role/</Message>
   900    </Error>
   901    <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   902  </ErrorResponse>`