Bookmark this page

Lab: Implementing Task Control

In this lab, you install the Apache web server and secure it using mod_ssl. You use conditions, handlers, and task failure handling in your playbook to deploy the environment.

Outcomes

  • Define conditionals in Ansible Playbooks

  • Set up loops that iterate over elements

  • Define handlers in playbooks

  • Handle task errors.

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 control-review

Procedure 4.4. Instructions

  1. On the workstation machine, change to the /home/student/control-review directory.

    [student@workstation ~]$ cd ~/control-review
    [student@workstation control-review]$
  2. The project directory contains a partially completed play in the playbook.yml playbook. Under the #Fail Fast Message comment, add a task that uses the ansible.builtin.fail module. Provide an appropriate name for the task.

    This task should only be executed when the remote system does not meet the following minimum requirements:

    • Has at least the amount of RAM specified by the min_ram_mb variable. The min_ram_mb variable is defined in the vars.yml file and has a value of 256.

    • Is running Red Hat Enterprise Linux.

    The completed task should consist of the following content:

      tasks:
        #Fail Fast Message
        - name: Show Failed System Requirements Message
          ansible.builtin.fail:
            msg: "The {{ inventory_hostname }} did not meet minimum reqs."
          when: >
            ansible_facts['memtotal_mb'] < min_ram_mb or
            ansible_facts['distribution'] != "RedHat"
  3. Under the #Install all Packages comment, add a task named Ensure required packages are present to install the latest version of any missing packages. Required packages are specified by the packages variable, which is defined in the vars.yml file.

    The completed task should consist of the following content:

        #Install all Packages
        - name: Ensure required packages are present
          ansible.builtin.dnf:
            name: "{{ packages }}"
            state: latest
  4. Under the #Enable and start services comment, add a task to start services. All services specified by the services variable, which is defined in the vars.yml file, should be started and enabled. Provide an appropriate name for the task.

    The completed task should consist of the following content:

        #Enable and start services
        - name: Ensure services are started and enabled
          ansible.builtin.service:
            name: "{{ item }}"
            state: started
            enabled: yes
          loop: "{{ services }}"
  5. Under the #Block of config tasks comment, add a task block to the play. This block contains two tasks:

    • A task to ensure that the directory specified by the ssl_cert_dir variable exists on the remote host. This directory stores the web server's certificates.

    • A task to copy all files specified by the web_config_files variable to the remote host. Examine the structure of the web_config_files variable in the vars.yml file. Configure the task to copy each file to the correct destination on the remote host.

      This task should trigger the restart web service handler if any of these files are changed on the remote server.

    Additionally, a debug task is executed if either of the two tasks above fail. In this case, the task prints the following message: One or more of the configuration changes failed, but the web service is still active.

    Provide an appropriate name for all tasks.

    The completed task block should consist of the following content:

        #Block of config tasks
        - name: Setting up the SSL cert directory and config files
          block:
            - name: Create SSL cert directory
              ansible.builtin.file:
                path: "{{ ssl_cert_dir }}"
                state: directory
    
            - name: Copy Config Files
              ansible.builtin.copy:
                src: "{{ item['src'] }}"
                dest: "{{ item['dest'] }}"
              loop: "{{ web_config_files }}"
              notify: restart web service
    
          rescue:
            - name: Configuration Error Message
              ansible.builtin.debug:
                msg: >
                  One or more of the configuration
                  changes failed, but the web service
                  is still active.
  6. The play configures the remote host to listen for standard HTTPS requests. Under the #Configure the firewall comment, add a task to configure firewalld.

    Ensure that the task configures the remote host to accept standard HTTP and HTTPS connections. The configuration changes must be effective immediately and persist after a reboot. Provide an appropriate name for the task.

    The completed task should consist of the following content:

        #Configure the firewall
        - name: ensure web server ports are open
          ansible.builtin.firewalld:
            service: "{{ item }}"
            immediate: true
            permanent: true
            state: enabled
          loop:
            - http
            - https
  7. Define the restart web service handler.

    When triggered, this task should restart the web service defined by the web_service variable, defined in the vars.yml file.

    Add a handlers section to the end of the play:

      handlers:
        - name: restart web service
          ansible.builtin.service:
            name: "{{ web_service }}"
            state: restarted

    The completed playbook should consist of the following content:

    ---
    - name: Playbook Control Lab
      hosts: webservers
      vars_files: vars.yml
      tasks:
        #Fail Fast Message
        - name: Show Failed System Requirements Message
          ansible.builtin.fail:
            msg: "The {{ inventory_hostname }} did not meet minimum reqs."
          when: >
            ansible_facts['memtotal_mb'] < min_ram_mb or
            ansible_facts['distribution'] != "RedHat"
    
        #Install all Packages
        - name: Ensure required packages are present
          ansible.builtin.dnf:
            name: "{{ packages }}"
            state: latest
    
        #Enable and start services
        - name: Ensure services are started and enabled
          ansible.builtin.service:
            name: "{{ item }}"
            state: started
            enabled: yes
          loop: "{{ services }}"
    
        #Block of config tasks
        - name: Setting up the SSL cert directory and config files
          block:
            - name: Create SSL cert directory
              ansible.builtin.file:
                path: "{{ ssl_cert_dir }}"
                state: directory
    
            - name: Copy Config Files
              ansible.builtin.copy:
                src: "{{ item['src'] }}"
                dest: "{{ item['dest'] }}"
              loop: "{{ web_config_files }}"
              notify: restart web service
    
          rescue:
            - name: Configuration Error Message
              ansible.builtin.debug:
                msg: >
                  One or more of the configuration
                  changes failed, but the web service
                  is still active.
    
        #Configure the firewall
        - name: ensure web server ports are open
          ansible.builtin.firewalld:
            service: "{{ item }}"
            immediate: true
            permanent: true
            state: enabled
          loop:
            - http
            - https
    
      #Add handlers
      handlers:
        - name: restart web service
          ansible.builtin.service:
            name: "{{ web_service }}"
            state: restarted
  8. From the ~/control-review directory, run the playbook.yml playbook. The playbook should execute without errors, and trigger the execution of the handler task.

    [student@workstation control-review]$ ansible-navigator run \
    > -m stdout playbook.yml
    
    PLAY [Playbook Control Lab] ****************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [serverb.lab.example.com]
    
    TASK [Show Failed System Requirements Message] *********************************
    skipping: [serverb.lab.example.com]
    
    TASK [Ensure required packages are present] ************************************
    changed: [serverb.lab.example.com]
    
    TASK [Ensure services are started and enabled] *********************************
    changed: [serverb.lab.example.com] => (item=httpd)
    ok: [serverb.lab.example.com] => (item=firewalld)
    
    TASK [Create SSL cert directory] ***********************************************
    changed: [serverb.lab.example.com]
    
    TASK [Copy Config Files] *******************************************************
    changed: [serverb.lab.example.com] => (item={'src': 'server.key', 'dest': '/etc/httpd/conf.d/ssl'})
    changed: [serverb.lab.example.com] => (item={'src': 'server.crt', 'dest': '/etc/httpd/conf.d/ssl'})
    changed: [serverb.lab.example.com] => (item={'src': 'ssl.conf', 'dest': '/etc/httpd/conf.d'})
    changed: [serverb.lab.example.com] => (item={'src': 'index.html', 'dest': '/var/www/html'})
    
    TASK [ensure web server ports are open] ****************************************
    changed: [serverb.lab.example.com] => (item=http)
    changed: [serverb.lab.example.com] => (item=https)
    
    RUNNING HANDLER [restart web service] ******************************************
    changed: [serverb.lab.example.com]
    
    PLAY RECAP *********************************************************************
    serverb.lab.example.com    : ok=7    changed=6    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  9. Verify that the web server now responds to HTTPS requests, using the self-signed custom certificate to encrypt the connection. The web server should return Configured for both HTTP and HTTPS.

    [student@workstation control-review]$ curl -k -vvv https://serverb.lab.example.com
    *   Trying 172.25.250.11:443...
    * Connected to serverb.lab.example.com (172.25.250.11) port 443 (#0)
    ...output omitted...
    < HTTP/1.1 200 OK
    < Date: Tue, 05 Jul 2022 19:36:48 GMT
    < Server: Apache/2.4.51 (Red Hat Enterprise Linux) OpenSSL/3.0.1
    < Last-Modified: Tue, 05 Jul 2022 19:35:30 GMT
    < ETag: "24-5e313f48fbb2c"
    < Accept-Ranges: bytes
    < Content-Length: 36
    < Content-Type: text/html; charset=UTF-8
    <
    Configured for both HTTP and HTTPS.
    * Connection #0 to host serverb.lab.example.com left intact

Evaluation

As the student user on the workstation machine, use the lab command to grade your work. Correct any reported failures and rerun the command until successful.

[student@workstation ~]$ lab grade control-review

Finish

On the workstation machine, change to the student user home directory and use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish control-review

This concludes the section.

Revision: rh294-9.0-c95c7de