ansible iam_user deletion does not work - ansible

I tried to delete an user by:
- name: "Remove user abc"
iam_user:
name: abc
state: absent
it gave me following error:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: DeleteConflictException: An error occurred (DeleteConflict) when calling the DeleteUser operation: Cannot delete entity, must delete access keys first.
fatal: [localhost]: FAILED! => {
"changed": false,
"error": {
"code": "DeleteConflict",
"message": "Cannot delete entity, must delete access keys first.",
"type": "Sender"
},
"response_metadata": {
"http_headers": {
"content-length": "298",
"content-type": "text/xml",
"date": "Thu, 12 Jul 2018 20:53:02 GMT",
"x-amzn-requestid": "91913df0-8615-11e8-b3e7-b16567885120"
},
"http_status_code": 409,
"request_id": "91913df0-8615-11e8-b3e7-b16567885120",
"retry_attempts": 0
}
}
MSG:
Unable to delete user intelerad-billing-mzhao-client-creator-user: An error occurred (DeleteConflict) when calling the DeleteUser operation: Cannot delete entity, must delete access keys first.
It seems there is even no ansible module to delete access key.
any hints?

AWS IAM APIs are finicky when it comes to user deletion. Deletion can be blocked if the user is assigned access keys or if the user's login profile doesn't exist.
Funny enough, Ansible has two modules that you can use to delete users: iam and iam_user, but one errors on access keys and the other errors on non-existant login profiles.
So let's go ahead and leverage AWS CLI for this one.
This playbook worked for me to create and delete a user with keys.
---
- name: Create / Delete IAM user with keys
hosts: localhost
connection: local
vars:
username: foo
tasks:
- name: Create user with keys
iam:
iam_type: user
name: "{{ username }}"
state: present
access_key_state: create
key_count: 2
- name: Get all the access keys
shell: aws iam list-access-keys --user-name {{ username }} --query 'AccessKeyMetadata[*].AccessKeyId'
register: access_key_list
- name: Delete each key
shell: aws iam delete-access-key --access-key-id {{ item }} --user-name {{ username }}
loop: "{{ access_key_list.stdout | from_json }}"
- name: Delete user
iam_user:
name: "{{ username }}"
state: absent
Note that the deletion task is iam_user. This is because plain iam will error if the user login profile doesn't exist.
Hope that helps!

Related

How can I pass login information with multiple username and password from the hashi vault when I run a playbook?

I have multiple repositories for those credentials I am keeping in hashi vault
vault:
Key : value
user1 : password
user2 : password
config.yml file
repo1: docker
user: user1
password: password
repo2: docker1
user: user2
password: password2
I have created json.j2 file for the same:
config.json.j2
{
"url" : "{{url}}",
"username" : "",
"password" : {{ repo_cred }},
}
And playbook that should that is giving me the list of username and password:
main.yml
tasks:
- name: lookup user name and password
set_fact:
repo_cred: "{{ lookup('hashi_vault', hashi_vault_params) }}"
delegate_to: localhost
vars:
hashi_vault_params: >-
secret={{ hashi_vault.secret }}
url={{ url }}
token={{ hashi_vault }}
ca_cert={{ hashi_vault }}
hashi_vault:
secret: "test/repo_pass"
token: "{{ vault_token }}"
url: "{{ service }}"
ca_cert: "{{ ca_cert }}"
- debug: msg="{{ repo_cred }}"
I am getting the list of username and password as output while running above task but I don't know how to make sure that the each repositories has their username and password.

Ansible template error while templating string : unexpected char '#' in email

I'm using Ansible to get a list of user emails from an API and I want to loop over them.
This is the json response I get from the API:
"users": [
{
"email": "email1#email.com",
"id": 1,
"is_admin": true
},
{
"email": "email2#email.com",
"id": 2,
"is_admin": false
},
]
edit:
the task after that which I need the email for:
- name: Send emails
register: result
uri:
url: http://api
method: GET
body_format: json
return_content: yes
body:
email: "{{ item.email }}"
scope: SCOPE
loop: "{{ users.json['users'] }}"
- name: Print result
debug:
var: result
the error I get:
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: unexpected char '#' at 16. String: {{ email#email.com }}"}
If I use email: item.email the json request body will be "body": {"email": "item.email"} instead of the email value
How Can I get the full email of each user?
You need to remove the {{ and }} markers from your var: directive. The value of var is implicitly evaluated in a Jinja template context so you don't need those markers:
- name: Print returned json dictionary
debug:
var: item.email
loop: "{{ users.json['users'] }}"
(Updated based on edits to your question)
The example you've shown doesn't generate the error you're asking about. Here's a complete reproducer with just the uri changed:
- hosts: localhost
gather_facts: false
vars:
users:
json:
users:
- email: email1#email.com
id: 1
is_admin: true
- email: email2#email.com
id: 2
is_admin: false
tasks:
- name: Send emails
register: result
uri:
url: https://eny1tdcqj6ghp.x.pipedream.net
method: GET
body_format: json
return_content: true
body:
email: "{{ item.email }}"
scope: SCOPE
loop: "{{ users.json['users'] }}"
This runs without errors (although note that I'm suspicious about the
use of a GET request with a JSON body; typically you would expect
that to be a POST request).
You can see the result of running this playbook here, which shows that the values being sent in the request are exactly what we expect from the data.

How to pass list of values dynamically to Ansible URI module

I have one Jfrog API URL using that I can all exiting/Created repos. I need to get those reposes and pass it to some other task to add one Group.
I need to get the naming replos like dev-user1, dev-user1 among diffrent users and pass that in
"repositories": ["dev-user1","dev-user2", "dev-user2"] like that automatically pass then only I can create it as one group. May I know how can I do that.
hosts: all
gather_facts: yes
tasks:
- name: Create a repo
uri:
url: https://raju.jfrog.io/raju/api/repositories/ansiraj-testing12349
method: POST
user: admin
password: xxxxx
body: >
{
"rclass": "virtual",
"packageType": "maven",
"repositories": ["{{ item }}"],
"handleSnapshots": false
}
force_basic_auth: yes
status_code: 200
body_format: json
with_items: "{{ servernames.strip().replace(' ', '').replace(',', '\n').split('\n') }}"
ansible-playbook var-virtual.yml --extra-var "servernames=ansiraju,ansiraj-testing"servernames
It is getting overwriting.
Even I have tried to pass like this.
I am confusing how to pass values in URI module repositories.
can anyone help me on this

Ansible error: with_items expects a list or a set

Here is the Ansible source code where with_items is linked to a dictionary type variable named "grafana_datasource_body". I always get an error message "ith_items expects a list or a set". Here is the source code and related output.
Ansible source code :
- name: Configure datasource creation http body
set_fact:
grafana_datasource_body:
name: "{{Ass_grafana_Datasource_Name}}"
type: "{{Ass_grafana_Datasource_Type}}"
isDefault: "{{Ass_grafana_Datasource_IsDefault}}"
access: "{{Ass_grafana_Datasource_Access}}"
basicAuth: "{{Ass_grafana_Datasource_BasicAuth}}"
url: "{{InfluxDB_Server}}:{{Ass_grafana_Datasource_Http_Port}}"
database: "{{Ass_grafana_Datasource_Db}}"
username: "{{Ass_grafana_Datasource_DbUser}}"
password: "{{Ass_grafana_Datasource_DbPassword}}"
when: Ass_grafana_Datasource_Name not in grafana_datasources_output.json|map(attribute='name')|list
- debug: msg="Datasource creation http body = {{grafana_datasource_body}}"
when: Ass_grafana_Datasource_Name not in grafana_datasources_output.json|map(attribute='name')|list
# Create non existing datasources
- name: datasource > Create datasource
register: grafana_datasources_create_output
failed_when: "'Datasource added' not in grafana_datasources_create_output|to_json"
uri:
url: "http://127.0.0.1:{{Ass_grafana_Listen_Http_Port}}/api/datasources"
method: POST
HEADER_Content-Type: application/json
body: '{{ item|to_json }}'
force_basic_auth: true
user: "{{Ass_grafana_Api_User}}"
password: "{{Ass_grafana_Api_Password}}"
status_code: 200
with_items: "{{grafana_datasource_body}}"
when: item.name not in grafana_datasources_output.json|map(attribute='name')|list
Output
TASK: [./grafana/grafana_Role | Configure datasource creation http body] ******
<10.0.20.7> ESTABLISH CONNECTION FOR USER: centos
ok: [10.0.20.7] => {"ansible_facts": {"grafana_datasource_body": {"access": "proxy", "basicAuth": "false", "database": "webcom-int", "isDefault": "true", "name": "MonTonton", "password": "webcom", "type": "influxdb", "url": "http://localhost:8086", "username": "webcom"}}}
TASK: [./grafana/grafana_Role | debug msg="Datasource creation http body = {{grafana_datasource_body}}"] ***
<10.0.20.7> ESTABLISH CONNECTION FOR USER: centos
ok: [10.0.20.7] => {
"msg": "Datasource creation http body = {'username': u'webcom', 'name': u'MonTonton', 'database': u'webcom-int', 'url': u'http://localhost:8086', 'basicAuth': u'false', 'access': u'proxy', 'password': u'webcom', 'type': u'influxdb', 'isDefault': u'true'}"
}
TASK: [./grafana/grafana_Role | datasource > Create datasource] ***************
fatal: [10.0.20.7] => with_items expects a list or a set
FATAL: all hosts have already failed -- aborting
Any real reason to use with_items loop here?
Replace
with_items: "{{grafana_datasource_body}}"
with
with_items: "{{ [grafana_datasource_body] }}"
this will work.
But you can use body: '{{ grafana_datasource_body|to_json }}' and don't use with_items.

Create influxdb user using Ansible

How can I create a user in Influxdb using ansible module ?
In influxdb ansible docs , I could not find that how to create a user.
I am trying to create it via influxdb API, but have not got success in that.
- name: create user in influxdb
uri:
url: "http://localhost:8086/query"
method: POST
body: "--data-urlencode 'q=CREATE USER myuser WITH PASSWORD 'mypass' WITH ALL PRIVILEGES'"
body_format: raw
The response is,
fatal: [192.168.122.62]: FAILED! => {"changed": false, "connection": "close", "content": "{\"error\":\"missing required parameter \\\"q\\\"\"}\n", "content_length": "45", "content_type": "application/json", "date": "Wed, 05 Jul 2017 12:08:26 GMT", "failed": true, "json": {"error": "missing required parameter \"q\""}, "msg": "Status code was not [200]: HTTP Error 400: Bad Request", "redirected": false, "request_id": "a6c36bfd-617a-11e7-800c-000000000000", "status": 400, "url": "http://localhost:8086/query", "x_influxdb_version": "1.2.2"}
I had a nightmare with quotes... BUT this one worked for me:
- name: "[Centos7_InfluxDB] Create InfluxDB user"
command: 'influx -database {{item.database}} -execute "CREATE USER {{item.user}} WITH PASSWORD
{{item.pass}} WITH ALL PRIVILEGES"'
with_items:
- { database: "sample_database", user: "adminuser", pass: "'adminpass'" }
This code should work as you expect :
- name: create user in influxdb
uri:
url: "http://localhost:8086/query"
method: POST
body: "q=CREATE USER myuser WITH PASSWORD 'mypass' WITH ALL PRIVILEGES"
You can easily create a user using the command module.
- name: Create InfluxDB user
command: "influx -execute \"CREATE USER {{item.user}} WITH PASSWORD
'{{item.pass}}' WITH ALL PRIVILEGES\""
with_items:
- { user: 'admin', pass: 'admin' }
This should be a lot more efficient than using the REST api.
If anyone's wondering about that as well - just keep in mind that there are community modules for Ansible that already do everything you want, without having to do it with raw/command modules

Resources