Chapter 4: Managing Variables and Facts
Exercise: Managing variables and facts
Put the whole chapter together: a play whose every name and path is a variable, a web page built from facts, and a test play that logs in with a password kept in a Vault-encrypted file. Try each task yourself before opening the solution.
A developer wants a web server on serverb.lab.example.com (in the webserver group) that protects its site with HTTP basic authentication. The files directory of ~/data-review already contains:
httpd.conf, an Apache configuration that enables basic authentication;.htaccess, which controls access to the document root;htpasswd, holding the credentials of permitted users.
Use these play variables:
| Variable | Value |
|---|---|
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 |
Notice that secrets_dest is built from another variable.
Managing variables and facts
- Define variables and use facts in a playbook, and use variables defined in an encrypted file.
Prerequisites: Complete control-node setup and the preceding lessons in this chapter. Run commands as student on workstation unless a step names another machine.
From the project directory, run the relevant home-lab check. For an exercise with several checkpoints, grade each state before changing or removing it:
lab grade data-reviewThe grader reads project files and host state. A passing report covers the listed checks; also perform the task’s independent connection, repeat-run, and reboot checks where requested.
Try an incorrect guest password in the verification play. Explain the HTTP response and restore the correct secret.
Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.
Deliver an authenticated HTTPS page on serverb from playbook.yml, using the variables and supplied configuration files described above.
- Install the web, firewall, and TLS packages. Apache and the firewall must run and start at boot; HTTPS must be allowed persistently.
- Configuration files must be root-owned, mode
0644. The secrets directory must be apache-owned, mode0500; its password file and the web-root.htaccessmust be apache-owned, mode0400. - The index page must identify the host's FQDN and default IPv4 address using facts.
- A workstation play must retrieve it as
guestusingweb_passfrom encryptedvars/secret.yml(practice passwordredhat). The lab's self-signed certificate is expected.
files/httpd.conf is Rocky's stock Apache configuration with one change: AllowOverride AuthConfig for the document root, so that .htaccess can require a login. files/htpasswd is generated on your workstation with one user, guest, password redhat.
Start the play and its variables
In ~/data-review, create playbook.yml with a play named install and configure webserver with basic auth for the webserver group, and define all the variables from the table.
---
- 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/htmlInstall the packages
Add tasks and one task that installs the latest firewall_pkg, web_pkg and ssl_pkg.
tasks:
- name: latest version of necessary packages installed
ansible.builtin.dnf:
name:
- "{{ firewall_pkg }}"
- "{{ web_pkg }}"
- "{{ ssl_pkg }}"
state: latestDeploy the Apache configuration
Copy httpdconf_src to httpdconf_dest, owned by root:root, mode 0644.
- name: configure web service
ansible.builtin.copy:
src: "{{ httpdconf_src }}"
dest: "{{ httpdconf_dest }}"
owner: root
group: root
mode: 0644Create the secrets directory
Use ansible.builtin.file to create secrets_dir, owned by apache:apache, mode 0500.
- name: secrets directory exists
ansible.builtin.file:
path: "{{ secrets_dir }}"
state: directory
owner: apache
group: apache
mode: 0500Install the password file
Copy secrets_src to secrets_dest, owned by apache:apache, mode 0400.
- name: htpasswd file exists
ansible.builtin.copy:
src: "{{ secrets_src }}"
dest: "{{ secrets_dest }}"
owner: apache
group: apache
mode: 0400Install .htaccess in the document root
Copy htaccess_src to {{ web_root }}/.htaccess, owned by apache:apache, mode 0400.
- name: .htaccess file installed in docroot
ansible.builtin.copy:
src: "{{ htaccess_src }}"
dest: "{{ web_root }}/.htaccess"
owner: apache
group: apache
mode: 0400Build index.html from facts
Create {{ web_root }}/index.html with the content HOSTNAME (IPADDRESS) has been customized by Ansible., where HOSTNAME is the host's FQDN and IPADDRESS its default IPv4 address. Use ansible.builtin.copy with content:.
- 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"Start the firewall, open HTTPS, start Apache
Three tasks: enable and start firewall_svc; permanently and immediately allow the https service in firewalld; enable and start web_svc.
- name: firewall service enabled 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: trueAdd a test play that uses a secret
Add a second play, test web server with basic auth, on workstation, without privilege escalation. Give it a play variable web_user: guest, and load vars/secret.yml with vars_files (you create that file next). Its tasks:
- request
https://serverb.lab.example.comwithansible.builtin.uri, using basic authentication asweb_user/web_pass, expecting status 200, and register the result asauth_test. serverb's certificate is not trusted, so turn off certificate validation; - print
auth_test.content.
- 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: false
force_basic_auth: true
user: "{{ web_user }}"
password: "{{ web_pass }}"
return_content: true
status_code: 200
register: auth_test
- ansible.builtin.debug:
var: auth_test.contentCreate the encrypted secret
Create vars/secret.yml with Ansible Vault, password redhat, containing web_pass: redhat.
[student@workstation data-review]$ mkdir vars
[student@workstation data-review]$ ansible-vault create vars/secret.yml
New Vault password: redhat
Confirm New Vault password: redhatweb_pass: redhatCheck the syntax, then run
[student@workstation data-review]$ ansible-navigator run -m stdout \
> --playbook-artifact-enable false \
> playbook.yml --syntax-check --vault-id @prompt
Vault password (default): redhat
playbook: /home/student/data-review/playbook.yml
[student@workstation data-review]$ ansible-navigator run -m stdout \
> --playbook-artifact-enable false \
> playbook.yml --vault-id @prompt
Vault password (default): redhat
...output omitted...
TASK [ansible.builtin.debug] ***************************************************
ok: [workstation] => {
"auth_test.content": "serverb.lab.example.com (172.25.250.11) has been customized by Ansible.\n"
}
PLAY RECAP *********************************************************************
serverb.lab.example.com : ok=10 changed=8 unreachable=0 failed=0 ...
workstation : ok=3 changed=0 unreachable=0 failed=0 ...The content returned over HTTPS, after authenticating with the vaulted password, is the page you built from serverb's facts.
Grade and finish
Check your work with lab grade data-review, then put the exercise away with lab finish data-review.