Skip to content

Instantly share code, notes, and snippets.

@tristanmorgan
Created August 10, 2017 07:08
Show Gist options
  • Save tristanmorgan/8fe883f89db4537ce35e0a23f6a537b6 to your computer and use it in GitHub Desktop.
Save tristanmorgan/8fe883f89db4537ce35e0a23f6a537b6 to your computer and use it in GitHub Desktop.
An attempt at calling Hashicorp Vault IAM Auth backend in Ruby
# Authenticate via the AWS EC2 authentication method (IAM method). If authentication is
# successful, the resulting token will be stored on the client and used
# for future requests.
#
# @example
# Vault.auth.aws_ec2_iam("dev-role-iam", "vault.example.com") #=> #<Vault::Secret lease_id="">
#
# @param [String] role
# @param [String] iam_auth_header_value
#
# @return [Secret]
def aws_ec2_iam(role, iam_auth_header_value)
uri_string = 'http://169.254.169.254/latest/dynamic/instance-identity/document'
uri = URI.parse(uri_string)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri_string)
document = JSON.parse(http.request(request))
uri_string = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/'
uri = URI.parse(uri_string)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri_string)
response = http.request(request)
uri_string += response
uri = URI.parse(uri_string)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri_string)
credentials = JSON.parse(http.request(request))
t = Time.now.utc
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
date_stamp = t.strftime('%Y%m%d')
region_name = document['region']
k_date = OpenSSL::HMAC.digest('sha256', 'AWS4' + credentials['SecretAccessKey'], date_stamp)
k_region = OpenSSL::HMAC.digest('sha256', k_date, region_name)
k_service = OpenSSL::HMAC.digest('sha256', k_region, 'iam')
k_signing = OpenSSL::HMAC.digest('sha256', k_service, 'aws4_request')
iam_auth_header_value ||= IAM_SERVER_ID_HEADER
request_body = Base64.strict_encode64('Action=GetCallerIdentity&Version=2011-06-15')
headers_hash = {
'Content-Length' => [request_body.length.to_s],
'User-Agent' => ['aws-sdk-go/1.4.12 (go1.7.1; linux; amd64)'],
'X-Vault-AWSIAM-Server-Id' => [iam_auth_header_value],
'X-Amz-Date' => [amzdate],
'Content-Type' => ['application/x-www-form-urlencoded; charset=utf-8'],
'Authorization' => [
"AWS4-HMAC-SHA256 Credential=#{credentials['AccessKeyId']}/#{date_stamp}/#{region_name}/iam/aws4_request, "\
"SignedHeaders=content-length;content-type;host;x-amz-date;x-vault-server, Signature=#{k_signing}"
]
}
payload = {
role: role,
iam_http_request_method: 'POST',
iam_request_url: Base64.strict_encode64('https://sts.amazonaws.com/'),
iam_request_headers: Base64.strict_encode64(JSON.dump(headers_hash)),
iam_request_body: request_body
}
json = client.post('/v1/auth/aws/login', JSON.fast_generate(payload))
secret = Secret.decode(json)
client.token = secret.auth.client_token
secret
end
@tristanmorgan
Copy link
Author

I have some errors here as found by @maschwenk in hashicorp/vault-ruby#161 , but I'm happy I got things moving a little further on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment