Blame vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go

Packit 63bb0d
package stscreds
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"io/ioutil"
Packit 63bb0d
	"strconv"
Packit 63bb0d
	"time"
Packit 63bb0d
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/awserr"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/client"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/credentials"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/service/sts"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/service/sts/stsiface"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
const (
Packit 63bb0d
	// ErrCodeWebIdentity will be used as an error code when constructing
Packit 63bb0d
	// a new error to be returned during session creation or retrieval.
Packit 63bb0d
	ErrCodeWebIdentity = "WebIdentityErr"
Packit 63bb0d
Packit 63bb0d
	// WebIdentityProviderName is the web identity provider name
Packit 63bb0d
	WebIdentityProviderName = "WebIdentityCredentials"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// now is used to return a time.Time object representing
Packit 63bb0d
// the current time. This can be used to easily test and
Packit 63bb0d
// compare test values.
Packit 63bb0d
var now = time.Now
Packit 63bb0d
Packit 63bb0d
// WebIdentityRoleProvider is used to retrieve credentials using
Packit 63bb0d
// an OIDC token.
Packit 63bb0d
type WebIdentityRoleProvider struct {
Packit 63bb0d
	credentials.Expiry
Packit 63bb0d
Packit 63bb0d
	client       stsiface.STSAPI
Packit 63bb0d
	ExpiryWindow time.Duration
Packit 63bb0d
Packit 63bb0d
	tokenFilePath   string
Packit 63bb0d
	roleARN         string
Packit 63bb0d
	roleSessionName string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewWebIdentityCredentials will return a new set of credentials with a given
Packit 63bb0d
// configuration, role arn, and token file path.
Packit 63bb0d
func NewWebIdentityCredentials(c client.ConfigProvider, roleARN, roleSessionName, path string) *credentials.Credentials {
Packit 63bb0d
	svc := sts.New(c)
Packit 63bb0d
	p := NewWebIdentityRoleProvider(svc, roleARN, roleSessionName, path)
Packit 63bb0d
	return credentials.NewCredentials(p)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewWebIdentityRoleProvider will return a new WebIdentityRoleProvider with the
Packit 63bb0d
// provided stsiface.STSAPI
Packit 63bb0d
func NewWebIdentityRoleProvider(svc stsiface.STSAPI, roleARN, roleSessionName, path string) *WebIdentityRoleProvider {
Packit 63bb0d
	return &WebIdentityRoleProvider{
Packit 63bb0d
		client:          svc,
Packit 63bb0d
		tokenFilePath:   path,
Packit 63bb0d
		roleARN:         roleARN,
Packit 63bb0d
		roleSessionName: roleSessionName,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// Retrieve will attempt to assume a role from a token which is located at
Packit 63bb0d
// 'WebIdentityTokenFilePath' specified destination and if that is empty an
Packit 63bb0d
// error will be returned.
Packit 63bb0d
func (p *WebIdentityRoleProvider) Retrieve() (credentials.Value, error) {
Packit 63bb0d
	b, err := ioutil.ReadFile(p.tokenFilePath)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		errMsg := fmt.Sprintf("unable to read file at %s", p.tokenFilePath)
Packit 63bb0d
		return credentials.Value{}, awserr.New(ErrCodeWebIdentity, errMsg, err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	sessionName := p.roleSessionName
Packit 63bb0d
	if len(sessionName) == 0 {
Packit 63bb0d
		// session name is used to uniquely identify a session. This simply
Packit 63bb0d
		// uses unix time in nanoseconds to uniquely identify sessions.
Packit 63bb0d
		sessionName = strconv.FormatInt(now().UnixNano(), 10)
Packit 63bb0d
	}
Packit 63bb0d
	req, resp := p.client.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{
Packit 63bb0d
		RoleArn:          &p.roleARN,
Packit 63bb0d
		RoleSessionName:  &sessionName,
Packit 63bb0d
		WebIdentityToken: aws.String(string(b)),
Packit 63bb0d
	})
Packit 63bb0d
	// InvalidIdentityToken error is a temporary error that can occur
Packit 63bb0d
	// when assuming an Role with a JWT web identity token.
Packit 63bb0d
	req.RetryErrorCodes = append(req.RetryErrorCodes, sts.ErrCodeInvalidIdentityTokenException)
Packit 63bb0d
	if err := req.Send(); err != nil {
Packit 63bb0d
		return credentials.Value{}, awserr.New(ErrCodeWebIdentity, "failed to retrieve credentials", err)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	p.SetExpiration(aws.TimeValue(resp.Credentials.Expiration), p.ExpiryWindow)
Packit 63bb0d
Packit 63bb0d
	value := credentials.Value{
Packit 63bb0d
		AccessKeyID:     aws.StringValue(resp.Credentials.AccessKeyId),
Packit 63bb0d
		SecretAccessKey: aws.StringValue(resp.Credentials.SecretAccessKey),
Packit 63bb0d
		SessionToken:    aws.StringValue(resp.Credentials.SessionToken),
Packit 63bb0d
		ProviderName:    WebIdentityProviderName,
Packit 63bb0d
	}
Packit 63bb0d
	return value, nil
Packit 63bb0d
}