Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/aws-iam-authenticator/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ var verifyCmd = &cobra.Command{

instanceRegion := getInstanceRegion(context.Background())

id, err := token.NewVerifier(clusterID, partition, instanceRegion).Verify(tok)
id, err := token.NewVerifier(clusterID, partition, instanceRegion, nil).Verify(tok)
if err != nil {
fmt.Fprintf(os.Stderr, "could not verify token: %v\n", err)
os.Exit(1)
Expand Down
14 changes: 8 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ module sigs.k8s.io/aws-iam-authenticator
go 1.24.4

require (
github.com/aws/aws-sdk-go-v2 v1.38.0
github.com/aws/aws-sdk-go-v2 v1.38.2
github.com/aws/aws-sdk-go-v2/config v1.31.0
github.com/aws/aws-sdk-go-v2/credentials v1.18.4
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3
github.com/aws/aws-sdk-go-v2/service/ec2 v1.244.0
github.com/aws/aws-sdk-go-v2/service/sts v1.37.0
github.com/aws/smithy-go v1.22.5
github.com/aws/smithy-go v1.23.0
github.com/fsnotify/fsnotify v1.9.0
github.com/gofrs/flock v0.12.1
github.com/google/go-cmp v0.7.0
github.com/manifoldco/promptui v0.9.0
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_golang v1.23.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.14.0
github.com/spf13/cobra v1.9.1
Expand All @@ -31,9 +31,10 @@ require (
)

require (
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/service/account v1.28.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.28.0 // indirect
Expand All @@ -56,14 +57,15 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/sagikazarmark/locafero v0.9.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
github.com/aws/aws-sdk-go-v2 v1.38.0 h1:UCRQ5mlqcFk9HJDIqENSLR3wiG1VTWlyUfLDEvY7RxU=
github.com/aws/aws-sdk-go-v2 v1.38.0/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg=
github.com/aws/aws-sdk-go-v2 v1.38.2 h1:QUkLO1aTW0yqW95pVzZS0LGFanL71hJ0a49w4TJLMyM=
github.com/aws/aws-sdk-go-v2 v1.38.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
github.com/aws/aws-sdk-go-v2/config v1.31.0 h1:9yH0xiY5fUnVNLRWO0AtayqwU1ndriZdN78LlhruJR4=
github.com/aws/aws-sdk-go-v2/config v1.31.0/go.mod h1:VeV3K72nXnhbe4EuxxhzsDc/ByrCSlZwUnWH52Nde/I=
github.com/aws/aws-sdk-go-v2/credentials v1.18.4 h1:IPd0Algf1b+Qy9BcDp0sCUcIWdCQPSzDoMK3a8pcbUM=
Expand All @@ -8,10 +10,16 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3 h1:GicIdnekoJsjq9wqnvyi2el
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.3/go.mod h1:R7BIi6WNC5mc1kfRM7XM/VHC3uRWkjc396sfabq4iOo=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3 h1:o9RnO+YZ4X+kt5Z7Nvcishlz0nksIt2PIzDglLMP0vA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.3/go.mod h1:+6aLJzOG1fvMOyzIySYjOFjcguGvVRL68R+uoRencN4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.5 h1:d45S2DqHZOkHu0uLUW92VdBoT5v0hh3EyR+DzMEh3ag=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.5/go.mod h1:G6e/dR2c2huh6JmIo9SXysjuLuDDGWMeYGibfW2ZrXg=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3 h1:joyyUFhiTQQmVK6ImzNU9TQSNRNeD9kOklqTzyk5v6s=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.3/go.mod h1:+vNIyZQP3b3B1tSLI0lxvrU9cfM7gpdRXMFfm67ZcPc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.5 h1:ENhnQOV3SxWHplOqNN1f+uuCNf9n4Y/PKpl6b1WRP0Q=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.5/go.mod h1:csQLMI+odbC0/J+UecSTztG70Dc4aTCOu4GyPNDNpVo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/service/account v1.28.1 h1:GJqHyB+4c8U0p+S7w/C1CGNb3gqgs1Sw6lTqMSpGcHA=
github.com/aws/aws-sdk-go-v2/service/account v1.28.1/go.mod h1:UCcTaFy22BpCwjdiXGTCiVjtBZgtJb56eos4OI43B9g=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.244.0 h1:KfETrpt7yv2nkSrjOltgmKyAl8scbzYc4TFtZeoV6uc=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.244.0/go.mod h1:EeWmteKqZjaMj45MUmPET1SisFI+HkqWIRQoyjMivcc=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM=
Expand All @@ -26,6 +34,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.37.0 h1:MG9VFW43M4A8BYeAfaJJZWrroinx
github.com/aws/aws-sdk-go-v2/service/sts v1.37.0/go.mod h1:JdeBDPgpJfuS6rU/hNglmOigKhyEZtBmbraLE4GK1J8=
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
Expand Down Expand Up @@ -119,10 +129,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
Expand Down
8 changes: 8 additions & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Metrics struct {
EC2DescribeInstanceCallCount prometheus.Counter
StsConnectionFailure *prometheus.CounterVec
StsResponses *prometheus.CounterVec
StsDisableRegionRequests prometheus.Counter
DynamicFileFailures prometheus.Counter
StsThrottling *prometheus.CounterVec
E2ELatency *prometheus.HistogramVec
Expand Down Expand Up @@ -86,6 +87,13 @@ func createMetrics(reg prometheus.Registerer) Metrics {
Help: "Sts responses with error code label",
}, []string{"ResponseCode", "StsRegion"},
),
StsDisableRegionRequests: factory.NewCounter(
prometheus.CounterOpts{
Name: "sts_disabled_region_call",
Namespace: Namespace,
Help: "Number of STS calls made to regions that are disabled / disabling",
},
),
Latency: factory.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: Namespace,
Expand Down
34 changes: 33 additions & 1 deletion pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (

awsconfig "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/account"
"github.com/aws/aws-sdk-go-v2/service/account/types"
"sigs.k8s.io/aws-iam-authenticator/pkg/config"
"sigs.k8s.io/aws-iam-authenticator/pkg/ec2provider"
"sigs.k8s.io/aws-iam-authenticator/pkg/errutil"
Expand Down Expand Up @@ -78,6 +80,7 @@ type handler struct {
backendModeConfigInitDone bool
scrubbedAccounts []string
cfg config.Config
disabledRegions map[string]bool
}

// New authentication webhook server.
Expand Down Expand Up @@ -216,14 +219,21 @@ func (c *Server) getHandler(ctx context.Context, backendMapper BackendMapper, ec
instanceRegion = instanceRegionOutput.Region
}

acctClient := account.NewFromConfig(cfg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would need additional permissions which could be breaking change. Is there a need for this, can we get any information based on failure code from sts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today, such cross region calls do not fail, but they succeed as the bearer token that we validate is simply a presignedURL. Just tried reproducing this behavior locally,

  1. Use account A with region HKG
$ aws-iam-authenticator token -i 126db5ea-e932-4251-b738-818fee4ed20c --role arn:aws:iam::509399613853:role/Admin --token-only --region ap-east-1
  1. Use the generated token and validate the with credentials exported for account B
$ aws-iam-authenticator verify -t <token> -i 126db5ea-e932-4251-b738-818fee4ed20c
Response:
&{ARN:arn:aws:sts::509399613853:assumed-role/Admin/aws-go-sdk-1756362745475065571 CanonicalARN:arn:aws:iam::509399613853:role/Admin AccountID:509399613853 UserID:AROAXNGUVIGO4AYZOL27A SessionName:aws-go-sdk-1756362745475065571 AccessKeyID:ASIAXNGUVIGOZP6UQQZD}

There is no error from STS to enforce this behavior. I could make it fail silently just like when imds clients are unavailable ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iam roles are global, is there a reason we think token from one region should not be allowed in other region? We have separation at the partition level currently.

disabledRegions, err := listDisabledRegions(ctx, acctClient)
if err != nil {
logrus.Errorf("failed to list region status for account : %v", err)
}

h := &handler{
verifier: token.NewVerifier(c.ClusterID, c.PartitionID, instanceRegion),
verifier: token.NewVerifier(c.ClusterID, c.PartitionID, instanceRegion, disabledRegions),
ec2Provider: ec2provider.New(ctx, c.ServerEC2DescribeInstancesRoleARN, c.SourceARN, instanceRegion, ec2DescribeQps, ec2DescribeBurst),
clusterID: c.ClusterID,
backendMapper: backendMapper,
scrubbedAccounts: c.Config.ScrubbedAWSAccounts,
cfg: c.Config,
backendModeConfigInitDone: false,
disabledRegions: disabledRegions,
}

h.HandleFunc("/authenticate", func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -242,6 +252,28 @@ func (c *Server) getHandler(ctx context.Context, backendMapper BackendMapper, ec
return h
}

func listDisabledRegions(ctx context.Context, client *account.Client) (map[string]bool, error) {
disabledRegions := make(map[string]bool)
listInput := &account.ListRegionsInput{
RegionOptStatusContains: []types.RegionOptStatus{types.RegionOptStatusDisabled, types.RegionOptStatusDisabling},
}

for {
listResult, err := client.ListRegions(ctx, listInput)
if err != nil {
return nil, fmt.Errorf("Error listing region status for account %v", err)
}
for _, res := range listResult.Regions {
disabledRegions[*res.RegionName] = true
}
if listResult.NextToken == nil {
break
}
}
return disabledRegions, nil

}

func BuildMapperChain(cfg config.Config, modes []string) (BackendMapper, error) {
backendMapper := BackendMapper{
mappers: []mapper.Mapper{},
Expand Down
10 changes: 9 additions & 1 deletion pkg/token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ type tokenVerifier struct {
partition string
region string
mutex sync.RWMutex
disabledRegions map[string]bool
}

// Returns the hostnames (regular and dualstack) for a service given a certain region and partition.
Expand Down Expand Up @@ -458,7 +459,7 @@ func validateInputRegion(region string) bool {
}

// NewVerifier creates a Verifier that is bound to the clusterID and uses the default http client.
func NewVerifier(clusterID, partitionID, region string) Verifier {
func NewVerifier(clusterID, partitionID, region string, disabledRegions map[string]bool) Verifier {
// Initialize metrics if they haven't already been initialized to avoid a
// nil pointer panic when setting metric values.
if !metrics.Initialized() {
Expand All @@ -476,6 +477,7 @@ func NewVerifier(clusterID, partitionID, region string) Verifier {
validSTShostnames: make(map[string]bool),
partition: partitionID,
region: region,
disabledRegions: disabledRegions,
}
}

Expand Down Expand Up @@ -623,6 +625,12 @@ func (v *tokenVerifier) Verify(token string) (*Identity, error) {
return nil, err
}

if v.disabledRegions != nil {
if _, ok := v.disabledRegions[stsRegion]; ok {
metrics.Get().StsDisableRegionRequests.Inc()
}
}

if parsedURL.Path != "/" {
return nil, FormatError{"unexpected path in pre-signed URL"}
}
Expand Down
49 changes: 45 additions & 4 deletions pkg/token/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/pkg/apis/clientauthentication"
clientauthv1 "k8s.io/client-go/pkg/apis/clientauthentication/v1"
Expand All @@ -40,7 +41,7 @@ func TestMain(m *testing.M) {
func validationErrorTest(t *testing.T, partition string, token string, expectedErr string) {
t.Helper()

_, err := NewVerifier("", partition, "").(*tokenVerifier).Verify(token)
_, err := NewVerifier("", partition, "", nil).(*tokenVerifier).Verify(token)
errorContains(t, err, expectedErr)
}

Expand All @@ -55,6 +56,45 @@ func validationSuccessTest(t *testing.T, partition, token string) {
}
}

func validationDisabledRegionMetricsTest(t *testing.T, partition, token string) {
t.Helper()
arn := "arn:aws:iam::123456789012:user/Alice"
account := "123456789012"
userID := "Alice"

body := jsonResponse(arn, account, userID)
statusCode := 200

var rc io.ReadCloser
if body != "" {
rc = io.NopCloser(bytes.NewReader([]byte(body)))
}
verifier := &tokenVerifier{
client: &http.Client{
Transport: &roundTripper{
err: nil,
resp: &http.Response{
StatusCode: statusCode,
Body: rc,
},
},
},
validSTShostnames: make(map[string]bool),
partition: partition,
disabledRegions: map[string]bool{"sa-east-1": true},
}

_, err := verifier.Verify(token)
if err != nil {
t.Errorf("received unexpected error: %s", err)
}

if value := testutil.ToFloat64(metrics.Get().StsDisableRegionRequests); value != 1.0 {
t.Errorf("disable region requests metrics value must be 1")
}

}

func errorContains(t *testing.T, err error, expectedErr string) {
t.Helper()
if err == nil || !strings.Contains(err.Error(), expectedErr) {
Expand Down Expand Up @@ -219,7 +259,7 @@ func TestSTSEndpoints(t *testing.T) {
}

for _, c := range cases {
verifier := NewVerifier("", c.partition, c.region).(*tokenVerifier)
verifier := NewVerifier("", c.partition, c.region, nil).(*tokenVerifier)
err := verifier.verifyHost(c.domain)
if err != nil && c.valid {
t.Errorf("%s is not valid endpoint for partition %s, %v", c.domain, c.partition, err)
Expand Down Expand Up @@ -262,7 +302,7 @@ func TestSTSEndpointResolution(t *testing.T) {
}

for _, c := range cases {
verifier := NewVerifier("", c.partition, c.region).(*tokenVerifier)
verifier := NewVerifier("", c.partition, c.region, nil).(*tokenVerifier)
err := verifier.verifyHost(c.domain)
if err != nil && c.valid {
t.Errorf("%s is not valid endpoint for partition %s, %v", c.domain, c.partition, err)
Expand Down Expand Up @@ -297,6 +337,7 @@ func TestVerifyTokenPreSTSValidations(t *testing.T) {
validationSuccessTest(t, "aws", toToken(fmt.Sprintf("https://sts.ca-central-1.amazonaws.com/?action=GetCallerIdentity&x-amz-signedheaders=x-k8s-aws-id&x-amz-date=%s&x-amz-expires=60", timeStr)))
validationSuccessTest(t, "aws", toToken(fmt.Sprintf("https://sts.eu-west-1.amazonaws.com/?action=GetCallerIdentity&x-amz-signedheaders=x-k8s-aws-id&x-amz-date=%s&x-amz-expires=60", timeStr)))
validationSuccessTest(t, "aws", toToken(fmt.Sprintf("https://sts.sa-east-1.amazonaws.com/?action=GetCallerIdentity&x-amz-signedheaders=x-k8s-aws-id&x-amz-date=%s&x-amz-expires=60", timeStr)))
validationDisabledRegionMetricsTest(t, "aws", toToken(fmt.Sprintf("https://sts.sa-east-1.amazonaws.com/?action=GetCallerIdentity&x-amz-signedheaders=x-k8s-aws-id&x-amz-date=%s&x-amz-expires=60", timeStr)))
validationErrorTest(t, "aws", toToken(fmt.Sprintf("https://sts.us-west-2.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAAAAAAAAAAAAAAAAA%%2F20220601%%2Fus-west-2%%2Fsts%%2Faws4_request&X-Amz-Date=%s&X-Amz-Expires=900&X-Amz-Security-Token=XXXXXXXXXXXXX&X-Amz-SignedHeaders=host%%3Bx-k8s-aws-id&x-amz-credential=eve&X-Amz-Signature=999999999999999999", timeStr)), "input token was not properly formatted: duplicate query parameter found:")
}

Expand Down Expand Up @@ -330,7 +371,7 @@ func TestVerifyNoRedirectsFollowed(t *testing.T) {
}))
defer ts.Close()

tokVerifier := NewVerifier("", "aws", "").(*tokenVerifier)
tokVerifier := NewVerifier("", "aws", "", nil).(*tokenVerifier)

resp, err := tokVerifier.client.Get(ts.URL)
if err != nil {
Expand Down