7798bd9a74
Fixes #9415 Co-authored-by: Theron Voran <tvoran@users.noreply.github.com>
104 lines
3.3 KiB
Go
104 lines
3.3 KiB
Go
package awsutil
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
|
|
"github.com/aws/aws-sdk-go/aws/defaults"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/sts"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type CredentialsConfig struct {
|
|
// The access key if static credentials are being used
|
|
AccessKey string
|
|
|
|
// The secret key if static credentials are being used
|
|
SecretKey string
|
|
|
|
// The session token if it is being used
|
|
SessionToken string
|
|
|
|
// If specified, the region will be provided to the config of the
|
|
// EC2RoleProvider's client. This may be useful if you want to e.g. reuse
|
|
// the client elsewhere.
|
|
Region string
|
|
|
|
// The filename for the shared credentials provider, if being used
|
|
Filename string
|
|
|
|
// The profile for the shared credentials provider, if being used
|
|
Profile string
|
|
|
|
// The http.Client to use, or nil for the client to use its default
|
|
HTTPClient *http.Client
|
|
}
|
|
|
|
func (c *CredentialsConfig) GenerateCredentialChain() (*credentials.Credentials, error) {
|
|
var providers []credentials.Provider
|
|
|
|
switch {
|
|
case c.AccessKey != "" && c.SecretKey != "":
|
|
// Add the static credential provider
|
|
providers = append(providers, &credentials.StaticProvider{
|
|
Value: credentials.Value{
|
|
AccessKeyID: c.AccessKey,
|
|
SecretAccessKey: c.SecretKey,
|
|
SessionToken: c.SessionToken,
|
|
}})
|
|
case c.AccessKey == "" && c.SecretKey == "":
|
|
// Attempt to get credentials from the IAM instance role below
|
|
|
|
default: // Have one or the other but not both and not neither
|
|
return nil, fmt.Errorf(
|
|
"static AWS client credentials haven't been properly configured (the access key or secret key were provided but not both)")
|
|
}
|
|
|
|
roleARN := os.Getenv("AWS_ROLE_ARN")
|
|
tokenPath := os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")
|
|
sessionName := os.Getenv("AWS_ROLE_SESSION_NAME")
|
|
if roleARN != "" && tokenPath != "" {
|
|
// this session is only created to create the WebIdentityRoleProvider, as the env variables are already there
|
|
// this automatically assumes the role, but the provider needs to be added to the chain
|
|
sess, err := session.NewSession()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "error creating a new session to create a WebIdentityRoleProvider")
|
|
}
|
|
//Add the web identity role credential provider
|
|
providers = append(providers, stscreds.NewWebIdentityRoleProvider(sts.New(sess), roleARN, sessionName, tokenPath))
|
|
}
|
|
|
|
// Add the environment credential provider
|
|
providers = append(providers, &credentials.EnvProvider{})
|
|
|
|
// Add the shared credentials provider
|
|
providers = append(providers, &credentials.SharedCredentialsProvider{
|
|
Filename: c.Filename,
|
|
Profile: c.Profile,
|
|
})
|
|
|
|
// Add the remote provider
|
|
def := defaults.Get()
|
|
if c.Region != "" {
|
|
def.Config.Region = aws.String(c.Region)
|
|
}
|
|
if c.HTTPClient != nil {
|
|
def.Config.HTTPClient = c.HTTPClient
|
|
}
|
|
|
|
providers = append(providers, defaults.RemoteCredProvider(*def.Config, def.Handlers))
|
|
|
|
// Create the credentials required to access the API.
|
|
creds := credentials.NewChainCredentials(providers)
|
|
if creds == nil {
|
|
return nil, fmt.Errorf("could not compile valid credential providers from static config, environment, shared, web identity or instance metadata")
|
|
}
|
|
|
|
return creds, nil
|
|
}
|