How to get the access key with iam_module of Ansible? - amazon-web-services

I am using Ansible to create AWS users. One of the features of Ansible is to create a user with access key. I am wondering how could I get the access key after the user was successfully created.
http://docs.ansible.com/ansible/iam_module.html
tasks:
- name: Create two new IAM users with API keys
iam:
iam_type: user
name: "{{ item }}"
state: present
password: "{{ temp_pass }}"
access_key_state: create
with_items:
- user

I tried in 2.0.1.0. Should work in 2.0.0.2.
tasks:
- iam:
iam_type: user
name: foo
state: present
access_key_state: create
register: credentials
- debug: var=credentials
Output
[debug] *******************************************************************
ok: [127.0.0.1] => {
"credentials": {
"changed": false,
"groups": null,
"keys": {
"AKIAXXXXXXXXXXTTGFXX": "Active"
},
"user_name": "foo"
}
}
It is not possible to get the secret as of Ansible 2.0.1.0. It is a bug. See iam module not very useful for managing access keys

In the meantime (I am using Ansible 2.3.2.0) that issue was successfully fixed:
- name: Create restricted bot user to access S3
iam:
iam_type: user
name: blubaa
state: present
access_key_state: create
connection: local
register: credentials
- debug: var=credentials
Output:
ok: [XXXXXXXXXX] => {
"credentials": {
"changed": true,
"groups": null,
"keys": [
{
"access_key_id": "AKIAJXXXXXXXXXXZX6GQ",
"create_date": "2017-08-26T01:04:05Z",
"status": "Active",
"user_name": "blubaa"
}
],
"user_meta": {
"access_keys": [
{
"access_key_id": "AKIAJXXXXXXXXXXZX6GQ",
"access_key_selector": "XXXX",
"create_date": "2017-08-26T01:04:05.720Z",
"secret_access_key": "wPwd2H0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkHB08Elo",
"status": "Active",
"user_name": "blubaa"
}
],
"created_user": {
"arn": "arn:aws:iam::30XXXXXXXXXX:user/blubaa",
"create_date": "2017-08-26T01:04:05.557Z",
"path": "/",
"user_id": "AIDAXXXXXXXXXXOYT7M",
"user_name": "blubaa"
},
"password": null
}
}
}

Related

Using CloudFormation, how can I create an Identity Pool that authorizes based on User Pool roles?

I'm using Serverless Framework to handle my CloudFormation stuff. I'm building a User Pool with groups that have their own roles. I want to build my Identity Pool so that the Cognito provider setting for Authenticated role selection is set to Choose role from token with a Role resolultion of DENY.
This is my relevant CloudFormation - ignore the ${self:custom....} stuff:
IdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
IdentityPoolName: ${self:custom.identityPoolName}
AllowUnauthenticatedIdentities: false
CognitoIdentityProviders:
- ClientId:
Ref: UserPoolClient
ProviderName:
Fn::GetAtt: ["UserPool", "ProviderName"]
IdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId:
Ref: IdentityPool
RoleMappings:
CognitoProvider:
IdentityProvider:
Fn::Join:
- ""
- - "cognito-idp."
- Ref: AWS::Region
- ".amazonaws.com/"
- Ref: UserPool
- ":"
- Ref: UserPoolClient
Type: Token
AmbiguousRoleResolution: Deny
This does_not work because the IdentityPoolRoleAttachment is requiring a Roles section. But I do_not want to use the authenticated and unauthenticated roles with the Identity Pool. I want the Identity Pool Cognito provider to only check the tokens being passed in.
This is the error I'm getting:
ServerlessError: An error occurred: IdentityPoolRoleAttachment - 1 validation error detected: Value null at 'roles' failed to satisfy constraint: Member must not be null (Service: AmazonCognitoIdentity; Status Code: 400; Error Code: ValidationException; Request ID: 80026230-eaa9-4045-86d8-6fe4c07cce9d).
How can I do this? Do I need to create an empty role and assigned it to the IdentityPoolRoleAttachment?
I am able to do this without Identity Pool roles in the console.
I was able to get this working without creating an empty role.
roles is not required according to doc but it seems like CFN cant handle null well.
you just need to set "roles": { }.
cdk code
new CfnIdentityPoolRoleAttachment(
this,
'ExampleCognitoIdentityPoolRoleAttachment',
{
identityPoolId: identityPool.ref,
roles: {},
roleMappings: {
mapping: {
type: 'Token',
ambiguousRoleResolution: 'Deny',
identityProvider: `cognito-idp.${cdk.Stack.of(this).region}.amazonaws.com/${userPool.userPoolId}:${cognitoAppClient.ref}`,
},
},
},
);
Cloudformation template output from cdk
"ExampleCognitoIdentityPoolRoleAttachment": {
"Type": "AWS::Cognito::IdentityPoolRoleAttachment",
"Properties": {
"IdentityPoolId": {
"Ref": "ExampleCognitoIdentityPool"
},
"RoleMappings": {
"mapping": {
"AmbiguousRoleResolution": "Deny",
"IdentityProvider": {
"Fn::Join": [
"",
[
"cognito-idp.eu-west-1.amazonaws.com/",
{
"Ref": "<UserPoolRef>"
},
":",
{
"Ref": "<UserPoolAppClientRef>"
}
]
]
},
"Type": "Token"
}
},
"Roles": { }
},
"Metadata": {
"aws:cdk:path": "example-stack/ExampleCognitoIdentityPoolRoleAttachment"
}
}

How to Set required attributes in aws cognito user pool using aws cloudformation template?

Aws cognito console screen
While creating user-pool using cloudformation template i wanted to add the following attributes(marked in the attached image link). I didn't find anything helpful in the AWS documentation.
It allows setting up Alias attributes as said in the aws cloudformation cognito documentation.
Has anybody tried this or has any idea regarding this?
I managed to get it done using the schema attribute of the AWS::cognito::UserPool:
"myApiUserPool": {
"Type": "AWS::Cognito::UserPool",
"Properties": {
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": true
},
"Schema": [
{
"Mutable": false,
"Name": "email",
"Required": true
},
{
"Mutable": false,
"Name": "family_name",
"Required": true
},
{
"Mutable": false,
"Name": "name",
"Required": true
}
],
"AutoVerifiedAttributes": [
"email"
],
"UserPoolName": {
"Fn::Sub": "myApiUserPool${envParameter}"
}
}
}
Here is the example with YAML.
Note: you cannot just update a attribute you need to delete the userpool and create it again with the new attributes (just comment out your pool section and redeploy it). Otherwise it will ask for a AttributeDataType, and if you include it, it will create a custom attribute instead of standard one.
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
# Generate a name based on the stage
UserPoolName: ${self:custom.stage}-cfp-user-pool
AliasAttributes:
- phone_number
- email
- preferred_username
Policies:
PasswordPolicy:
MinimumLength: 8
Schema:
- Name: email
Required: true
Mutable: true
Adding on #jWang1 and considering you don't want to delete a user pool with lots of active users but you really need to add a parameter during for sign up process, then you can just add a custom attribute to the template and enforce it as required through your authentication library or custom implementation
The minimum parameters to achieve this are:
UserPool:
Type: AWS::Cognito::UserPool
Properties:
Schema:
-
Name: <attr name>
AttributeDataType: Boolean | DateTime | Number | String

Ansible instance not appearing on AWS console

So I'm using Ansible on my MBP to try create key_pair and create/provision EC2 instances. Playbook runs fine with no error but when I check AWS console there is no new key and no new instance... Ping to supposedly created Public IP times out so I am thinking something failed. Ansible definitely hit AWS since if I disable the AWS access key then Ansible errors out, and not using the Ansible created key in the second task also fails so a key must have been created, just not uploaded to AWS?
Can you spot anything I did wrong?
Playbook yaml content:
- name: Create a sandbox instance
hosts: localhost
gather_facts: False
vars:
instance_type: t2.micro
image: ami-d1315fb1
region: us-west-1
tasks:
- name: Generate key
ec2_key:
name: ansible_key
region: "{{ region }}"
aws_access_key: #my_key
aws_secret_key: #my_key
state: present
- name: Launch instance
ec2:
key_name: ansible_key
group: default
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: true
region: "{{ region }}"
aws_access_key: #my_key
aws_secret_key: #my_key
register: ec2
- name: Print all ec2 variables
debug: var=ec2
Playbook runs fine with output being:
PLAY [Create a sandbox instance] ***********************************************
TASK [Generate key] ************************************************************
ok: [localhost]
TASK [Launch instance] *********************************************************
changed: [localhost]
TASK [Print all ec2 variables] *************************************************
ok: [localhost] => {
"ec2": {
"changed": true,
"instance_ids": [
"i-0898f09f8d3798961"
],
"instances": [
{
"ami_launch_index": "0",
"architecture": "x86_64",
"block_device_mapping": {
"/dev/sda1": {
"delete_on_termination": true,
"status": "attached",
"volume_id": "vol-04e9c4c4f5d85e60d"
}
},
"dns_name": "ec2-54-215-253-115.us-west1.compute.amazonaws.com",
"ebs_optimized": false,
"groups": {
"sg-778b5711": "default"
},
"hypervisor": "xen",
"id": "i-0898f09f8d3798961",
"image_id": "ami-d1315fb1",
"instance_type": "t2.micro",
"kernel": null,
"key_name": "ansible_key",
"launch_time": "2017-08-16T16:57:09.000Z",
"placement": "us-west-1b",
"private_dns_name": "ip-172-31-29-166.us-west1.compute.internal",
"private_ip": "172.31.29.166",
"public_dns_name": "ec2-54-215-253-115.us-west1.compute.amazonaws.com",
"public_ip": "54.215.253.115",
"ramdisk": null,
"region": "us-west-1",
"root_device_name": "/dev/sda1",
"root_device_type": "ebs",
"state": "running",
"state_code": 16,
"tags": {},
"tenancy": "default",
"virtualization_type": "hvm"
}
],
"tagged_instances": []
}
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
Here are the few things:
- sure, you have selected the N.California(us-west-1) region from the console
- For private part of the key to store inside the .ssh under your username, do the following steps:
- name: Create an EC2 key
ec2_key:
name: "ansible_key"
region: "us-west-1"
aws_access_key: #my_key
aws_secret_key: #my_ke
register: ec2_key
- name: save private key
copy:
content: "{{ ec2_key.key.private_key }}"
dest: "/Users/{{lookup('env', 'USER')}}/.ssh/aws-private.pem"
mode: 0600
when: ec2_key.changed
Note: Run this playbook from the scratch to create new key and save it into your ~/.ssh directory.

Ansible: Not able to get AMI ID of newly created AMI

I am using a playbook to create ami and trying to fetch the newly created ami id. But the debug is getting 'msg": "AMI not updated"'' Please help
- name: Create AMI
ec2_ami:
region: "{{ec2_region}}"
name: "aws-{{ec2_region}}"
state: present
instance_id: "{{ec2_info.instances.0.id}}"
wait: yes
tags:
Name: "aws-{{ec2_region}}-mr-ami"
deployment_type: "{{deployment_type}}"
pop_type: "{{pop_type}}"
register: image
- pause:
seconds: 10
- debug:
msg: "{{image}}"
- name: Set image id as fact
set_fact:
mr_ami_id: "{{image.image_id}}"
Playbook output
TASK [Create AMI]
*************************************************************************************************************************** ok: [localhost] => {
"changed": false,
"invocation": {
"module_args": {
"architecture": "x86_64",
"aws_access_key": null,
"aws_secret_key": null,
"delete_snapshot": false,
"description": "",
"device_mapping": null,
"ec2_url": null,
"image_id": null,
"instance_id": "i-065404d0d37e0acfb",
"kernel_id": null,
"launch_permissions": null,
"name": "aws-ap-southeast-2-MessageRelay",
"no_reboot": false,
"profile": null,
"region": "ap-southeast-2",
"root_device_name": null,
"security_token": null,
"state": "present",
"tags": {
"Name": "aws-ap-southeast-2-mr-ami",
"deployment_type": "dev",
"pop_type": "mgmt"
},
"validate_certs": true,
"virtualization_type": "hvm",
"wait": true,
"wait_timeout": "900"
}
},
"launch_permissions": {},
"msg": "AMI not updated" }
TASK [pause]
******************************************************************************************************************************** task path: /root/*********************/create_ami.yml:24 Pausing for 10 seconds (ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort) ok: [localhost] => {
"changed": false,
"delta": 10,
"rc": 0,
"start": "2017-08-01 08:48:29.756546",
"stderr": "",
"stdout": "Paused for 10.0 seconds",
"stop": "2017-08-01 08:48:39.756843",
"user_input": "" }
TASK [debug]
******************************************************************************************************************************** task path: /root/*****************/create_ami.yml:27 ok: [localhost]
=> {
"changed": false,
"msg": {
"changed": false,
"launch_permissions": {},
"msg": "AMI not updated"
} }
TASK [Set image id as fact]
***************************************************************************************************************** task path: /root/***********/trunk/ncs/pop-deployment/********_asg/tasks/create_ami.yml:30 fatal: [localhost]: FAILED! => {
"failed": true,
"msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'dict object' has no attribute 'image_id'\n\nThe error appears to have been in '/root/**************************/create_ami.yml': line 30, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Set image id as fact\n ^ here\n" }
PLAY RECAP
********************************************************************************************************************************** ip-10-10-5-111.ap-southeast-2.compute.internal : ok=13 changed=9 unreachable=0 failed=0 localhost : ok=69 changed=31 unreachable=0 failed=1
This was happening because AMI with name "aws-{{ec2_region}}" was already there and hence no new ami was getting created. I deleted the old AMI and ran the playbook again without any issues.

Searching Ansible debug messages for a string

I'm trying to find all the up interfaces on a switch, by looking at the results of some output from nxos_facts:
- name: get nxos facts via nxapi
nxos_facts:
provider: "{{ provider['nxapi'] }}"
gather_subset:
- "interfaces"
register: nxfacts_nxapi
- debug:
msg: "{{ nxfacts_nxapi.ansible_facts.ansible_net_interfaces | to_nice_json}} "
And I can successfully print out the debug to show the structure of the dictionary:
"ansible_net_interfaces": {
"Ethernet1/1": {
"bandwidth": 1000000,
"duplex": "full",
"ipv4": {
"address": "10.0.1.2",
"masklen": 24
},
"macaddress": "0800.276d.ee15",
"mtu": "1500",
"speed": "1000 Mb/s",
"state": "up",
"type": "100/1000/10000 Ethernet"
},
"Ethernet1/10": {
"bandwidth": 10000000,
"duplex": "auto",
"macaddress": "0800.276c.eecc",
"mode": "access",
"mtu": "1500",
"speed": "auto-speed",
"state": "down",
"type": "100/1000/10000 Ethernet"
},
But I'm struggling with the syntax to dereference the dictionary to only print when the "state" is "up"?
I'm running with the following version:
ansible 2.3.1.0
Any help is much appreciated.
You can iterate over the dictionary of interfaces and print only those elements for which the condition is true. Example:
- name: mytask
debug:
msg: "{{ item }}"
when: "item.value.state == 'up'"
with_dict: "{{ nxfacts_nxapi.ansible_facts.ansible_net_interfaces }}"