Reputation: 31
I'm trying to get the playbook show only the filtered result. But instead it showing filtered and non-filtered result. e.g: I just want it to show only the files that not owned by root in the output.
- set_fact:
target_file: /var/log/apache2/
- name: verify that the logs ownership/perms are belong to system administrators and service accounts.
block:
- find:
paths: "{{ target_file }}"
patterns: "*.log"
register: ownership
failed_when: ownership.files | selectattr('pw_name', '!=', 'root')
- debug:
var: ownership
- find:
paths: "{{ target_file }}"
patterns: "*.log"
register: group
failed_when: group.files | selectattr('gr_name', '!=', 'adm')
- find:
paths: "{{ target_file }}"
patterns: "*.log"
register: permissions
failed_when: permissions.files | selectattr('mode', '!=', '0640')
- set_fact:
stig_text: "PASSED"
rescue:
- name: change the permission and ownership of the files
become: true
file:
path: "{{ item.path }}"
owner: root
group: adm
mode: 0640
with_items: "{{ ownership.files }}"
register: change_perms
- set_fact:
stig_text: "PASSED"
when: change_perms.changed == true
Debug output:
TASK [debug] ************************************************************
ok: [localhost] => {
"ownership": {
"changed": false,
"examined": 18,
"failed": false,
"failed_when_result": false,
"files": [
{
"atime": 1652373886.9567592,
"ctime": 1652373886.9567592,
"dev": 2,
"gid": 0,
"gr_name": "root",
"inode": 3096224743982700,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1652373886.9567592,
"nlink": 1,
"path": "/var/log/alternatives.log",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 49270,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
{
"atime": 1623178394.0,
"ctime": 1652791696.643692,
"dev": 2,
"gid": 0,
"gr_name": "root",
"inode": 3377699720693451,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0600",
"mtime": 1623117753.0,
"nlink": 1,
"path": "/var/log/ubuntu-advantage.log",
"pw_name": "root",
"rgrp": false,
"roth": false,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 6,
"msg": ""
}
}
Upvotes: 1
Views: 1520
Reputation: 39089
Because your debug
is just after a command that would fail if pw_name
is not root
, due to your failed_when
condition, the debug
just won't happen if there is any problematic file, and enters the rescue tasks instead, so when you do see the any debug task result, it means there was no problematic file, in terms on ownership, really.
Now the reason being pointed, you have to understand that Ansible is all about idempotency:
An operation is idempotent if the result of performing it once is exactly the same as the result of performing it repeatedly without any intervening actions.
Source: https://docs.ansible.com/ansible/latest/reference_appendices/glossary.html
So, you don't even have to do anything complex here you just have to set the rights and ownership to what it should:
- name: change the permission and ownership of the files
file:
path: "{{ item }}"
owner: root
group: adm
mode: 0640
with_fileglob:
- /var/log/apache2/*.log
register: permission_audit
And then, if you want to make an audit report, you can do something like:
- name: List of security remediation run during this audit
debug:
var: >-
permission_audit.results
| selectattr('changed')
| map(attribute='diff')
Which would yield something like:
TASK [List of security remediation run during this audit] ********************
ok: [localhost] =>
permission_audit.results | selectattr('changed') | map(attribute='diff'):
- after:
mode: '0640'
path: /var/log/apache2/access.1.log
before:
mode: '0777'
path: /var/log/apache2/access.1.log
- after:
mode: '0640'
path: /var/log/apache2/access.2.log
before:
mode: '0777'
path: /var/log/apache2/access.2.log
If you want to show the success or the failure of the audit in the result of the playbook you can even go one step further and assert
the length of this list:
- name: Security audit result
assert:
that: permission_changes | length == 0
fail_msg: Audit on Apache log file rights failed
success_msg: Audit on Apache log file rights passed
vars:
permission_changes: >-
{{
permission_audit.results
| selectattr('changed')
| map(attribute='diff')
}}
And now our playbook will either end in
TASK [Security audit result] **********************************************
ok: [localhost] => changed=false
msg: Audit on Apache log file rights passed
PLAY RECAP ****************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
Or in
TASK [Security audit result] **********************************************
fatal: [localhost]: FAILED! => changed=false
assertion: permission_changes | length == 0
evaluated_to: false
msg: Audit on Apache log file rights failed
PLAY RECAP ****************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=1
Given ten log files; two having rights issues and the two tasks:
- file:
path: "{{ item }}"
owner: root
group: adm
mode: 0640
with_fileglob:
- /var/log/apache2/*.log
register: permission_audit
- name: List of security remediation run during this audit
debug:
var: >-
permission_audit.results
| selectattr('changed')
| map(attribute='diff')
This would yield:
TASK [file] *****************************************************************
changed: [localhost] => (item=/var/log/apache2/access.1.log)
ok: [localhost] => (item=/var/log/apache2/access.10.log)
ok: [localhost] => (item=/var/log/apache2/access.4.log)
ok: [localhost] => (item=/var/log/apache2/access.9.log)
ok: [localhost] => (item=/var/log/apache2/access.7.log)
ok: [localhost] => (item=/var/log/apache2/access.3.log)
ok: [localhost] => (item=/var/log/apache2/access.5.log)
ok: [localhost] => (item=/var/log/apache2/access.8.log)
ok: [localhost] => (item=/var/log/apache2/access.6.log)
changed: [localhost] => (item=/var/log/apache2/access.2.log)
TASK [List of security remediation run during this audit] *******************
ok: [localhost] =>
permission_audit.results | selectattr('changed') | map(attribute='diff'):
- after:
mode: '0640'
path: /var/log/apache2/access.1.log
before:
mode: '0777'
path: /var/log/apache2/access.1.log
- after:
mode: '0640'
path: /var/log/apache2/access.2.log
before:
mode: '0777'
path: /var/log/apache2/access.2.log
And if you rerun those same two tasks again, then it ends up in:
TASK [file] *****************************************************************
ok: [localhost] => (item=/var/log/apache2/access.1.log)
ok: [localhost] => (item=/var/log/apache2/access.10.log)
ok: [localhost] => (item=/var/log/apache2/access.4.log)
ok: [localhost] => (item=/var/log/apache2/access.9.log)
ok: [localhost] => (item=/var/log/apache2/access.7.log)
ok: [localhost] => (item=/var/log/apache2/access.3.log)
ok: [localhost] => (item=/var/log/apache2/access.5.log)
ok: [localhost] => (item=/var/log/apache2/access.8.log)
ok: [localhost] => (item=/var/log/apache2/access.6.log)
ok: [localhost] => (item=/var/log/apache2/access.2.log)
TASK [List of security remediation run during this audit] *******************
ok: [localhost] =>
permission_audit.results | selectattr('changed') | map(attribute='diff'): []
Now, with an empty list on the last debug, we know our security audit passed everything with a green check.
Upvotes: 1