To access AWS resources in another account you can create dedicated IAM user or use IAM roles. If you decide to create user, you need to generate username and password for AWS Console or access keys for API. Baking this keys in your code is almost always a bad idea.
By setting up roles for cross-account access you don’t need to create individual IAM users in each account and access key are automatically rotated for you. Lets take a look on an example how to use it with Ansible.
Example
Lets assume that we have Ansible running on EC2 instance in our source account. We want to create Route53 hosted zone in another account (target) using Ansible playbook. It may as well be some other resource, like EC2 or S3 bucket. Our requirement is that we do not want to hardcode any keys into playbooks or encrypt it using vault. To achieve that we can delegate access across AWS accounts using IAM roles.
Creating role in target account
1. Create IAM role with Another Account option. For account ID type source account ID.
2. Assign appropriate policy. Specify rights that you want to allow on destination account. In this example I wanted to create new hosted zone in Route53. For simplicity I used full access to Route53, but you should always narrow policy just for needed actions. You can read more about IAM in my previous post.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "route53:*",
"Resource": "*"
}
]
}
3. Write down ARN of created role.
Creating role in source account
1. Create role with AWS Service EC2 option in source account.
2. Create custom policy to allow sts:AssumeRole for target account role.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::{TARGET_ARN_ROLE}”
}
]
}
Assigning role to EC2 instance with Ansible
Assign source role to EC2 instance where you have installed your RedHat Ansible.
Creating Ansible playbook
Now you can use Ansible to create Route53 zone without adding access key/secret key into the code. First you must assume created role from target account. Next you can use route53_zone module to create mydomain.local zone. Instead of specifying key you can pass sts_assume_role returned values.
- name: Route53 add zone
hosts: localhost
tasks:
- sts_assume_role:
role_arn: "arn:aws:iam::ARN_TARGET_ACCOUNT"
role_session_name: "someRoleSession"
region: eu-west-1
register: assumed_role
- route53_zone:
aws_access_key: "{{ assumed_role.sts_creds.access_key }}"
aws_secret_key: "{{ assumed_role.sts_creds.secret_key }}"
security_token: "{{ assumed_role.sts_creds.session_token }}"
zone: mydomain.local
vpc_id: 'vpc-ID'
vpc_region: eu-west-1
How this works?
How Ansible knows the credentials? To use an IAM role, you have to make an API call to STS:AssumeRole, which will return a temporary access key ID, secret key, and security token that can then be used to sign future API calls. STS generates temporary credentials with a relatively short expiration time (1 hour, by default). You can access them via metadata from you Ansible EC2 instance:
http://169.254.169.254/latest/meta-data/iam/security-credentials/{role-name}
Ansible does the calls behind the scenes to obtain access keys. Same principle is used with other tools, like AWS CLI or it is included in AWS SDKs.
Materials
Delegate Access Across AWS Accounts Using IAM Roles
How to Use a Single IAM User to Easily Access All Your Accounts by Using the AWS CLI
Like!! I blog quite often and I genuinely thank you for your information. The article has truly peaked my interest.
I am regular visitor, how are you everybody? This article posted at this web site is in fact pleasant.