github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/backend/remote-state/s3/backend_complete_test.go (about)

     1  package s3
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"regexp"
     7  	"testing"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/aws/credentials"
    11  	"github.com/google/go-cmp/cmp"
    12  	awsbase "github.com/hashicorp/aws-sdk-go-base"
    13  	mockdata "github.com/hashicorp/aws-sdk-go-base"
    14  	servicemocks "github.com/hashicorp/aws-sdk-go-base"
    15  	"github.com/terramate-io/tf/configs/hcl2shim"
    16  	"github.com/terramate-io/tf/tfdiags"
    17  )
    18  
    19  type DiagsValidator func(*testing.T, tfdiags.Diagnostics)
    20  
    21  func ExpectNoDiags(t *testing.T, diags tfdiags.Diagnostics) {
    22  	expectDiagsCount(t, diags, 0)
    23  }
    24  
    25  func expectDiagsCount(t *testing.T, diags tfdiags.Diagnostics, c int) {
    26  	if l := len(diags); l != c {
    27  		t.Fatalf("Diagnostics: expected %d element, got %d\n%#v", c, l, diags)
    28  	}
    29  }
    30  
    31  func ExpectDiagsEqual(expected tfdiags.Diagnostics) DiagsValidator {
    32  	return func(t *testing.T, diags tfdiags.Diagnostics) {
    33  		if diff := cmp.Diff(diags, expected, cmp.Comparer(diagnosticComparer)); diff != "" {
    34  			t.Fatalf("unexpected diagnostics difference: %s", diff)
    35  		}
    36  	}
    37  }
    38  
    39  // ExpectDiagMatching returns a validator expeceting a single Diagnostic with fields matching the expectation
    40  func ExpectDiagMatching(severity tfdiags.Severity, summary matcher, detail matcher) DiagsValidator {
    41  	return func(t *testing.T, diags tfdiags.Diagnostics) {
    42  		for _, d := range diags {
    43  			if !summary.Match(d.Description().Summary) || !detail.Match(d.Description().Detail) {
    44  				t.Fatalf("expected Diagnostic matching %#v, got %#v",
    45  					tfdiags.Sourceless(
    46  						severity,
    47  						summary.String(),
    48  						detail.String(),
    49  					),
    50  					d,
    51  				)
    52  			}
    53  		}
    54  
    55  		expectDiagsCount(t, diags, 1)
    56  	}
    57  }
    58  
    59  type matcher interface {
    60  	fmt.Stringer
    61  	Match(string) bool
    62  }
    63  
    64  type equalsMatcher string
    65  
    66  func (m equalsMatcher) Match(s string) bool {
    67  	return string(m) == s
    68  }
    69  
    70  func (m equalsMatcher) String() string {
    71  	return string(m)
    72  }
    73  
    74  type regexpMatcher struct {
    75  	re *regexp.Regexp
    76  }
    77  
    78  func newRegexpMatcher(re string) regexpMatcher {
    79  	return regexpMatcher{
    80  		re: regexp.MustCompile(re),
    81  	}
    82  }
    83  
    84  func (m regexpMatcher) Match(s string) bool {
    85  	return m.re.MatchString(s)
    86  }
    87  
    88  func (m regexpMatcher) String() string {
    89  	return m.re.String()
    90  }
    91  
    92  func TestBackendConfig_Authentication(t *testing.T) {
    93  	testCases := map[string]struct {
    94  		config                     map[string]any
    95  		EnableEc2MetadataServer    bool
    96  		EnableEcsCredentialsServer bool
    97  		EnableWebIdentityEnvVars   bool
    98  		// EnableWebIdentityConfig    bool // Not supported
    99  		EnvironmentVariables     map[string]string
   100  		ExpectedCredentialsValue credentials.Value
   101  		MockStsEndpoints         []*servicemocks.MockEndpoint
   102  		SharedConfigurationFile  string
   103  		SharedCredentialsFile    string
   104  		ValidateDiags            DiagsValidator
   105  	}{
   106  		"empty config": {
   107  			config: map[string]any{},
   108  			ValidateDiags: ExpectDiagMatching(
   109  				tfdiags.Error,
   110  				equalsMatcher("Failed to configure AWS client"),
   111  				newRegexpMatcher("no valid credential sources for S3 Backend found"),
   112  			),
   113  		},
   114  
   115  		"config AccessKey": {
   116  			config: map[string]any{
   117  				"access_key": awsbase.MockStaticAccessKey,
   118  				"secret_key": servicemocks.MockStaticSecretKey,
   119  			},
   120  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   121  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   122  			},
   123  			ExpectedCredentialsValue: mockdata.MockStaticCredentials,
   124  			ValidateDiags:            ExpectNoDiags,
   125  		},
   126  
   127  		"config AccessKey config AssumeRoleARN access key": {
   128  			config: map[string]any{
   129  				"access_key":   awsbase.MockStaticAccessKey,
   130  				"secret_key":   servicemocks.MockStaticSecretKey,
   131  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   132  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   133  			},
   134  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   135  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   136  				servicemocks.MockStsAssumeRoleValidEndpoint,
   137  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   138  			},
   139  		},
   140  
   141  		"config AssumeRoleDuration": {
   142  			config: map[string]any{
   143  				"access_key":                   awsbase.MockStaticAccessKey,
   144  				"secret_key":                   servicemocks.MockStaticSecretKey,
   145  				"role_arn":                     servicemocks.MockStsAssumeRoleArn,
   146  				"session_name":                 servicemocks.MockStsAssumeRoleSessionName,
   147  				"assume_role_duration_seconds": 3600,
   148  			},
   149  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   150  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   151  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"DurationSeconds": "3600"}),
   152  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   153  			},
   154  		},
   155  
   156  		"config AssumeRoleExternalID": {
   157  			config: map[string]any{
   158  				"access_key":   awsbase.MockStaticAccessKey,
   159  				"secret_key":   servicemocks.MockStaticSecretKey,
   160  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   161  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   162  				"external_id":  servicemocks.MockStsAssumeRoleExternalId,
   163  			},
   164  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   165  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   166  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"ExternalId": servicemocks.MockStsAssumeRoleExternalId}),
   167  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   168  			},
   169  		},
   170  
   171  		"config AssumeRolePolicy": {
   172  			config: map[string]any{
   173  				"access_key":         awsbase.MockStaticAccessKey,
   174  				"secret_key":         servicemocks.MockStaticSecretKey,
   175  				"role_arn":           servicemocks.MockStsAssumeRoleArn,
   176  				"session_name":       servicemocks.MockStsAssumeRoleSessionName,
   177  				"assume_role_policy": servicemocks.MockStsAssumeRolePolicy,
   178  			},
   179  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   180  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   181  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"Policy": servicemocks.MockStsAssumeRolePolicy}),
   182  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   183  			},
   184  		},
   185  
   186  		"config AssumeRolePolicyARNs": {
   187  			config: map[string]any{
   188  				"access_key":              awsbase.MockStaticAccessKey,
   189  				"secret_key":              servicemocks.MockStaticSecretKey,
   190  				"role_arn":                servicemocks.MockStsAssumeRoleArn,
   191  				"session_name":            servicemocks.MockStsAssumeRoleSessionName,
   192  				"assume_role_policy_arns": []any{servicemocks.MockStsAssumeRolePolicyArn},
   193  			},
   194  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   195  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   196  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"PolicyArns.member.1.arn": servicemocks.MockStsAssumeRolePolicyArn}),
   197  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   198  			},
   199  		},
   200  
   201  		"config AssumeRoleTags": {
   202  			config: map[string]any{
   203  				"access_key":   awsbase.MockStaticAccessKey,
   204  				"secret_key":   servicemocks.MockStaticSecretKey,
   205  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   206  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   207  				"assume_role_tags": map[string]any{
   208  					servicemocks.MockStsAssumeRoleTagKey: servicemocks.MockStsAssumeRoleTagValue,
   209  				},
   210  			},
   211  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   212  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   213  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"Tags.member.1.Key": servicemocks.MockStsAssumeRoleTagKey, "Tags.member.1.Value": servicemocks.MockStsAssumeRoleTagValue}),
   214  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   215  			},
   216  		},
   217  
   218  		"config AssumeRoleTransitiveTagKeys": {
   219  			config: map[string]any{
   220  				"access_key":   awsbase.MockStaticAccessKey,
   221  				"secret_key":   servicemocks.MockStaticSecretKey,
   222  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   223  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   224  				"assume_role_tags": map[string]any{
   225  					servicemocks.MockStsAssumeRoleTagKey: servicemocks.MockStsAssumeRoleTagValue,
   226  				},
   227  				"assume_role_transitive_tag_keys": []any{servicemocks.MockStsAssumeRoleTagKey},
   228  			},
   229  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   230  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   231  				servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"Tags.member.1.Key": servicemocks.MockStsAssumeRoleTagKey, "Tags.member.1.Value": servicemocks.MockStsAssumeRoleTagValue, "TransitiveTagKeys.member.1": servicemocks.MockStsAssumeRoleTagKey}),
   232  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   233  			},
   234  		},
   235  
   236  		// NOT SUPPORTED: AssumeRoleSourceIdentity
   237  		// "config AssumeRoleSourceIdentity": {
   238  		// 	config: map[string]any{
   239  		// 		"access_key":                  awsbase.MockStaticAccessKey,
   240  		// 		"secret_key":                  servicemocks.MockStaticSecretKey,
   241  		// 		"role_arn":                    servicemocks.MockStsAssumeRoleArn,
   242  		// 		"session_name":                servicemocks.MockStsAssumeRoleSessionName,
   243  		// 		"assume_role_source_identity": servicemocks.MockStsAssumeRoleSourceIdentity,
   244  		// 	},
   245  		// 	ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   246  		// 	MockStsEndpoints: []*servicemocks.MockEndpoint{
   247  		// 		servicemocks.MockStsAssumeRoleValidEndpointWithOptions(map[string]string{"SourceIdentity": servicemocks.MockStsAssumeRoleSourceIdentity}),
   248  		// 		servicemocks.MockStsGetCallerIdentityValidEndpoint,
   249  		// 	},
   250  		// },
   251  
   252  		"config Profile shared credentials profile aws_access_key_id": {
   253  			config: map[string]any{
   254  				"profile": "SharedCredentialsProfile",
   255  			},
   256  			ExpectedCredentialsValue: credentials.Value{
   257  				AccessKeyID:     "ProfileSharedCredentialsAccessKey",
   258  				SecretAccessKey: "ProfileSharedCredentialsSecretKey",
   259  				ProviderName:    credentials.SharedCredsProviderName,
   260  			},
   261  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   262  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   263  			},
   264  			SharedCredentialsFile: `
   265  [default]
   266  aws_access_key_id = DefaultSharedCredentialsAccessKey
   267  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   268  
   269  [SharedCredentialsProfile]
   270  aws_access_key_id = ProfileSharedCredentialsAccessKey
   271  aws_secret_access_key = ProfileSharedCredentialsSecretKey
   272  `,
   273  			ValidateDiags: ExpectNoDiags,
   274  		},
   275  
   276  		"environment AWS_ACCESS_KEY_ID overrides config Profile": { // Legacy behavior
   277  			config: map[string]any{
   278  				"profile": "SharedCredentialsProfile",
   279  			},
   280  			EnvironmentVariables: map[string]string{
   281  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   282  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   283  			},
   284  			ExpectedCredentialsValue: servicemocks.MockEnvCredentials,
   285  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   286  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   287  			},
   288  			SharedCredentialsFile: `
   289  [default]
   290  aws_access_key_id = DefaultSharedCredentialsAccessKey
   291  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   292  
   293  [SharedCredentialsProfile]
   294  aws_access_key_id = ProfileSharedCredentialsAccessKey
   295  aws_secret_access_key = ProfileSharedCredentialsSecretKey
   296  `,
   297  			ValidateDiags: ExpectNoDiags,
   298  		},
   299  
   300  		"config Profile shared configuration credential_source Ec2InstanceMetadata": {
   301  			config: map[string]any{
   302  				"profile": "SharedConfigurationProfile",
   303  			},
   304  			EnableEc2MetadataServer:  true,
   305  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   306  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   307  				servicemocks.MockStsAssumeRoleValidEndpoint,
   308  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   309  			},
   310  			SharedConfigurationFile: fmt.Sprintf(`
   311  [profile SharedConfigurationProfile]
   312  credential_source = Ec2InstanceMetadata
   313  role_arn = %[1]s
   314  role_session_name = %[2]s
   315  `, servicemocks.MockStsAssumeRoleArn, servicemocks.MockStsAssumeRoleSessionName),
   316  		},
   317  
   318  		"config Profile shared configuration source_profile": {
   319  			config: map[string]any{
   320  				"profile": "SharedConfigurationProfile",
   321  			},
   322  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   323  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   324  				servicemocks.MockStsAssumeRoleValidEndpoint,
   325  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   326  			},
   327  			SharedConfigurationFile: fmt.Sprintf(`
   328  [profile SharedConfigurationProfile]
   329  role_arn = %[1]s
   330  role_session_name = %[2]s
   331  source_profile = SharedConfigurationSourceProfile
   332  
   333  [profile SharedConfigurationSourceProfile]
   334  aws_access_key_id = SharedConfigurationSourceAccessKey
   335  aws_secret_access_key = SharedConfigurationSourceSecretKey
   336  `, servicemocks.MockStsAssumeRoleArn, servicemocks.MockStsAssumeRoleSessionName),
   337  		},
   338  
   339  		"environment AWS_ACCESS_KEY_ID": {
   340  			config: map[string]any{},
   341  			EnvironmentVariables: map[string]string{
   342  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   343  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   344  			},
   345  			ExpectedCredentialsValue: mockdata.MockEnvCredentials,
   346  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   347  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   348  			},
   349  			ValidateDiags: ExpectNoDiags,
   350  		},
   351  
   352  		"environment AWS_ACCESS_KEY_ID config AssumeRoleARN access key": {
   353  			config: map[string]any{
   354  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   355  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   356  			},
   357  			EnvironmentVariables: map[string]string{
   358  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   359  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   360  			},
   361  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   362  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   363  				servicemocks.MockStsAssumeRoleValidEndpoint,
   364  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   365  			},
   366  		},
   367  
   368  		"environment AWS_PROFILE shared credentials profile aws_access_key_id": {
   369  			config: map[string]any{},
   370  			EnvironmentVariables: map[string]string{
   371  				"AWS_PROFILE": "SharedCredentialsProfile",
   372  			},
   373  			ExpectedCredentialsValue: credentials.Value{
   374  				AccessKeyID:     "ProfileSharedCredentialsAccessKey",
   375  				SecretAccessKey: "ProfileSharedCredentialsSecretKey",
   376  				ProviderName:    credentials.SharedCredsProviderName,
   377  			},
   378  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   379  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   380  			},
   381  			SharedCredentialsFile: `
   382  [default]
   383  aws_access_key_id = DefaultSharedCredentialsAccessKey
   384  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   385  
   386  [SharedCredentialsProfile]
   387  aws_access_key_id = ProfileSharedCredentialsAccessKey
   388  aws_secret_access_key = ProfileSharedCredentialsSecretKey
   389  `,
   390  			ValidateDiags: ExpectNoDiags,
   391  		},
   392  
   393  		"environment AWS_PROFILE shared configuration credential_source Ec2InstanceMetadata": {
   394  			config:                  map[string]any{},
   395  			EnableEc2MetadataServer: true,
   396  			EnvironmentVariables: map[string]string{
   397  				"AWS_PROFILE": "SharedConfigurationProfile",
   398  			},
   399  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   400  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   401  				servicemocks.MockStsAssumeRoleValidEndpoint,
   402  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   403  			},
   404  			SharedConfigurationFile: fmt.Sprintf(`
   405  [profile SharedConfigurationProfile]
   406  credential_source = Ec2InstanceMetadata
   407  role_arn = %[1]s
   408  role_session_name = %[2]s
   409  `, servicemocks.MockStsAssumeRoleArn, servicemocks.MockStsAssumeRoleSessionName),
   410  		},
   411  
   412  		"environment AWS_PROFILE shared configuration source_profile": {
   413  			config: map[string]any{},
   414  			EnvironmentVariables: map[string]string{
   415  				"AWS_PROFILE": "SharedConfigurationProfile",
   416  			},
   417  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   418  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   419  				servicemocks.MockStsAssumeRoleValidEndpoint,
   420  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   421  			},
   422  			SharedConfigurationFile: fmt.Sprintf(`
   423  [profile SharedConfigurationProfile]
   424  role_arn = %[1]s
   425  role_session_name = %[2]s
   426  source_profile = SharedConfigurationSourceProfile
   427  
   428  [profile SharedConfigurationSourceProfile]
   429  aws_access_key_id = SharedConfigurationSourceAccessKey
   430  aws_secret_access_key = SharedConfigurationSourceSecretKey
   431  `, servicemocks.MockStsAssumeRoleArn, servicemocks.MockStsAssumeRoleSessionName),
   432  		},
   433  
   434  		"environment AWS_SESSION_TOKEN": {
   435  			config: map[string]any{},
   436  			EnvironmentVariables: map[string]string{
   437  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   438  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   439  				"AWS_SESSION_TOKEN":     servicemocks.MockEnvSessionToken,
   440  			},
   441  			ExpectedCredentialsValue: mockdata.MockEnvCredentialsWithSessionToken,
   442  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   443  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   444  			},
   445  		},
   446  
   447  		"shared credentials default aws_access_key_id": {
   448  			config: map[string]any{},
   449  			ExpectedCredentialsValue: credentials.Value{
   450  				AccessKeyID:     "DefaultSharedCredentialsAccessKey",
   451  				SecretAccessKey: "DefaultSharedCredentialsSecretKey",
   452  				ProviderName:    credentials.SharedCredsProviderName,
   453  			},
   454  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   455  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   456  			},
   457  			SharedCredentialsFile: `
   458  [default]
   459  aws_access_key_id = DefaultSharedCredentialsAccessKey
   460  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   461  `,
   462  		},
   463  
   464  		"shared credentials default aws_access_key_id config AssumeRoleARN access key": {
   465  			config: map[string]any{
   466  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   467  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   468  			},
   469  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   470  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   471  				servicemocks.MockStsAssumeRoleValidEndpoint,
   472  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   473  			},
   474  			SharedCredentialsFile: `
   475  [default]
   476  aws_access_key_id = DefaultSharedCredentialsAccessKey
   477  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   478  `,
   479  		},
   480  
   481  		"web identity token access key": {
   482  			config:                   map[string]any{},
   483  			EnableWebIdentityEnvVars: true,
   484  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleWithWebIdentityCredentials,
   485  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   486  				servicemocks.MockStsAssumeRoleWithWebIdentityValidEndpoint,
   487  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   488  			},
   489  		},
   490  
   491  		"EC2 metadata access key": {
   492  			config:                   map[string]any{},
   493  			EnableEc2MetadataServer:  true,
   494  			ExpectedCredentialsValue: mockdata.MockEc2MetadataCredentials,
   495  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   496  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   497  			},
   498  			ValidateDiags: ExpectNoDiags,
   499  		},
   500  
   501  		"EC2 metadata access key config AssumeRoleARN access key": {
   502  			config: map[string]any{
   503  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   504  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   505  			},
   506  			EnableEc2MetadataServer:  true,
   507  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   508  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   509  				servicemocks.MockStsAssumeRoleValidEndpoint,
   510  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   511  			},
   512  		},
   513  
   514  		"ECS credentials access key": {
   515  			config:                     map[string]any{},
   516  			EnableEcsCredentialsServer: true,
   517  			ExpectedCredentialsValue:   mockdata.MockEcsCredentialsCredentials,
   518  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   519  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   520  			},
   521  		},
   522  
   523  		"ECS credentials access key config AssumeRoleARN access key": {
   524  			config: map[string]any{
   525  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   526  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   527  			},
   528  			EnableEcsCredentialsServer: true,
   529  			ExpectedCredentialsValue:   mockdata.MockStsAssumeRoleCredentials,
   530  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   531  				servicemocks.MockStsAssumeRoleValidEndpoint,
   532  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   533  			},
   534  		},
   535  
   536  		"AssumeWebIdentity envvar AssumeRoleARN access key": {
   537  			config: map[string]any{
   538  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   539  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   540  			},
   541  			EnableWebIdentityEnvVars: true,
   542  			ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   543  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   544  				servicemocks.MockStsAssumeRoleWithWebIdentityValidEndpoint,
   545  				servicemocks.MockStsAssumeRoleValidEndpoint,
   546  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   547  			},
   548  		},
   549  
   550  		// NOT SUPPORTED: AssumeWebIdentity config
   551  		// "AssumeWebIdentity config AssumeRoleARN access key": {
   552  		// 	config: map[string]any{
   553  		// 		"role_arn":     servicemocks.MockStsAssumeRoleArn,
   554  		// 		"session_name": servicemocks.MockStsAssumeRoleSessionName,
   555  		// 	},
   556  		// 	EnableWebIdentityConfig:  true,
   557  		// 	ExpectedCredentialsValue: mockdata.MockStsAssumeRoleCredentials,
   558  		// 	MockStsEndpoints: []*servicemocks.MockEndpoint{
   559  		// 		servicemocks.MockStsAssumeRoleWithWebIdentityValidEndpoint,
   560  		// 		servicemocks.MockStsAssumeRoleValidEndpoint,
   561  		// 		servicemocks.MockStsGetCallerIdentityValidEndpoint,
   562  		// 	},
   563  		// },
   564  
   565  		"config AccessKey over environment AWS_ACCESS_KEY_ID": {
   566  			config: map[string]any{
   567  				"access_key": awsbase.MockStaticAccessKey,
   568  				"secret_key": servicemocks.MockStaticSecretKey,
   569  			},
   570  			EnvironmentVariables: map[string]string{
   571  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   572  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   573  			},
   574  			ExpectedCredentialsValue: mockdata.MockStaticCredentials,
   575  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   576  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   577  			},
   578  			ValidateDiags: ExpectNoDiags,
   579  		},
   580  
   581  		"config AccessKey over shared credentials default aws_access_key_id": {
   582  			config: map[string]any{
   583  				"access_key": awsbase.MockStaticAccessKey,
   584  				"secret_key": servicemocks.MockStaticSecretKey,
   585  			},
   586  			ExpectedCredentialsValue: mockdata.MockStaticCredentials,
   587  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   588  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   589  			},
   590  			SharedCredentialsFile: `
   591  [default]
   592  aws_access_key_id = DefaultSharedCredentialsAccessKey
   593  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   594  `,
   595  			ValidateDiags: ExpectNoDiags,
   596  		},
   597  
   598  		"config AccessKey over EC2 metadata access key": {
   599  			config: map[string]any{
   600  				"access_key": awsbase.MockStaticAccessKey,
   601  				"secret_key": servicemocks.MockStaticSecretKey,
   602  			},
   603  			ExpectedCredentialsValue: mockdata.MockStaticCredentials,
   604  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   605  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   606  			},
   607  		},
   608  
   609  		"config AccessKey over ECS credentials access key": {
   610  			config: map[string]any{
   611  				"access_key": awsbase.MockStaticAccessKey,
   612  				"secret_key": servicemocks.MockStaticSecretKey,
   613  			},
   614  			EnableEcsCredentialsServer: true,
   615  			ExpectedCredentialsValue:   mockdata.MockStaticCredentials,
   616  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   617  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   618  			},
   619  		},
   620  
   621  		"environment AWS_ACCESS_KEY_ID over shared credentials default aws_access_key_id": {
   622  			config: map[string]any{},
   623  			EnvironmentVariables: map[string]string{
   624  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   625  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   626  			},
   627  			ExpectedCredentialsValue: mockdata.MockEnvCredentials,
   628  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   629  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   630  			},
   631  			SharedCredentialsFile: `
   632  [default]
   633  aws_access_key_id = DefaultSharedCredentialsAccessKey
   634  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   635  `,
   636  			ValidateDiags: ExpectNoDiags,
   637  		},
   638  
   639  		"environment AWS_ACCESS_KEY_ID over EC2 metadata access key": {
   640  			config: map[string]any{},
   641  			EnvironmentVariables: map[string]string{
   642  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   643  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   644  			},
   645  			ExpectedCredentialsValue: mockdata.MockEnvCredentials,
   646  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   647  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   648  			},
   649  		},
   650  
   651  		"environment AWS_ACCESS_KEY_ID over ECS credentials access key": {
   652  			config: map[string]any{},
   653  			EnvironmentVariables: map[string]string{
   654  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   655  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   656  			},
   657  			EnableEcsCredentialsServer: true,
   658  			ExpectedCredentialsValue:   mockdata.MockEnvCredentials,
   659  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   660  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   661  			},
   662  		},
   663  
   664  		"shared credentials default aws_access_key_id over EC2 metadata access key": {
   665  			config: map[string]any{},
   666  			ExpectedCredentialsValue: credentials.Value{
   667  				AccessKeyID:     "DefaultSharedCredentialsAccessKey",
   668  				SecretAccessKey: "DefaultSharedCredentialsSecretKey",
   669  				ProviderName:    credentials.SharedCredsProviderName,
   670  			},
   671  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   672  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   673  			},
   674  			SharedCredentialsFile: `
   675  [default]
   676  aws_access_key_id = DefaultSharedCredentialsAccessKey
   677  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   678  `,
   679  		},
   680  
   681  		"shared credentials default aws_access_key_id over ECS credentials access key": {
   682  			config:                     map[string]any{},
   683  			EnableEcsCredentialsServer: true,
   684  			ExpectedCredentialsValue: credentials.Value{
   685  				AccessKeyID:     "DefaultSharedCredentialsAccessKey",
   686  				SecretAccessKey: "DefaultSharedCredentialsSecretKey",
   687  				ProviderName:    credentials.SharedCredsProviderName,
   688  			},
   689  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   690  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   691  			},
   692  			SharedCredentialsFile: `
   693  [default]
   694  aws_access_key_id = DefaultSharedCredentialsAccessKey
   695  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   696  `,
   697  		},
   698  
   699  		"ECS credentials access key over EC2 metadata access key": {
   700  			config:                     map[string]any{},
   701  			EnableEcsCredentialsServer: true,
   702  			ExpectedCredentialsValue:   mockdata.MockEcsCredentialsCredentials,
   703  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   704  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   705  			},
   706  		},
   707  
   708  		"retrieve region from shared configuration file": {
   709  			config: map[string]any{
   710  				"access_key": awsbase.MockStaticAccessKey,
   711  				"secret_key": servicemocks.MockStaticSecretKey,
   712  			},
   713  			ExpectedCredentialsValue: mockdata.MockStaticCredentials,
   714  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   715  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   716  			},
   717  			SharedConfigurationFile: `
   718  [default]
   719  region = us-east-1
   720  `,
   721  		},
   722  
   723  		"assume role error": {
   724  			config: map[string]any{
   725  				"access_key":   awsbase.MockStaticAccessKey,
   726  				"secret_key":   servicemocks.MockStaticSecretKey,
   727  				"role_arn":     servicemocks.MockStsAssumeRoleArn,
   728  				"session_name": servicemocks.MockStsAssumeRoleSessionName,
   729  			},
   730  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   731  				servicemocks.MockStsAssumeRoleInvalidEndpointInvalidClientTokenId,
   732  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   733  			},
   734  			ValidateDiags: ExpectDiagMatching(
   735  				tfdiags.Error,
   736  				equalsMatcher("Failed to configure AWS client"),
   737  				newRegexpMatcher(`IAM Role \(.+\) cannot be assumed.`),
   738  			),
   739  		},
   740  
   741  		"skip EC2 Metadata API check": {
   742  			config: map[string]any{
   743  				"skip_metadata_api_check": true,
   744  			},
   745  			// The IMDS server must be enabled so that auth will succeed if the IMDS is called
   746  			EnableEc2MetadataServer: true,
   747  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   748  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   749  			},
   750  			ValidateDiags: ExpectDiagMatching(
   751  				tfdiags.Error,
   752  				equalsMatcher("Failed to configure AWS client"),
   753  				newRegexpMatcher("no valid credential sources for S3 Backend found"),
   754  			),
   755  		},
   756  
   757  		"invalid profile name from envvar": {
   758  			config: map[string]any{},
   759  			EnvironmentVariables: map[string]string{
   760  				"AWS_PROFILE": "no-such-profile",
   761  			},
   762  			SharedCredentialsFile: `
   763  [some-profile]
   764  aws_access_key_id = DefaultSharedCredentialsAccessKey
   765  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   766  `,
   767  			ValidateDiags: ExpectDiagMatching(
   768  				tfdiags.Error,
   769  				equalsMatcher("Failed to configure AWS client"),
   770  				newRegexpMatcher("no valid credential sources for S3 Backend found"),
   771  			),
   772  		},
   773  
   774  		"invalid profile name from config": {
   775  			config: map[string]any{
   776  				"profile": "no-such-profile",
   777  			},
   778  			SharedCredentialsFile: `
   779  [some-profile]
   780  aws_access_key_id = DefaultSharedCredentialsAccessKey
   781  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   782  `,
   783  			ValidateDiags: ExpectDiagMatching(
   784  				tfdiags.Error,
   785  				equalsMatcher("Failed to configure AWS client"),
   786  				newRegexpMatcher("no valid credential sources for S3 Backend found"),
   787  			),
   788  		},
   789  
   790  		"AWS_ACCESS_KEY_ID overrides AWS_PROFILE": {
   791  			config: map[string]any{},
   792  			EnvironmentVariables: map[string]string{
   793  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   794  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   795  				"AWS_PROFILE":           "SharedCredentialsProfile",
   796  			},
   797  			SharedCredentialsFile: `
   798  [default]
   799  aws_access_key_id = DefaultSharedCredentialsAccessKey
   800  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   801  
   802  [SharedCredentialsProfile]
   803  aws_access_key_id = ProfileSharedCredentialsAccessKey
   804  aws_secret_access_key = ProfileSharedCredentialsSecretKey
   805  `,
   806  			MockStsEndpoints: []*servicemocks.MockEndpoint{
   807  				servicemocks.MockStsGetCallerIdentityValidEndpoint,
   808  			},
   809  			ExpectedCredentialsValue: mockdata.MockEnvCredentials,
   810  			ValidateDiags:            ExpectNoDiags,
   811  		},
   812  
   813  		"AWS_ACCESS_KEY_ID does not override invalid profile name from envvar": {
   814  			config: map[string]any{},
   815  			EnvironmentVariables: map[string]string{
   816  				"AWS_ACCESS_KEY_ID":     servicemocks.MockEnvAccessKey,
   817  				"AWS_SECRET_ACCESS_KEY": servicemocks.MockEnvSecretKey,
   818  				"AWS_PROFILE":           "no-such-profile",
   819  			},
   820  			SharedCredentialsFile: `
   821  [some-profile]
   822  aws_access_key_id = DefaultSharedCredentialsAccessKey
   823  aws_secret_access_key = DefaultSharedCredentialsSecretKey
   824  `,
   825  			ValidateDiags: ExpectDiagMatching(
   826  				tfdiags.Error,
   827  				equalsMatcher("Failed to configure AWS client"),
   828  				newRegexpMatcher("error validating provider credentials:"),
   829  			),
   830  		},
   831  	}
   832  
   833  	for name, tc := range testCases {
   834  		tc := tc
   835  
   836  		t.Run(name, func(t *testing.T) {
   837  			oldEnv := initSessionTestEnv()
   838  			defer popEnv(oldEnv)
   839  
   840  			// Populate required fields
   841  			tc.config["region"] = "us-east-1"
   842  			tc.config["bucket"] = "bucket"
   843  			tc.config["key"] = "key"
   844  
   845  			if tc.ValidateDiags == nil {
   846  				tc.ValidateDiags = ExpectNoDiags
   847  			}
   848  
   849  			if tc.EnableEc2MetadataServer {
   850  				closeEc2Metadata := awsMetadataApiMock(append(
   851  					ec2metadata_securityCredentialsEndpoints,
   852  					ec2metadata_instanceIdEndpoint,
   853  					ec2metadata_iamInfoEndpoint,
   854  				))
   855  				defer closeEc2Metadata()
   856  			}
   857  
   858  			if tc.EnableEcsCredentialsServer {
   859  				closeEcsCredentials := ecsCredentialsApiMock()
   860  				defer closeEcsCredentials()
   861  			}
   862  
   863  			if tc.EnableWebIdentityEnvVars /*|| tc.EnableWebIdentityConfig*/ {
   864  				file, err := os.CreateTemp("", "aws-sdk-go-base-web-identity-token-file")
   865  				if err != nil {
   866  					t.Fatalf("unexpected error creating temporary web identity token file: %s", err)
   867  				}
   868  
   869  				defer os.Remove(file.Name())
   870  
   871  				err = os.WriteFile(file.Name(), []byte(servicemocks.MockWebIdentityToken), 0600)
   872  
   873  				if err != nil {
   874  					t.Fatalf("unexpected error writing web identity token file: %s", err)
   875  				}
   876  
   877  				if tc.EnableWebIdentityEnvVars {
   878  					os.Setenv("AWS_ROLE_ARN", servicemocks.MockStsAssumeRoleWithWebIdentityArn)
   879  					os.Setenv("AWS_ROLE_SESSION_NAME", servicemocks.MockStsAssumeRoleWithWebIdentitySessionName)
   880  					os.Setenv("AWS_WEB_IDENTITY_TOKEN_FILE", file.Name())
   881  				} /*else if tc.EnableWebIdentityConfig {
   882  					tc.Config.AssumeRoleWithWebIdentity = &AssumeRoleWithWebIdentity{
   883  						RoleARN:              servicemocks.MockStsAssumeRoleWithWebIdentityArn,
   884  						SessionName:          servicemocks.MockStsAssumeRoleWithWebIdentitySessionName,
   885  						WebIdentityTokenFile: file.Name(),
   886  					}
   887  				}*/
   888  			}
   889  
   890  			ts := servicemocks.MockAwsApiServer("STS", tc.MockStsEndpoints)
   891  			defer ts.Close()
   892  
   893  			tc.config["sts_endpoint"] = ts.URL
   894  
   895  			if tc.SharedConfigurationFile != "" {
   896  				file, err := os.CreateTemp("", "aws-sdk-go-base-shared-configuration-file")
   897  
   898  				if err != nil {
   899  					t.Fatalf("unexpected error creating temporary shared configuration file: %s", err)
   900  				}
   901  
   902  				defer os.Remove(file.Name())
   903  
   904  				err = os.WriteFile(file.Name(), []byte(tc.SharedConfigurationFile), 0600)
   905  
   906  				if err != nil {
   907  					t.Fatalf("unexpected error writing shared configuration file: %s", err)
   908  				}
   909  
   910  				setSharedConfigFile(file.Name())
   911  			}
   912  
   913  			if tc.SharedCredentialsFile != "" {
   914  				file, err := os.CreateTemp("", "aws-sdk-go-base-shared-credentials-file")
   915  
   916  				if err != nil {
   917  					t.Fatalf("unexpected error creating temporary shared credentials file: %s", err)
   918  				}
   919  
   920  				defer os.Remove(file.Name())
   921  
   922  				err = os.WriteFile(file.Name(), []byte(tc.SharedCredentialsFile), 0600)
   923  
   924  				if err != nil {
   925  					t.Fatalf("unexpected error writing shared credentials file: %s", err)
   926  				}
   927  
   928  				tc.config["shared_credentials_file"] = file.Name()
   929  			}
   930  
   931  			for k, v := range tc.EnvironmentVariables {
   932  				os.Setenv(k, v)
   933  			}
   934  
   935  			b, diags := configureBackend(t, tc.config)
   936  
   937  			tc.ValidateDiags(t, diags)
   938  
   939  			if diags.HasErrors() {
   940  				return
   941  			}
   942  
   943  			credentials, err := b.s3Client.Config.Credentials.Get()
   944  			if err != nil {
   945  				t.Fatalf("Error when requesting credentials: %s", err)
   946  			}
   947  
   948  			if diff := cmp.Diff(credentials, tc.ExpectedCredentialsValue); diff != "" {
   949  				t.Fatalf("unexpected credentials: (- got, + expected)\n%s", diff)
   950  			}
   951  		})
   952  	}
   953  }
   954  
   955  func TestBackendConfig_Region(t *testing.T) {
   956  	testCases := map[string]struct {
   957  		config                  map[string]any
   958  		EnvironmentVariables    map[string]string
   959  		IMDSRegion              string
   960  		SharedConfigurationFile string
   961  		ExpectedRegion          string
   962  	}{
   963  		// NOT SUPPORTED: region is required
   964  		// "no configuration": {
   965  		// 	config: map[string]any{
   966  		// 		"access_key": awsbase.MockStaticAccessKey,
   967  		// 		"secret_key": servicemocks.MockStaticSecretKey,
   968  		// 	},
   969  		// 	ExpectedRegion: "",
   970  		// },
   971  
   972  		"config": {
   973  			config: map[string]any{
   974  				"access_key": awsbase.MockStaticAccessKey,
   975  				"secret_key": servicemocks.MockStaticSecretKey,
   976  				"region":     "us-east-1",
   977  			},
   978  			ExpectedRegion: "us-east-1",
   979  		},
   980  
   981  		"AWS_REGION": {
   982  			config: map[string]any{
   983  				"access_key": awsbase.MockStaticAccessKey,
   984  				"secret_key": servicemocks.MockStaticSecretKey,
   985  			},
   986  			EnvironmentVariables: map[string]string{
   987  				"AWS_REGION": "us-east-1",
   988  			},
   989  			ExpectedRegion: "us-east-1",
   990  		},
   991  		"AWS_DEFAULT_REGION": {
   992  			config: map[string]any{
   993  				"access_key": awsbase.MockStaticAccessKey,
   994  				"secret_key": servicemocks.MockStaticSecretKey,
   995  			},
   996  			EnvironmentVariables: map[string]string{
   997  				"AWS_DEFAULT_REGION": "us-east-1",
   998  			},
   999  			ExpectedRegion: "us-east-1",
  1000  		},
  1001  		"AWS_REGION overrides AWS_DEFAULT_REGION": {
  1002  			config: map[string]any{
  1003  				"access_key": awsbase.MockStaticAccessKey,
  1004  				"secret_key": servicemocks.MockStaticSecretKey,
  1005  			},
  1006  			EnvironmentVariables: map[string]string{
  1007  				"AWS_REGION":         "us-east-1",
  1008  				"AWS_DEFAULT_REGION": "us-west-2",
  1009  			},
  1010  			ExpectedRegion: "us-east-1",
  1011  		},
  1012  
  1013  		// NOT SUPPORTED: region from shared configuration file
  1014  		// 		"shared configuration file": {
  1015  		// 			config: map[string]any{
  1016  		// 				"access_key": awsbase.MockStaticAccessKey,
  1017  		// 				"secret_key": servicemocks.MockStaticSecretKey,
  1018  		// 			},
  1019  		// 			SharedConfigurationFile: `
  1020  		// [default]
  1021  		// region = us-east-1
  1022  		// `,
  1023  		// 			ExpectedRegion: "us-east-1",
  1024  		// 		},
  1025  
  1026  		// NOT SUPPORTED: region from IMDS
  1027  		// "IMDS": {
  1028  		// 	config:         map[string]any{},
  1029  		// 	IMDSRegion:     "us-east-1",
  1030  		// 	ExpectedRegion: "us-east-1",
  1031  		// },
  1032  
  1033  		"config overrides AWS_REGION": {
  1034  			config: map[string]any{
  1035  				"access_key": awsbase.MockStaticAccessKey,
  1036  				"secret_key": servicemocks.MockStaticSecretKey,
  1037  				"region":     "us-east-1",
  1038  			},
  1039  			EnvironmentVariables: map[string]string{
  1040  				"AWS_REGION": "us-west-2",
  1041  			},
  1042  			ExpectedRegion: "us-east-1",
  1043  		},
  1044  		"config overrides AWS_DEFAULT_REGION": {
  1045  			config: map[string]any{
  1046  				"access_key": awsbase.MockStaticAccessKey,
  1047  				"secret_key": servicemocks.MockStaticSecretKey,
  1048  				"region":     "us-east-1",
  1049  			},
  1050  			EnvironmentVariables: map[string]string{
  1051  				"AWS_DEFAULT_REGION": "us-west-2",
  1052  			},
  1053  			ExpectedRegion: "us-east-1",
  1054  		},
  1055  
  1056  		"config overrides IMDS": {
  1057  			config: map[string]any{
  1058  				"access_key": awsbase.MockStaticAccessKey,
  1059  				"secret_key": servicemocks.MockStaticSecretKey,
  1060  				"region":     "us-west-2",
  1061  			},
  1062  			IMDSRegion:     "us-east-1",
  1063  			ExpectedRegion: "us-west-2",
  1064  		},
  1065  
  1066  		"AWS_REGION overrides shared configuration": {
  1067  			config: map[string]any{
  1068  				"access_key": awsbase.MockStaticAccessKey,
  1069  				"secret_key": servicemocks.MockStaticSecretKey,
  1070  			},
  1071  			EnvironmentVariables: map[string]string{
  1072  				"AWS_REGION": "us-east-1",
  1073  			},
  1074  			SharedConfigurationFile: `
  1075  [default]
  1076  region = us-west-2
  1077  `,
  1078  			ExpectedRegion: "us-east-1",
  1079  		},
  1080  		"AWS_DEFAULT_REGION overrides shared configuration": {
  1081  			config: map[string]any{
  1082  				"access_key": awsbase.MockStaticAccessKey,
  1083  				"secret_key": servicemocks.MockStaticSecretKey,
  1084  			},
  1085  			EnvironmentVariables: map[string]string{
  1086  				"AWS_DEFAULT_REGION": "us-east-1",
  1087  			},
  1088  			SharedConfigurationFile: `
  1089  [default]
  1090  region = us-west-2
  1091  `,
  1092  			ExpectedRegion: "us-east-1",
  1093  		},
  1094  
  1095  		"AWS_REGION overrides IMDS": {
  1096  			config: map[string]any{
  1097  				"access_key": awsbase.MockStaticAccessKey,
  1098  				"secret_key": servicemocks.MockStaticSecretKey,
  1099  			},
  1100  			EnvironmentVariables: map[string]string{
  1101  				"AWS_REGION": "us-east-1",
  1102  			},
  1103  			IMDSRegion:     "us-west-2",
  1104  			ExpectedRegion: "us-east-1",
  1105  		},
  1106  	}
  1107  
  1108  	for name, tc := range testCases {
  1109  		tc := tc
  1110  
  1111  		t.Run(name, func(t *testing.T) {
  1112  			oldEnv := initSessionTestEnv()
  1113  			defer popEnv(oldEnv)
  1114  
  1115  			// Populate required fields
  1116  			tc.config["bucket"] = "bucket"
  1117  			tc.config["key"] = "key"
  1118  
  1119  			for k, v := range tc.EnvironmentVariables {
  1120  				os.Setenv(k, v)
  1121  			}
  1122  
  1123  			if tc.IMDSRegion != "" {
  1124  				closeEc2Metadata := awsMetadataApiMock(append(
  1125  					ec2metadata_securityCredentialsEndpoints,
  1126  					ec2metadata_instanceIdEndpoint,
  1127  					ec2metadata_iamInfoEndpoint,
  1128  					ec2metadata_instanceIdentityEndpoint(tc.IMDSRegion),
  1129  				))
  1130  				defer closeEc2Metadata()
  1131  			}
  1132  
  1133  			if tc.SharedConfigurationFile != "" {
  1134  				file, err := os.CreateTemp("", "aws-sdk-go-base-shared-configuration-file")
  1135  
  1136  				if err != nil {
  1137  					t.Fatalf("unexpected error creating temporary shared configuration file: %s", err)
  1138  				}
  1139  
  1140  				defer os.Remove(file.Name())
  1141  
  1142  				err = os.WriteFile(file.Name(), []byte(tc.SharedConfigurationFile), 0600)
  1143  
  1144  				if err != nil {
  1145  					t.Fatalf("unexpected error writing shared configuration file: %s", err)
  1146  				}
  1147  
  1148  				setSharedConfigFile(file.Name())
  1149  			}
  1150  
  1151  			tc.config["skip_credentials_validation"] = true
  1152  
  1153  			b, diags := configureBackend(t, tc.config)
  1154  			if diags.HasErrors() {
  1155  				t.Fatalf("configuring backend: %s", diagnosticsString(diags))
  1156  			}
  1157  
  1158  			if a, e := aws.StringValue(b.s3Client.Config.Region), tc.ExpectedRegion; a != e {
  1159  				t.Errorf("expected Region %q, got: %q", e, a)
  1160  			}
  1161  		})
  1162  	}
  1163  }
  1164  
  1165  func setSharedConfigFile(filename string) {
  1166  	os.Setenv("AWS_SDK_LOAD_CONFIG", "1")
  1167  	os.Setenv("AWS_CONFIG_FILE", filename)
  1168  }
  1169  
  1170  func configureBackend(t *testing.T, config map[string]any) (*Backend, tfdiags.Diagnostics) {
  1171  	b := New().(*Backend)
  1172  	configSchema := populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(config))
  1173  
  1174  	configSchema, diags := b.PrepareConfig(configSchema)
  1175  
  1176  	if diags.HasErrors() {
  1177  		return b, diags
  1178  	}
  1179  
  1180  	confDiags := b.Configure(configSchema)
  1181  	diags = diags.Append(confDiags)
  1182  
  1183  	return b, diags
  1184  }