@@ -28,7 +28,10 @@ type RefreshableCred struct {
28
28
AccessKeyId string
29
29
SecretAccessKey string
30
30
Token string
31
+ Code string
32
+ Type string
31
33
Expiration time.Time
34
+ LastUpdated time.Time
32
35
}
33
36
34
37
type Endpoint struct {
@@ -50,6 +53,9 @@ const DEFAULT_TOKEN_TTL_SECONDS = "21600"
50
53
51
54
const X_FORWARDED_FOR_HEADER = "X-Forwarded-For"
52
55
56
+ const REFRESHABLE_CRED_TYPE = "AWS-HMAC"
57
+ const REFRESHABLE_CRED_CODE = "Success"
58
+
53
59
const MAX_TOKENS = 256
54
60
55
61
var mutex sync.Mutex
@@ -120,6 +126,27 @@ func CheckValidToken(w http.ResponseWriter, r *http.Request) error {
120
126
return nil
121
127
}
122
128
129
+ // Helper function that finds a token's TTL in seconds
130
+ func FindTokenTTLSeconds (r * http.Request ) (string , error ) {
131
+ token := r .Header .Get (EC2_METADATA_TOKEN_HEADER )
132
+ if token == "" {
133
+ msg := "no token provided"
134
+ return "" , errors .New (msg )
135
+ }
136
+
137
+ mutex .Lock ()
138
+ expiration , ok := tokenMap [token ]
139
+ mutex .Unlock ()
140
+ if ok {
141
+ tokenTTLFloat := expiration .Sub (time .Now ()).Seconds ()
142
+ tokenTTLInt64 := int64 (tokenTTLFloat )
143
+ return strconv .FormatInt (tokenTTLInt64 , 10 ), nil
144
+ } else {
145
+ msg := "invalid token provided"
146
+ return "" , errors .New (msg )
147
+ }
148
+ }
149
+
123
150
func AllIssuesHandlers (cred * RefreshableCred , roleName string , opts * CredentialsOpts ) (http.HandlerFunc , http.HandlerFunc , http.HandlerFunc ) {
124
151
// Handles PUT requests to /latest/api/token/
125
152
putTokenHandler := func (w http.ResponseWriter , r * http.Request ) {
@@ -158,6 +185,7 @@ func AllIssuesHandlers(cred *RefreshableCred, roleName string, opts *Credentials
158
185
expirationTime := time .Now ().Add (time .Second * time .Duration (tokenTTL ))
159
186
InsertToken (token , expirationTime )
160
187
188
+ w .Header ().Set (EC2_METADATA_TOKEN_TTL_HEADER , tokenTTLStr )
161
189
io .WriteString (w , token ) // nosemgrep
162
190
}
163
191
@@ -173,6 +201,12 @@ func AllIssuesHandlers(cred *RefreshableCred, roleName string, opts *Credentials
173
201
return
174
202
}
175
203
204
+ tokenTTL , err := FindTokenTTLSeconds (r )
205
+ if err != nil {
206
+ w .WriteHeader (http .StatusUnauthorized )
207
+ return
208
+ }
209
+ w .Header ().Set (EC2_METADATA_TOKEN_TTL_HEADER , tokenTTL )
176
210
io .WriteString (w , roleName ) // nosemgrep
177
211
}
178
212
@@ -195,7 +229,11 @@ func AllIssuesHandlers(cred *RefreshableCred, roleName string, opts *Credentials
195
229
cred .SecretAccessKey = credentialProcessOutput .SecretAccessKey
196
230
cred .Token = credentialProcessOutput .SessionToken
197
231
cred .Expiration , _ = time .Parse (time .RFC3339 , credentialProcessOutput .Expiration )
232
+ cred .Code = REFRESHABLE_CRED_CODE
233
+ cred .LastUpdated = time .Now ()
234
+ cred .Type = REFRESHABLE_CRED_TYPE
198
235
err := json .NewEncoder (w ).Encode (cred )
236
+
199
237
if err != nil {
200
238
w .WriteHeader (http .StatusInternalServerError )
201
239
io .WriteString (w , "failed to encode credentials" )
@@ -209,6 +247,13 @@ func AllIssuesHandlers(cred *RefreshableCred, roleName string, opts *Credentials
209
247
return
210
248
}
211
249
}
250
+
251
+ tokenTTL , err := FindTokenTTLSeconds (r )
252
+ if err != nil {
253
+ w .WriteHeader (http .StatusUnauthorized )
254
+ return
255
+ }
256
+ w .Header ().Set (EC2_METADATA_TOKEN_TTL_HEADER , tokenTTL )
212
257
}
213
258
214
259
return putTokenHandler , getRoleNameHandler , getCredentialsHandler
@@ -228,6 +273,9 @@ func Serve(port int, credentialsOptions CredentialsOpts) {
228
273
refreshableCred .SecretAccessKey = credentialProcessOutput .SecretAccessKey
229
274
refreshableCred .Token = credentialProcessOutput .SessionToken
230
275
refreshableCred .Expiration , _ = time .Parse (time .RFC3339 , credentialProcessOutput .Expiration )
276
+ refreshableCred .Code = REFRESHABLE_CRED_CODE
277
+ refreshableCred .LastUpdated = time .Now ()
278
+ refreshableCred .Type = REFRESHABLE_CRED_TYPE
231
279
endpoint := & Endpoint {PortNum : port , TmpCred : refreshableCred }
232
280
endpoint .Server = & http.Server {}
233
281
roleResourceParts := strings .Split (roleArn .Resource , "/" )
0 commit comments