deps: Update aws-sdk-go-based to 0.6.0

This commit is contained in:
Angie Pinilla 2020-08-18 12:49:31 -04:00
parent 27affd06ce
commit 582fb73a7c
12 changed files with 471 additions and 232 deletions

View File

@ -18,50 +18,6 @@ import (
"github.com/hashicorp/terraform/states/remote"
)
const (
mockStsAssumeRoleArn = `arn:aws:iam::555555555555:role/AssumeRole`
mockStsAssumeRolePolicy = `{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "*",
"Resource": "*",
}
}`
mockStsAssumeRolePolicyArn = `arn:aws:iam::555555555555:policy/AssumeRolePolicy1`
mockStsAssumeRoleSessionName = `AssumeRoleSessionName`
mockStsAssumeRoleTagKey = `AssumeRoleTagKey`
mockStsAssumeRoleTagValue = `AssumeRoleTagValue`
mockStsAssumeRoleTransitiveTagKey = `AssumeRoleTagKey`
mockStsAssumeRoleValidResponse = `<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::555555555555:assumed-role/role/AssumeRoleSessionName</Arn>
<AssumedRoleId>ARO123EXAMPLE123:AssumeRoleSessionName</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>AssumeRoleAccessKey</AccessKeyId>
<SecretAccessKey>AssumeRoleSecretKey</SecretAccessKey>
<SessionToken>AssumeRoleSessionToken</SessionToken>
<Expiration>2099-12-31T23:59:59Z</Expiration>
</Credentials>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>`
mockStsGetCallerIdentityValidResponseBody = `<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<GetCallerIdentityResult>
<Arn>arn:aws:iam::222222222222:user/Alice</Arn>
<UserId>AKIAI44QH8DHBEXAMPLE</UserId>
<Account>222222222222</Account>
</GetCallerIdentityResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</GetCallerIdentityResponse>`
)
var (
mockStsGetCallerIdentityRequestBody = url.Values{
"Action": []string{"GetCallerIdentity"},
@ -132,8 +88,8 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "role_arn",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -141,15 +97,15 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
@ -159,8 +115,8 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "assume_role_duration_seconds",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -168,26 +124,26 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{"POST", "/", url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"3600"},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
{
Config: map[string]interface{}{
"bucket": "tf-test",
"external_id": "AssumeRoleExternalId",
"external_id": awsbase.MockStsAssumeRoleExternalId,
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "external_id",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -195,27 +151,27 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{"POST", "/", url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"ExternalId": []string{"AssumeRoleExternalId"},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"ExternalId": []string{awsbase.MockStsAssumeRoleExternalId},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
{
Config: map[string]interface{}{
"assume_role_policy": mockStsAssumeRolePolicy,
"assume_role_policy": awsbase.MockStsAssumeRolePolicy,
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "assume_role_policy",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -223,27 +179,27 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{"POST", "/", url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"Policy": []string{mockStsAssumeRolePolicy},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"Policy": []string{awsbase.MockStsAssumeRolePolicy},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
{
Config: map[string]interface{}{
"assume_role_policy_arns": []interface{}{mockStsAssumeRolePolicyArn},
"assume_role_policy_arns": []interface{}{awsbase.MockStsAssumeRolePolicyArn},
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "assume_role_policy_arns",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -251,29 +207,29 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"PolicyArns.member.1.arn": []string{mockStsAssumeRolePolicyArn},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"PolicyArns.member.1.arn": []string{awsbase.MockStsAssumeRolePolicyArn},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
{
Config: map[string]interface{}{
"assume_role_tags": map[string]interface{}{
mockStsAssumeRoleTagKey: mockStsAssumeRoleTagValue,
awsbase.MockStsAssumeRoleTagKey: awsbase.MockStsAssumeRoleTagValue,
},
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "assume_role_tags",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -281,31 +237,31 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"Tags.member.1.Key": []string{mockStsAssumeRoleTagKey},
"Tags.member.1.Value": []string{mockStsAssumeRoleTagValue},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Tags.member.1.Key": []string{awsbase.MockStsAssumeRoleTagKey},
"Tags.member.1.Value": []string{awsbase.MockStsAssumeRoleTagValue},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},
{
Config: map[string]interface{}{
"assume_role_tags": map[string]interface{}{
mockStsAssumeRoleTagKey: mockStsAssumeRoleTagValue,
awsbase.MockStsAssumeRoleTagKey: awsbase.MockStsAssumeRoleTagValue,
},
"assume_role_transitive_tag_keys": []interface{}{mockStsAssumeRoleTagKey},
"assume_role_transitive_tag_keys": []interface{}{awsbase.MockStsAssumeRoleTagKey},
"bucket": "tf-test",
"key": "state",
"region": "us-west-1",
"role_arn": mockStsAssumeRoleArn,
"session_name": mockStsAssumeRoleSessionName,
"role_arn": awsbase.MockStsAssumeRoleArn,
"session_name": awsbase.MockStsAssumeRoleSessionName,
},
Description: "assume_role_transitive_tag_keys",
MockStsEndpoints: []*awsbase.MockEndpoint{
@ -313,18 +269,18 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{mockStsAssumeRoleArn},
"RoleSessionName": []string{mockStsAssumeRoleSessionName},
"Tags.member.1.Key": []string{mockStsAssumeRoleTagKey},
"Tags.member.1.Value": []string{mockStsAssumeRoleTagValue},
"TransitiveTagKeys.member.1": []string{mockStsAssumeRoleTagKey},
"RoleArn": []string{awsbase.MockStsAssumeRoleArn},
"RoleSessionName": []string{awsbase.MockStsAssumeRoleSessionName},
"Tags.member.1.Key": []string{awsbase.MockStsAssumeRoleTagKey},
"Tags.member.1.Value": []string{awsbase.MockStsAssumeRoleTagValue},
"TransitiveTagKeys.member.1": []string{awsbase.MockStsAssumeRoleTagKey},
"Version": []string{"2011-06-15"},
}.Encode()},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsAssumeRoleValidResponse, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsAssumeRoleValidResponseBody, ContentType: "text/xml"},
},
{
Request: &awsbase.MockRequest{Method: "POST", Uri: "/", Body: mockStsGetCallerIdentityRequestBody},
Response: &awsbase.MockResponse{StatusCode: 200, Body: mockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
Response: &awsbase.MockResponse{StatusCode: 200, Body: awsbase.MockStsGetCallerIdentityValidResponseBody, ContentType: "text/xml"},
},
},
},

2
go.mod
View File

@ -51,7 +51,7 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.8.5 // indirect
github.com/hashicorp/aws-sdk-go-base v0.5.0
github.com/hashicorp/aws-sdk-go-base v0.6.0
github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089
github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-azure-helpers v0.10.0

6
go.sum
View File

@ -74,8 +74,6 @@ github.com/antchfx/xpath v0.0.0-20190129040759-c8489ed3251e h1:ptBAamGVd6CfRsUty
github.com/antchfx/xpath v0.0.0-20190129040759-c8489ed3251e/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xquery v0.0.0-20180515051857-ad5b8c7a47b0 h1:JaCC8jz0zdMLk2m+qCCVLLLM/PL93p84w4pK3aJWj60=
github.com/antchfx/xquery v0.0.0-20180515051857-ad5b8c7a47b0/go.mod h1:LzD22aAzDP8/dyiCKFp31He4m2GPjl0AFyzDtZzUu9M=
github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU=
github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
@ -240,8 +238,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/aws-sdk-go-base v0.5.0 h1:fk7ID0v3PWL/KNL8FvkBPu8Sm93EPUCCmtZCiTXLySE=
github.com/hashicorp/aws-sdk-go-base v0.5.0/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY=
github.com/hashicorp/aws-sdk-go-base v0.6.0 h1:qmUbzM36msbBF59YctwuO5w0M2oNXjlilgKpnEhx1uw=
github.com/hashicorp/aws-sdk-go-base v0.6.0/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY=
github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089 h1:1eDpXAxTh0iPv+1kc9/gfSI2pxRERDsTk/lNGolwHn8=
github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=

View File

@ -1,3 +1,13 @@
# v0.6.0 (unreleased)
BREAKING CHANGES
* AWS error checking function have been moved to `tfawserr` package. `IsAWSErr` has been renamed to `ErrMessageContains` and `IsAWSErrExtended` has been renamed to `ErrMessageAndOrigErrContain`. #37
ENHANCEMENTS
* Additional AWS error checking function have been added to the `tfawserr` package - `ErrCodeEquals`, `ErrCodeContains` and `ErrStatusCodeEquals`.
# v0.5.0 (June 4, 2020)
BREAKING CHANGES

View File

@ -6,7 +6,7 @@ An opinionated [AWS Go SDK](https://github.com/aws/aws-sdk-go) library for consi
## Requirements
- [Go](https://golang.org/doc/install) 1.12
- [Go](https://golang.org/doc/install) 1.13
## Development
@ -25,3 +25,16 @@ $ golangci-lint run ./...
# Optionally if Make is available; both run the same linting
$ make lint
```
## Release Process
- Push a new `vX.Y.Z` tag to the repository
- Close associated `vX.Y.Z` milestone
- For Terraform AWS Provider: Renovate will automatically detect the update and submit a dependency pull request (usually within an hour)
- For Terraform S3 Backend: Submit a new dependency pull request by running:
```sh
go get github.com/hashicorp/aws-sdk-go-base@vX.Y.Z
go mod tidy
go mod vendor
```

View File

@ -17,6 +17,7 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-multierror"
homedir "github.com/mitchellh/go-homedir"
@ -183,7 +184,7 @@ func GetCredentialsFromSession(c *Config) (*awsCredentials.Credentials, error) {
sess, err := session.NewSessionWithOptions(*options)
if err != nil {
if IsAWSErr(err, "NoCredentialProviders", "") {
if tfawserr.ErrCodeEquals(err, "NoCredentialProviders") {
return nil, c.NewNoValidCredentialSourcesError(err)
}
return nil, fmt.Errorf("Error creating AWS session: %w", err)
@ -229,7 +230,7 @@ func GetCredentials(c *Config) (*awsCredentials.Credentials, error) {
creds := awsCredentials.NewChainCredentials(providers)
cp, err := creds.Get()
if err != nil {
if IsAWSErr(err, "NoCredentialProviders", "") {
if tfawserr.ErrCodeEquals(err, "NoCredentialProviders") {
creds, err = GetCredentialsFromSession(c)
if err != nil {
return nil, err

View File

@ -1,44 +0,0 @@
package awsbase
import (
"errors"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// IsAWSErr returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() matches code
// * Error.Message() contains message
func IsAWSErr(err error, code string, message string) bool {
var awsErr awserr.Error
if errors.As(err, &awsErr) {
return awsErr.Code() == code && strings.Contains(awsErr.Message(), message)
}
return false
}
// IsAWSErrExtended returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() matches code
// * Error.Message() contains message
// * Error.OrigErr() contains origErrMessage
func IsAWSErrExtended(err error, code string, message string, origErrMessage string) bool {
if !IsAWSErr(err, code, message) {
return false
}
if origErrMessage == "" {
return true
}
// Ensure OrigErr() is non-nil, to prevent panics
if origErr := err.(awserr.Error).OrigErr(); origErr != nil {
return strings.Contains(origErr.Error(), origErrMessage)
}
return false
}

View File

@ -7,14 +7,263 @@ import (
"log"
"net/http"
"net/http/httptest"
"net/url"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
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/credentials/endpointcreds"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
)
const (
MockEc2MetadataAccessKey = `Ec2MetadataAccessKey`
MockEc2MetadataSecretKey = `Ec2MetadataSecretKey`
MockEc2MetadataSessionToken = `Ec2MetadataSessionToken`
MockEcsCredentialsAccessKey = `EcsCredentialsAccessKey`
MockEcsCredentialsSecretKey = `EcsCredentialsSecretKey`
MockEcsCredentialsSessionToken = `EcsCredentialsSessionToken`
MockEnvAccessKey = `EnvAccessKey`
MockEnvSecretKey = `EnvSecretKey`
MockEnvSessionToken = `EnvSessionToken`
MockStaticAccessKey = `StaticAccessKey`
MockStaticSecretKey = `StaticSecretKey`
MockStsAssumeRoleAccessKey = `AssumeRoleAccessKey`
MockStsAssumeRoleArn = `arn:aws:iam::555555555555:role/AssumeRole`
MockStsAssumeRoleExternalId = `AssumeRoleExternalId`
MockStsAssumeRoleInvalidResponseBodyInvalidClientTokenId = `<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<Error>
<Type>Sender</Type>
<Code>InvalidClientTokenId</Code>
<Message>The security token included in the request is invalid.</Message>
</Error>
<RequestId>4d0cf5ec-892a-4d3f-84e4-30e9987d9bdd</RequestId>
</ErrorResponse>`
MockStsAssumeRolePolicy = `{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "*",
"Resource": "*",
}
}`
MockStsAssumeRolePolicyArn = `arn:aws:iam::555555555555:policy/AssumeRolePolicy1`
MockStsAssumeRoleSecretKey = `AssumeRoleSecretKey`
MockStsAssumeRoleSessionName = `AssumeRoleSessionName`
MockStsAssumeRoleSessionToken = `AssumeRoleSessionToken`
MockStsAssumeRoleTagKey = `AssumeRoleTagKey`
MockStsAssumeRoleTagValue = `AssumeRoleTagValue`
MockStsAssumeRoleTransitiveTagKey = `AssumeRoleTagKey`
MockStsAssumeRoleValidResponseBody = `<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::555555555555:assumed-role/role/AssumeRoleSessionName</Arn>
<AssumedRoleId>ARO123EXAMPLE123:AssumeRoleSessionName</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>AssumeRoleAccessKey</AccessKeyId>
<SecretAccessKey>AssumeRoleSecretKey</SecretAccessKey>
<SessionToken>AssumeRoleSessionToken</SessionToken>
<Expiration>2099-12-31T23:59:59Z</Expiration>
</Credentials>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>`
MockStsAssumeRoleWithWebIdentityAccessKey = `AssumeRoleWithWebIdentityAccessKey`
MockStsAssumeRoleWithWebIdentityArn = `arn:aws:iam::666666666666:role/WebIdentityToken`
MockStsAssumeRoleWithWebIdentitySecretKey = `AssumeRoleWithWebIdentitySecretKey`
MockStsAssumeRoleWithWebIdentitySessionName = `AssumeRoleWithWebIdentitySessionName`
MockStsAssumeRoleWithWebIdentitySessionToken = `AssumeRoleWithWebIdentitySessionToken`
MockStsAssumeRoleWithWebIdentityValidResponseBody = `<AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleWithWebIdentityResult>
<SubjectFromWebIdentityToken>amzn1.account.AF6RHO7KZU5XRVQJGXK6HB56KR2A</SubjectFromWebIdentityToken>
<Audience>client.6666666666666666666.6666@apps.example.com</Audience>
<AssumedRoleUser>
<Arn>arn:aws:sts::666666666666:assumed-role/FederatedWebIdentityRole/AssumeRoleWithWebIdentitySessionName</Arn>
<AssumedRoleId>ARO123EXAMPLE123:AssumeRoleWithWebIdentitySessionName</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<SessionToken>AssumeRoleWithWebIdentitySessionToken</SessionToken>
<SecretAccessKey>AssumeRoleWithWebIdentitySecretKey</SecretAccessKey>
<Expiration>2099-12-31T23:59:59Z</Expiration>
<AccessKeyId>AssumeRoleWithWebIdentityAccessKey</AccessKeyId>
</Credentials>
<Provider>www.amazon.com</Provider>
</AssumeRoleWithWebIdentityResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</AssumeRoleWithWebIdentityResponse>`
MockStsGetCallerIdentityAccountID = `222222222222`
MockStsGetCallerIdentityInvalidResponseBodyAccessDenied = `<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<Error>
<Type>Sender</Type>
<Code>AccessDenied</Code>
<Message>User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: sts:GetCallerIdentity</Message>
</Error>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ErrorResponse>`
MockStsGetCallerIdentityPartition = `aws`
MockStsGetCallerIdentityValidResponseBody = `<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<GetCallerIdentityResult>
<Arn>arn:aws:iam::222222222222:user/Alice</Arn>
<UserId>AKIAI44QH8DHBEXAMPLE</UserId>
<Account>222222222222</Account>
</GetCallerIdentityResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</GetCallerIdentityResponse>`
MockWebIdentityToken = `WebIdentityToken`
)
var (
MockEc2MetadataCredentials = awsCredentials.Value{
AccessKeyID: MockEc2MetadataAccessKey,
ProviderName: ec2rolecreds.ProviderName,
SecretAccessKey: MockEc2MetadataSecretKey,
SessionToken: MockEc2MetadataSessionToken,
}
MockEcsCredentialsCredentials = awsCredentials.Value{
AccessKeyID: MockEcsCredentialsAccessKey,
ProviderName: endpointcreds.ProviderName,
SecretAccessKey: MockEcsCredentialsSecretKey,
SessionToken: MockEcsCredentialsSessionToken,
}
MockEnvCredentials = awsCredentials.Value{
AccessKeyID: MockEnvAccessKey,
ProviderName: awsCredentials.EnvProviderName,
SecretAccessKey: MockEnvSecretKey,
}
MockEnvCredentialsWithSessionToken = awsCredentials.Value{
AccessKeyID: MockEnvAccessKey,
ProviderName: awsCredentials.EnvProviderName,
SecretAccessKey: MockEnvSecretKey,
SessionToken: MockEnvSessionToken,
}
MockStaticCredentials = awsCredentials.Value{
AccessKeyID: MockStaticAccessKey,
ProviderName: awsCredentials.StaticProviderName,
SecretAccessKey: MockStaticSecretKey,
}
MockStsAssumeRoleCredentials = awsCredentials.Value{
AccessKeyID: MockStsAssumeRoleAccessKey,
ProviderName: stscreds.ProviderName,
SecretAccessKey: MockStsAssumeRoleSecretKey,
SessionToken: MockStsAssumeRoleSessionToken,
}
MockStsAssumeRoleInvalidEndpointInvalidClientTokenId = &MockEndpoint{
Request: &MockRequest{
Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{MockStsAssumeRoleArn},
"RoleSessionName": []string{MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsAssumeRoleInvalidResponseBodyInvalidClientTokenId,
ContentType: "text/xml",
StatusCode: http.StatusForbidden,
},
}
MockStsAssumeRoleValidEndpoint = &MockEndpoint{
Request: &MockRequest{
Body: url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{MockStsAssumeRoleArn},
"RoleSessionName": []string{MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsAssumeRoleValidResponseBody,
ContentType: "text/xml",
StatusCode: http.StatusOK,
},
}
MockStsAssumeRoleWithWebIdentityValidEndpoint = &MockEndpoint{
Request: &MockRequest{
Body: url.Values{
"Action": []string{"AssumeRoleWithWebIdentity"},
"RoleArn": []string{MockStsAssumeRoleWithWebIdentityArn},
"RoleSessionName": []string{MockStsAssumeRoleWithWebIdentitySessionName},
"Version": []string{"2011-06-15"},
"WebIdentityToken": []string{MockWebIdentityToken},
}.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsAssumeRoleWithWebIdentityValidResponseBody,
ContentType: "text/xml",
StatusCode: http.StatusOK,
},
}
MockStsAssumeRoleWithWebIdentityCredentials = awsCredentials.Value{
AccessKeyID: MockStsAssumeRoleWithWebIdentityAccessKey,
ProviderName: stscreds.WebIdentityProviderName,
SecretAccessKey: MockStsAssumeRoleWithWebIdentitySecretKey,
SessionToken: MockStsAssumeRoleWithWebIdentitySessionToken,
}
MockStsGetCallerIdentityInvalidEndpointAccessDenied = &MockEndpoint{
Request: &MockRequest{
Body: url.Values{
"Action": []string{"GetCallerIdentity"},
"Version": []string{"2011-06-15"},
}.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsGetCallerIdentityInvalidResponseBodyAccessDenied,
ContentType: "text/xml",
StatusCode: http.StatusForbidden,
},
}
MockStsGetCallerIdentityValidEndpoint = &MockEndpoint{
Request: &MockRequest{
Body: url.Values{
"Action": []string{"GetCallerIdentity"},
"Version": []string{"2011-06-15"},
}.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsGetCallerIdentityValidResponseBody,
ContentType: "text/xml",
StatusCode: http.StatusOK,
},
}
)
// MockAwsApiServer establishes a httptest server to simulate behaviour of a real AWS API server
func MockAwsApiServer(svcName string, endpoints []*MockEndpoint) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -96,11 +345,11 @@ func ecsCredentialsApiMock() func() {
log.Printf("[DEBUG] Mock ECS credentials server received request: %s", r.RequestURI)
if r.RequestURI == "/creds" {
_ = json.NewEncoder(w).Encode(map[string]string{
"AccessKeyId": "EcsCredentialsAccessKey",
"AccessKeyId": MockEcsCredentialsAccessKey,
"Expiration": time.Now().UTC().Format(time.RFC3339),
"RoleArn": "arn:aws:iam::000000000000:role/EcsCredentials",
"SecretAccessKey": "EcsCredentialsSecretKey",
"Token": "EcsCredentialsSessionToken",
"SecretAccessKey": MockEcsCredentialsSecretKey,
"Token": MockEcsCredentialsSessionToken,
})
return
}
@ -111,6 +360,34 @@ func ecsCredentialsApiMock() func() {
return ts.Close
}
// MockStsAssumeRoleValidEndpointWithOptions returns a valid STS AssumeRole response with configurable request options.
func MockStsAssumeRoleValidEndpointWithOptions(options map[string]string) *MockEndpoint {
urlValues := url.Values{
"Action": []string{"AssumeRole"},
"DurationSeconds": []string{"900"},
"RoleArn": []string{MockStsAssumeRoleArn},
"RoleSessionName": []string{MockStsAssumeRoleSessionName},
"Version": []string{"2011-06-15"},
}
for k, v := range options {
urlValues.Set(k, v)
}
return &MockEndpoint{
Request: &MockRequest{
Body: urlValues.Encode(),
Method: http.MethodPost,
Uri: "/",
},
Response: &MockResponse{
Body: MockStsAssumeRoleValidResponseBody,
ContentType: "text/xml",
StatusCode: http.StatusOK,
},
}
}
// MockEndpoint represents a basic request and response that can be used for creating simple httptest server routes.
type MockEndpoint struct {
Request *MockRequest
@ -193,77 +470,6 @@ const iamResponse_GetUser_unauthorized = `<ErrorResponse xmlns="https://iam.amaz
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ErrorResponse>`
var stsResponse_AssumeRole_valid = fmt.Sprintf(`<AssumeRoleResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleResult>
<AssumedRoleUser>
<Arn>arn:aws:sts::555555555555:assumed-role/role/AssumeRoleSessionName</Arn>
<AssumedRoleId>ARO123EXAMPLE123:AssumeRoleSessionName</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<AccessKeyId>AssumeRoleAccessKey</AccessKeyId>
<SecretAccessKey>AssumeRoleSecretKey</SecretAccessKey>
<SessionToken>AssumeRoleSessionToken</SessionToken>
<Expiration>%s</Expiration>
</Credentials>
</AssumeRoleResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</AssumeRoleResponse>`, time.Now().UTC().Format(time.RFC3339))
const stsResponse_AssumeRole_InvalidClientTokenId = `<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<Error>
<Type>Sender</Type>
<Code>InvalidClientTokenId</Code>
<Message>The security token included in the request is invalid.</Message>
</Error>
<RequestId>4d0cf5ec-892a-4d3f-84e4-30e9987d9bdd</RequestId>
</ErrorResponse>`
var stsResponse_AssumeRoleWithWebIdentity_valid = fmt.Sprintf(`<AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<AssumeRoleWithWebIdentityResult>
<SubjectFromWebIdentityToken>amzn1.account.AF6RHO7KZU5XRVQJGXK6HB56KR2A</SubjectFromWebIdentityToken>
<Audience>client.6666666666666666666.6666@apps.example.com</Audience>
<AssumedRoleUser>
<Arn>arn:aws:sts::666666666666:assumed-role/FederatedWebIdentityRole/AssumeRoleWithWebIdentitySessionName</Arn>
<AssumedRoleId>ARO123EXAMPLE123:AssumeRoleWithWebIdentitySessionName</AssumedRoleId>
</AssumedRoleUser>
<Credentials>
<SessionToken>AssumeRoleWithWebIdentitySessionToken</SessionToken>
<SecretAccessKey>AssumeRoleWithWebIdentitySecretKey</SecretAccessKey>
<Expiration>%s</Expiration>
<AccessKeyId>AssumeRoleWithWebIdentityAccessKey</AccessKeyId>
</Credentials>
<Provider>www.amazon.com</Provider>
</AssumeRoleWithWebIdentityResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</AssumeRoleWithWebIdentityResponse>`, time.Now().UTC().Format(time.RFC3339))
const stsResponse_GetCallerIdentity_valid = `<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<GetCallerIdentityResult>
<Arn>arn:aws:iam::222222222222:user/Alice</Arn>
<UserId>AKIAI44QH8DHBEXAMPLE</UserId>
<Account>222222222222</Account>
</GetCallerIdentityResult>
<ResponseMetadata>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ResponseMetadata>
</GetCallerIdentityResponse>`
const stsResponse_GetCallerIdentity_valid_expectedAccountID = `222222222222`
const stsResponse_GetCallerIdentity_valid_expectedPartition = `aws`
const stsResponse_GetCallerIdentity_unauthorized = `<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
<Error>
<Type>Sender</Type>
<Code>AccessDenied</Code>
<Message>User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: sts:GetCallerIdentity</Message>
</Error>
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
</ErrorResponse>`
const iamResponse_GetUser_federatedFailure = `<ErrorResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<Error>
<Type>Sender</Type>
@ -304,5 +510,3 @@ const iamResponse_ListRoles_unauthorized = `<ErrorResponse xmlns="https://iam.am
</Error>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ErrorResponse>`
const webIdentityToken = `WebIdentityToken`

View File

@ -13,10 +13,16 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/go-cleanhttp"
)
const (
// AppendUserAgentEnvVar is a conventionally used environment variable
// containing additional HTTP User-Agent information.
// If present and its value is non-empty, it is directly appended to the
// User-Agent header for HTTP requests.
AppendUserAgentEnvVar = "TF_APPEND_USER_AGENT"
// Maximum network retries.
// We depend on the AWS Go SDK DefaultRetryer exponential backoff.
// Ensure that if the AWS Config MaxRetries is set high (which it is by
@ -78,7 +84,7 @@ func GetSession(c *Config) (*session.Session, error) {
sess, err := session.NewSessionWithOptions(*options)
if err != nil {
if IsAWSErr(err, "NoCredentialProviders", "") {
if tfawserr.ErrCodeEquals(err, "NoCredentialProviders") {
return nil, c.NewNoValidCredentialSourcesError(err)
}
return nil, fmt.Errorf("Error creating AWS session: %w", err)
@ -92,6 +98,13 @@ func GetSession(c *Config) (*session.Session, error) {
sess.Handlers.Build.PushBack(request.MakeAddToUserAgentHandler(product.Name, product.Version, product.Extra...))
}
// Add custom input from ENV to the User-Agent request header
// Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/9149
if v := os.Getenv(AppendUserAgentEnvVar); v != "" {
log.Printf("[DEBUG] Using additional User-Agent Info: %s", v)
sess.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler(v))
}
// Generally, we want to configure a lower retry theshold for networking issues
// as the session retry threshold is very high by default and can mask permanent
// networking failures, such as a non-existent service endpoint.
@ -104,13 +117,13 @@ func GetSession(c *Config) (*session.Session, error) {
}
// RequestError: send request failed
// caused by: Post https://FQDN/: dial tcp: lookup FQDN: no such host
if IsAWSErrExtended(r.Error, "RequestError", "send request failed", "no such host") {
if tfawserr.ErrMessageAndOrigErrContain(r.Error, "RequestError", "send request failed", "no such host") {
log.Printf("[WARN] Disabling retries after next request due to networking issue")
r.Retryable = aws.Bool(false)
}
// RequestError: send request failed
// caused by: Post https://FQDN/: dial tcp IPADDRESS:443: connect: connection refused
if IsAWSErrExtended(r.Error, "RequestError", "send request failed", "connection refused") {
if tfawserr.ErrMessageAndOrigErrContain(r.Error, "RequestError", "send request failed", "connection refused") {
log.Printf("[WARN] Disabling retries after next request due to networking issue")
r.Retryable = aws.Bool(false)
}

View File

@ -0,0 +1,77 @@
package tfawserr
import (
"errors"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// ErrMessageAndOrigErrContain returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() matches code
// * Error.Message() contains message
// * Error.OrigErr() contains origErrMessage
func ErrMessageAndOrigErrContain(err error, code string, message string, origErrMessage string) bool {
if !ErrMessageContains(err, code, message) {
return false
}
if origErrMessage == "" {
return true
}
// Ensure OrigErr() is non-nil, to prevent panics
if origErr := err.(awserr.Error).OrigErr(); origErr != nil {
return strings.Contains(origErr.Error(), origErrMessage)
}
return false
}
// ErrCodeEquals returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() equals code
func ErrCodeEquals(err error, code string) bool {
var awsErr awserr.Error
if errors.As(err, &awsErr) {
return awsErr.Code() == code
}
return false
}
// ErrCodeContains returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() contains code
func ErrCodeContains(err error, code string) bool {
var awsErr awserr.Error
if errors.As(err, &awsErr) {
return strings.Contains(awsErr.Code(), code)
}
return false
}
// ErrMessageContains returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() equals code
// * Error.Message() contains message
func ErrMessageContains(err error, code string, message string) bool {
var awsErr awserr.Error
if errors.As(err, &awsErr) {
return awsErr.Code() == code && strings.Contains(awsErr.Message(), message)
}
return false
}
// ErrStatusCodeEquals returns true if the error matches all these conditions:
// * err is of type awserr.RequestFailure
// * RequestFailure.StatusCode() equals statusCode
// It is always preferable to use ErrMessageContains() except in older APIs (e.g. S3)
// that sometimes only respond with status codes.
func ErrStatusCodeEquals(err error, statusCode int) bool {
var awsErr awserr.RequestFailure
if errors.As(err, &awsErr) {
return awsErr.StatusCode() == statusCode
}
return false
}

3
vendor/modules.txt vendored
View File

@ -306,9 +306,10 @@ github.com/gophercloud/utils/terraform/auth
## explicit
# github.com/grpc-ecosystem/grpc-gateway v1.8.5
## explicit
# github.com/hashicorp/aws-sdk-go-base v0.5.0
# github.com/hashicorp/aws-sdk-go-base v0.6.0
## explicit
github.com/hashicorp/aws-sdk-go-base
github.com/hashicorp/aws-sdk-go-base/tfawserr
# github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089
## explicit
github.com/hashicorp/consul/api

View File

@ -418,3 +418,13 @@ to lock any workspace state, even if they do not have access to read or write
that state. If a malicious user has such access they could block attempts to
use Terraform against some or all of your workspaces as long as locking is
enabled in the backend configuration.
### Configuring Custom User-Agent Information
Note this feature is optional and only available in Terraform v0.13.1+.
By default, the underlying AWS client used by the Terraform AWS Provider creates requests with User-Agent headers including information about Terraform and AWS Go SDK versions. To provide additional information in the User-Agent headers, the `TF_APPEND_USER_AGENT` environment variable can be set and its value will be directly added to HTTP requests. e.g.
```sh
$ export TF_APPEND_USER_AGENT="JenkinsAgent/i-12345678 BuildID/1234 (Optional Extra Information)"
```