Obtain credentials from IAM EC2 instance meta-data
greghendershott opened this issue · 0 comments
Code running on an EC2 instance with an appropriate IAM role can GET http://169.254.169.254/latest/meta-data/iam/security-credentials/{role-name}
and obtain:
- temporary access and secret keys
- a value for an
X-Amz-Security-Token
header that must be supplied in requests signed with those keys - an expiration -- the app should
GET
new credentials about 15 minutes beforehand.
This can be a better way to manage keys. More information: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html.
This is easy enough to do yourself with code something like:
;; Set this to the name of the EC2 instance IAM role if any
(define/contract ec2-credentials-role (parameter/c (or/c #f string?)) (make-parameter #f))
;; Note: These aren't parameters because parameters are
;; thread-specific and we'll need to update this from a thread (in the
;; case where we get temporary credentials from EC2 instance
;; meta-data).
(struct aws-creds (access secret token) #:transparent)
(define the-creds (begin
(unless (current-ec2-credentials-role)
(with-handlers ([exn:fail? void])
(read-keys)))
(aws-creds (public-key)
(private-key)
#f)))
(when (current-ec2-credentials-role)
(let loop ()
(with-handlers ([exn:fail? void])
(define url
(string->url
(string-append "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
(current-ec2-credentials-role))))
(define ht (call/input-url url get-pure-port read-json))
(define expires (gmt-8601-string->seconds (hash-ref ht 'Expiration)))
(set! the-creds (aws-creds (hash-ref ht 'AccessKeyId)
(hash-ref ht 'SecretAccessKey)
(hash-ref ht 'Token)))
;; Refresh 15 minutes before expiration
(void
(thread
(λ ()
(sleep (- expires (current-seconds) (* 15 60)))
(loop)))))))
Now your app config only needs to supply the instance role name, not the keys.
Although easy enough to write this, it would be a nice-to-have for this library to supply.
The must-have is that the Token
must be supplied as an X-Amz-Security-Token
request header. In other words, there should also be some function like:
(define (refresh-aws-creds h)
(match-define (aws-creds access secret token) the-creds)
(public-key access)
(private-key secret)
(if token
(hash-set h 'X-Amz-Security-Token token)
h))
And, various modules in this library would need to be modified to use it to (maybe) add the header prior to the AWSv4 authentication signature calculation.