In this lab, you write and run an Ansible Playbook that uses variables, secrets, and facts.
Outcomes
You should be able to define variables and use facts in a playbook, as well as use variables defined in an encrypted file.
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.
The serverb.lab.example.com managed host is defined in this inventory as a member of the webserver host group.
A developer has asked you to write an Ansible Playbook to automate the setup of a web server environment on serverb.lab.example.com, which controls user access to its website using basic authentication.
The files subdirectory contains the following files:
An httpd.conf configuration file for the Apache web service for basic authentication
A .htaccess file, used to control access to the web server's document root directory
An htpasswd file containing credentials for permitted users
[student@workstation ~]$ lab start data-review
Procedure 3.4. Instructions
In the working directory, create the playbook.yml playbook.
In the playbook, start creating a play to install and configure the web server hosts with an Apache HTTP Server that has basic authentication enabled.
Configure the webserver host group to contain the managed hosts for the play.
Define the following play variables:
| Variable | Values |
|---|---|
firewall_pkg
|
firewalld
|
firewall_svc
|
firewalld
|
web_pkg
|
httpd
|
web_svc
|
httpd
|
ssl_pkg
|
mod_ssl
|
httpdconf_src
|
files/httpd.conf
|
httpdconf_dest
|
/etc/httpd/conf/httpd.conf
|
htaccess_src
|
files/.htaccess
|
secrets_dir
|
/etc/httpd/secrets
|
secrets_src
|
files/htpasswd
|
secrets_dest
|
"{{ secrets_dir }}/htpasswd"
|
web_root
|
/var/www/html
|
Change into the /home/student/data-review directory.
[student@workstation ~]$ cd ~/data-review
[student@workstation data-review]$Create the playbook.yml playbook file and edit it in a text editor.
The beginning of the file should appear as follows:
---
- name: install and configure webserver with basic auth
hosts: webserver
vars:
firewall_pkg: firewalld
firewall_svc: firewalld
web_pkg: httpd
web_svc: httpd
ssl_pkg: mod_ssl
httpdconf_src: files/httpd.conf
httpdconf_dest: /etc/httpd/conf/httpd.conf
htaccess_src: files/.htaccess
secrets_dir: /etc/httpd/secrets
secrets_src: files/htpasswd
secrets_dest: "{{ secrets_dir }}/htpasswd"
web_root: /var/www/htmlAdd a tasks section to the play.
Write a task that ensures the latest version of the necessary packages are installed.
These packages are defined by the firewall_pkg, web_pkg, and ssl_pkg variables.
Define the beginning of the tasks section by adding the following line to the play:
tasks:
Add the following lines to the play to define a task that uses the ansible.builtin.dnf module to install the required packages:
- name: latest version of necessary packages installed
ansible.builtin.dnf:
name:
- "{{ firewall_pkg }}"
- "{{ web_pkg }}"
- "{{ ssl_pkg }}"
state: latestAdd a second task to the play that ensures that the file specified by the httpdconf_src variable has been copied (with the ansible.builtin.copy module) to the location specified by the httpdconf_dest variable on the managed host.
The file must be owned by the root user and the root group.
Set 0644 as the file permissions.
Add the following lines to the play to define a task that uses the ansible.builtin.copy module to copy the contents of the file defined by the httpdconf_src variable to the location specified by the httpdconf_dest variable.
- name: configure web service
ansible.builtin.copy:
src: "{{ httpdconf_src }}"
dest: "{{ httpdconf_dest }}"
owner: root
group: root
mode: 0644Add a third task that uses the ansible.builtin.file module to create the directory specified by the secrets_dir variable on the managed host.
This directory holds the password files used for the basic authentication of web services.
The file must be owned by the apache user and the apache group.
Set 0500 as the file permissions.
Add a fourth task that uses the ansible.builtin.copy module to add an htpasswd file, used for basic authentication of web users.
The source should be defined by the secrets_src variable.
The destination should be defined by the secrets_dest variable.
The file must be owned by the apache user and group.
Set 0400 as the file permissions.
Add a fifth task that uses the ansible.builtin.copy module to create a .htaccess file in the document root directory of the web server.
Copy the file specified by the htaccess_src variable to {{ web_root }}/.htaccess.
The file must be owned by the apache user and the apache group.
Set 0400 as the file permissions.
Add the following lines to the play to define a task that uses the ansible.builtin.copy module to create the .htaccess file using the file defined by the htaccess_src variable.
- name: .htaccess file installed in docroot
ansible.builtin.copy:
src: "{{ htaccess_src }}"
dest: "{{ web_root }}/.htaccess"
owner: apache
group: apache
mode: 0400Add a sixth task that uses the ansible.builtin.copy module to create the web content file, index.html, in the directory specified by the web_root variable.
The file should contain the message , where HOSTNAME (IPADDRESS) has been customized by Ansible.HOSTNAME is the fully qualified host name of the managed host and IPADDRESS is its IPv4 IP address.
Use the content option with the ansible.builtin.copy module to specify the content of the file, and Ansible facts to specify the host name and IP address.
Add the following lines to the play to define a task that uses the ansible.builtin.copy module to create the index.html file in the directory defined by the web_root variable.
Populate the file with the content specified using the ansible_facts['fqdn'] and ansible_facts['default_ipv4']['address'] Ansible facts retrieved from the managed host.
- name: create index.html
ansible.builtin.copy:
content: "{{ ansible_facts['fqdn'] }} ({{ ansible_facts['default_ipv4']['address'] }}) has been customized by Ansible.\n"
dest: "{{ web_root }}/index.html"Add a seventh task that uses the ansible.builtin.service module to enable and start the firewall service on the managed host.
Add an eighth task that uses the ansible.posix.firewalld module to enable access to the https service that is needed for users to access web services on the managed host.
This firewall change should be permanent and should take place immediately.
Add a final task that uses the ansible.builtin.service module to enable and start the web service on the managed host for all configuration changes to take effect.
The name of the web service is defined by the web_svc variable.
Define a second play in the playbook.yml file that uses the workstation machine as the managed host to test authentication to the web server.
It does not need privilege escalation.
Define a variable named web_user with the value guest.
Add the following line to define the start of a second play. Note that there is no indentation.
- name: test web server with basic auth
Add the following line to indicate that the play applies to the workstation managed host.
hosts: workstation
Add the following line to disable privilege escalation.
become: false
Add the following lines to define the web_user play variable.
vars:
web_user: guestAdd a directive to the play that adds additional variables from a variable file named vars/secret.yml.
This file contains a variable named web_pass that specifies the password for the web user.
You create this file later in the lab.
Define the start of the task list.
Add two tasks to the second play.
The first task uses the ansible.builtin.uri module to request content from https://serverb.lab.example.com using basic authentication.
Use the web_user and web_pass variables to authenticate to the web server.
The task should verify a return HTTP status code of 200.
Register the task result in a variable named auth_test.
Note that the certificate presented by serverb is not trusted, so you need to avoid certificate validation.
The second task uses the ansible.builtin.debug module to print the content returned from the web server, which is contained in the auth_test variable.
Add the following lines to create the task for verifying the web service from the control node. Be sure to indent the first line with four spaces.
- name: connect to web server with basic auth
ansible.builtin.uri:
url: https://serverb.lab.example.com
validate_certs: no
force_basic_auth: yes
user: "{{ web_user }}"
password: "{{ web_pass }}"
return_content: yes
status_code: 200
register: auth_testCreate the second task using the ansible.builtin.debug module.
The content returned from the web server is added to the registered variable as the key content.
- ansible.builtin.debug:
var: auth_test.contentThe completed playbook should consist of the following content:
---
- name: install and configure webserver with basic auth
hosts: webserver
vars:
firewall_pkg: firewalld
firewall_svc: firewalld
web_pkg: httpd
web_svc: httpd
ssl_pkg: mod_ssl
httpdconf_src: files/httpd.conf
httpdconf_dest: /etc/httpd/conf/httpd.conf
htaccess_src: files/.htaccess
secrets_dir: /etc/httpd/secrets
secrets_src: files/htpasswd
secrets_dest: "{{ secrets_dir }}/htpasswd"
web_root: /var/www/html
tasks:
- name: latest version of necessary packages installed
ansible.builtin.dnf:
name:
- "{{ firewall_pkg }}"
- "{{ web_pkg }}"
- "{{ ssl_pkg }}"
state: latest
- name: configure web service
ansible.builtin.copy:
src: "{{ httpdconf_src }}"
dest: "{{ httpdconf_dest }}"
owner: root
group: root
mode: 0644
- name: secrets directory exists
ansible.builtin.file:
path: "{{ secrets_dir }}"
state: directory
owner: apache
group: apache
mode: 0500
- name: htpasswd file exists
ansible.builtin.copy:
src: "{{ secrets_src }}"
dest: "{{ secrets_dest }}"
owner: apache
group: apache
mode: 0400
- name: .htaccess file installed in docroot
ansible.builtin.copy:
src: "{{ htaccess_src }}"
dest: "{{ web_root }}/.htaccess"
owner: apache
group: apache
mode: 0400
- name: create index.html
ansible.builtin.copy:
content: "{{ ansible_facts['fqdn'] }} ({{ ansible_facts['default_ipv4']['address'] }}) has been customized by Ansible.\n"
dest: "{{ web_root }}/index.html"
- name: firewall service enable and started
ansible.builtin.service:
name: "{{ firewall_svc }}"
state: started
enabled: true
- name: open the port for the web server
ansible.posix.firewalld:
service: https
state: enabled
immediate: true
permanent: true
- name: web service enabled and started
ansible.builtin.service:
name: "{{ web_svc }}"
state: started
enabled: true
- name: test web server with basic auth
hosts: workstation
become: false
vars:
- web_user: guest
vars_files:
- vars/secret.yml
tasks:
- name: connect to web server with basic auth
ansible.builtin.uri:
url: https://serverb.lab.example.com
validate_certs: no
force_basic_auth: yes
user: "{{ web_user }}"
password: "{{ web_pass }}"
return_content: yes
status_code: 200
register: auth_test
- ansible.builtin.debug:
var: auth_test.contentSave and close the playbook.yml file.
Create a vars/secret.yml file, encrypted with Ansible Vault.
Use the password redhat to encrypt it.
It should set the web_pass variable to redhat, which is the web user's password.
Create a subdirectory named vars in the working directory.
[student@workstation data-review]$ mkdir varsCreate the encrypted variable file, vars/secret.yml, using Ansible Vault.
Set the password for the encrypted file to redhat.
[student@workstation data-review]$ansible-vault create vars/secret.ymlNew Vault password:redhatConfirm New Vault password:redhat
Add the following variable definition to the file:
web_pass: redhat
Save and close the file.
Run the playbook.yml playbook.
Verify that content is successfully returned from the web server, and that it matches what was configured in an earlier task.
Before running the playbook, verify that its syntax is correct by running ansible-navigator with the --syntax-check option.
Use --vault-id @prompt to be prompted for the Vault password.
Enter redhat when prompted for the password.
If it reports any errors, correct them before moving to the next step.
You should see output similar to the following:
[student@workstation data-review]$ansible-navigator run -m stdout \>--playbook-artifact-enable false \>playbook.yml --syntax-check --vault-id @promptVault password (default):redhatplaybook: /home/student/data-review/playbook.yml
Using the ansible-navigator command, run the playbook with the --vault-id @prompt option.
Enter redhat when prompted for the password.
[student@workstation data-review]$ansible-navigator run -m stdout \>--playbook-artifact-enable false \>playbook.yml --vault-id @promptVault password:redhatPLAY [Install and configure webserver with basic auth] ********************* ...output omitted... TASK [connect to web server with basic auth] *********************************** ok: [workstation] TASK [debug] ******************************************************************* ok: [workstation] => { "auth_test.content": "serverb.lab.example.com (172.25.250.11) has been customized by Ansible.\n" } PLAY RECAP ********************************************************************* workstation : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 serverb.lab.example.com : ok=10 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
This concludes the section.