From 8855191052e1e5a0f1ef659ab0b88615321243b9 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 23 May 2023 17:56:52 -0400 Subject: [PATCH 01/24] Squash and Merge sso token provider code and unit test --- aws/credentials/ssocreds/sso_cached_token.go | 215 ++++++++++++++++ .../ssocreds/sso_cached_token_test.go | 188 ++++++++++++++ .../ssocreds/testdata/expired_token.json | 8 + .../ssocreds/testdata/invalid_json.json | 1 + .../testdata/missing_accessToken.json | 7 + .../ssocreds/testdata/missing_clientId.json | 7 + .../testdata/missing_clientSecret.json | 7 + .../ssocreds/testdata/missing_expiresAt.json | 7 + .../testdata/missing_refreshToken.json | 7 + .../ssocreds/testdata/valid_token.json | 13 + aws/credentials/ssocreds/token_provider.go | 141 +++++++++++ .../ssocreds/token_provider_test.go | 230 ++++++++++++++++++ 12 files changed, 831 insertions(+) create mode 100644 aws/credentials/ssocreds/sso_cached_token.go create mode 100644 aws/credentials/ssocreds/sso_cached_token_test.go create mode 100644 aws/credentials/ssocreds/testdata/expired_token.json create mode 100644 aws/credentials/ssocreds/testdata/invalid_json.json create mode 100644 aws/credentials/ssocreds/testdata/missing_accessToken.json create mode 100644 aws/credentials/ssocreds/testdata/missing_clientId.json create mode 100644 aws/credentials/ssocreds/testdata/missing_clientSecret.json create mode 100644 aws/credentials/ssocreds/testdata/missing_expiresAt.json create mode 100644 aws/credentials/ssocreds/testdata/missing_refreshToken.json create mode 100644 aws/credentials/ssocreds/testdata/valid_token.json create mode 100644 aws/credentials/ssocreds/token_provider.go create mode 100644 aws/credentials/ssocreds/token_provider_test.go diff --git a/aws/credentials/ssocreds/sso_cached_token.go b/aws/credentials/ssocreds/sso_cached_token.go new file mode 100644 index 00000000000..755c0179240 --- /dev/null +++ b/aws/credentials/ssocreds/sso_cached_token.go @@ -0,0 +1,215 @@ +package ssocreds + +import ( + "crypto/sha1" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/aws/aws-sdk-go/internal/shareddefaults" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "time" +) + +var osUserHomeDur = shareddefaults.UserHomeDir + +// StandardCachedTokenFilepath returns the filepath for the cached SSO token file, or +// error if unable get derive the path. Key that will be used to compute a SHA1 +// value that is hex encoded. +// +// Derives the filepath using the Key as: +// +// ~/.aws/sso/cache/.json +func StandardCachedTokenFilepath(key string) (string, error) { + homeDir := osUserHomeDur() + if len(homeDir) == 0 { + return "", fmt.Errorf("unable to get USER's home directory for cached token") + } + hash := sha1.New() + if _, err := hash.Write([]byte(key)); err != nil { + return "", fmt.Errorf("unable to compute cached token filepath key SHA1 hash, %w", err) + } + + cacheFilename := strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json" + + return filepath.Join(homeDir, ".aws", "sso", "cache", cacheFilename), nil +} + +type tokenKnownFields struct { + AccessToken string `json:"accessToken,omitempty"` + ExpiresAt *rfc3339 `json:"expiresAt,omitempty"` + + RefreshToken string `json:"refreshToken,omitempty"` + ClientID string `json:"clientId,omitempty"` + ClientSecret string `json:"clientSecret,omitempty"` +} + +type cachedToken struct { + tokenKnownFields + UnknownFields map[string]interface{} `json:"-"` +} + +func (t cachedToken) MarshalJSON() ([]byte, error) { + fields := map[string]interface{}{} + + setTokenFieldString(fields, "accessToken", t.AccessToken) + setTokenFieldRFC3339(fields, "expiresAt", t.ExpiresAt) + + setTokenFieldString(fields, "refreshToken", t.RefreshToken) + setTokenFieldString(fields, "clientId", t.ClientID) + setTokenFieldString(fields, "clientSecret", t.ClientSecret) + + for k, v := range t.UnknownFields { + if _, ok := fields[k]; ok { + return nil, fmt.Errorf("unknown token field %v, duplicates known field", k) + } + fields[k] = v + } + + return json.Marshal(fields) +} + +func setTokenFieldString(fields map[string]interface{}, key, value string) { + if value == "" { + return + } + fields[key] = value +} +func setTokenFieldRFC3339(fields map[string]interface{}, key string, value *rfc3339) { + if value == nil { + return + } + fields[key] = value +} + +func (t *cachedToken) UnmarshalJSON(b []byte) error { + var fields map[string]interface{} + if err := json.Unmarshal(b, &fields); err != nil { + return nil + } + + t.UnknownFields = map[string]interface{}{} + + for k, v := range fields { + var err error + switch k { + case "accessToken": + err = getTokenFieldString(v, &t.AccessToken) + case "expiresAt": + err = getTokenFieldRFC3339(v, &t.ExpiresAt) + case "refreshToken": + err = getTokenFieldString(v, &t.RefreshToken) + case "clientId": + err = getTokenFieldString(v, &t.ClientID) + case "clientSecret": + err = getTokenFieldString(v, &t.ClientSecret) + default: + t.UnknownFields[k] = v + } + + if err != nil { + return fmt.Errorf("field %q, %w", k, err) + } + } + + return nil +} + +func getTokenFieldString(v interface{}, value *string) error { + var ok bool + *value, ok = v.(string) + if !ok { + return fmt.Errorf("expect value to be string, got %T", v) + } + return nil +} + +func getTokenFieldRFC3339(v interface{}, value **rfc3339) error { + var stringValue string + if err := getTokenFieldString(v, &stringValue); err != nil { + return err + } + + timeValue, err := parseRFC3339(stringValue) + if err != nil { + return err + } + + *value = &timeValue + return nil +} + +func loadCachedAccessToken(filename string) (cachedToken, error) { + fileBytes, err := ioutil.ReadFile(filename) + if err != nil { + return cachedToken{}, fmt.Errorf("failed to read cached SSO token file, %w", err) + } + + var t cachedToken + if err := json.Unmarshal(fileBytes, &t); err != nil { + return cachedToken{}, fmt.Errorf("failed to parse cached SSO token file, %w", err) + } + + if len(t.AccessToken) == 0 || t.ExpiresAt == nil || time.Time(*t.ExpiresAt).IsZero() { + return cachedToken{}, fmt.Errorf( + "cached SSO token must contain accessToken and expiresAt fields") + } + + return t, nil +} + +func storeCachedToken(filename string, t cachedToken, fileMode os.FileMode) (err error) { + tmpFilename := filename + ".tmp-" + strconv.FormatInt(nowTime().UnixNano(), 10) + if err := writeCacheFile(tmpFilename, fileMode, t); err != nil { + return err + } + + if err := os.Rename(tmpFilename, filename); err != nil { + return fmt.Errorf("failed to replace old cached SSO token file, %w", err) + } + + return nil +} + +func writeCacheFile(filename string, fileMode os.FileMode, t cachedToken) (err error) { + var f *os.File + f, err = os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_RDWR, fileMode) + if err != nil { + return fmt.Errorf("failed to create cached SSO token file %w", err) + } + + defer func() { + closeErr := f.Close() + if err == nil && closeErr != nil { + err = fmt.Errorf("failed to close cached SSO token file, %w", closeErr) + } + }() + + encoder := json.NewEncoder(f) + + if err = encoder.Encode(t); err != nil { + return fmt.Errorf("failed to serialize cached SSO token, %w", err) + } + + return nil +} + +func parseRFC3339(v string) (rfc3339, error) { + parsed, err := time.Parse(time.RFC3339, v) + if err != nil { + return rfc3339{}, fmt.Errorf("expected RFC3339 timestamp: %w", err) + } + + return rfc3339(parsed), nil +} + +func (r *rfc3339) MarshalJSON() ([]byte, error) { + value := time.Time(*r).Format(time.RFC3339) + + // Use JSON unmarshal to unescape the quoted value making use of JSON's + // quoting rules. + return json.Marshal(value) +} diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go new file mode 100644 index 00000000000..509fb48049c --- /dev/null +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -0,0 +1,188 @@ +package ssocreds + +import ( + "github.com/aws/smithy-go/ptr" + "github.com/google/go-cmp/cmp" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + "time" +) + +var tokenCmpOptions = cmp.Options{ + cmp.AllowUnexported(cachedToken{}, tokenKnownFields{}, rfc3339{}), +} + +func TestStandardSSOCacheTokenFilepath(t *testing.T) { + origHomeDur := osUserHomeDur + defer func() { + osUserHomeDur = origHomeDur + }() + + cases := map[string]struct { + key string + osUserHomeDir func() string + expectFilename string + expectErr string + }{ + "success": { + key: "https://example.awsapps.com/start", + osUserHomeDir: func() string { + return os.TempDir() + }, + expectFilename: filepath.Join(os.TempDir(), ".aws", "sso", "cache", + "e8be5486177c5b5392bd9aa76563515b29358e6e.json"), + }, + "failure": { + key: "https://example.awsapps.com/start", + osUserHomeDir: func() string { + return "" + }, + expectErr: "some error", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + osUserHomeDur = c.osUserHomeDir + + actual, err := StandardCachedTokenFilepath(c.key) + if c.expectErr != "" { + if err == nil { + t.Fatalf("expect error, got none") + } + return + } + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if e, a := c.expectFilename, actual; e != a { + t.Errorf("expect %v filename, got %v", e, a) + } + }) + } +} + +func TestLoadCachedToken(t *testing.T) { + cases := map[string]struct { + filename string + expectToken cachedToken + expectErr string + }{ + "file not found": { + filename: filepath.Join("testdata", "does_not_exist.json"), + expectErr: "failed to read cached SSO token file", + }, + "invalid json": { + filename: filepath.Join("testdata", "invalid_json.json"), + expectErr: "failed to parse cached SSO token file", + }, + "missing accessToken": { + filename: filepath.Join("testdata", "missing_accessToken.json"), + expectErr: "must contain accessToken and expiresAt fields", + }, + "missing expiresAt": { + filename: filepath.Join("testdata", "missing_expiresAt.json"), + expectErr: "must contain accessToken and expiresAt fields", + }, + "standard token": { + filename: filepath.Join("testdata", "valid_token.json"), + expectToken: cachedToken{ + tokenKnownFields: tokenKnownFields{ + AccessToken: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", + ExpiresAt: (*rfc3339)(ptr.Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), + ClientID: "client id", + ClientSecret: "client secret", + RefreshToken: "refresh token", + }, + UnknownFields: map[string]interface{}{ + "unknownField": "some value", + "registrationExpiresAt": "2044-04-04T07:00:01Z", + "region": "region", + "startURL": "start URL", + }, + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + actualToken, err := loadCachedAccessToken(c.filename) + if c.expectErr != "" { + if err == nil { + t.Fatalf("expect %v error, got none", c.expectErr) + } + if e, a := c.expectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect %v error, got %v", e, a) + } + return + } + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if diff := cmp.Diff(c.expectToken, actualToken, tokenCmpOptions...); diff != "" { + t.Errorf("expect tokens match\n%s", diff) + } + }) + } +} + +func TestStoreCachedToken(t *testing.T) { + tempDir, err := ioutil.TempDir(os.TempDir(), "aws-sdk-go-"+t.Name()) + if err != nil { + t.Fatalf("failed to create temporary test directory, %v", err) + } + defer func() { + if err := os.RemoveAll(tempDir); err != nil { + t.Errorf("failed to cleanup temporary test directory, %v", err) + } + }() + + cases := map[string]struct { + token cachedToken + filename string + fileMode os.FileMode + }{ + "standard token": { + filename: filepath.Join(tempDir, "token_file.json"), + fileMode: 0600, + token: cachedToken{ + tokenKnownFields: tokenKnownFields{ + AccessToken: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", + ExpiresAt: (*rfc3339)(ptr.Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), + ClientID: "client id", + ClientSecret: "client secret", + RefreshToken: "refresh token", + }, + UnknownFields: map[string]interface{}{ + "unknownField": "some value", + "registrationExpiresAt": "2044-04-04T07:00:01Z", + "region": "region", + "startURL": "start URL", + }, + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + err := storeCachedToken(c.filename, c.token, c.fileMode) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + actual, err := loadCachedAccessToken(c.filename) + if err != nil { + t.Fatalf("failed to load stored token, %v", err) + } + + if diff := cmp.Diff(c.token, actual, tokenCmpOptions...); diff != "" { + t.Errorf("expect tokens match\n%s", diff) + } + }) + } +} diff --git a/aws/credentials/ssocreds/testdata/expired_token.json b/aws/credentials/ssocreds/testdata/expired_token.json new file mode 100644 index 00000000000..7e648605571 --- /dev/null +++ b/aws/credentials/ssocreds/testdata/expired_token.json @@ -0,0 +1,8 @@ +{ + "accessToken": "expired access token", + "expiresAt": "2021-12-21T12:21:00Z", + "clientId": "client id", + "clientSecret": "client secret", + "refreshToken": "refresh token", + "unknownField": "some value" +} diff --git a/aws/credentials/ssocreds/testdata/invalid_json.json b/aws/credentials/ssocreds/testdata/invalid_json.json new file mode 100644 index 00000000000..98232c64fce --- /dev/null +++ b/aws/credentials/ssocreds/testdata/invalid_json.json @@ -0,0 +1 @@ +{ diff --git a/aws/credentials/ssocreds/testdata/missing_accessToken.json b/aws/credentials/ssocreds/testdata/missing_accessToken.json new file mode 100644 index 00000000000..dba6cace2ad --- /dev/null +++ b/aws/credentials/ssocreds/testdata/missing_accessToken.json @@ -0,0 +1,7 @@ +{ + "clientId": "client id", + "clientSecret": "client secret", + "refreshToken": "refresh token", + "missing_accessToken": "access token", + "expiresAt": "2044-04-04T07:00:01Z" +} diff --git a/aws/credentials/ssocreds/testdata/missing_clientId.json b/aws/credentials/ssocreds/testdata/missing_clientId.json new file mode 100644 index 00000000000..76dadfcfe42 --- /dev/null +++ b/aws/credentials/ssocreds/testdata/missing_clientId.json @@ -0,0 +1,7 @@ +{ + "missing_clientId": "client id", + "clientSecret": "client secret", + "refreshToken": "refresh token", + "accessToken": "access token", + "expiresAt": "2021-12-21T12:21:00Z" +} diff --git a/aws/credentials/ssocreds/testdata/missing_clientSecret.json b/aws/credentials/ssocreds/testdata/missing_clientSecret.json new file mode 100644 index 00000000000..aa28fc9f046 --- /dev/null +++ b/aws/credentials/ssocreds/testdata/missing_clientSecret.json @@ -0,0 +1,7 @@ +{ + "clientId": "client id", + "missing_clientSecret": "client secret", + "refreshToken": "refresh token", + "accessToken": "access token", + "expiresAt": "2021-12-21T12:21:00Z" +} diff --git a/aws/credentials/ssocreds/testdata/missing_expiresAt.json b/aws/credentials/ssocreds/testdata/missing_expiresAt.json new file mode 100644 index 00000000000..cd578891273 --- /dev/null +++ b/aws/credentials/ssocreds/testdata/missing_expiresAt.json @@ -0,0 +1,7 @@ +{ + "clientId": "client id", + "clientSecret": "client secret", + "refreshToken": "refresh token", + "accessToken": "access token", + "missing_expiresAt": "2044-04-04T07:00:01Z" +} diff --git a/aws/credentials/ssocreds/testdata/missing_refreshToken.json b/aws/credentials/ssocreds/testdata/missing_refreshToken.json new file mode 100644 index 00000000000..9afcff7465d --- /dev/null +++ b/aws/credentials/ssocreds/testdata/missing_refreshToken.json @@ -0,0 +1,7 @@ +{ + "clientId": "client id", + "clientSecret": "client secret", + "missing_refreshToken": "refresh token", + "accessToken": "access token", + "expiresAt": "2021-12-21T12:21:00Z" +} diff --git a/aws/credentials/ssocreds/testdata/valid_token.json b/aws/credentials/ssocreds/testdata/valid_token.json new file mode 100644 index 00000000000..528d11c4f10 --- /dev/null +++ b/aws/credentials/ssocreds/testdata/valid_token.json @@ -0,0 +1,13 @@ +{ + "accessToken": "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", + "expiresAt": "2044-04-04T07:00:01Z", + + "refreshToken": "refresh token", + "clientId": "client id", + "clientSecret": "client secret", + + "unknownField": "some value", + "region": "region", + "registrationExpiresAt": "2044-04-04T07:00:01Z", + "startURL": "start URL" +} diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go new file mode 100644 index 00000000000..3b9075a5e52 --- /dev/null +++ b/aws/credentials/ssocreds/token_provider.go @@ -0,0 +1,141 @@ +package ssocreds + +import ( + "context" + "fmt" + "github.com/aws/smithy-go/ptr" + "os" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ssooidc" + "github.com/aws/smithy-go/auth/bearer" +) + +// CreateTokenAPIClient provides the interface for the SSOTokenProvider's API +// client for calling CreateToken operation to refresh the SSO token. +type CreateTokenAPIClient interface { + CreateToken(input *ssooidc.CreateTokenInput) (*ssooidc.CreateTokenOutput, error) +} + +// SSOTokenProviderOptions provides the options for configuring the +// SSOTokenProvider. +type SSOTokenProviderOptions struct { + // Client that can be overridden + Client CreateTokenAPIClient + + // The path the file containing the cached SSO token will be read from. + // Initialized the NewSSOTokenProvider's cachedTokenFilepath parameter. + CachedTokenFilepath string +} + +// SSOTokenProvider provides a utility for refreshing SSO AccessTokens for +// Bearer Authentication. The SSOTokenProvider can only be used to refresh +// already cached SSO Tokens. This utility cannot perform the initial SSO +// create token. +// +// The SSOTokenProvider is not safe to use concurrently. It must be wrapped in +// a utility such as smithy-go's auth/bearer#TokenCache. The SDK's +// config.LoadDefaultConfig will automatically wrap the SSOTokenProvider with +// the smithy-go TokenCache, if the external configuration loaded configured +// for an SSO session. +// +// The initial SSO create token should be preformed with the AWS CLI before the +// Go application using the SSOTokenProvider will need to retrieve the SSO +// token. If the AWS CLI has not created the token cache file, this provider +// will return an error when attempting to retrieve the cached token. +// +// This provider will attempt to refresh the cached SSO token periodically if +// needed when RetrieveBearerToken is called. +// +// A utility such as the AWS CLI must be used to initially create the SSO +// session and cached token file. +// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html +type SSOTokenProvider struct { + options SSOTokenProviderOptions +} + +var _ bearer.TokenProvider = (*SSOTokenProvider)(nil) + +// NewSSOTokenProvider returns an initialized SSOTokenProvider that will +// periodically refresh the SSO token cached stored in the cachedTokenFilepath. +// The cachedTokenFilepath file's content will be rewritten by the token +// provider when the token is refreshed. +// +// The client must be configured for the AWS region the SSO token was created for. +func NewSSOTokenProvider(client CreateTokenAPIClient, cachedTokenFilepath string, optFns ...func(o *SSOTokenProviderOptions)) *SSOTokenProvider { + options := SSOTokenProviderOptions{ + Client: client, + CachedTokenFilepath: cachedTokenFilepath, + } + for _, fn := range optFns { + fn(&options) + } + + provider := &SSOTokenProvider{ + options: options, + } + + return provider +} + +// RetrieveBearerToken returns the SSO token stored in the cachedTokenFilepath +// the SSOTokenProvider was created with. If the token has expired +// RetrieveBearerToken will attempt to refresh it. If the token cannot be +// refreshed or is not present an error will be returned. +// +// A utility such as the AWS CLI must be used to initially create the SSO +// session and cached token file. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html +func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (bearer.Token, error) { + cachedToken, err := loadCachedAccessToken(p.options.CachedTokenFilepath) + if err != nil { + return bearer.Token{}, err + } + + if cachedToken.ExpiresAt != nil && nowTime().After(time.Time(*cachedToken.ExpiresAt)) { + cachedToken, err = p.refreshToken(cachedToken) + if err != nil { + return bearer.Token{}, fmt.Errorf("refresh cached SSO token failed, %w", err) + } + } + + expiresAt := ptr.ToTime((*time.Time)(cachedToken.ExpiresAt)) + return bearer.Token{ + Value: cachedToken.AccessToken, + CanExpire: !expiresAt.IsZero(), + Expires: expiresAt, + }, nil +} + +func (p SSOTokenProvider) refreshToken(token cachedToken) (cachedToken, error) { + if token.ClientSecret == "" || token.ClientID == "" || token.RefreshToken == "" { + return cachedToken{}, fmt.Errorf("cached SSO token is expired, or not present, and cannot be refreshed") + } + + createResult, err := p.options.Client.CreateToken(&ssooidc.CreateTokenInput{ + ClientId: &token.ClientID, + ClientSecret: &token.ClientSecret, + RefreshToken: &token.RefreshToken, + GrantType: aws.String("refresh_token"), + }) + if err != nil { + return cachedToken{}, fmt.Errorf("unable to refresh SSO token, %w", err) + } + + expiresAt := nowTime().Add(time.Duration(*createResult.ExpiresIn) * time.Second) + + token.AccessToken = *createResult.AccessToken + token.ExpiresAt = (*rfc3339)(&expiresAt) + token.RefreshToken = *createResult.RefreshToken + + fileInfo, err := os.Stat(p.options.CachedTokenFilepath) + if err != nil { + return cachedToken{}, fmt.Errorf("failed to stat cached SSO token file %w", err) + } + + if err = storeCachedToken(p.options.CachedTokenFilepath, token, fileInfo.Mode()); err != nil { + return cachedToken{}, fmt.Errorf("unable to cache refreshed SSO token, %w", err) + } + + return token, nil +} diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go new file mode 100644 index 00000000000..698d5553aac --- /dev/null +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -0,0 +1,230 @@ +//go:build go1.16 +// +build go1.16 + +package ssocreds + +import ( + "context" + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ssooidc" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + "time" + + smithybearer "github.com/aws/smithy-go/auth/bearer" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +func TestSSOTokenProvider(t *testing.T) { + restoreTime := swapNowTime(time.Date(2021, 12, 21, 12, 21, 1, 0, time.UTC)) + defer restoreTime() + + tempDir, err := ioutil.TempDir(os.TempDir(), "aws-sdk-go-"+t.Name()) + if err != nil { + t.Fatalf("failed to create temporary test directory, %v", err) + } + defer func() { + if err := os.RemoveAll(tempDir); err != nil { + t.Errorf("failed to cleanup temporary test directory, %v", err) + } + }() + + cases := map[string]struct { + setup func() error + postRetrieve func() error + client CreateTokenAPIClient + cacheFilePath string + optFns []func(*SSOTokenProviderOptions) + + expectToken smithybearer.Token + expectErr string + }{ + "no cache file": { + cacheFilePath: filepath.Join("testdata", "file_not_exists"), + expectErr: "failed to read cached SSO token file", + }, + "invalid json cache file": { + cacheFilePath: filepath.Join("testdata", "invalid_json.json"), + expectErr: "failed to parse cached SSO token file", + }, + "missing accessToken": { + cacheFilePath: filepath.Join("testdata", "missing_accessToken.json"), + expectErr: "must contain accessToken and expiresAt fields", + }, + "missing expiresAt": { + cacheFilePath: filepath.Join("testdata", "missing_expiresAt.json"), + expectErr: "must contain accessToken and expiresAt fields", + }, + "expired no clientSecret": { + cacheFilePath: filepath.Join("testdata", "missing_clientSecret.json"), + expectErr: "cached SSO token is expired, or not present", + }, + "expired no clientId": { + cacheFilePath: filepath.Join("testdata", "missing_clientId.json"), + expectErr: "cached SSO token is expired, or not present", + }, + "expired no refreshToken": { + cacheFilePath: filepath.Join("testdata", "missing_refreshToken.json"), + expectErr: "cached SSO token is expired, or not present", + }, + "valid sso token": { + cacheFilePath: filepath.Join("testdata", "valid_token.json"), + expectToken: smithybearer.Token{ + Value: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", + CanExpire: true, + Expires: time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC), + }, + }, + "refresh expired token": { + setup: func() error { + testFile, err := os.ReadFile(filepath.Join("testdata", "expired_token.json")) + if err != nil { + return err + } + + return os.WriteFile(filepath.Join(tempDir, "expired_token.json"), testFile, 0600) + }, + postRetrieve: func() error { + actual, err := loadCachedAccessToken(filepath.Join(tempDir, "expired_token.json")) + if err != nil { + return err + + } + expect := cachedToken{ + tokenKnownFields: tokenKnownFields{ + AccessToken: "updated access token", + ExpiresAt: (*rfc3339)(aws.Time(time.Date(2021, 12, 21, 12, 31, 1, 0, time.UTC))), + + RefreshToken: "updated refresh token", + ClientID: "client id", + ClientSecret: "client secret", + }, + UnknownFields: map[string]interface{}{ + "unknownField": "some value", + }, + } + + if diff := cmp.Diff(expect, actual, tokenCmpOptions...); diff != "" { + return fmt.Errorf("expect token file match\n%s", diff) + } + return nil + }, + cacheFilePath: filepath.Join(tempDir, "expired_token.json"), + client: &mockCreateTokenAPIClient{ + expectInput: &ssooidc.CreateTokenInput{ + ClientId: aws.String("client id"), + ClientSecret: aws.String("client secret"), + RefreshToken: aws.String("refresh token"), + GrantType: aws.String("refresh_token"), + }, + output: &ssooidc.CreateTokenOutput{ + AccessToken: aws.String("updated access token"), + ExpiresIn: aws.Int64(600), + RefreshToken: aws.String("updated refresh token"), + }, + }, + expectToken: smithybearer.Token{ + Value: "updated access token", + CanExpire: true, + Expires: time.Date(2021, 12, 21, 12, 31, 1, 0, time.UTC), + }, + }, + "fail refresh expired token": { + setup: func() error { + testFile, err := os.ReadFile(filepath.Join("testdata", "expired_token.json")) + if err != nil { + return err + } + return os.WriteFile(filepath.Join(tempDir, "expired_token.json"), testFile, 0600) + }, + postRetrieve: func() error { + actual, err := loadCachedAccessToken(filepath.Join(tempDir, "expired_token.json")) + if err != nil { + return err + + } + expect := cachedToken{ + tokenKnownFields: tokenKnownFields{ + AccessToken: "access token", + ExpiresAt: (*rfc3339)(aws.Time(time.Date(2021, 12, 21, 12, 21, 1, 0, time.UTC))), + + RefreshToken: "refresh token", + ClientID: "client id", + ClientSecret: "client secret", + }, + } + + if diff := cmp.Diff(expect, actual, tokenCmpOptions...); diff != "" { + return fmt.Errorf("expect token file match\n%s", diff) + } + return nil + }, + cacheFilePath: filepath.Join(tempDir, "expired_token.json"), + client: &mockCreateTokenAPIClient{ + err: fmt.Errorf("sky is falling"), + }, + expectErr: "unable to refresh SSO token, sky is falling", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + if c.setup != nil { + if err := c.setup(); err != nil { + t.Fatalf("failed to setup test, %v", err) + } + } + provider := NewSSOTokenProvider(c.client, c.cacheFilePath, c.optFns...) + + token, err := provider.RetrieveBearerToken(context.Background()) + if c.expectErr != "" { + if err == nil { + t.Fatalf("expect %v error, got none", c.expectErr) + } + if e, a := c.expectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect %v error, got %v", e, a) + } + return + } + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if diff := cmp.Diff(c.expectToken, token, tokenCmpOptions...); diff != "" { + t.Errorf("expect token match\n%s", diff) + } + + if c.postRetrieve != nil { + if err := c.postRetrieve(); err != nil { + t.Fatalf("post retrieve failed, %v", err) + } + } + }) + } +} + +type mockCreateTokenAPIClient struct { + expectInput *ssooidc.CreateTokenInput + output *ssooidc.CreateTokenOutput + err error +} + +func (c *mockCreateTokenAPIClient) CreateToken(input *ssooidc.CreateTokenInput) ( + *ssooidc.CreateTokenOutput, error, +) { + if c.expectInput != nil { + opts := cmp.Options{ + cmpopts.IgnoreUnexported(ssooidc.CreateTokenInput{}), + } + if diff := cmp.Diff(c.expectInput, input, opts...); diff != "" { + return nil, fmt.Errorf("expect input match\n%s", diff) + } + } + + return c.output, c.err +} From 3bf12a6794a7c74f8585089513ad986fd72be3ce Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 23 May 2023 22:50:03 -0400 Subject: [PATCH 02/24] Squash and Merge ssocred rfc3339 code location change --- aws/credentials/ssocreds/provider.go | 20 -------------------- aws/credentials/ssocreds/sso_cached_token.go | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/aws/credentials/ssocreds/provider.go b/aws/credentials/ssocreds/provider.go index 6eda2a5557f..95de5520f09 100644 --- a/aws/credentials/ssocreds/provider.go +++ b/aws/credentials/ssocreds/provider.go @@ -4,7 +4,6 @@ import ( "crypto/sha1" "encoding/hex" "encoding/json" - "fmt" "io/ioutil" "path/filepath" "strings" @@ -123,25 +122,6 @@ func getCacheFileName(url string) (string, error) { return strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json", nil } -type rfc3339 time.Time - -func (r *rfc3339) UnmarshalJSON(bytes []byte) error { - var value string - - if err := json.Unmarshal(bytes, &value); err != nil { - return err - } - - parse, err := time.Parse(time.RFC3339, value) - if err != nil { - return fmt.Errorf("expected RFC3339 timestamp: %v", err) - } - - *r = rfc3339(parse) - - return nil -} - type token struct { AccessToken string `json:"accessToken"` ExpiresAt rfc3339 `json:"expiresAt"` diff --git a/aws/credentials/ssocreds/sso_cached_token.go b/aws/credentials/ssocreds/sso_cached_token.go index 755c0179240..6c4b9562034 100644 --- a/aws/credentials/ssocreds/sso_cached_token.go +++ b/aws/credentials/ssocreds/sso_cached_token.go @@ -197,6 +197,25 @@ func writeCacheFile(filename string, fileMode os.FileMode, t cachedToken) (err e return nil } +type rfc3339 time.Time + +func (r *rfc3339) UnmarshalJSON(bytes []byte) error { + var value string + + if err := json.Unmarshal(bytes, &value); err != nil { + return err + } + + parse, err := time.Parse(time.RFC3339, value) + if err != nil { + return fmt.Errorf("expected RFC3339 timestamp: %v", err) + } + + *r = rfc3339(parse) + + return nil +} + func parseRFC3339(v string) (rfc3339, error) { parsed, err := time.Parse(time.RFC3339, v) if err != nil { From 9e666eabfebe1b8f54e2c99be1c87708ca69bc76 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 23 May 2023 23:09:51 -0400 Subject: [PATCH 03/24] Squash and Merge pending changelog content --- CHANGELOG_PENDING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 8a1927a39ca..7208a1147b7 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,3 +3,5 @@ ### SDK Enhancements ### SDK Bugs +* `ssocreds`: Add sso token provider logic. + * This new feature will be used to support sso-session section config \ No newline at end of file From e3644bf83d359cb4655b8b5553d073dee5de61b4 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 24 May 2023 11:25:32 -0400 Subject: [PATCH 04/24] Deprecate smithy go dependency and Merge bearer token code --- .../ssocreds/sso_cached_token_test.go | 10 ++++--- aws/credentials/ssocreds/token_provider.go | 27 ++++++++++--------- .../ssocreds/token_provider_test.go | 7 +++-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index 509fb48049c..3a4d9c33013 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -1,7 +1,6 @@ package ssocreds import ( - "github.com/aws/smithy-go/ptr" "github.com/google/go-cmp/cmp" "io/ioutil" "os" @@ -93,7 +92,7 @@ func TestLoadCachedToken(t *testing.T) { expectToken: cachedToken{ tokenKnownFields: tokenKnownFields{ AccessToken: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", - ExpiresAt: (*rfc3339)(ptr.Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), + ExpiresAt: (*rfc3339)(Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), ClientID: "client id", ClientSecret: "client secret", RefreshToken: "refresh token", @@ -153,7 +152,7 @@ func TestStoreCachedToken(t *testing.T) { token: cachedToken{ tokenKnownFields: tokenKnownFields{ AccessToken: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", - ExpiresAt: (*rfc3339)(ptr.Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), + ExpiresAt: (*rfc3339)(Time(time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC))), ClientID: "client id", ClientSecret: "client secret", RefreshToken: "refresh token", @@ -186,3 +185,8 @@ func TestStoreCachedToken(t *testing.T) { }) } } + +// Time returns a pointer value for the time.Time value passed in. +func Time(v time.Time) *time.Time { + return &v +} diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index 3b9075a5e52..90e0b751f67 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -3,13 +3,11 @@ package ssocreds import ( "context" "fmt" - "github.com/aws/smithy-go/ptr" "os" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ssooidc" - "github.com/aws/smithy-go/auth/bearer" ) // CreateTokenAPIClient provides the interface for the SSOTokenProvider's API @@ -34,10 +32,9 @@ type SSOTokenProviderOptions struct { // already cached SSO Tokens. This utility cannot perform the initial SSO // create token. // -// The SSOTokenProvider is not safe to use concurrently. It must be wrapped in -// a utility such as smithy-go's auth/bearer#TokenCache. The SDK's +// The SSOTokenProvider is not safe to use concurrently. The SDK's // config.LoadDefaultConfig will automatically wrap the SSOTokenProvider with -// the smithy-go TokenCache, if the external configuration loaded configured +// the , if the external configuration loaded configured // for an SSO session. // // The initial SSO create token should be preformed with the AWS CLI before the @@ -55,8 +52,6 @@ type SSOTokenProvider struct { options SSOTokenProviderOptions } -var _ bearer.TokenProvider = (*SSOTokenProvider)(nil) - // NewSSOTokenProvider returns an initialized SSOTokenProvider that will // periodically refresh the SSO token cached stored in the cachedTokenFilepath. // The cachedTokenFilepath file's content will be rewritten by the token @@ -86,21 +81,21 @@ func NewSSOTokenProvider(client CreateTokenAPIClient, cachedTokenFilepath string // // A utility such as the AWS CLI must be used to initially create the SSO // session and cached token file. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html -func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (bearer.Token, error) { +func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (Token, error) { cachedToken, err := loadCachedAccessToken(p.options.CachedTokenFilepath) if err != nil { - return bearer.Token{}, err + return Token{}, err } if cachedToken.ExpiresAt != nil && nowTime().After(time.Time(*cachedToken.ExpiresAt)) { cachedToken, err = p.refreshToken(cachedToken) if err != nil { - return bearer.Token{}, fmt.Errorf("refresh cached SSO token failed, %w", err) + return Token{}, fmt.Errorf("refresh cached SSO token failed, %w", err) } } - expiresAt := ptr.ToTime((*time.Time)(cachedToken.ExpiresAt)) - return bearer.Token{ + expiresAt := ToTime((*time.Time)(cachedToken.ExpiresAt)) + return Token{ Value: cachedToken.AccessToken, CanExpire: !expiresAt.IsZero(), Expires: expiresAt, @@ -139,3 +134,11 @@ func (p SSOTokenProvider) refreshToken(token cachedToken) (cachedToken, error) { return token, nil } + +func ToTime(p *time.Time) (v time.Time) { + if p == nil { + return v + } + + return *p +} diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 698d5553aac..24cf1d492d5 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -15,7 +15,6 @@ import ( "testing" "time" - smithybearer "github.com/aws/smithy-go/auth/bearer" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" ) @@ -41,7 +40,7 @@ func TestSSOTokenProvider(t *testing.T) { cacheFilePath string optFns []func(*SSOTokenProviderOptions) - expectToken smithybearer.Token + expectToken Token expectErr string }{ "no cache file": { @@ -74,7 +73,7 @@ func TestSSOTokenProvider(t *testing.T) { }, "valid sso token": { cacheFilePath: filepath.Join("testdata", "valid_token.json"), - expectToken: smithybearer.Token{ + expectToken: Token{ Value: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", CanExpire: true, Expires: time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC), @@ -128,7 +127,7 @@ func TestSSOTokenProvider(t *testing.T) { RefreshToken: aws.String("updated refresh token"), }, }, - expectToken: smithybearer.Token{ + expectToken: Token{ Value: "updated access token", CanExpire: true, Expires: time.Date(2021, 12, 21, 12, 31, 1, 0, time.UTC), From 6354a341d0bfbbcb99eb135c77350dbc51a31f1f Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 24 May 2023 12:37:06 -0400 Subject: [PATCH 05/24] Deprecate go-cmp dependency --- .../ssocreds/sso_cached_token_test.go | 14 ++++------- .../ssocreds/token_provider_test.go | 23 ++++++++----------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index 3a4d9c33013..f6ad87a29a1 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -1,19 +1,15 @@ package ssocreds import ( - "github.com/google/go-cmp/cmp" "io/ioutil" "os" "path/filepath" + "reflect" "strings" "testing" "time" ) -var tokenCmpOptions = cmp.Options{ - cmp.AllowUnexported(cachedToken{}, tokenKnownFields{}, rfc3339{}), -} - func TestStandardSSOCacheTokenFilepath(t *testing.T) { origHomeDur := osUserHomeDur defer func() { @@ -123,8 +119,8 @@ func TestLoadCachedToken(t *testing.T) { t.Fatalf("expect no error, got %v", err) } - if diff := cmp.Diff(c.expectToken, actualToken, tokenCmpOptions...); diff != "" { - t.Errorf("expect tokens match\n%s", diff) + if !reflect.DeepEqual(c.expectToken, actualToken) { + t.Errorf("expect token file %v but got actual %v", c.expectToken, actualToken) } }) } @@ -179,8 +175,8 @@ func TestStoreCachedToken(t *testing.T) { t.Fatalf("failed to load stored token, %v", err) } - if diff := cmp.Diff(c.token, actual, tokenCmpOptions...); diff != "" { - t.Errorf("expect tokens match\n%s", diff) + if !reflect.DeepEqual(c.token, actual) { + t.Errorf("expect token file %v but got actual %v", c.token, actual) } }) } diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 24cf1d492d5..ccad411d741 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -11,12 +11,10 @@ import ( "io/ioutil" "os" "path/filepath" + "reflect" "strings" "testing" "time" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" ) func TestSSOTokenProvider(t *testing.T) { @@ -108,8 +106,8 @@ func TestSSOTokenProvider(t *testing.T) { }, } - if diff := cmp.Diff(expect, actual, tokenCmpOptions...); diff != "" { - return fmt.Errorf("expect token file match\n%s", diff) + if !reflect.DeepEqual(expect, actual) { + return fmt.Errorf("expect token file %v but got actual %v", expect, actual) } return nil }, @@ -158,8 +156,8 @@ func TestSSOTokenProvider(t *testing.T) { }, } - if diff := cmp.Diff(expect, actual, tokenCmpOptions...); diff != "" { - return fmt.Errorf("expect token file match\n%s", diff) + if !reflect.DeepEqual(expect, actual) { + return fmt.Errorf("expect token file %v but got actual %v", expect, actual) } return nil }, @@ -194,8 +192,8 @@ func TestSSOTokenProvider(t *testing.T) { t.Fatalf("expect no error, got %v", err) } - if diff := cmp.Diff(c.expectToken, token, tokenCmpOptions...); diff != "" { - t.Errorf("expect token match\n%s", diff) + if !reflect.DeepEqual(c.expectToken, token) { + t.Errorf("expect %v, got %v", c.expectToken, token) } if c.postRetrieve != nil { @@ -217,11 +215,8 @@ func (c *mockCreateTokenAPIClient) CreateToken(input *ssooidc.CreateTokenInput) *ssooidc.CreateTokenOutput, error, ) { if c.expectInput != nil { - opts := cmp.Options{ - cmpopts.IgnoreUnexported(ssooidc.CreateTokenInput{}), - } - if diff := cmp.Diff(c.expectInput, input, opts...); diff != "" { - return nil, fmt.Errorf("expect input match\n%s", diff) + if !reflect.DeepEqual(c.expectInput, input) { + return nil, fmt.Errorf("expect token file %v but got actual %v", c.expectInput, input) } } From 3e9df76ed85cd6ef6548c44d5865f08b20cf8feb Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 24 May 2023 14:58:02 -0400 Subject: [PATCH 06/24] Merge changed sso token provider error format --- aws/credentials/ssocreds/sso_cached_token.go | 18 +++++++++--------- aws/credentials/ssocreds/token_provider.go | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token.go b/aws/credentials/ssocreds/sso_cached_token.go index 6c4b9562034..721bc5ed360 100644 --- a/aws/credentials/ssocreds/sso_cached_token.go +++ b/aws/credentials/ssocreds/sso_cached_token.go @@ -30,7 +30,7 @@ func StandardCachedTokenFilepath(key string) (string, error) { } hash := sha1.New() if _, err := hash.Write([]byte(key)); err != nil { - return "", fmt.Errorf("unable to compute cached token filepath key SHA1 hash, %w", err) + return "", fmt.Errorf("unable to compute cached token filepath key SHA1 hash, %v", err) } cacheFilename := strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json" @@ -111,7 +111,7 @@ func (t *cachedToken) UnmarshalJSON(b []byte) error { } if err != nil { - return fmt.Errorf("field %q, %w", k, err) + return fmt.Errorf("field %q, %v", k, err) } } @@ -145,12 +145,12 @@ func getTokenFieldRFC3339(v interface{}, value **rfc3339) error { func loadCachedAccessToken(filename string) (cachedToken, error) { fileBytes, err := ioutil.ReadFile(filename) if err != nil { - return cachedToken{}, fmt.Errorf("failed to read cached SSO token file, %w", err) + return cachedToken{}, fmt.Errorf("failed to read cached SSO token file, %v", err) } var t cachedToken if err := json.Unmarshal(fileBytes, &t); err != nil { - return cachedToken{}, fmt.Errorf("failed to parse cached SSO token file, %w", err) + return cachedToken{}, fmt.Errorf("failed to parse cached SSO token file, %v", err) } if len(t.AccessToken) == 0 || t.ExpiresAt == nil || time.Time(*t.ExpiresAt).IsZero() { @@ -168,7 +168,7 @@ func storeCachedToken(filename string, t cachedToken, fileMode os.FileMode) (err } if err := os.Rename(tmpFilename, filename); err != nil { - return fmt.Errorf("failed to replace old cached SSO token file, %w", err) + return fmt.Errorf("failed to replace old cached SSO token file, %v", err) } return nil @@ -178,20 +178,20 @@ func writeCacheFile(filename string, fileMode os.FileMode, t cachedToken) (err e var f *os.File f, err = os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_RDWR, fileMode) if err != nil { - return fmt.Errorf("failed to create cached SSO token file %w", err) + return fmt.Errorf("failed to create cached SSO token file %v", err) } defer func() { closeErr := f.Close() if err == nil && closeErr != nil { - err = fmt.Errorf("failed to close cached SSO token file, %w", closeErr) + err = fmt.Errorf("failed to close cached SSO token file, %v", closeErr) } }() encoder := json.NewEncoder(f) if err = encoder.Encode(t); err != nil { - return fmt.Errorf("failed to serialize cached SSO token, %w", err) + return fmt.Errorf("failed to serialize cached SSO token, %v", err) } return nil @@ -219,7 +219,7 @@ func (r *rfc3339) UnmarshalJSON(bytes []byte) error { func parseRFC3339(v string) (rfc3339, error) { parsed, err := time.Parse(time.RFC3339, v) if err != nil { - return rfc3339{}, fmt.Errorf("expected RFC3339 timestamp: %w", err) + return rfc3339{}, fmt.Errorf("expected RFC3339 timestamp: %v", err) } return rfc3339(parsed), nil diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index 90e0b751f67..ffa62542df0 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -90,7 +90,7 @@ func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (Token, error if cachedToken.ExpiresAt != nil && nowTime().After(time.Time(*cachedToken.ExpiresAt)) { cachedToken, err = p.refreshToken(cachedToken) if err != nil { - return Token{}, fmt.Errorf("refresh cached SSO token failed, %w", err) + return Token{}, fmt.Errorf("refresh cached SSO token failed, %v", err) } } @@ -114,7 +114,7 @@ func (p SSOTokenProvider) refreshToken(token cachedToken) (cachedToken, error) { GrantType: aws.String("refresh_token"), }) if err != nil { - return cachedToken{}, fmt.Errorf("unable to refresh SSO token, %w", err) + return cachedToken{}, fmt.Errorf("unable to refresh SSO token, %v", err) } expiresAt := nowTime().Add(time.Duration(*createResult.ExpiresIn) * time.Second) @@ -125,11 +125,11 @@ func (p SSOTokenProvider) refreshToken(token cachedToken) (cachedToken, error) { fileInfo, err := os.Stat(p.options.CachedTokenFilepath) if err != nil { - return cachedToken{}, fmt.Errorf("failed to stat cached SSO token file %w", err) + return cachedToken{}, fmt.Errorf("failed to stat cached SSO token file %v", err) } if err = storeCachedToken(p.options.CachedTokenFilepath, token, fileInfo.Mode()); err != nil { - return cachedToken{}, fmt.Errorf("unable to cache refreshed SSO token, %w", err) + return cachedToken{}, fmt.Errorf("unable to cache refreshed SSO token, %v", err) } return token, nil From 14a703c280cc1b6f34ee3f9f47907ccbdf607c60 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 24 May 2023 15:05:15 -0400 Subject: [PATCH 07/24] Merge modified pending changelog --- CHANGELOG_PENDING.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 97ef11f8472..b9cb5887a7e 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -4,6 +4,4 @@ ### SDK Bugs * `ssocreds`: Add sso token provider logic. - * This new feature will be used to support sso-session section config -* `service/sms`: Remove deprecated services (SMS) integration tests. - * SMS integration tests will fail because SMS deprecated their service. + * This new feature will be used to support sso-session section config \ No newline at end of file From 6f1639474932d5caf5b626ad1da93f3e81ae4fa0 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 24 May 2023 15:26:57 -0400 Subject: [PATCH 08/24] Deleted sms smoke json model that is generated from unknown merging from main branch --- models/apis/sms/2016-10-24/smoke.json | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 models/apis/sms/2016-10-24/smoke.json diff --git a/models/apis/sms/2016-10-24/smoke.json b/models/apis/sms/2016-10-24/smoke.json deleted file mode 100644 index 2cc40fdaeaf..00000000000 --- a/models/apis/sms/2016-10-24/smoke.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": 1, - "defaultRegion": "us-west-2", - "testCases": [ - { - "operationName": "GetConnectors", - "input": {}, - "errorExpectedFromService": false - }, - { - "operationName": "DeleteReplicationJob", - "input": { - "replicationJobId": "invalidId" - }, - "errorExpectedFromService": true - } - ] -} From d0894cf42411e2cdd0e2537bd6efc8aa562141c1 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Thu, 25 May 2023 14:21:59 -0400 Subject: [PATCH 09/24] Modify and merge sso token provider logic --- .../bearer_token.go => bearer/token.go} | 12 +++++------ aws/credentials/ssocreds/sso_cached_token.go | 15 +++++--------- .../ssocreds/sso_cached_token_test.go | 4 ++-- aws/credentials/ssocreds/token_provider.go | 20 ++++++++----------- .../ssocreds/token_provider_test.go | 11 +++++----- 5 files changed, 27 insertions(+), 35 deletions(-) rename aws/credentials/{ssocreds/bearer_token.go => bearer/token.go} (76%) diff --git a/aws/credentials/ssocreds/bearer_token.go b/aws/credentials/bearer/token.go similarity index 76% rename from aws/credentials/ssocreds/bearer_token.go rename to aws/credentials/bearer/token.go index 67a48325891..78b8a8d95fe 100644 --- a/aws/credentials/ssocreds/bearer_token.go +++ b/aws/credentials/bearer/token.go @@ -1,7 +1,7 @@ -package ssocreds +package bearer import ( - "context" + "github.com/aws/aws-sdk-go/aws" "time" ) @@ -24,16 +24,16 @@ func (t Token) Expired(now time.Time) bool { // TokenProvider provides interface for retrieving bearer tokens. type TokenProvider interface { - RetrieveBearerToken(context.Context) (Token, error) + RetrieveBearerToken(aws.Context) (Token, error) } // TokenProviderFunc provides a helper utility to wrap a function as a type // that implements the TokenProvider interface. -type TokenProviderFunc func(context.Context) (Token, error) +type TokenProviderFunc func(aws.Context) (Token, error) // RetrieveBearerToken calls the wrapped function, returning the Token or // error. -func (fn TokenProviderFunc) RetrieveBearerToken(ctx context.Context) (Token, error) { +func (fn TokenProviderFunc) RetrieveBearerToken(ctx aws.Context) (Token, error) { return fn(ctx) } @@ -44,6 +44,6 @@ type StaticTokenProvider struct { } // RetrieveBearerToken returns the static token specified. -func (s StaticTokenProvider) RetrieveBearerToken(context.Context) (Token, error) { +func (s StaticTokenProvider) RetrieveBearerToken(aws.Context) (Token, error) { return s.Token, nil } diff --git a/aws/credentials/ssocreds/sso_cached_token.go b/aws/credentials/ssocreds/sso_cached_token.go index 721bc5ed360..cd5dc6ff5d2 100644 --- a/aws/credentials/ssocreds/sso_cached_token.go +++ b/aws/credentials/ssocreds/sso_cached_token.go @@ -142,7 +142,7 @@ func getTokenFieldRFC3339(v interface{}, value **rfc3339) error { return nil } -func loadCachedAccessToken(filename string) (cachedToken, error) { +func loadCachedToken(filename string) (cachedToken, error) { fileBytes, err := ioutil.ReadFile(filename) if err != nil { return cachedToken{}, fmt.Errorf("failed to read cached SSO token file, %v", err) @@ -201,19 +201,14 @@ type rfc3339 time.Time func (r *rfc3339) UnmarshalJSON(bytes []byte) error { var value string + var err error - if err := json.Unmarshal(bytes, &value); err != nil { + if err = json.Unmarshal(bytes, &value); err != nil { return err } - parse, err := time.Parse(time.RFC3339, value) - if err != nil { - return fmt.Errorf("expected RFC3339 timestamp: %v", err) - } - - *r = rfc3339(parse) - - return nil + *r, err = parseRFC3339(value) + return err } func parseRFC3339(v string) (rfc3339, error) { diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index f6ad87a29a1..2dfd5030368 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -105,7 +105,7 @@ func TestLoadCachedToken(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { - actualToken, err := loadCachedAccessToken(c.filename) + actualToken, err := loadCachedToken(c.filename) if c.expectErr != "" { if err == nil { t.Fatalf("expect %v error, got none", c.expectErr) @@ -170,7 +170,7 @@ func TestStoreCachedToken(t *testing.T) { t.Fatalf("expect no error, got %v", err) } - actual, err := loadCachedAccessToken(c.filename) + actual, err := loadCachedToken(c.filename) if err != nil { t.Fatalf("failed to load stored token, %v", err) } diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index ffa62542df0..7f5cac300ff 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -7,6 +7,7 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" ) @@ -32,11 +33,6 @@ type SSOTokenProviderOptions struct { // already cached SSO Tokens. This utility cannot perform the initial SSO // create token. // -// The SSOTokenProvider is not safe to use concurrently. The SDK's -// config.LoadDefaultConfig will automatically wrap the SSOTokenProvider with -// the , if the external configuration loaded configured -// for an SSO session. -// // The initial SSO create token should be preformed with the AWS CLI before the // Go application using the SSOTokenProvider will need to retrieve the SSO // token. If the AWS CLI has not created the token cache file, this provider @@ -81,21 +77,21 @@ func NewSSOTokenProvider(client CreateTokenAPIClient, cachedTokenFilepath string // // A utility such as the AWS CLI must be used to initially create the SSO // session and cached token file. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html -func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (Token, error) { - cachedToken, err := loadCachedAccessToken(p.options.CachedTokenFilepath) +func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (bearer.Token, error) { + cachedToken, err := loadCachedToken(p.options.CachedTokenFilepath) if err != nil { - return Token{}, err + return bearer.Token{}, err } if cachedToken.ExpiresAt != nil && nowTime().After(time.Time(*cachedToken.ExpiresAt)) { cachedToken, err = p.refreshToken(cachedToken) if err != nil { - return Token{}, fmt.Errorf("refresh cached SSO token failed, %v", err) + return bearer.Token{}, fmt.Errorf("refresh cached SSO token failed, %v", err) } } - expiresAt := ToTime((*time.Time)(cachedToken.ExpiresAt)) - return Token{ + expiresAt := toTime((*time.Time)(cachedToken.ExpiresAt)) + return bearer.Token{ Value: cachedToken.AccessToken, CanExpire: !expiresAt.IsZero(), Expires: expiresAt, @@ -135,7 +131,7 @@ func (p SSOTokenProvider) refreshToken(token cachedToken) (cachedToken, error) { return token, nil } -func ToTime(p *time.Time) (v time.Time) { +func toTime(p *time.Time) (v time.Time) { if p == nil { return v } diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index ccad411d741..cabd47f2192 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" "io/ioutil" "os" @@ -38,7 +39,7 @@ func TestSSOTokenProvider(t *testing.T) { cacheFilePath string optFns []func(*SSOTokenProviderOptions) - expectToken Token + expectToken bearer.Token expectErr string }{ "no cache file": { @@ -71,7 +72,7 @@ func TestSSOTokenProvider(t *testing.T) { }, "valid sso token": { cacheFilePath: filepath.Join("testdata", "valid_token.json"), - expectToken: Token{ + expectToken: bearer.Token{ Value: "dGhpcyBpcyBub3QgYSByZWFsIHZhbHVl", CanExpire: true, Expires: time.Date(2044, 4, 4, 7, 0, 1, 0, time.UTC), @@ -87,7 +88,7 @@ func TestSSOTokenProvider(t *testing.T) { return os.WriteFile(filepath.Join(tempDir, "expired_token.json"), testFile, 0600) }, postRetrieve: func() error { - actual, err := loadCachedAccessToken(filepath.Join(tempDir, "expired_token.json")) + actual, err := loadCachedToken(filepath.Join(tempDir, "expired_token.json")) if err != nil { return err @@ -125,7 +126,7 @@ func TestSSOTokenProvider(t *testing.T) { RefreshToken: aws.String("updated refresh token"), }, }, - expectToken: Token{ + expectToken: bearer.Token{ Value: "updated access token", CanExpire: true, Expires: time.Date(2021, 12, 21, 12, 31, 1, 0, time.UTC), @@ -140,7 +141,7 @@ func TestSSOTokenProvider(t *testing.T) { return os.WriteFile(filepath.Join(tempDir, "expired_token.json"), testFile, 0600) }, postRetrieve: func() error { - actual, err := loadCachedAccessToken(filepath.Join(tempDir, "expired_token.json")) + actual, err := loadCachedToken(filepath.Join(tempDir, "expired_token.json")) if err != nil { return err From 45be7cfcb8932ebe1dca01ca8a4d87c9442ed39d Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Thu, 25 May 2023 14:53:20 -0400 Subject: [PATCH 10/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index b9cb5887a7e..f5ae0e4a8d0 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `ssocreds`: Add sso token provider logic. - * This new feature will be used to support sso-session section config \ No newline at end of file +* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. + * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From e35aaeec106b90800a5fee107c2170f93c269a2f Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Thu, 25 May 2023 15:07:08 -0400 Subject: [PATCH 11/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f5ae0e4a8d0..77e83777781 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. +* `aws/credentials/ssocreds`: Implement SSO token provider to support for `sso-session` in AWS shared config. * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From 3154ff051d949e0b3a43a1b353083f22946efd4e Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Thu, 25 May 2023 15:48:15 -0400 Subject: [PATCH 12/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 77e83777781..f5ae0e4a8d0 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `aws/credentials/ssocreds`: Implement SSO token provider to support for `sso-session` in AWS shared config. +* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From 3c021ea77d1c3f128782459ef6d244ea4f395129 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Fri, 26 May 2023 12:16:47 -0400 Subject: [PATCH 13/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f5ae0e4a8d0..77e83777781 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. +* `aws/credentials/ssocreds`: Implement SSO token provider to support for `sso-session` in AWS shared config. * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From 359ee1ea00a3d0a82a88cb9abdf3f9072ffbd953 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Fri, 26 May 2023 13:13:56 -0400 Subject: [PATCH 14/24] Modify and Merge bearer token directory and sso token provider var name --- aws/{credentials => }/bearer/token.go | 0 aws/credentials/ssocreds/sso_cached_token.go | 4 ++-- aws/credentials/ssocreds/sso_cached_token_test.go | 6 +++--- aws/credentials/ssocreds/token_provider.go | 2 +- aws/credentials/ssocreds/token_provider_test.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename aws/{credentials => }/bearer/token.go (100%) diff --git a/aws/credentials/bearer/token.go b/aws/bearer/token.go similarity index 100% rename from aws/credentials/bearer/token.go rename to aws/bearer/token.go diff --git a/aws/credentials/ssocreds/sso_cached_token.go b/aws/credentials/ssocreds/sso_cached_token.go index cd5dc6ff5d2..a7e76282b98 100644 --- a/aws/credentials/ssocreds/sso_cached_token.go +++ b/aws/credentials/ssocreds/sso_cached_token.go @@ -14,7 +14,7 @@ import ( "time" ) -var osUserHomeDur = shareddefaults.UserHomeDir +var resolvedOsUserHomeDir = shareddefaults.UserHomeDir // StandardCachedTokenFilepath returns the filepath for the cached SSO token file, or // error if unable get derive the path. Key that will be used to compute a SHA1 @@ -24,7 +24,7 @@ var osUserHomeDur = shareddefaults.UserHomeDir // // ~/.aws/sso/cache/.json func StandardCachedTokenFilepath(key string) (string, error) { - homeDir := osUserHomeDur() + homeDir := resolvedOsUserHomeDir() if len(homeDir) == 0 { return "", fmt.Errorf("unable to get USER's home directory for cached token") } diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index 2dfd5030368..5b5e8c9c1e9 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -11,9 +11,9 @@ import ( ) func TestStandardSSOCacheTokenFilepath(t *testing.T) { - origHomeDur := osUserHomeDur + origHomeDur := resolvedOsUserHomeDir defer func() { - osUserHomeDur = origHomeDur + resolvedOsUserHomeDir = origHomeDur }() cases := map[string]struct { @@ -41,7 +41,7 @@ func TestStandardSSOCacheTokenFilepath(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { - osUserHomeDur = c.osUserHomeDir + resolvedOsUserHomeDir = c.osUserHomeDir actual, err := StandardCachedTokenFilepath(c.key) if c.expectErr != "" { diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index 7f5cac300ff..2e34ae15f1d 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -7,7 +7,7 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials/bearer" + "github.com/aws/aws-sdk-go/aws/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" ) diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index cabd47f2192..1e6b9dac83f 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -7,7 +7,7 @@ import ( "context" "fmt" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials/bearer" + "github.com/aws/aws-sdk-go/aws/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" "io/ioutil" "os" From 19a523b742bc72e55e65eb8cbd2b158491290ec2 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Fri, 26 May 2023 14:27:23 -0400 Subject: [PATCH 15/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 77e83777781..f5ae0e4a8d0 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `aws/credentials/ssocreds`: Implement SSO token provider to support for `sso-session` in AWS shared config. +* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From da6f599eea72d2e11952b64e2e94460c0498e3a8 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Fri, 26 May 2023 15:10:26 -0400 Subject: [PATCH 16/24] Modify and Merge changelog entry --- CHANGELOG_PENDING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index f5ae0e4a8d0..77e83777781 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -3,5 +3,5 @@ ### SDK Enhancements ### SDK Bugs -* `aws/credentials/ssocreds`: Implement SSO token provider and support for `sso-session` in AWS shared config. +* `aws/credentials/ssocreds`: Implement SSO token provider to support for `sso-session` in AWS shared config. * Fixes [4649](https://github.com/aws/aws-sdk-go/issues/4649) \ No newline at end of file From 8affb62828688287860fac5644d976d98e05d3b1 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Fri, 26 May 2023 15:49:39 -0400 Subject: [PATCH 17/24] Modify and Merge context used in token provider --- aws/credentials/ssocreds/token_provider.go | 3 +-- aws/credentials/ssocreds/token_provider_test.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index 2e34ae15f1d..cbd731b3b75 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -1,7 +1,6 @@ package ssocreds import ( - "context" "fmt" "os" "time" @@ -77,7 +76,7 @@ func NewSSOTokenProvider(client CreateTokenAPIClient, cachedTokenFilepath string // // A utility such as the AWS CLI must be used to initially create the SSO // session and cached token file. https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html -func (p SSOTokenProvider) RetrieveBearerToken(ctx context.Context) (bearer.Token, error) { +func (p SSOTokenProvider) RetrieveBearerToken(ctx aws.Context) (bearer.Token, error) { cachedToken, err := loadCachedToken(p.options.CachedTokenFilepath) if err != nil { return bearer.Token{}, err diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 1e6b9dac83f..824b4871963 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -4,7 +4,6 @@ package ssocreds import ( - "context" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/bearer" @@ -179,7 +178,7 @@ func TestSSOTokenProvider(t *testing.T) { } provider := NewSSOTokenProvider(c.client, c.cacheFilePath, c.optFns...) - token, err := provider.RetrieveBearerToken(context.Background()) + token, err := provider.RetrieveBearerToken(aws.BackgroundContext()) if c.expectErr != "" { if err == nil { t.Fatalf("expect %v error, got none", c.expectErr) From 2ffc7e231f84982df5da17c867175b7ef550db69 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 30 May 2023 12:53:54 -0400 Subject: [PATCH 18/24] Modify and Merge ssocreds test tag --- aws/credentials/ssocreds/sso_cached_token_test.go | 3 +++ aws/credentials/ssocreds/token_provider_test.go | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index 5b5e8c9c1e9..5f469a22311 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -1,3 +1,6 @@ +//go:build go1.7 +// +build go1.7 + package ssocreds import ( diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 824b4871963..9f9ec2080b4 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -1,5 +1,5 @@ -//go:build go1.16 -// +build go1.16 +//go:build go1.7 +// +build go1.7 package ssocreds From 6e4eb053c4f9e3a850aba34762833acd3fda1243 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 30 May 2023 13:23:36 -0400 Subject: [PATCH 19/24] Modify and Merge ssocreds token provider test tag --- aws/credentials/ssocreds/token_provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 9f9ec2080b4..824b4871963 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -1,5 +1,5 @@ -//go:build go1.7 -// +build go1.7 +//go:build go1.16 +// +build go1.16 package ssocreds From b2ca51c27e2aeec26c0bf8e4918ea4b9ada1628d Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Tue, 30 May 2023 13:54:59 -0400 Subject: [PATCH 20/24] Modify and Merge ssocreds cached token test tag --- aws/credentials/ssocreds/sso_cached_token_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index 5f469a22311..e059ba6d609 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -1,5 +1,5 @@ -//go:build go1.7 -// +build go1.7 +//go:build go1.16 +// +build go1.16 package ssocreds From 9b2a2a131879f7cecf2ed504e34a710e78b8869b Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 31 May 2023 11:08:57 -0400 Subject: [PATCH 21/24] Modify and Merge ssocreds cached token test tag --- aws/credentials/ssocreds/sso_cached_token_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/sso_cached_token_test.go b/aws/credentials/ssocreds/sso_cached_token_test.go index e059ba6d609..64197c9ac69 100644 --- a/aws/credentials/ssocreds/sso_cached_token_test.go +++ b/aws/credentials/ssocreds/sso_cached_token_test.go @@ -1,5 +1,5 @@ -//go:build go1.16 -// +build go1.16 +//go:build go1.9 +// +build go1.9 package ssocreds From 7564841212ba904b59e22b14f4808af477346e28 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 31 May 2023 13:11:50 -0400 Subject: [PATCH 22/24] Modify and Merge ssocreds token provider test tag --- aws/credentials/ssocreds/token_provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 824b4871963..75854d4b991 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -1,5 +1,5 @@ -//go:build go1.16 -// +build go1.16 +//go:build go1.9 +// +build go1.9 package ssocreds From 1558f1a0b41e16a10555b80b56a84fa690b172a6 Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 31 May 2023 13:40:52 -0400 Subject: [PATCH 23/24] Modify and Merge ssocreds token provider test tag --- aws/credentials/ssocreds/token_provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 75854d4b991..824b4871963 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -1,5 +1,5 @@ -//go:build go1.9 -// +build go1.9 +//go:build go1.16 +// +build go1.16 package ssocreds From 89c821a95d08f6059ed5ec8a927ea606d27dec6f Mon Sep 17 00:00:00 2001 From: Tianyi Wang Date: Wed, 31 May 2023 13:57:48 -0400 Subject: [PATCH 24/24] Modify and Merge bearer token directory --- aws/{ => auth}/bearer/token.go | 0 aws/credentials/ssocreds/token_provider.go | 2 +- aws/credentials/ssocreds/token_provider_test.go | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename aws/{ => auth}/bearer/token.go (100%) diff --git a/aws/bearer/token.go b/aws/auth/bearer/token.go similarity index 100% rename from aws/bearer/token.go rename to aws/auth/bearer/token.go diff --git a/aws/credentials/ssocreds/token_provider.go b/aws/credentials/ssocreds/token_provider.go index cbd731b3b75..2ca4babc936 100644 --- a/aws/credentials/ssocreds/token_provider.go +++ b/aws/credentials/ssocreds/token_provider.go @@ -2,11 +2,11 @@ package ssocreds import ( "fmt" + "github.com/aws/aws-sdk-go/aws/auth/bearer" "os" "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" ) diff --git a/aws/credentials/ssocreds/token_provider_test.go b/aws/credentials/ssocreds/token_provider_test.go index 824b4871963..53cb265a7ba 100644 --- a/aws/credentials/ssocreds/token_provider_test.go +++ b/aws/credentials/ssocreds/token_provider_test.go @@ -6,7 +6,7 @@ package ssocreds import ( "fmt" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/bearer" + "github.com/aws/aws-sdk-go/aws/auth/bearer" "github.com/aws/aws-sdk-go/service/ssooidc" "io/ioutil" "os"