Ansible automation

Ansible is an automation tool, a secure shell frontend with expect like functionality. Due to it using SSH it's a very simple service to utilise and requires only python to be installed on each managed machine. SSH should to be configured using authorized keys and is not documented here.

It is recommended to develop the process manually before implementing it in Ansible to allow understanding of any issues that may arise when using Ansible.

Environment

Kali Linux

Operating System

Windows 10 WSL1

Install

Ansible requires a minimum of Python2 version 2.7 or Python3 version 3.5. on the controller and hosts under control.

Controller

First install python3 pip as root and after ansible as the logged in user.

sudo -s
apt update
apt full-upgrade
apt install python3-pip
exit

Now add ~/.local/bin to your $PATH and install pip search to discover ansible tools.

pip3 install pip-search --break-system-packages
pip_search ansible

First hit looks something like this:

📂 ansible            │ 6.1.0       │ 12-07-2022 │ Radically simple IT automation

Install ansible locally (this can take time).

pip3 install ansible --break-system-packages
rehash

Show version

ansible --version
ansible [core 2.13.1]
  config file = None
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/user/.local/bin/ansible
  python version = 3.10.5 (main, Jun  8 2022, 09:26:22) [GCC 11.3.0]
  jinja version = 3.1.2
  libyaml = True

Show options

ansible --help
usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
               [--become-user BECOME_USER]
               [-K | --become-password-file BECOME_PASSWORD_FILE] [-i INVENTORY]
               [--list-hosts] [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o]
               [-t TREE] [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
               [-c CONNECTION] [-T TIMEOUT] [--ssh-common-args SSH_COMMON_ARGS]
               [--sftp-extra-args SFTP_EXTRA_ARGS] [--scp-extra-args SCP_EXTRA_ARGS]
               [--ssh-extra-args SSH_EXTRA_ARGS]
               [-k | --connection-password-file CONNECTION_PASSWORD_FILE] [-C]
               [--syntax-check] [-D] [-e EXTRA_VARS] [--vault-id VAULT_IDS]
               [--ask-vault-password | --vault-password-file VAULT_PASSWORD_FILES]
               [-f FORKS] [-M MODULE_PATH] [--playbook-dir BASEDIR]
               [--task-timeout TASK_TIMEOUT] [-a MODULE_ARGS] [-m MODULE_NAME]
               pattern

Define and run a single task 'playbook' against a set of hosts

positional arguments:
  pattern               host pattern

options:
  --ask-vault-password, --ask-vault-pass
                        ask for vault password
  --become-password-file BECOME_PASSWORD_FILE, --become-pass-file BECOME_PASSWORD_FILE
                        Become password file
  --connection-password-file CONNECTION_PASSWORD_FILE, --conn-pass-file CONNECTION_PASSWORD_FILE
                        Connection password file
  --list-hosts          outputs a list of matching hosts; does not execute anything
                        else
  --playbook-dir BASEDIR
                        Since this tool does not use playbooks, use this as a
                        substitute playbook directory. This sets the relative path
                        for many features including roles/ group_vars/ etc.
  --syntax-check        perform a syntax check on the playbook, but do not execute
                        it
  --task-timeout TASK_TIMEOUT
                        set task timeout limit in seconds, must be positive integer.
  --vault-id VAULT_IDS  the vault identity to use
  --vault-password-file VAULT_PASSWORD_FILES, --vault-pass-file VAULT_PASSWORD_FILES
                        vault password file
  --version             show program's version number, config file location,
                        configured module search path, module location, executable
                        location and exit
  -B SECONDS, --background SECONDS
                        run asynchronously, failing after X seconds (default=N/A)
  -C, --check           don't make any changes; instead, try to predict some of the
                        changes that may occur
  -D, --diff            when changing (small) files and templates, show the
                        differences in those files; works great with --check
  -K, --ask-become-pass
                        ask for privilege escalation password
  -M MODULE_PATH, --module-path MODULE_PATH
                        prepend colon-separated path(s) to module library (default=~
                        /.ansible/plugins/modules:/usr/share/ansible/plugins/modules
                        )
  -P POLL_INTERVAL, --poll POLL_INTERVAL
                        set the poll interval if using -B (default=15)
  -a MODULE_ARGS, --args MODULE_ARGS
                        The action's options in space separated k=v format: -a
                        'opt1=val1 opt2=val2'
  -e EXTRA_VARS, --extra-vars EXTRA_VARS
                        set additional variables as key=value or YAML/JSON, if
                        filename prepend with @
  -f FORKS, --forks FORKS
                        specify number of parallel processes to use (default=5)
  -h, --help            show this help message and exit
  -i INVENTORY, --inventory INVENTORY, --inventory-file INVENTORY
                        specify inventory host path or comma separated host list.
                        --inventory-file is deprecated
  -k, --ask-pass        ask for connection password
  -l SUBSET, --limit SUBSET
                        further limit selected hosts to an additional pattern
  -m MODULE_NAME, --module-name MODULE_NAME
                        Name of the action to execute (default=command)
  -o, --one-line        condense output
  -t TREE, --tree TREE  log output to this directory
  -v, --verbose         Causes Ansible to print more debug messages. Adding multiple
                        -v will increase the verbosity, the builtin plugins
                        currently evaluate up to -vvvvvv. A reasonable level to
                        start is -vvv, connection debugging might require -vvvv.

Privilege Escalation Options:
  control how and which user you become as on target hosts

  --become-method BECOME_METHOD
                        privilege escalation method to use (default=sudo), use
                        `ansible-doc -t become -l` to list valid choices.
  --become-user BECOME_USER
                        run operations as this user (default=root)
  -b, --become          run operations with become (does not imply password
                        prompting)

Connection Options:
  control as whom and how to connect to hosts

  --private-key PRIVATE_KEY_FILE, --key-file PRIVATE_KEY_FILE
                        use this file to authenticate the connection
  --scp-extra-args SCP_EXTRA_ARGS
                        specify extra arguments to pass to scp only (e.g. -l)
  --sftp-extra-args SFTP_EXTRA_ARGS
                        specify extra arguments to pass to sftp only (e.g. -f, -l)
  --ssh-common-args SSH_COMMON_ARGS
                        specify common arguments to pass to sftp/scp/ssh (e.g.
                        ProxyCommand)
  --ssh-extra-args SSH_EXTRA_ARGS
                        specify extra arguments to pass to ssh only (e.g. -R)
  -T TIMEOUT, --timeout TIMEOUT
                        override the connection timeout in seconds (default=10)
  -c CONNECTION, --connection CONNECTION
                        connection type to use (default=smart)
  -u REMOTE_USER, --user REMOTE_USER
                        connect as this user (default=None)

Some actions do not make sense in Ad-Hoc (include, meta, etc)
Managed host

Install python3 on each host you wish to perform operations on

apt install python3 python3-openssl

The user must also have access to super user via sudo.

Configuration

Generate default configuration

mkdir -p ~/.ansible
ansible-config init --disabled -t all > ~/.ansible.cfg

Create an inventory file of hosts and change entry in cfg file, eg

touch ~/.ansible/hosts
sed -i 's/;inventory=\/etc\/ansible\/hosts/inventory=~\/.ansible\/hosts/' ~/.ansible.cfg

Add some machines to the hosts file

[home]
pi1
pi2
pi3

Test

ansible --list-hosts home
  hosts (3):
    pi1
    pi2
    pi3

Ansible uses so-called “playbooks” which contain configuration parameters for the supported modules.

Here is one to upgrade debian.

upgrade.yml

---
- hosts: home
  become: yes
  tasks:
  - name: Upgrade
    ansible.builtin.apt:
      update_cache: yes
      upgrade: full

Running the ruleset is accomplished with ansible-playbook. In the following example, the “junk” reported is the output from the TCSH time setting. Ansible uses a regular ssh login terminal to perform the apt upgrade process.

ansible-playbook ~/.ansible/upgrade.yml
PLAY [home] ***************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
[WARNING]: Module invocation had junk after the JSON data: 0:02.07s
ok: [PiG]
[WARNING]: Module invocation had junk after the JSON data: 0:05.04s
ok: [PiD]
[WARNING]: Module invocation had junk after the JSON data: 0:05.12s
ok: [PiE]
[WARNING]: Module invocation had junk after the JSON data: 0:05.64s
ok: [PiH]
[WARNING]: Module invocation had junk after the JSON data: 0:04.10s
ok: [PiI]
[WARNING]: Module invocation had junk after the JSON data: 0:12.91s
ok: [PiF]

TASK [Upgrade] ************************************************************************************************************
[WARNING]: Module invocation had junk after the JSON data: 1:23.50s
changed: [PiH]
[WARNING]: Module invocation had junk after the JSON data: 0:26.67s
ok: [PiI]
[WARNING]: Module invocation had junk after the JSON data: 5:36.97s
changed: [PiE]
[WARNING]: Module invocation had junk after the JSON data: 6:02.16s
changed: [PiG]
[WARNING]: Module invocation had junk after the JSON data: 6:03.53s
changed: [PiD]
[WARNING]: Module invocation had junk after the JSON data: 17:49.68s
changed: [PiF]

PLAY RECAP ****************************************************************************************************************
PiD                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
PiE                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
PiF                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
PiG                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
PiH                        : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
PiI                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

18:09.41s

One way to fix the “junk” problem found above is to set the TERM variable to ANSIBLE as an SSH option and then detect that in the profile at the remote end.

In .ansible.cfg

# (string) Common extra args for all SSH CLI tools.
ssh_common_args=-o SetEnv='TERM=ANSIBLE'

And in the CSH/TCSH profile, something like this:

if ($TERM == "ANSIBLE") then
   unset time
else
   set time = ( 0 "%Es" )
endif

If you want to see the remote host environment, you can do something like this:

ansible home -m command -a "env"

Resources

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information