====== Ansible ======
Ansible is an ssh based configuration management system. These notes are primarily for my benefit so don't believe anything here!
[[http://books.stuartherbert.com/putting-ansible-to-work/working-with-config-files.html]]
Ansible can also be run from within [[cloud:packer|packer]] from HashiCorp as a Provisioner.
[[https://www.youtube.com/watch?v=jBiueVhDg1Q]]
===== Install pip3 =====
root@client01:~# apt install python3-pip
root@client01:~# which pip3
/usr/bin/pip3
===== Installing Ansible =====
Ansible is a python package and can be installed with pip:-
/usr/bin/pip3 install ansible
Testing if the python-yum module is present:-
python -c \"import yum; print('yum python OK')\"
===== Running playbook locally on just localhost =====
# ansible-playbook playbook.yml -c local
-c is connection.
===== Running a specific section of a playbook =====
ansible-playbook -vv -i hosts-ansible.ans -u ec2-user --sudo --private-key ansible_id_rsa main.yml --tags "section6.1"
Breaks down to:-
| -vv | verbosity required |
| -i hosts-ansible.ans | hosts list to apply to |
| -u ec2-user | Username to log in to instance with |
| --sudo | Use sudo to become root |
| --private-key ans.rsa | Private key half for key based auth |
| main.yml | Entry point file for the playbook|
| --tags "sectionXX" | Run only specific sections identified by tag XX |
===== Regex bug =====
Running this gives a horrible error:-
- name: 5.3.1 set minimum password length.
lineinfile:
state: present
dest: /etc/security/pwquality.conf
backrefs: yes
regexp: '^(#).(minlen.=.)(.*$)'
line: '\28'
TASK [cisHardening : 5.3.1 set minimum password length.] ***********************
fatal: [amazonlinux02]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/ec2-user/.ansible/tmp/ansible-tmp-1536138790.76-173731145979288/lineinfile\", line 2515, in \r\n main()\r\n File \"/home/ec2-user/.ansible/tmp/ansible-tmp-1536138790.76-173731145979288/lineinfile\", line 371, in main\r\n ins_aft, ins_bef, create, backup, backrefs)\r\n File \"/home/ec2-user/.ansible/tmp/ansible-tmp-1536138790.76-173731145979288/lineinfile\", line 236, in present\r\n new_line = m.expand(line)\r\n File \"/usr/lib64/python2.7/re.py\", line 282, in _expand\r\n return sre_parse.expand_template(template, match)\r\n File \"/usr/lib64/python2.7/sre_parse.py\", line 861, in expand_template\r\n raise error, \"invalid group reference\"\r\nsre_constants.error: invalid group reference\r\n", "msg": "MODULE FAILURE", "parsed": false}
From several vague posts, it seems related to the regex handeling, but other very similar blocks of code run just fine:-
- name: 5.3.1 require 1 digit in password
lineinfile:
dest: /etc/security/pwquality.conf
backrefs: yes
regexp: '^(#).(dcredit.=.)(.*$)'
line: '\2-1'
Seems to be related to this line, changing the regex clears the fault:-
line: '\28'
This works:-
regexp: '^(#).(minlen.=)(.*$)'
line: '\2 8'
Maybe there is a way to quote the test (8) after the capturing group (\2).
===== Debug command =====
- name: Add motd line
copy:
src: ../files/js-ccoe.j2
dest: /etc/update-motd.d/31-JS_banner
mode: 0755
register: jsccoe
- debug: var=jsccoe
- name: Run motd updater
command: creates="/etc/update-motd.d/31-JS_banner" /usr/sbin/update-motd
#shell: /usr/sbin/update-motd
when: jsccoe.changed
TASK [cisHardening : debug] ****************************************************
ok: [amazonlinux02] => {
"jsccoe": {
"changed": true,
"checksum": "f66ca742894820e4601b36d75d4f222078db1b7f",
"dest": "/etc/update-motd.d/31-JS_banner",
"gid": 0,
"group": "root",
"md5sum": "319100e8f871ea498d79cf4f0f635b82",
"mode": "0755",
"owner": "root",
"secontext": "system_u:object_r:etc_t:s0",
"size": 298,
"src": "/home/ec2-user/.ansible/tmp/ansible-tmp-1536673397.14-245770485880175/source",
"state": "file",
"uid": 0
}
}
===== Manipulating the outcome of a test =====
Debug can be used to show the outcome of a check, depending on the result this may affect idempotency, and can be overriden, see below.
- debug: var=VARIABLEfromREGISTER
debug: can also show all the suffixes to a variable which can be tested such as ''changed'' and the unix ''rc'' return code from ''$?''
# Get users with bash shell, but not root and check /home/$USER exists, throws error if no home dir. $? gives 0 if exists, 2 if no home dir
- name: 6.2.7 Ensure all users' home directories exist (Scored)
shell: for USER in $(cat /etc/passwd | grep -v root | grep -E "bash" | sed -r 's/(^[^:]*):(.*)/\1/'); do ls -d /home/$USER; done
always_run: yes
ignore_errors: yes
register: HomeDirOK
failed_when: HomeDirOK.rc != 0
changed_when: HomeDirOK.rc != 0
tags:
- scored
- section6.2
- section6.2.7
===== Tips =====
Copy file to remote system:-
- name: Copy file to system
copy:
src: ../files/checkRootPathEnv.sh
dest: /root/checkRootPathEnv.sh
owner: root
group: root
mode: 0700
tags:
- scored
Command module:- command: creates="/path/to/file.txt" cp xxx yyy etc... Tests specify a filename that is used to control whether or not the command needs to be run.
- name: 4.2.1.4 Create and Set Permissions on rsyslog Log Files (Scored)
shell: touch /var/log/{{ item }} creates=/var/log/{{ item }}
with_items:
- messages
- kern.log
- daemon.log
- unused.log
- syslog
tags:
- scored
===== Conditional code =====
- name: Create home directory for cwagent (RedHat Linux)
file:
path: /home/cwagent
state: directory
owner: cwagent
group: cwagent
mode: 0750
when: ansible_distribution_file_variety == "RedHat"
===== Manipulate login shell =====
- name: change user default shell to no-login
user:
name: cwdeviceuser
shell: /sbin/nologin
====== Examples ======
Set up a hosts file for ansible with sections for each group of hosts
$ cat hosts-ansible.ans
[webServers]
amazonlinux02
amazonlinux03
[databaseServers]
amazonlinux03
Run ansible directly (without playbook) to run remote command to install package:-
$ ansible -i hosts-ansible.ans -u ec2-user --sudo --private-key ansible_id_rsa webServers -a "rpm -q postfix"
amazonlinux02 | SUCCESS | rc=0 >>
postfix-2.10.1-6.amzn2.0.1.x86_64
amazonlinux03 | SUCCESS | rc=0 >>
postfix-2.10.1-6.amzn2.0.1.x86_64
andrew@puppet:~/ansible$
===== Install NTP (Chrony?) =====
- name: 3.6 Configure Network Time Protocol (ipv4) (Scored)
service: >
name=ntpd
state=started
enabled=yes
tags:
- scored
- section3.6
- name: 3.6 Configure Network Time Protocol (ipv4) (Scored)
lineinfile: >
dest=/etc/ntp.conf
state=present
regexp="^restrict default"
line="restrict default kod nomodify notrap nopeer noquery"
insertafter=EOF
tags:
- scored
- section3.6
- name: 3.6 Configure Network Time Protocol (ipv6) (Scored)
lineinfile: >
dest=/etc/ntp.conf
state=present
regexp="^restrict -6 default"
line="restrict -6 default kod nomodify notrap nopeer noquery"
insertafter=EOF
tags:
- scored
- section3.6
This page has been accessed for:- \\
Today: {{counter|today}} \\
Yesterday: {{counter|yesterday}} \\
Until now: {{counter|total}} \\