From c1018eb4d5969cf2b36894eddb63be19f1412fe5 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 14 Feb 2023 12:03:39 -0500 Subject: [PATCH 1/5] Avoid retries on expired credentials --- awsauth_test.go | 14 +++++++++++ servicemocks/mock.go | 48 ++++++++++++++++++++++++++++++++++++ v2/awsv1shim/session.go | 7 ++++++ v2/awsv1shim/session_test.go | 18 +++++++++++++- 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/awsauth_test.go b/awsauth_test.go index e292c1a6..eb6de15e 100644 --- a/awsauth_test.go +++ b/awsauth_test.go @@ -320,6 +320,20 @@ func TestGetAccountIDAndPartitionFromSTSGetCallerIdentity(t *testing.T) { }, ErrCount: 1, }, + { + Description: "sts:GetCallerIdentity expired token with invalid response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, + }, + ErrCount: 1, + }, + { + Description: "sts:GetCallerIdentity expired token with valid response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyExpiredToken, + }, + ErrCount: 1, + }, { Description: "sts:GetCallerIdentity success", MockEndpoints: []*servicemocks.MockEndpoint{ diff --git a/servicemocks/mock.go b/servicemocks/mock.go index 38bc8af6..47867361 100644 --- a/servicemocks/mock.go +++ b/servicemocks/mock.go @@ -113,6 +113,24 @@ const ( User: arn:aws:iam::123456789012:user/Bob is not authorized to perform: sts:GetCallerIdentity 01234567-89ab-cdef-0123-456789abcdef +` + MockStsGetCallerIdentityValidResponseBodyExpiredToken = ` + + Sender + ExpiredToken + The security token included in the request is expired + + + 01234567-89ab-cdef-0123-456789abcdef + +` + MockStsGetCallerIdentityInvalidResponseBodyExpiredToken = ` + + Sender + ExpiredToken + The security token included in the request is expired + +01234567-89ab-cdef-0123-456789abcdef ` MockStsGetCallerIdentityPartition = `aws` MockStsGetCallerIdentityValidResponseBody = ` @@ -211,6 +229,36 @@ var ( StatusCode: http.StatusForbidden, }, } + MockStsGetCallerIdentityInvalidBodyExpiredToken = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityInvalidResponseBodyExpiredToken, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } + MockStsGetCallerIdentityValidBodyExpiredToken = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityValidResponseBodyExpiredToken, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } MockStsGetCallerIdentityValidEndpoint = &MockEndpoint{ Request: &MockRequest{ Body: url.Values{ diff --git a/v2/awsv1shim/session.go b/v2/awsv1shim/session.go index 904b27b8..b579469d 100644 --- a/v2/awsv1shim/session.go +++ b/v2/awsv1shim/session.go @@ -148,6 +148,13 @@ func GetSession(ctx context.Context, awsC *awsv2.Config, c *awsbase.Config) (*se }) r.Retryable = aws.Bool(false) } + + if r.IsErrorExpired() { + logger.Warn(ctx, "Disabling retries after next request due to expired credentials", map[string]any{ + "error": r.Error, + }) + r.Retryable = aws.Bool(false) + } }) return sess, nil diff --git a/v2/awsv1shim/session_test.go b/v2/awsv1shim/session_test.go index e4e048fa..d18e2b4b 100644 --- a/v2/awsv1shim/session_test.go +++ b/v2/awsv1shim/session_test.go @@ -561,7 +561,7 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey [default] aws_access_key_id = DefaultSharedCredentialsAccessKey aws_secret_access_key = DefaultSharedCredentialsSecretKey - `, +`, }, { Config: &awsbase.Config{ @@ -872,6 +872,22 @@ region = us-east-1 servicemocks.MockStsGetCallerIdentityValidEndpoint, }, }, + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "expired token error", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredToken") + //return tfawserr.ErrCodeEquals(err, "ExpiredToken") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, + }, + }, + // { // Config: &awsbase.Config{ // AccessKey: servicemocks.MockStaticAccessKey, From 503670f3d254e3e7a117bc209ab5463d47889ec5 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Tue, 14 Feb 2023 12:06:04 -0500 Subject: [PATCH 2/5] Remove unncessary comment --- v2/awsv1shim/session_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/v2/awsv1shim/session_test.go b/v2/awsv1shim/session_test.go index d18e2b4b..151cb7b8 100644 --- a/v2/awsv1shim/session_test.go +++ b/v2/awsv1shim/session_test.go @@ -881,7 +881,6 @@ region = us-east-1 Description: "expired token error", ExpectedError: func(err error) bool { return strings.Contains(err.Error(), "ExpiredToken") - //return tfawserr.ErrCodeEquals(err, "ExpiredToken") }, MockStsEndpoints: []*servicemocks.MockEndpoint{ servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, From ea09e4c0ad3322b3ac6ae36ca51cc391ec870f6e Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 16 Feb 2023 22:33:19 -0500 Subject: [PATCH 3/5] Correct order of operations --- v2/awsv1shim/session.go | 15 +++--- v2/awsv1shim/session_test.go | 98 ++++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 11 deletions(-) diff --git a/v2/awsv1shim/session.go b/v2/awsv1shim/session.go index b579469d..7706d9f0 100644 --- a/v2/awsv1shim/session.go +++ b/v2/awsv1shim/session.go @@ -129,9 +129,17 @@ func GetSession(ctx context.Context, awsC *awsv2.Config, c *awsbase.Config) (*se sess.Handlers.Retry.PushBack(func(r *request.Request) { logger := logging.RetrieveLogger(r.Context()) + if r.IsErrorExpired() { + logger.Warn(ctx, "Disabling retries after next request due to expired credentials", map[string]any{ + "error": r.Error, + }) + r.Retryable = aws.Bool(false) + } + if r.RetryCount < constants.MaxNetworkRetryCount { return } + // RequestError: send request failed // caused by: Post https://FQDN/: dial tcp: lookup FQDN: no such host if tfawserr.ErrMessageAndOrigErrContain(r.Error, request.ErrCodeRequestError, "send request failed", "no such host") { @@ -148,13 +156,6 @@ func GetSession(ctx context.Context, awsC *awsv2.Config, c *awsbase.Config) (*se }) r.Retryable = aws.Bool(false) } - - if r.IsErrorExpired() { - logger.Warn(ctx, "Disabling retries after next request due to expired credentials", map[string]any{ - "error": r.Error, - }) - r.Retryable = aws.Bool(false) - } }) return sess, nil diff --git a/v2/awsv1shim/session_test.go b/v2/awsv1shim/session_test.go index 151cb7b8..80da6cd8 100644 --- a/v2/awsv1shim/session_test.go +++ b/v2/awsv1shim/session_test.go @@ -878,7 +878,7 @@ region = us-east-1 Region: "us-east-1", SecretKey: servicemocks.MockStaticSecretKey, }, - Description: "expired token error", + Description: "ExpiredToken invalid body", ExpectedError: func(err error) bool { return strings.Contains(err.Error(), "ExpiredToken") }, @@ -886,7 +886,76 @@ region = us-east-1 servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, }, }, - + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "ExpiredToken valid body", // in case they change it + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredToken") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyExpiredToken, + }, + }, + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "ExpiredTokenException invalid body", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredTokenException") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredTokenException, + }, + }, + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "ExpiredTokenException valid body", // in case they change it + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredTokenException") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyExpiredTokenException, + }, + }, + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "RequestExpired invalid body", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "RequestExpired") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyRequestExpired, + }, + }, + { + Config: &awsbase.Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "RequestExpired valid body", // in case they change it + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "RequestExpired") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyRequestExpired, + }, + }, // { // Config: &awsbase.Config{ // AccessKey: servicemocks.MockStaticAccessKey, @@ -1133,7 +1202,7 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey t.Fatalf("unexpected GetAwsConfig() '%[1]T' error: %[1]s", err) } - t.Logf("received expected error: %s", err) + t.Logf("received expected error (awsbase.GetAwsConfig): %s", err) return } actualSession, err := GetSession(ctx, &awsConfig, testCase.Config) @@ -1146,7 +1215,7 @@ aws_secret_access_key = DefaultSharedCredentialsSecretKey t.Fatalf("unexpected GetSession() '%[1]T' error: %[1]s", err) } - t.Logf("received expected error: %s", err) + t.Logf("received expected error (GetSession): %s", err) return } @@ -2300,6 +2369,27 @@ func TestSessionRetryHandlers(t *testing.T) { ExpectedRetryableValue: true, // defaults to true for non-AWS errors ExpectRetryToBeAttempted: false, // Does not actually get retried, because over max retry limit }, + { + Description: "ExpiredToken error no retries", + RetryCount: maxRetries, + Error: awserr.New("ExpiredToken", "The security token included in the request is expired", nil), + ExpectedRetryableValue: false, + ExpectRetryToBeAttempted: false, + }, + { + Description: "ExpiredTokenException error no retries", + RetryCount: maxRetries, + Error: awserr.New("ExpiredTokenException", "The security token included in the request is expired", nil), + ExpectedRetryableValue: false, + ExpectRetryToBeAttempted: false, + }, + { + Description: "RequestExpired error no retries", + RetryCount: maxRetries, + Error: awserr.New("RequestExpired", "The security token included in the request is expired", nil), + ExpectedRetryableValue: false, + ExpectRetryToBeAttempted: false, + }, { Description: "send request no such host failed under MaxNetworkRetryCount", RetryCount: constants.MaxNetworkRetryCount - 1, From fb34edb7cef5717693248c71f0ee5ab897c5709c Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 16 Feb 2023 22:33:48 -0500 Subject: [PATCH 4/5] Add mocks for other possible expired credentials errors --- servicemocks/mock.go | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/servicemocks/mock.go b/servicemocks/mock.go index 47867361..804be234 100644 --- a/servicemocks/mock.go +++ b/servicemocks/mock.go @@ -114,6 +114,8 @@ const ( 01234567-89ab-cdef-0123-456789abcdef ` + // MockStsGetCallerIdentityValidResponseBodyExpiredToken uses code "ExpiredToken", seemingly the most common + // code. Errors usually have an invalid body but this may be fixed at some point. MockStsGetCallerIdentityValidResponseBodyExpiredToken = ` Sender @@ -124,6 +126,8 @@ const ( 01234567-89ab-cdef-0123-456789abcdef ` + // MockStsGetCallerIdentityInvalidResponseBodyExpiredToken uses code "ExpiredToken", seemingly the most common + // code. Errors usually have an invalid body. MockStsGetCallerIdentityInvalidResponseBodyExpiredToken = ` Sender @@ -131,6 +135,50 @@ const ( The security token included in the request is expired 01234567-89ab-cdef-0123-456789abcdef +` + // MockStsGetCallerIdentityValidResponseBodyExpiredTokenException uses code "ExpiredTokenException", a more rare code + // but used at least by Fargate. Errors usually have an invalid body but this may change. + MockStsGetCallerIdentityValidResponseBodyExpiredTokenException = ` + + Sender + ExpiredTokenException + The security token included in the request is expired + + + 01234567-89ab-cdef-0123-456789abcdef + +` + // MockStsGetCallerIdentityInvalidResponseBodyExpiredTokenException uses code "ExpiredTokenException", a more rare code + // but used at least by Fargate. Errors usually have an invalid body but this may change. + MockStsGetCallerIdentityInvalidResponseBodyExpiredTokenException = ` + + Sender + ExpiredTokenException + The security token included in the request is expired + +01234567-89ab-cdef-0123-456789abcdef +` + // MockStsGetCallerIdentityValidResponseBodyRequestExpired uses code "RequestExpired", a code only used in EC2. + // Errors usually have an invalid body but this may change. + MockStsGetCallerIdentityValidResponseBodyRequestExpired = ` + + Sender + RequestExpired + The security token included in the request is expired + + + 01234567-89ab-cdef-0123-456789abcdef + +` + // MockStsGetCallerIdentityInvalidResponseBodyRequestExpired uses code "RequestExpired", a code only used in EC2. + // Errors usually have an invalid body but this may change. + MockStsGetCallerIdentityInvalidResponseBodyRequestExpired = ` + + Sender + RequestExpired + The security token included in the request is expired + +01234567-89ab-cdef-0123-456789abcdef ` MockStsGetCallerIdentityPartition = `aws` MockStsGetCallerIdentityValidResponseBody = ` @@ -259,6 +307,66 @@ var ( StatusCode: http.StatusForbidden, }, } + MockStsGetCallerIdentityInvalidBodyExpiredTokenException = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityInvalidResponseBodyExpiredTokenException, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } + MockStsGetCallerIdentityValidBodyExpiredTokenException = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityValidResponseBodyExpiredTokenException, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } + MockStsGetCallerIdentityInvalidBodyRequestExpired = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityInvalidResponseBodyRequestExpired, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } + MockStsGetCallerIdentityValidBodyRequestExpired = &MockEndpoint{ + Request: &MockRequest{ + Body: url.Values{ + "Action": []string{"GetCallerIdentity"}, + "Version": []string{"2011-06-15"}, + }.Encode(), + Method: http.MethodPost, + Uri: "/", + }, + Response: &MockResponse{ + Body: MockStsGetCallerIdentityValidResponseBodyRequestExpired, + ContentType: "text/xml", + StatusCode: http.StatusForbidden, + }, + } MockStsGetCallerIdentityValidEndpoint = &MockEndpoint{ Request: &MockRequest{ Body: url.Values{ From c4d0ab071c76e3260d8ca0e84fb324716d127fa1 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Thu, 16 Feb 2023 22:34:32 -0500 Subject: [PATCH 5/5] Add tests for mocks and to show lack of retries --- aws_config.go | 2 +- aws_config_test.go | 117 +++++++++++++++++++++++++++++++++++++++++++++ awsauth_test.go | 32 ++++++++++++- 3 files changed, 148 insertions(+), 3 deletions(-) diff --git a/aws_config.go b/aws_config.go index 9f4b5052..ba7cba5e 100644 --- a/aws_config.go +++ b/aws_config.go @@ -96,7 +96,7 @@ func GetAwsConfig(ctx context.Context, c *Config) (context.Context, aws.Config, if !c.SkipCredsValidation { if _, _, err := getAccountIDAndPartitionFromSTSGetCallerIdentity(baseCtx, stsClient(baseCtx, awsConfig, c)); err != nil { - return ctx, awsConfig, fmt.Errorf("error validating provider credentials: %w", err) + return ctx, awsConfig, fmt.Errorf("validating provider credentials: %w", err) } } diff --git a/aws_config_test.go b/aws_config_test.go index 14619667..fd9b4f47 100644 --- a/aws_config_test.go +++ b/aws_config_test.go @@ -22,6 +22,7 @@ import ( "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/aws/aws-sdk-go-v2/service/sts" + "github.com/aws/smithy-go" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" @@ -94,6 +95,52 @@ func TestGetAwsConfig(t *testing.T) { servicemocks.MockStsGetCallerIdentityValidEndpoint, }, }, + { + Config: &Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + MaxRetries: 100, + }, + Description: "ExpiredToken", + ExpectedRegion: "us-east-1", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredToken") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, + }, + }, + { + Config: &Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "ExpiredTokenException", + ExpectedRegion: "us-east-1", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "ExpiredTokenException") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredTokenException, + }, + }, + { + Config: &Config{ + AccessKey: servicemocks.MockStaticAccessKey, + Region: "us-east-1", + SecretKey: servicemocks.MockStaticSecretKey, + }, + Description: "RequestExpired", + ExpectedRegion: "us-east-1", + ExpectedError: func(err error) bool { + return strings.Contains(err.Error(), "RequestExpired") + }, + MockStsEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyRequestExpired, + }, + }, { Config: &Config{ AccessKey: servicemocks.MockStaticAccessKey, @@ -3043,6 +3090,76 @@ func TestRetryHandlers(t *testing.T) { return results }(), }, + "no retries for ExpiredToken": { + NextHandler: func() middleware.FinalizeHandler { + num := 0 + reqsErrs := make([]error, 2) + for i := 0; i < 2; i++ { + reqsErrs[i] = &smithy.OperationError{ + ServiceID: "STS", + OperationName: "GetCallerIdentity", + Err: &smithyhttp.ResponseError{ + Response: &smithyhttp.Response{ + Response: &http.Response{ + StatusCode: 403, + }, + }, + Err: &smithy.GenericAPIError{ + Code: "ExpiredToken", + Message: "The security token included in the request is expired", + }, + }, + } + } + return middleware.FinalizeHandlerFunc(func(ctx context.Context, in middleware.FinalizeInput) (out middleware.FinalizeOutput, metadata middleware.Metadata, err error) { + if num >= len(reqsErrs) { + err = fmt.Errorf("more requests than expected") + } else { + err = reqsErrs[num] + num++ + } + return out, metadata, err + }) + }, + Err: &smithy.OperationError{ + ServiceID: "STS", + OperationName: "GetCallerIdentity", + Err: &smithyhttp.ResponseError{ + Response: &smithyhttp.Response{ + Response: &http.Response{ + StatusCode: 403, + }, + }, + Err: &smithy.GenericAPIError{ + Code: "ExpiredToken", + Message: "The security token included in the request is expired", + }, + }, + }, + ExpectResults: func() retry.AttemptResults { + results := retry.AttemptResults{ + Results: make([]retry.AttemptResult, 1), + } + results.Results[0] = retry.AttemptResult{ + Err: &smithy.OperationError{ + ServiceID: "STS", + OperationName: "GetCallerIdentity", + Err: &smithyhttp.ResponseError{ + Response: &smithyhttp.Response{ + Response: &http.Response{ + StatusCode: 403, + }, + }, + Err: &smithy.GenericAPIError{ + Code: "ExpiredToken", + Message: "The security token included in the request is expired", + }, + }, + }, + } + return results + }(), + }, "stops at maxRetries for other network errors": { NextHandler: func() middleware.FinalizeHandler { num := 0 diff --git a/awsauth_test.go b/awsauth_test.go index eb6de15e..15492cfc 100644 --- a/awsauth_test.go +++ b/awsauth_test.go @@ -321,19 +321,47 @@ func TestGetAccountIDAndPartitionFromSTSGetCallerIdentity(t *testing.T) { ErrCount: 1, }, { - Description: "sts:GetCallerIdentity expired token with invalid response", + Description: "sts:GetCallerIdentity ExpiredToken with invalid JSON response", MockEndpoints: []*servicemocks.MockEndpoint{ servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredToken, }, ErrCount: 1, }, { - Description: "sts:GetCallerIdentity expired token with valid response", + Description: "sts:GetCallerIdentity ExpiredToken with valid JSON response", MockEndpoints: []*servicemocks.MockEndpoint{ servicemocks.MockStsGetCallerIdentityValidBodyExpiredToken, }, ErrCount: 1, }, + { + Description: "sts:GetCallerIdentity ExpiredTokenException with invalid JSON response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyExpiredTokenException, + }, + ErrCount: 1, + }, + { + Description: "sts:GetCallerIdentity ExpiredTokenException with valid JSON response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyExpiredTokenException, + }, + ErrCount: 1, + }, + { + Description: "sts:GetCallerIdentity RequestExpired with invalid JSON response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityInvalidBodyRequestExpired, + }, + ErrCount: 1, + }, + { + Description: "sts:GetCallerIdentity RequestExpired with valid JSON response", + MockEndpoints: []*servicemocks.MockEndpoint{ + servicemocks.MockStsGetCallerIdentityValidBodyRequestExpired, + }, + ErrCount: 1, + }, { Description: "sts:GetCallerIdentity success", MockEndpoints: []*servicemocks.MockEndpoint{