1package awsutil
2
3import (
4	"fmt"
5	"net/http"
6
7	"github.com/aws/aws-sdk-go/aws"
8	"github.com/aws/aws-sdk-go/aws/credentials"
9	"github.com/aws/aws-sdk-go/aws/defaults"
10)
11
12type CredentialsConfig struct {
13	// The access key if static credentials are being used
14	AccessKey string
15
16	// The secret key if static credentials are being used
17	SecretKey string
18
19	// The session token if it is being used
20	SessionToken string
21
22	// If specified, the region will be provided to the config of the
23	// EC2RoleProvider's client. This may be useful if you want to e.g. reuse
24	// the client elsewhere.
25	Region string
26
27	// The filename for the shared credentials provider, if being used
28	Filename string
29
30	// The profile for the shared credentials provider, if being used
31	Profile string
32
33	// The http.Client to use, or nil for the client to use its default
34	HTTPClient *http.Client
35}
36
37func (c *CredentialsConfig) GenerateCredentialChain() (*credentials.Credentials, error) {
38	var providers []credentials.Provider
39
40	switch {
41	case c.AccessKey != "" && c.SecretKey != "":
42		// Add the static credential provider
43		providers = append(providers, &credentials.StaticProvider{
44			Value: credentials.Value{
45				AccessKeyID:     c.AccessKey,
46				SecretAccessKey: c.SecretKey,
47				SessionToken:    c.SessionToken,
48			}})
49	case c.AccessKey == "" && c.SecretKey == "":
50		// Attempt to get credentials from the IAM instance role below
51
52	default: // Have one or the other but not both and not neither
53		return nil, fmt.Errorf(
54			"static AWS client credentials haven't been properly configured (the access key or secret key were provided but not both)")
55	}
56
57	// Add the environment credential provider
58	providers = append(providers, &credentials.EnvProvider{})
59
60	// Add the shared credentials provider
61	providers = append(providers, &credentials.SharedCredentialsProvider{
62		Filename: c.Filename,
63		Profile:  c.Profile,
64	})
65
66	// Add the remote provider
67	def := defaults.Get()
68	if c.Region != "" {
69		def.Config.Region = aws.String(c.Region)
70	}
71	if c.HTTPClient != nil {
72		def.Config.HTTPClient = c.HTTPClient
73	}
74
75	providers = append(providers, defaults.RemoteCredProvider(*def.Config, def.Handlers))
76
77	// Create the credentials required to access the API.
78	creds := credentials.NewChainCredentials(providers)
79	if creds == nil {
80		return nil, fmt.Errorf("could not compile valid credential providers from static config, environment, shared, or instance metadata")
81	}
82
83	return creds, nil
84}
85