@@ -16,6 +16,7 @@ import (
1616 "time"
1717
1818 "github.com/aws/aws-sdk-go-v2/aws"
19+ "github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds"
1920 "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
2021 "github.com/aws/aws-sdk-go-v2/internal/awstesting"
2122 "github.com/aws/aws-sdk-go-v2/service/sso"
@@ -82,9 +83,15 @@ func setupCredentialsEndpoints() (aws.EndpointResolverWithOptions, func()) {
8283
8384 ec2MetadataServer := httptest .NewServer (http .HandlerFunc (
8485 func (w http.ResponseWriter , r * http.Request ) {
85- if r .URL .Path == "/latest/meta-data/iam/security-credentials/RoleName" {
86+ if r .URL .Path == "/latest/meta-data/iam/security-credentials-extended /RoleName" {
8687 w .Write ([]byte (ec2MetadataResponse ))
87- } else if r .URL .Path == "/latest/meta-data/iam/security-credentials/" {
88+ } else if r .URL .Path == "/latest/meta-data/iam/security-credentials-extended/LoadOptions" {
89+ w .Write ([]byte (ec2MetadataResponseLoadOptions ))
90+ } else if r .URL .Path == "/latest/meta-data/iam/security-credentials-extended/EnvCfg" {
91+ w .Write ([]byte (ec2MetadataResponseEnvCfg ))
92+ } else if r .URL .Path == "/latest/meta-data/iam/security-credentials-extended/SharedCfg" {
93+ w .Write ([]byte (ec2MetadataResponseSharedCfg ))
94+ } else if r .URL .Path == "/latest/meta-data/iam/security-credentials-extended/" {
8895 w .Write ([]byte ("RoleName" ))
8996 } else if r .URL .Path == "/latest/api/token" {
9097 header := w .Header ()
@@ -750,6 +757,103 @@ func TestResolveCredentialsEcsContainer(t *testing.T) {
750757
751758}
752759
760+ func TestResolveCredentialsEC2RoleCreds (t * testing.T ) {
761+ testCases := map [string ]struct {
762+ expectedAccessKey string
763+ expectedSecretKey string
764+ envVar map [string ]string
765+ configFile string
766+ configProfile string
767+ loadOptions func (* LoadOptions ) error
768+ }{
769+ "no config whatsoever" : {
770+ expectedAccessKey : "ec2-access-key" ,
771+ expectedSecretKey : "ec2-secret-key" ,
772+ envVar : map [string ]string {},
773+ configFile : "" ,
774+ },
775+ "env cfg" : {
776+ expectedAccessKey : "ec2-access-key-envcfg" ,
777+ expectedSecretKey : "ec2-secret-key-envcfg" ,
778+ envVar : map [string ]string {
779+ "AWS_EC2_INSTANCE_PROFILE_NAME" : "EnvCfg" ,
780+ },
781+ configFile : "" ,
782+ },
783+ "shared cfg" : {
784+ expectedAccessKey : "ec2-access-key-sharedcfg" ,
785+ expectedSecretKey : "ec2-secret-key-sharedcfg" ,
786+ envVar : map [string ]string {},
787+ configFile : filepath .Join ("testdata" , "config_source_shared" ),
788+ configProfile : "ec2metadata-profilename" ,
789+ },
790+ "loadopts + env cfg + shared cfg" : {
791+ expectedAccessKey : "ec2-access-key-loadopts" ,
792+ expectedSecretKey : "ec2-secret-key-loadopts" ,
793+ envVar : map [string ]string {
794+ "AWS_EC2_INSTANCE_PROFILE_NAME" : "EnvCfg" ,
795+ },
796+ configFile : filepath .Join ("testdata" , "config_source_shared" ),
797+ configProfile : "ec2metadata-profilename" ,
798+ loadOptions : WithEC2RoleCredentialOptions (func (o * ec2rolecreds.Options ) {
799+ o .ProfileName = "LoadOptions"
800+ }),
801+ },
802+ }
803+
804+ for name , tc := range testCases {
805+ t .Run (name , func (t * testing.T ) {
806+ endpointResolver , cleanupFn := setupCredentialsEndpoints ()
807+ defer cleanupFn ()
808+
809+ // setupCredentialsEndpoints sets this above and then we hold onto
810+ // it for this test
811+ ec2MetadataURL := os .Getenv ("AWS_EC2_METADATA_SERVICE_ENDPOINT" )
812+
813+ restoreEnv := awstesting .StashEnv ()
814+ defer awstesting .PopEnv (restoreEnv )
815+
816+ os .Setenv ("AWS_EC2_METADATA_SERVICE_ENDPOINT" , ec2MetadataURL )
817+ for k , v := range tc .envVar {
818+ os .Setenv (k , v )
819+ }
820+ var sharedConfigFiles []string
821+ if tc .configFile != "" {
822+ sharedConfigFiles = append (sharedConfigFiles , tc .configFile )
823+ }
824+ opts := []func (* LoadOptions ) error {
825+ WithEndpointResolverWithOptions (endpointResolver ),
826+ WithRetryer (func () aws.Retryer { return aws.NopRetryer {} }),
827+ WithSharedConfigFiles (sharedConfigFiles ),
828+ WithSharedCredentialsFiles ([]string {}),
829+ }
830+ if len (tc .configProfile ) != 0 {
831+ opts = append (opts , WithSharedConfigProfile (tc .configProfile ))
832+ }
833+
834+ if tc .loadOptions != nil {
835+ opts = append (opts , tc .loadOptions )
836+ }
837+
838+ cfg , err := LoadDefaultConfig (context .TODO (), opts ... )
839+ if err != nil {
840+ t .Fatalf ("could not load config: %s" , err )
841+ }
842+ actual , err := cfg .Credentials .Retrieve (context .TODO ())
843+ if err != nil {
844+ t .Fatalf ("could not retrieve credentials: %s" , err )
845+ }
846+ if actual .AccessKeyID != tc .expectedAccessKey {
847+ t .Errorf ("expected access key to be %s, got %s" , tc .expectedAccessKey , actual .AccessKeyID )
848+ }
849+ if actual .SecretAccessKey != tc .expectedSecretKey {
850+ t .Errorf ("expected secret key to be %s, got %s" , tc .expectedSecretKey , actual .SecretAccessKey )
851+ }
852+ })
853+ }
854+
855+ }
856+
753857type stubErrorClient struct {
754858 err error
755859}
0 commit comments