You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wechatminiprogram/vendor/github.com/aws/aws-sdk-go-v2/credentials/ssocreds/sso_credentials_provider.go

137 lines
4.0 KiB

package ssocreds
import (
"context"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/internal/sdk"
"github.com/aws/aws-sdk-go-v2/service/sso"
)
// ProviderName is the name of the provider used to specify the source of
// credentials.
const ProviderName = "SSOProvider"
// GetRoleCredentialsAPIClient is a API client that implements the
// GetRoleCredentials operation.
type GetRoleCredentialsAPIClient interface {
GetRoleCredentials(context.Context, *sso.GetRoleCredentialsInput, ...func(*sso.Options)) (
*sso.GetRoleCredentialsOutput, error,
)
}
// Options is the Provider options structure.
type Options struct {
// The Client which is configured for the AWS Region where the AWS SSO user
// portal is located.
Client GetRoleCredentialsAPIClient
// The AWS account that is assigned to the user.
AccountID string
// The role name that is assigned to the user.
RoleName string
// The URL that points to the organization's AWS Single Sign-On (AWS SSO)
// user portal.
StartURL string
// The filepath the cached token will be retrieved from. If unset Provider will
// use the startURL to determine the filepath at.
//
// ~/.aws/sso/cache/<sha1-hex-encoded-startURL>.json
//
// If custom cached token filepath is used, the Provider's startUrl
// parameter will be ignored.
CachedTokenFilepath string
}
// Provider is an AWS credential provider that retrieves temporary AWS
// credentials by exchanging an SSO login token.
type Provider struct {
options Options
cachedTokenFilepath string
}
// New returns a new AWS Single Sign-On (AWS SSO) credential provider. The
// provided client is expected to be configured for the AWS Region where the
// AWS SSO user portal is located.
func New(client GetRoleCredentialsAPIClient, accountID, roleName, startURL string, optFns ...func(options *Options)) *Provider {
options := Options{
Client: client,
AccountID: accountID,
RoleName: roleName,
StartURL: startURL,
}
for _, fn := range optFns {
fn(&options)
}
return &Provider{
options: options,
cachedTokenFilepath: options.CachedTokenFilepath,
}
}
// Retrieve retrieves temporary AWS credentials from the configured Amazon
// Single Sign-On (AWS SSO) user portal by exchanging the accessToken present
// in ~/.aws/sso/cache.
func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
if p.cachedTokenFilepath == "" {
cachedTokenFilepath, err := StandardCachedTokenFilepath(p.options.StartURL)
if err != nil {
return aws.Credentials{}, &InvalidTokenError{Err: err}
}
p.cachedTokenFilepath = cachedTokenFilepath
}
tokenFile, err := loadCachedToken(p.cachedTokenFilepath)
if err != nil {
return aws.Credentials{}, &InvalidTokenError{Err: err}
}
if tokenFile.ExpiresAt == nil || sdk.NowTime().After(time.Time(*tokenFile.ExpiresAt)) {
return aws.Credentials{}, &InvalidTokenError{}
}
output, err := p.options.Client.GetRoleCredentials(ctx, &sso.GetRoleCredentialsInput{
AccessToken: &tokenFile.AccessToken,
AccountId: &p.options.AccountID,
RoleName: &p.options.RoleName,
})
if err != nil {
return aws.Credentials{}, err
}
return aws.Credentials{
AccessKeyID: aws.ToString(output.RoleCredentials.AccessKeyId),
SecretAccessKey: aws.ToString(output.RoleCredentials.SecretAccessKey),
SessionToken: aws.ToString(output.RoleCredentials.SessionToken),
CanExpire: true,
Expires: time.Unix(0, output.RoleCredentials.Expiration*int64(time.Millisecond)).UTC(),
Source: ProviderName,
}, nil
}
// InvalidTokenError is the error type that is returned if loaded token has
// expired or is otherwise invalid. To refresh the SSO session run AWS SSO
// login with the corresponding profile.
type InvalidTokenError struct {
Err error
}
func (i *InvalidTokenError) Unwrap() error {
return i.Err
}
func (i *InvalidTokenError) Error() string {
const msg = "the SSO session has expired or is invalid"
if i.Err == nil {
return msg
}
return msg + ": " + i.Err.Error()
}