Table of Contents

Ansible

Experimenting environment

Here is an environment for experimenting:

https://github.com/skipidar/ExperimentsProject-4Ansible-usingVagrant/wiki

Configuration of ansible

Add hosts here: /etc/ansible/hosts

local ansible_host=127.0.0.1   ansible_connection=local

slave ansible_host=10.0.0.11 ansible_user=vagrant ansible_ssh_private_key_file=/home/vagrant/.ssh/key.myexperimental.openssh.ppk

Add the ssh private-key in openSSH form here, which will be used by ansible

/home/vagrant/.ssh/id_rsa

Example:

-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAxQRyoCBSijfLHpuQKR+0/nsO4p66r4xDre0nJZ8FgHwW+ATd
zRr/Mu6C5DgS1ENY9No8yOH56zqnqlhoQpTY5d+wypbkkF3AG3N0D0DrHK4CHjjP
NylHAm4+ATuU68agYOVTPycY19DXaAgQBqtJlRVHhMB9ZJ+ugAdKINjpW//8uwvP
HisH6GYbA5zWugNHmyfNLdYdJcdozTUprHFkRz6E2HyCxEuhurbcHtsEEfgCd93f
bHn2utRg24VIRFNZF24C6N/OSrsmdKbYsQV/VygHEo6VYM4DUOcz1nzU5f3f5k1p
itgBbyVqIID++XwxNCl8wAjUWFEHvA+xyf4ZywIBJQKCAQB/y4ifN498P92y/R89
RP/HqcR3UjPnfZOvFl6U8YcHO7vfJcBNsKWI0g+2oOmecN/Bavb+18S0QbjdMm0k
RN+3s7DyHK/u8LP2IWAJ5OuIOYTVVUgjx79bhcdavt0jUGgHf/6lgSTfBAFYPJTG
Dj2RIo9BWkN/iiwABLp2K9WjdHiYwMm2bQqZx2lB4oNPyfhdEUAmd2cdVCfH60mq
315KRjO9TgH3ORz43I62rFwSiEaP2VDWhG8nOiMp8wONhaES41uZ05pGA6F9cAdO
DvPpK4QcwZ8KZdkJQJBhXu3UvfIS1C6AZ7b08lf+ifU5shqZMerVPxY6RC6FzSRV
rs7tAoGBAPSrlQjDhHcCLFd/FyCuTaYQQhokbYRdeZ1bRj5Sv62XB6K8u6NeuKIB
4v3W24dnZb51xhk4SOFOXC2lxR0q56MxVsZwl+5vRJEt7wlVYy4yK8JH4r1shDZG
/FxQzIfkjxIxMoVhqKL2tdhlE+p0ZPZFRiTCvougXDCaMAfdlGrfAoGBAM4j+DoM
E8s5JlaUSIDws5f7axrOGy8lwWNzDtnHmVqoX/0Ck0cIcEhj1SzuYG64qtc5qL7p
ej9lU+eqaYWfPbLo+LnrIadaMPxQAG7DS0PILoPJAVgZl3PGUfjvk0kEH03YE8cj
OiRpefS9rbp2z1HtYQ30iQZzdmS+Q2c9ptqVAoGALkn5md/M8+unhizNBi7Qa4aJ
C91g09pVR0ielitUsiN9/DGLSGvdvckBbks+Sgyki9EXo+gNycK3fkH03AEyvgJq
XOTeeTelMDkfYqFzoPS8K6y8May/ETAGOvqHj1TBHx4QehllF+l8WV87HoS5J6w9
s+19/r15OaChTZifidcCgYEAgCQyhPLAMjhIQ6hIvtrQgRHoofW93wmhulxHgHUn
+hWjc8NUocb5sHVo1r2xkO9VcQgqoDBFEqbFdFUs1oWVDll4BN5FWjElXpKYfDQ1
tINbL1Nvicq4F4keMvXKQiUoN073iaBGvLBE5D6OloE0xDmdMjA5gIz2kaa0Rxh8
egkCgYB7QihLpX+8sDAyENjs5ylJgsOV8N6e2Twhqjy1B0j0SZoXToOB/Grohk5m
BZOsSCeSn4Qb+N8aX0EFXuUHCZVXsYnv8fpiZEYReXNij0mi5MbYby8eY24V9iuO
Xixof23aO5mPprsvg/s+GHfbXtZmApDi+wVoN9YNMN43ovxB+w==
-----END RSA PRIVATE KEY-----

Add the ssh public-key in openSSH form here, which will be used by ansible

/home/vagrant/.ssh/authorized_keys

Example:

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAxQRyoCBSijfLHpuQKR+0/nsO4p66r4xDre0nJZ8FgHwW+ATdzRr/Mu6C5DgS1ENY9No8yOH56zqnqlhoQpTY5d+wypbkkF3AG3N0D0DrHK4CHjjPNylHAm4+ATuU68agYOVTPycY19DXaAgQBqtJlRVHhMB9ZJ+ugAdKINjpW//8uwvPHisH6GYbA5zWugNHmyfNLdYdJcdozTUprHFkRz6E2HyCxEuhurbcHtsEEfgCd93fbHn2utRg24VIRFNZF24C6N/OSrsmdKbYsQV/VygHEo6VYM4DUOcz1nzU5f3f5k1pitgBbyVqIID++XwxNCl8wAjUWFEHvA+xyf4Zyw== rsa-key-20170928vagrant@master:~$

Configure the ssh-key permissions. Ansible will check them and if someone else can access the keys decine the usage of the key.

chmod -R 700 /home/vagrant/.ssh

Debugging the connection

Try connecting to the server using ssh

ssh ec2-user@48.114.120.127 -p 22 -i /root/vagrant-home/ssh/demokey.pem

Try using the -vvvv parameter.

ansible slave -vvvv -m ping

Introduction

Here is a good introduction: https://serversforhackers.com/c/an-ansible-tutorial

Commands

Send a command to all ansible hosts

ansible all -m ping -u "ec2-user"

Send a command to slave only

ansible slave -m ping -u "ec2-user"

Execute a shell command remotely.
The module used here is shell - it is not that the shell is executed remotely, but using the argument -m an ansible module is used. The -a flag is used to pass any arguments to the module

ansible all -s -m shell -a 'apt-get install nginx'

Playbook

Hierarchy:

Tasks

Create the following playbook in a file addmycowsay.yaml

---
- hosts: local
  tasks:
   - name: install cowsay
     apt: pkg=cowsay state=installed update_cache=true

And execute the playbook

ansible-playbook addmycowsay.yaml

So the syntax is the following:

---
- hosts: <LOCATION>
  tasks:
   - name: <COMMENT>
     <MODULE>: pkg=<APT_PACKAGE> state=installed update_cache=true

Handlers

---
- hosts: local
  tasks:
   - name: Install Nginx
     apt: pkg=nginx state=installed update_cache=true
     notify:
      - Start Nginx

  handlers:
   - name: Start Nginx
     service: name=nginx state=started

Become non root

To allow becoming non priviledged user to things must be set to True in /etc/ansible/ansible.cfg

Important: The given settings must be uncommented at the right locations in ansible.cfg. It is insufficient to append those settings to ansible.cfg.

allow_world_readable_tmpfiles = True
pipelining = True

To uncomment them programmatically do

sed -i 's/.*pipelining.*/pipelining = True/' /etc/ansible/ansible.cfg
sed -i 's/.*allow_world_readable_tmpfiles .*/allow_world_readable_tmpfiles = True/' /etc/ansible/ansible.cfg

Here is an example playbook, which shows how to become the user “oracle”

# Setup the infrastructure for Faktura
- hosts: "myhost"
  become: yes
  become_method: sudo
  become_user: oracle
  vars:
    allow_world_readable_tmpfiles: true
  tasks:         


        # an error is thorwn when becoming unpriviledged user. Hence use sudo
        - name: install oracle client
          shell: |
                whoami
          args:
            chdir: /tmp/client
          environment:
            DISTRIB: /tmp/client

Remove Old SSH Key Fingerprint

When connecting to an unknown host - your are asked whether to trust it. Linux then stores a fingerprint of the key associated with the host.

If the host then changes, e.g. because of the replacement of the EC2 machine behind the host - connection will fail.

To remove the fingerprint do:

ssh-keygen -R '45.157.214.126'

Extra vars alias arguments

Pass external variables as arguments to the playbook, to e.g. define hosts outside of the playbook.

ansible-playbook myplaybook.yaml --extra-vars "host=yourhost"

And here is myplaybook:

- hosts: "{{ host }}"
  become: true
  become_method: sudo
  become_user: root
  
  ...

Ansible behind proxy

If you configure the Hosts to use corkscrew, then ansible will be able to reach the machines:

Open /home/vagrant/.ssh/config, add

Host *
    ProxyCommand corkscrew 194.138.0.33 9400 %h %p

Galaxy

You can use the galaxy (https://galaxy.ansible.com/intro) to share roles or download them.

A role “cmacrae.sensu” might be downloaded using

ansible-galaxy install cmacrae.sensu

After that you can embed the role into your playbooks:

---
- name: Install sensu
  hosts: slave
  become: true
  roles:
    - { role: cmacrae.sensu, sensu_master: true, sensu_include_dashboard: true  }

MODULE FAILURE - rc 127

When ssh works, but the ping fails with

$ ansible slaves -m ping -vvvv

ansible 2.5.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/vagrant/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609]
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 127
}

Then it will help to ssh to the remote host and install python

ssh 34.242.178.166 -l ubuntu -i /home/vagrant/.ssh/DevOpsBootCamp.openssh.ppk
ubuntu@34.242.178.166: sudo apt install python

Check https://github.com/ansible/ansible/issues/25941

AWX installation

The UI, which enables team management and delegation is available as the AWX project https://github.com/ansible/awx

Importing and Including

include*Is done evaluated at runtime
Import*Is done at compile time. PREFER THAT.

import_tasks

Can be used, to extract equal steps you want to reuse in a separate file.

import_tasks* Allows passing variables. Requires the imported file to have only tasks, no “hosts” etc.

Usecase: requirements for a Renderer/Viewer which needs the same preparations.

common_requirements.yaml It is important, that you dont have the header here. Only tasks

  - name: Creates product configuration file
    file:
      path: /etc/apt/apt.conf.d/product
      state: touch
      owner: ubuntu
      group: ubuntu
      mode: 0700

  - name: product config content
    copy:
      dest: "/etc/apt/apt.conf.d/product"
      content: |
        Acquire::https::repo.product.com {
          Verify-Peer "true";
          Verify-Host "true";

          SslCert "/etc/ssl/product/MYCERT.crt";
          SslKey "/etc/ssl/product/MYKEY.key";
        };

Renderer:

---
- hosts: "{{ host }}"
  become: true
  become_method: sudo
  become_user: root
  tasks:

  - name: Install product requirements
    import_tasks: common_requirements.yml
    vars:
      host: aws

  - name: Install renderer
    become: true
    apt: product_renderer

Viewer:

---
- hosts: "{{ host }}"
  become: true
  become_method: sudo
  become_user: root
  tasks:

  - name: Install product requirements
    import_tasks: common_requirements.yml
    vars:
      host: aws

  - name: Install VIEWER, reusing the tasks
    become: true
    apt: product_viewer

import_playbook

Unfortunately lacks the possibility to pass in variables. Which makes it unusable

Read remote files

To read remote file do use slurp

  - name: set facts
    set_fact:
      dest_timestamp: /tmp/progress/timestamp
      
      
  - name: Slurp timestamp file
    slurp:
      src: "{{ dest_timestamp }}"
    register: slurpfile

  - name: set the timestamp fact
    set_fact:
      timestamp: "{{ slurpfile['content'] | b64decode }}"

  - name: timestamp variable
    debug: msg="{{ timestamp }}"
      
      

Execute a shell script, as a user with a valid environment

Sometimes you face the issues, that the environment variables defined by some tool, installed for a special user - are not defined, when you execute the tool.

To execute some installed software in a valid environment,
with /home/bashrc
with /etc/profile.d
etc

use the following approach.

      # unfortunately the environment defined by tool in /etc/profile.d - is not taken up by ansible. Explicitely requesting the interactive shell is necessary here
      - name: processing step
        shell:
          sudo -iu ubuntu yourtool.sh   > /tmp/logs/yourtool.log 2>&1
        args:
          executable: /bin/bash


       -i [command]
                   The -i (simulate initial login) option runs the shell specified in the passwd(5) entry of the target user as a login shell.  This means that login-specific
                   resource files such as .profile or .login will be read by the shell.  If a command is specified, it is passed to the shell for execution.  Otherwise, an
                   interactive shell is executed.  sudo attempts to change to that user's home directory before running the shell.  It also initializes the environment, leaving
                   DISPLAY and TERM unchanged, setting HOME, MAIL, SHELL, USER, LOGNAME, and PATH, as well as the contents of /etc/environment on Linux and AIX systems.  All other
                   environment variables are removed.

See https://github.com/ansible/ansible/issues/4854

UNfortunately the aproach with become_user - does not have the same result