Search code examples
amazon-web-servicesansibleaws-cloudformationamazon-ecsansible-tower

Deploying cloudformation stack to AWS using Ansible Tower


I'm new to Ansible, Ansible Tower, and AWS Cloud Formation and am trying to have Ansible Tower deploy an EC2 Container Service using a Cloud Formation template. I try to run the deploy job and am running into this error below.

 TASK [create/update stack] *****************************************************
  task path: /var/lib/awx/projects/_6__api/tasks/create_stack.yml:2
  <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: awx
  <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo         $HOME/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790 `" && echo ansible-tmp-1470427494.79-207756006727790="` echo $HOME/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790 `" ) && sleep 0'
<127.0.0.1> PUT /tmp/tmpgAsKKv TO /var/lib/awx/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790/cloudformation
<127.0.0.1> EXEC /bin/sh -c 'sudo -H -S -n -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-coqlkeqywlqhagfixtfpfotjgknremaw; LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 AWS_DEFAULT_REGION=us-west-2 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /var/lib/awx/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790/cloudformation; rm -rf "/var/lib/awx/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790/" > /dev/null 2>&1'"'"' && sleep 0'
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "cloudformation"}, "module_stderr": "/bin/sh: /usr/bin/sudo: Permission denied\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}

This is the create/update task:

---
- name: create/update stack
  cloudformation:
    stack_name: my-stack
    state: present
    template: templates/stack.yml
    template_format: yaml
    template_parameters:
      VpcId: "{{ vpc_id }}"
      SubnetId: "{{ subnet_id }}"
      KeyPair: "{{ ec2_keypair }}"
      DbUsername: "{{ db_username }}"
      DbPassword: "{{ db_password }}"
      InstanceCount: "{{ instance_count | default(1) }}"
   tags:
     Environment: test
  register: cf_stack

- debug: msg={{ cf_stack }}
  when: debug is defined

The playbook that Ansible Tower executes is a site.yml file:

---
- name: Deployment Playbook
  hosts: localhost
  connection: local
  gather_facts: no
  environment:
    AWS_DEFAULT_REGION: "{{ lookup('env', 'AWS_DEFAULT_REGION') | default('us-west-2', true) }}"
  tasks:
    - include: tasks/create_stack.yml
    - include: tasks/deploy_app.yml

This is what my playbook folder structure looks like:

/deploy
    /group_vars
       all
    /library
       aws_ecs_service.py
       aws_ecs_task.py 
       aws_ecs_taskdefinition.py
    /tasks
      stack.yml
    /templates
      site.yml

I'm basing everything really on Justin Menga's pluralsight course "Continuous Delivery using Docker and Ansible", but he uses Jenkins, not Ansible Tower, which is probably why the disconnect. Anyway, hopefully that is enough information, let me know if I should also provide the stack.yml file. The files under the library directory are Menga's customized modules from his video course.

Thanks for reading all this and for any potential help! This is a link to his deploy playbook repository that I closely modeled everything after, https://github.com/jmenga/todobackend-deploy. Things that I took out are the DB RDS stuff.


Solution

  • If you look at the two last lines of the error message you can see that it is attempting to escalate privileges but failing:

    <127.0.0.1> EXEC /bin/sh -c 'sudo -H -S -n -u root /bin/sh -c '"'"'echo BECOME-SUCCESS-coqlkeqywlqhagfixtfpfotjgknremaw; LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 AWS_DEFAULT_REGION=us-west-2 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /var/lib/awx/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790/cloudformation; rm -rf "/var/lib/awx/.ansible/tmp/ansible-tmp-1470427494.79-207756006727790/" > /dev/null 2>&1'"'"' && sleep 0'
    fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "cloudformation"}, "module_stderr": "/bin/sh: /usr/bin/sudo: Permission denied\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
    

    As this is a local task it is attempting to switch to the root user on the box that Ansible Tower is running on and the user presumably (and for good reason) doesn't have the privileges to do this.

    With normal Ansible you can avoid this by not specifying the --become or -b flags on the command line or by specifying become: false in the task/play definition.

    As you pointed out in the comments, with Ansible Tower it's a case of unticking the "Enable Privilege Escalation" option in the job template.