Difference between revisions of "Ansible Howto"

From Cactus Howto
Jump to navigationJump to search
 
(61 intermediate revisions by the same user not shown)
Line 5: Line 5:
* changing root passwords: https://www.redpill-linpro.com/sysadvent/2017/12/02/ansible-change-passwords.html
* changing root passwords: https://www.redpill-linpro.com/sysadvent/2017/12/02/ansible-change-passwords.html


== installation ==
== installation ansible host ==
=== on ubuntu >= 18.04 ===
=== on ubuntu >= 18.04 ===
sudo apt install ansible
sudo apt install ansible
Line 13: Line 13:


<pre>
<pre>
as root:
sudo echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list
echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt-key adv --keyserver-options http-proxy=http://10.5.1.10:3128/ --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt update
sudo apt update
sudo apt upgrade
sudo apt upgrade
Line 27: Line 27:
useradd -m tim -s /bin/bash
useradd -m tim -s /bin/bash
passwd tim
passwd tim

install sudo (as root, if sudo does not exist)
apt-get install sudo
add user to sudo group
add user to sudo group
grep sudo /etc/group
grep sudo /etc/group
Line 33: Line 36:
grep sudo /etc/sudoers
grep sudo /etc/sudoers
%sudo ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL
make sure root path is set correctly when executing command via sudo:
grep secure_path /etc/sudoers
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
this can be automated later (with ansible working) using the following adhoc command:
ansible all -m lineinfile -a "dest=/etc/sudoers state=present line='secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"'" -b -K

=== Install python (if it does not already exist) ===
sudo apt install python


from here in user context
from here in user context
Line 40: Line 51:
echo "<ssh-public-key>" >> /home/tim/.ssh/authorized_keys
echo "<ssh-public-key>" >> /home/tim/.ssh/authorized_keys
chmod 600 /home/tim/.ssh/authorized_keys
chmod 600 /home/tim/.ssh/authorized_keys

=== additional useful packages on clients ===
install acl package to make sure "become_user" works correctly in debian:
ansible debsrv1 -m package -a "name=acl state=present" -b -K
install python (needed for Fedora clients):
ansible debsrv1 -m package -a "name=python state=present" -b -K


== initial ansible serverconfig ==
== initial ansible serverconfig ==
Edit /etc/ansible/hosts
=== fill /etc/ansible/hosts ===
add all your hosts/groups to your /etc/ansible/hosts file




Line 55: Line 73:
or better:
or better:
sudo apt install keychain
sudo apt install keychain
then add
echo "eval `keychain --eval id_rsa`" >>/home/tim/.bashrc
eval `keychain --eval id_rsa`
to $HOME/.bashrc

Make ssh timeout resistant:
tim@spike-vm:~$ cat .ssh/config
Host *
ServerAliveInterval 240


=== test client connectivity ===
=== test client connectivity ===
Line 98: Line 123:
</pre>
</pre>


= ansible playbooks =
= ansible ad-hoc commands =


== use cases add file ==
== execute commands on remote hosts ==
== use cases append to file ==
=== execute simple command ===
ansible spiegel -m command -a "ls -la"


=== execute command as root via sudo ===
Example add public key to authorized_keys
ansible spiegel -m command -a "checkrestart" -b -K


== use cases edit file ==
== restart service ==
ansible spiegel -m service -a "name=puppet state=restarted" -b -K

== gather system information ==

=== display os version ===
ansible all -m setup -a "filter=ansible_lsb"

== use case add file ==

== use case add public key to authorized_keys ==
ansible all -m authorized_key -a "user=tim key='ssh-rsa AAAA...XXX == tim@hostname'"

== use case edit file ==
=== Add alias in .bashrc ===
ansible "target host" -m lineinfile -a "dest=/home/tim/.bashrc create=yes state=present line='alias ll=\'ls -l\''"

=== Add new user "newuser" to sudo group ===
ansible "target host" -m lineinfile -a "backrefs=yes dest=/etc/group regexp='^(sudo:x:27:)(.*)' line='\1newuser,\2'"

=== Change setting: remove (deprecated) settings in config file only on specific os versions ===
tim@spike-vm:~$ cat test.conf
abc=123
pfad=44
xcd=77

tim@spike-vm:~/ansi$ ansible-playbook -l debians /home/tim/ansi/comment-out-lines.yml -K -e "path=test.conf regex='pfad'"

tim@spike-vm:~$ cat test.conf
abc=123
# removed deprecated config line "pfad=44"
xcd=77

playbook:
<pre>
tim@spike-vm:~$ cat /home/tim/ansi/comment-out-lines.yml
---

# expects variable regex to contain the string that matches the start of the config line
# expects variable path to contain the filename
# limited to debian version >= 9
- hosts: all
become: yes
tasks:

- name: comment out config line
lineinfile:
backup=yes
state=present
path={{ path }}
regexp='^({{ regex }}.*)'
backrefs=yes
line='# removed deprecated config line "\1"'
when: >
ansible_distribution == 'Debian'
and
ansible_lsb.major_release|int >= 9
tim@spike-vm:~$
</pre>
== use case install package ==
Install package "acl":
ansible debsrv1 -m package -a "name=acl state=present" -b -K

= simple ansible playbooks =


== use cases debian/ubuntu sys management using apt ==
== use cases debian/ubuntu sys management using apt ==
Line 117: Line 207:
become: yes
become: yes
tasks:
tasks:
- name: assert ansible version
- name: assert ansible version
assert:
assert:
that:
that:
- "{{ ansible_version.string | version_compare('2.4', '>=') }}"
- "{{ ansible_version.string is version_compare('2.4', '>=') }}"
msg: Ansible 2.4 or above is required
msg: Ansible 2.4 or above is required
- name: .deb do dist-upgrade
- name: .deb do dist-upgrade
apt: >
apt: >
update_cache=yes
update_cache=yes
cache_valid_time=1200
cache_valid_time=1200
upgrade=dist
upgrade=dist
autoremove=yes
autoremove=yes
purge=yes
purge=yes
when: >
when: >
ansible_distribution == 'Debian'
ansible_distribution == 'Debian'
or
or
ansible_distribution == 'Ubuntu'
ansible_distribution == 'Ubuntu'
</pre>
</pre>


=== reboot / restart services that need it ===
For use of checkrestart, install package:
sudo apt install needrestart

=== autoremove unused packages ===
=== autoremove unused packages ===
This only works for ansible >=2.4.
This only works for ansible >=2.4.


tim@spike-vm:~/ansi$ ansible-playbook -l puppet apt-autoremove.yml -K
tim@spike-vm:~/ansi$ ansible-playbook -l puppet apt-autoremove.yml -K

tim@spike-vm:~/ansi$ cat apt-autoremove.yml


<pre>
<pre>
tim@spike-vm:~/ansi$ cat apt-autoremove.yml
---
---


Line 149: Line 246:
assert:
assert:
that:
that:
- "{{ ansible_version.string | version_compare('2.4', '>=') }}"
- "{{ ansible_version.string is version_compare('2.4', '>=') }}"
msg: Ansible 2.4 or above is required
msg: Ansible 2.4 or above is required
- name: Autoremove unused packages
- name: Autoremove unused packages
Line 158: Line 255:
or
or
ansible_distribution == 'Ubuntu'
ansible_distribution == 'Ubuntu'
</pre>
tim@spike-vm:~/ansi$



=== use case install apt package ===
=== use case install apt package ===
Line 185: Line 281:
- name: install package "{{ package }}"
- name: install package "{{ package }}"
apt:
apt:
name: apache2
name: "{{ package }}"
when: >
when: >
ansible_distribution == 'Debian'
ansible_distribution == 'Debian'
Line 192: Line 288:


== use case change passwords for linux systems ==
== use case change passwords for linux systems ==

To make password encryption work:
apt install python-passlib

=== change password for your own user on all targets ===
<pre>
tim@spike-vm:~/ansi$ ansible-playbook change-user-password.yml -l spike -K
SUDO password:
Enter New Password:
confirm Enter New Password:

PLAY [all] ******************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************
ok: [spike]

TASK [Change password of calling user] **************************************************************************************************
changed: [spike]

PLAY RECAP ******************************************************************************************************************************
spike : ok=2 changed=1 unreachable=0 failed=0

tim@spike-vm:~/ansi$
</pre>
playbook:
<pre>
tim@spike-vm:~/ansi$ cat change-user-password.yml
---
- hosts: all
become: yes
gather_facts: yes

vars_prompt:
- name: "new_password"
prompt: "Enter New Password"
private: yes
encrypt: "sha512_crypt"
confirm: yes
salt_size: 7

tasks:
- name: Change password of calling user
user: name={{ lookup('env', 'USER') }} update_password=always password={{new_password}}
tim@spike-vm:~/ansi$
</pre>

=== change root password ===

<pre>
tim@spike-vm:~/ansi$ cat change-root-password.yml
---
- hosts: all
become: yes
gather_facts: yes

vars_prompt:
- name: "new_password"
prompt: "Enter New Password"
private: yes
encrypt: "sha512_crypt"
confirm: yes
salt_size: 7

tasks:
- name: Change password of root user
user: name=root update_password=always password={{new_password}}
tim@spike-vm:~/ansi$
</pre>

call with:
tim@spike-vm:~/ansi$ ansible-playbook change-root-password.yml -l puppet -K


= ansible advanced topics =
= ansible advanced topics =
Line 200: Line 367:


=== check point R80 API ===
=== check point R80 API ===

== using ansible via cron in pull mode ==

see https://github.com/ansible/ansible-examples/blob/master/language_features/ansible_pull.yml

= ansible tower / AWX =

== Documentation ==
Documentation setting up AWX: https://www.jeffgeerling.com/blog/2017/ansible-open-sources-ansible-tower-awx

* prepare
tower-cli config host http://<old-awx-host.example.com>
tower-cli config username <user>
tower-cli config password <pass>

== Backup & Restore ==
Backup and restore (or migration): https://github.com/autops/awx-migrate, https://github.com/ansible/awx/blob/devel/DATA_MIGRATION.md

=== Backup ===
tower-cli receive --all > assets.json

=== Restore ===
tower-cli send backup.json

Then add credentials manually as they are not part of the backup.

Latest revision as of 16:39, 22 September 2019

ansible first steps

documentation

installation ansible host

on ubuntu >= 18.04

sudo apt install ansible

on ubuntu older than 18.04 and debian (up to 9/stretch)

These systems ship with ansible versions older than 2.4. For apt module to work smoothly (e.g. autoremove) we really should have ansible 2.4 or above.

as root:
 echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list
sudo apt-key adv --keyserver-options http-proxy=http://10.5.1.10:3128/ --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt update
sudo apt upgrade
sudo apt install ansible

prepare a client for ansible usage

using user tim for ssh sessions, setting user up for sudo, ssh pub key auth

as root user

useradd -m tim -s /bin/bash
passwd tim

install sudo (as root, if sudo does not exist)

apt-get install sudo

add user to sudo group

grep sudo /etc/group
sudo:x:<id>:tim

allow sudo group to use all commands via sudo

grep sudo  /etc/sudoers
%sudo	ALL=(ALL:ALL) ALL

make sure root path is set correctly when executing command via sudo:

grep secure_path /etc/sudoers
Defaults  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

this can be automated later (with ansible working) using the following adhoc command:

ansible all -m lineinfile -a "dest=/etc/sudoers state=present line='secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"'" -b -K

Install python (if it does not already exist)

 sudo apt install python

from here in user context

su - tim
mkdir /home/tim/.ssh
chmod 700 /home/tim/.ssh
echo "<ssh-public-key>" >> /home/tim/.ssh/authorized_keys
chmod 600 /home/tim/.ssh/authorized_keys

additional useful packages on clients

install acl package to make sure "become_user" works correctly in debian:

ansible debsrv1 -m package -a "name=acl state=present" -b -K

install python (needed for Fedora clients):

ansible debsrv1 -m package -a "name=python state=present" -b -K

initial ansible serverconfig

fill /etc/ansible/hosts

add all your hosts/groups to your /etc/ansible/hosts file


setup ssh shell

tim@spike-vm:~/ansi$ ssh-agent bash
tim@spike-vm:~/ansi$ ssh-add /home/tim/.ssh/id_rsa
Enter passphrase for /home/tim/.ssh/id_rsa: 
Identity added: /home/tim/.ssh/id_rsa (/home/tim/.ssh/id_rsa)
tim@spike-vm:~/ansi$

or better:

sudo apt install keychain

then add

eval `keychain --eval id_rsa`

to $HOME/.bashrc

Make ssh timeout resistant:

tim@spike-vm:~$ cat .ssh/config 
Host *
ServerAliveInterval 240

test client connectivity

tim@spike-vm:~/ansi$ ansible itchy -m ping
itchy | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
tim@spike-vm:~/ansi$


Logging

Ansible has built-in support for logging. Add the following lines to your ansible configuration file:

[defaults] 
log_path=/var/log/ansible.log

and then run

tim@spike-vm:~$ sudo touch /var/log/ansible.log
tim@spike-vm:~$ sudo chmod 666 /var/log/ansible.log

This simply logs the command line output to the file

Debugging

Use -v switch to see playbook stdout:

tim@spike-vm:~$ ansible-playbook ansi/update-upgrade.yml -K -v
Using /etc/ansible/ansible.cfg as config file
SUDO password: 
/etc/ansible/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/etc/ansible/hosts did not meet script requirements, check plugin documentation if this is unexpected

PLAY [all] *******************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************
ok: [itchy]
...
TASK [.deb do dist-upgrade] **************************************************************************************************************************
ok: [gware] => {"changed": false, "msg": "Reading package lists...\nBuilding dependency tree...\nReading state information...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n", "stderr": "", "stderr_lines": [], "stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\n0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.\n", "stdout_lines": ["Reading package lists...", "Building dependency tree...", "Reading state information...", "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded."]}

ansible ad-hoc commands

execute commands on remote hosts

execute simple command

ansible spiegel -m command -a "ls -la"

execute command as root via sudo

ansible spiegel -m command -a "checkrestart" -b -K

restart service

ansible spiegel -m service -a "name=puppet state=restarted" -b -K

gather system information

display os version

ansible all -m setup -a "filter=ansible_lsb"

use case add file

use case add public key to authorized_keys

ansible all -m authorized_key -a "user=tim key='ssh-rsa AAAA...XXX == tim@hostname'"

use case edit file

Add alias in .bashrc

ansible "target host" -m lineinfile -a "dest=/home/tim/.bashrc create=yes state=present line='alias ll=\'ls -l\"

Add new user "newuser" to sudo group

ansible "target host" -m lineinfile -a "backrefs=yes dest=/etc/group regexp='^(sudo:x:27:)(.*)' line='\1newuser,\2'"

Change setting: remove (deprecated) settings in config file only on specific os versions

tim@spike-vm:~$ cat test.conf
abc=123
pfad=44
xcd=77
tim@spike-vm:~/ansi$ ansible-playbook -l debians /home/tim/ansi/comment-out-lines.yml -K -e "path=test.conf regex='pfad'"
tim@spike-vm:~$ cat test.conf
abc=123
# removed deprecated config line "pfad=44"
xcd=77

playbook:

tim@spike-vm:~$ cat /home/tim/ansi/comment-out-lines.yml 
---

# expects variable regex to contain the string that matches the start of the config line
# expects variable path to contain the filename
# limited to debian version >= 9
- hosts: all
  become: yes
  tasks:

  - name: comment out config line
    lineinfile:
         backup=yes
         state=present
         path={{ path }}
         regexp='^({{ regex }}.*)'
         backrefs=yes
         line='# removed deprecated config line "\1"'
    when: >
           ansible_distribution == 'Debian'
           and
           ansible_lsb.major_release|int >= 9
tim@spike-vm:~$ 

use case install package

Install package "acl":

ansible debsrv1 -m package -a "name=acl state=present" -b -K

simple ansible playbooks

use cases debian/ubuntu sys management using apt

update and upgrade packages

tim@spike-vm:~/ansi$ cat apt-update-upgrade.yml

---

- hosts: all
  become: yes
  tasks:
    - name: assert ansible version
      assert:
        that:
          - "{{ ansible_version.string is version_compare('2.4', '>=') }}"
        msg: Ansible 2.4 or above is required
    - name: .deb do dist-upgrade
      apt: >
         update_cache=yes
         cache_valid_time=1200
         upgrade=dist
         autoremove=yes
         purge=yes
      when: >
         ansible_distribution == 'Debian'
         or
         ansible_distribution == 'Ubuntu'


reboot / restart services that need it

For use of checkrestart, install package:

 sudo apt install needrestart

autoremove unused packages

This only works for ansible >=2.4.

tim@spike-vm:~/ansi$ ansible-playbook -l puppet apt-autoremove.yml -K
tim@spike-vm:~/ansi$ cat apt-autoremove.yml
---

- hosts: all
  become: yes
  tasks:
     - name: assert ansible version
       assert:
         that:
           - "{{ ansible_version.string is version_compare('2.4', '>=') }}"
         msg: Ansible 2.4 or above is required
     - name: Autoremove unused packages
       apt:
         autoremove: yes
       when: >
        ansible_distribution == 'Debian'
        or
        ansible_distribution == 'Ubuntu'

use case install apt package

tim@spike-vm:~/ansi$ ansible-playbook -l puppet apt-install.yml -K -e "package=apache2"
SUDO password: 

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [puppet]

TASK [install package "apache2"] ***********************************************
ok: [puppet]

PLAY RECAP *********************************************************************
puppet                     : ok=2    changed=0    unreachable=0    failed=0   
tim@spike-vm:~/ansi$ cat apt-install.yml 
---

- hosts: all
 become: yes
 tasks:
    - name: install package "Template:Package"
      apt:
       name: "Template:Package"
      when: >
       ansible_distribution == 'Debian'
       or
       ansible_distribution == 'Ubuntu'

use case change passwords for linux systems

To make password encryption work:

apt install python-passlib  

change password for your own user on all targets

tim@spike-vm:~/ansi$ ansible-playbook change-user-password.yml -l spike -K
SUDO password: 
Enter New Password: 
confirm Enter New Password: 

PLAY [all] ******************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************
ok: [spike]

TASK [Change password of calling user] **************************************************************************************************
changed: [spike]

PLAY RECAP ******************************************************************************************************************************
spike                      : ok=2    changed=1    unreachable=0    failed=0   

tim@spike-vm:~/ansi$ 

playbook:

tim@spike-vm:~/ansi$ cat change-user-password.yml 
---
- hosts: all
  become: yes
  gather_facts: yes

  vars_prompt:
    - name: "new_password"
      prompt: "Enter New Password"
      private: yes
      encrypt: "sha512_crypt"
      confirm: yes
      salt_size: 7

  tasks:
    - name: Change password of calling user
      user: name={{ lookup('env', 'USER') }} update_password=always password={{new_password}}
tim@spike-vm:~/ansi$ 

change root password

tim@spike-vm:~/ansi$ cat change-root-password.yml 
---
- hosts: all
  become: yes
  gather_facts: yes

  vars_prompt:
    - name: "new_password"
      prompt: "Enter New Password"
      private: yes
      encrypt: "sha512_crypt"
      confirm: yes
      salt_size: 7

  tasks:
    - name: Change password of root user
      user: name=root update_password=always password={{new_password}}
tim@spike-vm:~/ansi$ 

call with:

tim@spike-vm:~/ansi$ ansible-playbook change-root-password.yml -l puppet -K

ansible advanced topics

use case add firewall rule

iptables

check point R80 API

using ansible via cron in pull mode

see https://github.com/ansible/ansible-examples/blob/master/language_features/ansible_pull.yml

ansible tower / AWX

Documentation

Documentation setting up AWX: https://www.jeffgeerling.com/blog/2017/ansible-open-sources-ansible-tower-awx

  • prepare
tower-cli config host http://<old-awx-host.example.com>
tower-cli config username <user>
tower-cli config password <pass>

Backup & Restore

Backup and restore (or migration): https://github.com/autops/awx-migrate, https://github.com/ansible/awx/blob/devel/DATA_MIGRATION.md

Backup

tower-cli receive --all > assets.json

Restore

tower-cli send backup.json

Then add credentials manually as they are not part of the backup.