...

Source file src/github.com/aws/aws-sdk-go-v2/credentials/stscreds/web_identity_provider.go

Documentation: github.com/aws/aws-sdk-go-v2/credentials/stscreds

     1  package stscreds
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"strconv"
     8  	"time"
     9  
    10  	"github.com/aws/aws-sdk-go-v2/aws"
    11  	"github.com/aws/aws-sdk-go-v2/aws/retry"
    12  	"github.com/aws/aws-sdk-go-v2/internal/sdk"
    13  	"github.com/aws/aws-sdk-go-v2/service/sts"
    14  	"github.com/aws/aws-sdk-go-v2/service/sts/types"
    15  )
    16  
    17  var invalidIdentityTokenExceptionCode = (&types.InvalidIdentityTokenException{}).ErrorCode()
    18  
    19  const (
    20  	// WebIdentityProviderName is the web identity provider name
    21  	WebIdentityProviderName = "WebIdentityCredentials"
    22  )
    23  
    24  // AssumeRoleWithWebIdentityAPIClient is a client capable of the STS AssumeRoleWithWebIdentity operation.
    25  type AssumeRoleWithWebIdentityAPIClient interface {
    26  	AssumeRoleWithWebIdentity(ctx context.Context, params *sts.AssumeRoleWithWebIdentityInput, optFns ...func(*sts.Options)) (*sts.AssumeRoleWithWebIdentityOutput, error)
    27  }
    28  
    29  // WebIdentityRoleProvider is used to retrieve credentials using
    30  // an OIDC token.
    31  type WebIdentityRoleProvider struct {
    32  	options WebIdentityRoleOptions
    33  }
    34  
    35  // WebIdentityRoleOptions is a structure of configurable options for WebIdentityRoleProvider
    36  type WebIdentityRoleOptions struct {
    37  	// Client implementation of the AssumeRoleWithWebIdentity operation. Required
    38  	Client AssumeRoleWithWebIdentityAPIClient
    39  
    40  	// JWT Token Provider. Required
    41  	TokenRetriever IdentityTokenRetriever
    42  
    43  	// IAM Role ARN to assume. Required
    44  	RoleARN string
    45  
    46  	// Session name, if you wish to uniquely identify this session.
    47  	RoleSessionName string
    48  
    49  	// Expiry duration of the STS credentials. STS will assign a default expiry
    50  	// duration if this value is unset. This is different from the Duration
    51  	// option of AssumeRoleProvider, which automatically assigns 15 minutes if
    52  	// Duration is unset.
    53  	//
    54  	// See the STS AssumeRoleWithWebIdentity API reference guide for more
    55  	// information on defaults.
    56  	// https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html
    57  	Duration time.Duration
    58  
    59  	// An IAM policy in JSON format that you want to use as an inline session policy.
    60  	Policy *string
    61  
    62  	// The Amazon Resource Names (ARNs) of the IAM managed policies that you
    63  	// want to use as managed session policies.  The policies must exist in the
    64  	// same account as the role.
    65  	PolicyARNs []types.PolicyDescriptorType
    66  }
    67  
    68  // IdentityTokenRetriever is an interface for retrieving a JWT
    69  type IdentityTokenRetriever interface {
    70  	GetIdentityToken() ([]byte, error)
    71  }
    72  
    73  // IdentityTokenFile is for retrieving an identity token from the given file name
    74  type IdentityTokenFile string
    75  
    76  // GetIdentityToken retrieves the JWT token from the file and returns the contents as a []byte
    77  func (j IdentityTokenFile) GetIdentityToken() ([]byte, error) {
    78  	b, err := ioutil.ReadFile(string(j))
    79  	if err != nil {
    80  		return nil, fmt.Errorf("unable to read file at %s: %v", string(j), err)
    81  	}
    82  
    83  	return b, nil
    84  }
    85  
    86  // NewWebIdentityRoleProvider will return a new WebIdentityRoleProvider with the
    87  // provided stsiface.ClientAPI
    88  func NewWebIdentityRoleProvider(client AssumeRoleWithWebIdentityAPIClient, roleARN string, tokenRetriever IdentityTokenRetriever, optFns ...func(*WebIdentityRoleOptions)) *WebIdentityRoleProvider {
    89  	o := WebIdentityRoleOptions{
    90  		Client:         client,
    91  		RoleARN:        roleARN,
    92  		TokenRetriever: tokenRetriever,
    93  	}
    94  
    95  	for _, fn := range optFns {
    96  		fn(&o)
    97  	}
    98  
    99  	return &WebIdentityRoleProvider{options: o}
   100  }
   101  
   102  // Retrieve will attempt to assume a role from a token which is located at
   103  // 'WebIdentityTokenFilePath' specified destination and if that is empty an
   104  // error will be returned.
   105  func (p *WebIdentityRoleProvider) Retrieve(ctx context.Context) (aws.Credentials, error) {
   106  	b, err := p.options.TokenRetriever.GetIdentityToken()
   107  	if err != nil {
   108  		return aws.Credentials{}, fmt.Errorf("failed to retrieve jwt from provide source, %w", err)
   109  	}
   110  
   111  	sessionName := p.options.RoleSessionName
   112  	if len(sessionName) == 0 {
   113  		// session name is used to uniquely identify a session. This simply
   114  		// uses unix time in nanoseconds to uniquely identify sessions.
   115  		sessionName = strconv.FormatInt(sdk.NowTime().UnixNano(), 10)
   116  	}
   117  	input := &sts.AssumeRoleWithWebIdentityInput{
   118  		PolicyArns:       p.options.PolicyARNs,
   119  		RoleArn:          &p.options.RoleARN,
   120  		RoleSessionName:  &sessionName,
   121  		WebIdentityToken: aws.String(string(b)),
   122  	}
   123  	if p.options.Duration != 0 {
   124  		// If set use the value, otherwise STS will assign a default expiration duration.
   125  		input.DurationSeconds = aws.Int32(int32(p.options.Duration / time.Second))
   126  	}
   127  	if p.options.Policy != nil {
   128  		input.Policy = p.options.Policy
   129  	}
   130  
   131  	resp, err := p.options.Client.AssumeRoleWithWebIdentity(ctx, input, func(options *sts.Options) {
   132  		options.Retryer = retry.AddWithErrorCodes(options.Retryer, invalidIdentityTokenExceptionCode)
   133  	})
   134  	if err != nil {
   135  		return aws.Credentials{}, fmt.Errorf("failed to retrieve credentials, %w", err)
   136  	}
   137  
   138  	// InvalidIdentityToken error is a temporary error that can occur
   139  	// when assuming an Role with a JWT web identity token.
   140  
   141  	value := aws.Credentials{
   142  		AccessKeyID:     aws.ToString(resp.Credentials.AccessKeyId),
   143  		SecretAccessKey: aws.ToString(resp.Credentials.SecretAccessKey),
   144  		SessionToken:    aws.ToString(resp.Credentials.SessionToken),
   145  		Source:          WebIdentityProviderName,
   146  		CanExpire:       true,
   147  		Expires:         *resp.Credentials.Expiration,
   148  	}
   149  	return value, nil
   150  }
   151  

View as plain text