In this exercise, you use standard Ansible modules to create, install, edit, and remove files on managed hosts and manage the permissions, ownership, and SELinux contexts of those files.
Outcomes
Retrieve files from managed hosts, by host name, and store them locally.
Create playbooks that use common file management modules from the ansible.builtin Ansible Content Collection such as copy, file, lineinfile, and blockinfile.
As the student user on the workstation machine, use the lab command to prepare your system for this exercise.
This command prepares your environment and ensures that all required resources are available.
[student@workstation ~]$ lab start file-manage
Procedure 5.1. Instructions
As the student user on workstation, change to the /home/student/file-manage working directory.
Create a playbook called secure_log_backups.yml in the current working directory.
Configure the playbook to use the ansible.builtin.fetch module to retrieve the /var/log/secure log file from each of the managed hosts and store them on the control node.
The playbook should create the secure-backups directory with subdirectories named after the host name of each managed host.
Store the backup files in their respective subdirectories.
Navigate to the /home/student/file-manage working directory.
[student@workstation ~]$ cd ~/file-manage
[student@workstation file-manage]$Create the secure_log_backups.yml playbook.
It should contain a play to fetch the log files from all managed hosts in the inventory, and the play should connect as the remote root user:
--- - name: Use the fetch module to retrieve secure log files hosts: all remote_user: root
Add a task to the play in the secure_log_backups.yml playbook.
That task must retrieve the /var/log/secure log file from the managed hosts and store it in the ~/file-manage/secure-backups directory.
The ansible.builtin.fetch module creates the ~/file-manage/secure-backups directory if it does not exist.
Use the flat: no parameter to ensure the default behavior of appending the host name, path, and file name to the destination.
tasks:
- name: Fetch the /var/log/secure log file from managed hosts
ansible.builtin.fetch:
src: /var/log/secure
dest: secure-backups
flat: noBefore running the playbook, use the ansible-navigator run --syntax-check command to verify its syntax.
Correct any errors before moving to the next step.
[student@workstation file-manage]$ansible-navigator run \>-m stdout secure_log_backups.yml --syntax-checkplaybook: /home/student/file-manage/secure_log_backups.yml
Use the ansible-navigator run command to execute the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout secure_log_backups.ymlPLAY [Use the fetch module to retrieve secure log files] ****************** TASK [Gathering Facts] **************************************************** ok: [servera.lab.example.com] ok: [serverb.lab.example.com] TASK [Fetch the /var/log/secure file from managed hosts] ****************** changed: [serverb.lab.example.com] changed: [servera.lab.example.com] PLAY RECAP **************************************************************** servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Confirm that the playbook retrieved the /var/log/secure files from the managed hosts.
[student@workstation file-manage]$tree -F secure-backupssecure-backups ├── servera.lab.example.com/ │ └── var/ │ └── log/ │ └──secure└── serverb.lab.example.com/ └── var/ └── log/ └──secure
Create the copy_file.yml playbook in the current working directory.
Configure a play in the playbook that connects as the root user and copies the /home/student/file-manage/files/users.txt file to all managed hosts.
Edit the copy_file.yml playbook so that it contains one play that starts with the following initial content:
--- - name: Using the copy module hosts: all remote_user: root
Add a task to the play that uses the ansible.builtin.copy module to copy the /home/student/file-manage/files/users.txt file to all managed hosts.
It must set the following parameters for the users.txt file:
| Parameter | Values |
|---|---|
src
|
files/users.txt
|
dest
|
/home/devops/users.txt
|
owner
|
devops
|
group
|
devops
|
mode
|
u+rw,g-wx,o-rwx
|
setype
|
samba_share_t
|
tasks:
- name: Copy a file to managed hosts and set attributes
ansible.builtin.copy:
src: files/users.txt
dest: /home/devops/users.txt
owner: devops
group: devops
mode: u+rw,g-wx,o-rwx
setype: samba_share_tUse the ansible-navigator run --syntax-check command to verify the syntax of the copy_file.yml playbook.
[student@workstation file-manage]$ansible-navigator run \>-m stdout copy_file.yml --syntax-checkplaybook: /home/student/file-manage/copy_file.yml
Run the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout copy_file.ymlPLAY [Using the copy module] ******************************************* TASK [Gathering Facts] ************************************************* ok: [serverb.lab.example.com] ok: [servera.lab.example.com] TASK [Copy a file to managed hosts and set attributes] ***************** changed: [servera.lab.example.com] changed: [serverb.lab.example.com] PLAY RECAP ************************************************************* servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use the ls -Z command as user devops on the servera machine to verify the attributes of the users.txt file on the managed hosts.
[student@workstation file-manage]$ssh devops@servera 'ls -Z'unconfined_u:object_r:samba_share_t:s0 users.txt
In a preceding step, you set the samba_share_t SELinux type field for the users.txt file.
However, you have decided that you want to change the SELinux context on that file to the default context from the SELinux policy of each system.
Create a playbook called selinux_defaults.yml in the current working directory.
Configure a play in the playbook that uses the ansible.builtin.file module to set the default SELinux context on the file /home/devops/users.txt for user, role, type, and level fields.
To avoid unnecessary changes to the file context by your plays, normally you would also edit the play in copy_file.yml to remove the setype keyword from the ansible.builtin.copy task in its play.
For simplicity, this exercise skips this step.
Create the selinux_defaults.yml playbook.
It should contain the following play that uses the ansible.builtin.file module to set the default context on the file.
---
- name: Using the file module to ensure SELinux file context
hosts: all
remote_user: root
tasks:
- name: SELinux file context is set to defaults
ansible.builtin.file:
path: /home/devops/users.txt
seuser: _default
serole: _default
setype: _default
selevel: _defaultUse the ansible-navigator run --syntax-check command to verify the syntax of the selinux_defaults.yml playbook.
[student@workstation file-manage]$ansible-navigator run \>-m stdout selinux_defaults.yml --syntax-checkplaybook: /home/student/file-manage/selinux_defaults.yml
Run the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout selinux_defaults.ymlPLAY [Using the file module to ensure SELinux file context] ************ TASK [Gathering Facts] ************************************************* ok: [serverb.lab.example.com] ok: [servera.lab.example.com] TASK [SELinux file context is set to defaults] ************************* changed: [serverb.lab.example.com] changed: [servera.lab.example.com] PLAY RECAP ************************************************************* servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use the ls -Z command as user devops on the servera machine to verify the default file attributes of unconfined_u:object_r:user_home_t:s0.
[student@workstation file-manage]$ssh devops@servera 'ls -Z'unconfined_u:object_r:user_home_t:s0 users.txt
Create a playbook called add_line.yml in the current working directory.
Configure a play in the playbook to use the ansible.builtin.lineinfile module to append the line This line was added by the lineinfile module. to the /home/devops/users.txt file on all managed hosts.
Create the add_line.yml playbook.
It should contain the following play:
---
- name: Add text to an existing file
hosts: all
remote_user: devops
tasks:
- name: Add a single line of text to a file
ansible.builtin.lineinfile:
path: /home/devops/users.txt
line: This line was added by the lineinfile module.
state: presentUse ansible-navigator run --syntax-check command to verify the syntax of the add_line.yml playbook.
[student@workstation file-manage]$ansible-navigator run \>-m stdout add_line.yml --syntax-checkplaybook: /home/student/file-manage/add_line.yml
Run the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout add_line.ymlPLAY [Add text to an existing file] ************************************ TASK [Gathering Facts] ************************************************* ok: [serverb.lab.example.com] ok: [servera.lab.example.com] TASK [Add a single line of text to a file] ***************************** changed: [servera.lab.example.com] changed: [serverb.lab.example.com] PLAY RECAP ************************************************************* servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use the cat command as the devops user on the servera machine to verify the content of the users.txt file on the managed hosts.
[student@workstation file-manage]$ ssh devops@servera 'cat users.txt'
This line was added by the lineinfile module.Create a playbook called add_block.yml in the current working directory.
Configure a play in the playbook to use the ansible.builtin.blockinfile module to append the following block of text to the /home/devops/users.txt file on all managed hosts.
This block of text consists of two lines. They have been added by the blockinfile module.
Create the add_block.yml playbook.
Edit it to contain the following play:
---
- name: Add block of text to a file
hosts: all
remote_user: devops
tasks:
- name: Add a block of text to an existing file
ansible.builtin.blockinfile:
path: /home/devops/users.txt
block: |
This block of text consists of two lines.
They have been added by the blockinfile module.
state: presentUse the ansible-navigator run --syntax-check command to verify the syntax of the add_block.yml playbook.
[student@workstation file-manage]$ansible-navigator run \>-m stdout add_block.yml --syntax-checkplaybook: /home/student/file-manage/add_block.yml
Run the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout add_block.ymlPLAY [Add block of text to a file] **************************************** TASK [Gathering Facts] **************************************************** ok: [serverb.lab.example.com] ok: [servera.lab.example.com] TASK [Add a block of text to an existing file] **************************** changed: [servera.lab.example.com] changed: [serverb.lab.example.com] PLAY RECAP **************************************************************** servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use the cat command as the devops user on the servera machine to verify the correct content of the /home/devops/users.txt file on the managed host.
[student@workstation file-manage]$ ssh devops@servera 'cat users.txt'
This line was added by the lineinfile module.
# BEGIN ANSIBLE MANAGED BLOCK
This block of text consists of two lines.
They have been added by the blockinfile module.
# END ANSIBLE MANAGED BLOCKCreate a playbook called remove_file.yml in the current working directory.
Configure a play in the playbook to use the ansible.builtin.file module to remove the /home/devops/users.txt file from all managed hosts.
Create the remove_file.yml playbook.
Edit it to contain the following play:
---
- name: Use the file module to remove a file
hosts: all
remote_user: devops
tasks:
- name: Remove a file from managed hosts
ansible.builtin.file:
path: /home/devops/users.txt
state: absentUse the ansible-navigator run --syntax-check command to verify the syntax of the remove_file.yml playbook.
[student@workstation file-manage]$ansible-navigator run \>-m stdout remove_file.yml --syntax-checkplaybook: /home/student/file-manage/remove_file.yml
Run the playbook:
[student@workstation file-manage]$ansible-navigator run \>-m stdout remove_file.ymlPLAY [Use the file module to remove a file] ******************************* TASK [Gathering Facts] **************************************************** ok: [serverb.lab.example.com] ok: [servera.lab.example.com] TASK [Remove a file from managed hosts] *********************************** changed: [serverb.lab.example.com] changed: [servera.lab.example.com] PLAY RECAP **************************************************************** servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Use the ls -l command as the devops user on the servera machine to confirm that the users.txt file no longer exists on the managed hosts.
[student@workstation file-manage]$ ssh devops@servera 'ls -l'
total 0This concludes the section.