...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package endpointcreds
34
35 import (
36 "context"
37 "fmt"
38 "net/http"
39 "strings"
40
41 "github.com/aws/aws-sdk-go-v2/aws"
42 "github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client"
43 "github.com/aws/smithy-go/middleware"
44 )
45
46
47 const ProviderName = `CredentialsEndpointProvider`
48
49 type getCredentialsAPIClient interface {
50 GetCredentials(context.Context, *client.GetCredentialsInput, ...func(*client.Options)) (*client.GetCredentialsOutput, error)
51 }
52
53
54
55 type Provider struct {
56
57
58
59 client getCredentialsAPIClient
60
61 options Options
62 }
63
64
65 type HTTPClient interface {
66 Do(*http.Request) (*http.Response, error)
67 }
68
69
70 type Options struct {
71
72 Endpoint string
73
74
75 HTTPClient HTTPClient
76
77
78 APIOptions []func(*middleware.Stack) error
79
80
81 Retryer aws.Retryer
82
83
84
85
86
87
88
89
90 AuthorizationToken string
91
92
93
94
95
96
97
98
99
100 AuthorizationTokenProvider AuthTokenProvider
101 }
102
103
104
105 type AuthTokenProvider interface {
106 GetToken() (string, error)
107 }
108
109
110
111 type TokenProviderFunc func() (string, error)
112
113
114 func (p TokenProviderFunc) GetToken() (string, error) {
115 return p()
116 }
117
118
119
120 func New(endpoint string, optFns ...func(*Options)) *Provider {
121 o := Options{
122 Endpoint: endpoint,
123 }
124
125 for _, fn := range optFns {
126 fn(&o)
127 }
128
129 p := &Provider{
130 client: client.New(client.Options{
131 HTTPClient: o.HTTPClient,
132 Endpoint: o.Endpoint,
133 APIOptions: o.APIOptions,
134 Retryer: o.Retryer,
135 }),
136 options: o,
137 }
138
139 return p
140 }
141
142
143
144 func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
145 resp, err := p.getCredentials(ctx)
146 if err != nil {
147 return aws.Credentials{}, fmt.Errorf("failed to load credentials, %w", err)
148 }
149
150 creds := aws.Credentials{
151 AccessKeyID: resp.AccessKeyID,
152 SecretAccessKey: resp.SecretAccessKey,
153 SessionToken: resp.Token,
154 Source: ProviderName,
155 }
156
157 if resp.Expiration != nil {
158 creds.CanExpire = true
159 creds.Expires = *resp.Expiration
160 }
161
162 return creds, nil
163 }
164
165 func (p *Provider) getCredentials(ctx context.Context) (*client.GetCredentialsOutput, error) {
166 authToken, err := p.resolveAuthToken()
167 if err != nil {
168 return nil, fmt.Errorf("resolve auth token: %v", err)
169 }
170
171 return p.client.GetCredentials(ctx, &client.GetCredentialsInput{
172 AuthorizationToken: authToken,
173 })
174 }
175
176 func (p *Provider) resolveAuthToken() (string, error) {
177 authToken := p.options.AuthorizationToken
178
179 var err error
180 if p.options.AuthorizationTokenProvider != nil {
181 authToken, err = p.options.AuthorizationTokenProvider.GetToken()
182 if err != nil {
183 return "", err
184 }
185 }
186
187 if strings.ContainsAny(authToken, "\r\n") {
188 return "", fmt.Errorf("authorization token contains invalid newline sequence")
189 }
190
191 return authToken, nil
192 }
193
View as plain text