Call from ec2 instance to 169.254.169.254 for security credentials returns invalid credentials

amazon ec2amazon-web-servicesauthenticationcredentials

So in theory, if a person needs valid credentials for an Amazon server, instead of hardcoding in their access key/password, one can call out to 169.254.169.254 for credentials to access certain resources like so:

   js = ''
   open('http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>') { |f|
       f.each_line {|line| js += line}
   }
   credentials = JSON.load(js)

   ndnode[:s3_access_key_id] = credentials['AccessKeyId']
   ndnode[:s3_secret_access_key] = credentials['SecretAccessKey']

and then using the access stuff here:

   conn = AWS::EC2::Base.new(:access_key_id => ndnode[:s3_access_key_id],
       :secret_access_key => ndnode[:s3_secret_access_key])
   # THIS ALWAYS FAILS
   result = conn.describe_instances(:instance_id => instance_id)

I dislike the idea of hardcoding my access key and password into the source, and I'd like a workaround.

1) Am I and my boss correct that this is a way to do that workaround?
2) If yes to 1, what is the correct way of doing it? If no to 1, is there a way to avoid checking credentials into the source (either here or in a config file) and what is it?
3) In response to @Edwin's response, where in the AWS gem API do I put the security token? Boto has been reported to let me connect with the credentials that I'm given, which means forking off a process, and setting some environment variables, so that Ruby can use the Boto connection's asking for information.

Best Answer

Many of the AWS SDKs have support for IAM Roles in EC2 Profiles built in. With .Net, you use a parameterless constructor to use them. Make sure you're using a recent version of the SDK.

Here's Amazon's page on how to use the Ruby SDK with IAM Roles.