francsw / EX407-Ansible-Automation

Red Hat Certified Specialist in Ansible Automation (EX407) Preparation Course
0 stars 0 forks source link

EX407-Ansible-Automation

Red Hat Certified Specialist in Ansible Automation (EX407) Preparation Course

Understanding Core Components of Ansible

Understanding Core Components of Ansible Part 1

This series of lessons lays the foundation for the remainder of the course content. Through a combination of lecture and command line demonstration, Students will gain a broad overview of Ansible. This particular lesson, focuses on Ansible inventories.

Inventories

img

Output:

innaghiyev1c.mylabserver.com | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

Understanding Core Components of Ansible Part 2

This series of lessons lays the foundation for the remainder of the course content. Through a combination of lecture and command line demonstration, Students will gain a broad overview of Ansible. This particular lesson covers the following topics at a very high level: modules, variables, facts, plays, playbooks, and configuration files.

innaghiyev1c.mylabserver.com | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.31.37.72"
        ],
        "ansible_all_ipv6_addresses": [
            "2a05:d01c:2c7:d802:4db1:18cc:f13f:a1cf",
            "fe80::9e:19ff:fe1e:7376"
        ],
        "ansible_apparmor": {
            "status": "enabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "10/16/2017",
        "ansible_bios_version": "1.0",

A Brief Tour of the Ansible Configuration File

The Ansible master configuration file is reviewed on a live system in this demonstration. Key configuration values are discussed as well as how to modify those values.

some basic default values...

inventory = /etc/ansible/hosts

library = /usr/share/my_modules/

module_utils = /usr/share/my_module_utils/

remote_tmp = ~/.ansible/tmp

local_tmp = ~/.ansible/tmp

plugin_filters_cfg = /etc/ansible/plugin_filters.yml

forks = 5

poll_interval = 15

sudo_user = root

ask_sudo_pass = True

ask_pass = True

transport = smart

remote_port = 22

module_lang = C

module_set_locale = False


- Another handy block is following

[privilege_escalation]

become=True

become_method=sudo

become_user=root

become_ask_pass=False


### LAB: Getting Started with Ansible
The very first step to harnessing the power of Ansible is configuring your environment. This activity goes over installing Ansible on a control node and configuring two managed servers for use with Ansible. We will also create a simple inventory and run an Ansible command to verify our configuration is correct.

##### Additional Information and Resources
Your CIO has greenlit a proof of concept for Ansible in your environment. You are to set up an Ansible control node in a test environment and verify basic functionality. You have three demo hosts, one to be the control node (`control1`), and two to serve as managed nodes (`node1` and `node2`). You must complete the following steps:

- Install Ansible on the `control` node.
- Configure the `ansible` user on the control node for ssh shared key access to managed nodes.
  Note: do not use a passphrase for the key pair.
- Create a simple Ansible inventory on the control node in `/home/ansible/inventory` containing node1 and node2.
- Configure sudo access for Ansible on `node1` and `node2` so that Ansible may use `sudo` for any command with no password prompt.
- Verify each managed node can be accessed by Ansible from the control node using the `ping` module. Redirect the output of a successful command to `/home/ansible/output`.

Important Notes:
- The user `ansible` is already present on all servers for your convenience.
- The `ansible` user has the same password as the `cloud_user`.
- `/etc/hosts` entries are present on `control1` for the managed nodes.

##### Install Ansible on the control node.
- To install Ansible on the control node, run  ansible.

yum install ansible


- If package not found run

yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm


##### Configure the `ansible` user on the control node for ssh shared key access to managed nodes. Do not use a passphrase for the key pair.
- To create a keypair for the ansible user on the control host, run the following:
  - `sudo su - ansible`
  - `ssh-keygen` (accept all defaults: press enter for each prompt)

- Copy the `public key` to both `node1` and `node2`.

- As the ansible user on the control host:
  - `ssh-copy-id node1` (accept the host key if prompted, authenticate as ansible user)
  - `ssh-copy-id node2` (accept the host key if prompted, authenticate as ansible user)

##### Create a simple Ansible inventory on the control node in `/home/ansible/inventory` containing `node1` and `node2`.
- On the control host:
  - `sudo su - ansible` (if not already ansible user)
  - `touch /home/ansible/inventory`
  - `echo "node1" >> /home/ansible/inventory`
  - `echo "node2" >> /home/ansible/inventory`

##### Configure sudo access for Ansible on `node1` and `node2` such that Ansible may use sudo for any command with no password prompt.
- Log in to node1 as cloud_user and edit the sudoers file to contain appropriate access for the ansible user:
  - `ssh cloud_user@node1`
  - `sudo visudo`
  - Add the following line to the file and save:

ansible ALL=(ALL) NOPASSWD: ALL


- Repeate these steps for `node2`.

##### Verify each managed node is able to be accessed by Ansible from the control node using the `ping` module. Redirect the output of a successful command to `/home/ansible/output`.
- To verify each node, run the following as the `ansible` user from the control host:
  - `ansible -i /home/ansible/inventory node1 -m ping`
  - `ansible -i /home/ansible/inventory node2 -m ping`
- To redirect output of a successful command to `/home/ansible/output`:
  - `ansible -i /home/ansible/inventory node1 -m ping > /home/ansible/output`

## Run Ad-Hoc Ansible Commands
### Run Ad-Hoc Ansible Commands
Learn how to use ad-hoc ansible commands for simple system managment. This lecture covers one of the key objectives for Red Hat exam 407.

- Overview:
    - What is an ad-hoc command in Ansible? 
    - Use cases for ad-hoc commands
    - Ad-hoc vs Playbook
    - Ansible command syntax
    - Common modules

- What is an ad-hoc command in Ansible
    - You can run ansible either ad-hoc or as a playbook
    - Both methods have the same capabilities
    - Ad-hoc commands are effectively one-liners

- Use cases for Ad-hoc
    - Operational commands
        - Checking log contents
        - Daemon control
        - Process management
    - Informational commands
        - Check installed software
        - Check system properties
        - Gather system performance information
    - Research
        - Work with unfamiliar modules on test systems
        - Practice for playbook engineering

##### Ad-hoc vs Playbook

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img2.png)

##### Common Modules

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img3.png)

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img4.png)

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img5.png)

### Demonstration: Ansible Ad-Hoc Commands Part 1

- Let's use `yum` as an example of ad-hoc command
    - `ansible myserver.example.com -i inv.ini -m yum -b -a "name=elinks state=latest"` - install **elinks** with **latest** version
        - `-i` - key for inventory host file
        - `-m yum` - use `yum` module 
        - `-b` - become (by default become **root**). Can be changed in `/etc/ansible/ansible.cfg` file
        - `-a "name=elinks state=latest"` - arguments. For `yum` module we're using **name** and **state**
    - `ansible myserver.example.com -i inv.ini -m yum -b -a "name=elinks state=absent"` - state **absent** will uninstall **elinks**

### Demonstration: Ansible Ad-Hoc Commands Part 2

- Let's work with a **file** module
    - `ansible myserver.example.com -i inv.ini -m file -a "name=/home/user/newfile state=touch"`
        - `-m file` - using **file** module
        - `-a "name=/home/user/newfile state=touch"` - arguments **name** - for declaring path of file and **state** what to do with it. 
    - `ansible myserver.example.com -i inv.ini -m file -a "name=/home/user/newfile"` - get **properties** of the file
    - `ansible myserver.example.com -i inv.ini -m file -a "name=/home/user/newfile mode=0400"` - set a **mode** of the file to **0400**
    - `ansible myserver.example.com -i inv.ini -m file -b -a "name=/home/user/newfile owner=root"` - we are changing file owner to **root** and using `-b`
    key for become. 
    - `ansible myserver.example.com -i inv.ini -m user -b -a "name=sam"` - create user **sam**
        - `-m user` - using **user** module
        - `-a "name=sam"` - as argument we indicate user name  
    - `ansible myserver.example.com -i inv.ini -m user -b -a "name=sam append=yes groups=wheel"` - add user to a **wheel** group.
        - `append=yes` - for appending group, otherwise it will wipe out previous groups
        - `groups=wheel` - define which group needs to be added

### LAB: Ad-Hoc Ansible Commands
One of the keys to success with Ansible is being able to run `ad-hoc` commands. The value of `ad-hoc` commands is underscored by the fact that it is an objective of the Red Hat Certified Ansible Specialist exam. This exercise guides students through crafting many `ad-hoc` commands which will not only build experience with the concept but also broaden the students' exposure to various Ansible command modules.

#### Additional Information and Resources
Some consultants have been employed to perform audits on a number of systems in your company's environment. You must create the user accounts noted in `/home/ansible/userlist.txt` and set up the provided public keys for their accounts. The security team has built a jump host for the consultants to access production systems and provided the full key-pair to you so you may set up and test the connection. All hosts in `dbsystems` will need the provided public key installed so the consultants may use key-pair authentication to access the systems. Also, you must ensure the `auditd` service is enabled and running on all systems.

To summarize, you must do the following:
- Create the user accounts noted in `/home/ansible/userlist.txt`.
- Copy the `authorized_keys` file for each user to the correct location so the new accounts can log in with ssh key authentication.
- Ensure `auditd` is enabled and running on all systems.

Important notes:
- For your convenience, Ansible is already on the control node. If you connect to the server by clicking on the Public IP address in your browser, make sure to change to the ansible user with the `su - ansible` command.

- The user `ansible` is present on all servers with appropriate shared keys for access to managed servers from the control node. Make sure to use this user to complete the commands.
- The `ansible` user has the same password as `cloud_user`.
- The default Ansible inventory has been configured for you with the appropriate hosts and groups.
- `/etc/hosts` entries are present on `control1` for the managed servers.

#### Learning Objectives
##### Create the User Accounts Noted in `/home/ansible/userlist.txt`
- `ansible dbsystems -b -m user -a "name=consultant"`
- `ansible dbsystems -b -m user -a "name=supervisor"`

##### Place Key Files in the Correct Location, `/home/$USER/.ssh/authorized_keys`, on Hosts in `dbsystems`
- `ansible dbsystems -b -m file -a "path=/home/consultant/.ssh state=directory owner=consultant group=consultant mode=0755"`
- `ansible dbsystems -b -m copy -a "src=/home/ansible/keys/consultant/authorized_keys dest=/home/consultant/.ssh/authorized_keys mode=0600 owner=consultant group=consultant"`
- `ansible dbsystems -b -m file -a "path=/home/supervisor/.ssh state=directory owner=supervisor group=supervisor mode=0755"`
- `ansible dbsystems -b -m copy -a "src=/home/ansible/keys/supervisor/authorized_keys dest=/home/supervisor/.ssh/authorized_keys mode=0600 owner=supervisor group=supervisor"`

##### Ensure `auditd` Is Enabled and Running on All Hosts
- `ansible all -b -m service -a "name=auditd state=started enabled=yes"`

## Inventory Management
### Inventory Essentials and Inventory Variables
In Ansible, inventories are crucially important as they serve as the foundation for ansible automation. This lecture extends on the basic inventory concpets already covered such as file format and location.  Students will be introduced to the concept of static and dynamic inventories and learn about how inventories and variables work together. 

##### Overview
- Use both static and dynamic inventories to define groups of hosts:
    - What is the inventory
    - File formats
    - Statis vs. Dynamic
    - Variables and inventories
- Utilize an existing dynamic inventory script:
    - On dynamic inventories
    - Some popular options

##### What is an Inventory
- An inventory is a list of hosts that Ansible manages
- Inventory location may be specified as follows:
    - Default: /etc/ansible/hosts
    - Specified by CLI: ansible -i <filename>
    - Can be set in ansible.cfg
- The inventory file may contain hosts, patterns, groups, and variables
- You may specofy the inventory as a directory containing a series of inventory files (both static and dynamic)
- The inventory may be specified in YAML or INI format
- Can be static or dynamic

##### File Formats 

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img6.png)

##### Static vs. Dynamic

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img7.png)

##### Variables and Inventories

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img8.png)

### Demo: Variables and Inventories
Being able to work with inventories and variables is an essential skill for any user of Ansible. This command line demonstration will show students the best practices for using variables within inventories.

Inside of **inventory** directory we have following structure: 

[cloud_user@innaghiyev2c inventory]$ ls -l total 4 drwxrwxr-x. 2 cloud_user cloud_user 23 Feb 28 05:18 group_vars drwxrwxr-x. 2 cloud_user cloud_user 25 Feb 27 10:53 host_vars -rw-rw-r--. 1 cloud_user cloud_user 127 Feb 27 10:41 inventory


Where:
- `inventory` - stores our hosts

[cloud_user@innaghiyev2c inventory]$ cat inventory innaghiyev1c ansible_host=innaghiyev1c.mylabserver.com

[labservers] innaghiyev3c.mylabserver.com innaghiyev1c.mylabserver.com


- `group_vars` - contains group name of our hosts' group. `labservers` - name of group, which contains variables

[cloud_user@innaghiyev2c inventory]$ ls -l group_vars/ total 4 -rw-rw-r--. 1 cloud_user cloud_user 50 Feb 28 05:18 labservers [cloud_user@innaghiyev2c inventory]$ cat group_vars/labservers logs : /var/log/messages secure : /var/log/secure


- `host_vars` - contains hostname with stored variable inside. `innaghiyev1c` - name of the host, which contains variables

[cloud_user@innaghiyev2c inventory]$ ls host_vars/ innaghiyev1c [cloud_user@innaghiyev2c inventory]$ cat host_vars/innaghiyev1c opt_dir : /opt


### Demo: Using YAML in Inventories
Inventories may be specified in INI or YAML format. This demonstration goes over how to use YAML to create an inventory. Students will benefit from a refresher on YAML syntax as well as review key details on Ansible inventories.

This is how YAML inventory file looks like:

all: hosts: innaghiyev1c.mylabserver.com: children: production: hosts: innaghiyev1c.mylabserver.com: innaghiyev3c.mylabserver.com: labservers: hosts: innaghiyev[1:3]c.mylabserver.com:


### Dynamic Inventories
Being able to use dynamic inventories in essential skill for any Ansible specialist. This lecture goes over the details of how dynamic inventories in Ansible work.

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img9.png)

Some Popular Options:

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img10.png)

### Demo: Dynamic Inventories
- `chmod +x script.py` - script for dynamic inventory must be executable. Output of your script must be in **JSON** format
- `ansible all -i script.py -m ping` - usage of dynamic inventory is the same as a static one

### LAB: Working with Ansible Inventories
#### Additional Information and Resources
Your company has decided the backup software license is frivolous and unnecessary. As a consequence, the license was not renewed. Your supervisor has created a simple script and an Ansible playbook to create an archive of select files, depending on pre-defined Ansible host groups, as a stop-gap measure. You will create the inventory file to complete the backup strategy.

You must do the following:
- Create the inventory file in **/home/ansible/inventory**.
- Configure the host group **media** to contain media1 and media2.
- Define the following variables for **media** with their accompanying values:
  - **media_content** should be set to `/var/media/content/`.
  - **media_index** should be set to `/opt/media/mediaIndex`.
- Configure the host group **webservers** to contain the hosts web1 and web2.
- Define the following variables for `webservers` with their accompanying values:
  - **httpd_webroot** should be set to `/var/www/`
  - **httpd_config** should be set to `/etc/httpd/`
- Define the variable **script_files** specifically for web1. The value of **script_files** should be set to `/usr/local/scripts`.
- You can run `/home/ansible/scripts/backup.sh` to test your inventory. If you have correctly configured the inventory, it should not error.
- Do not edit anything in **/home/ansible/scripts/**.

Important notes:
- For your convenience, Ansible has been installed on the control node.
- The user `ansible` has already been created on all servers with appropriate shared keys for access to managed servers from the control node.
- The `ansible` user has the same password as `cloud_user`.
- `/etc/hosts` entries have been made on control1 for the managed servers.
- Do not edit anything in `/home/ansible/scripts/`.

#### Learning Objectives
##### Create the `inventory` File in `/home/ansible/`
- `touch /home/ansible/inventory`
##### Configure the Host Group `media` to Contain `media1` and `media2`
- `echo "[media]" >> /home/ansible/inventory`
- `echo "media1" >> /home/ansible/inventory`
- `echo "media2" >> /home/ansible/inventory`
##### Define Variables for `media` with Their Accompanying Values
- `mkdir /home/ansible/group_vars`
- `touch /home/ansible/group_vars/media`
- `echo "media_content: /var/media/content/" >> /home/ansible/group_vars/media`
- `echo "media_index: /opt/media/mediaIndex" >> /home/ansible/group_vars/media`
##### Configure the Host Group `webservers` to Contain the Hosts `web1` and `web2`
- `echo "[webservers]" >> /home/ansible/inventory`
- `echo "web1" >> /home/ansible/inventory`
- `echo "web2" >> /home/ansible/inventory`
##### Define Variables for `webservers` with Their Accompanying Values
- `touch /home/ansible/group_vars/webservers`
- `echo "httpd_webroot: /var/www/" >> /home/ansible/group_vars/webservers`
- `echo "httpd_config: /etc/httpd/" >> /home/ansible/group_vars/webservers`
##### Define the Variable `script_files` Specifically for `web1`, Setting Its Value to `/usr/local/scripts`
- `mkdir /home/ansible/host_vars`
- `touch /home/ansible/host_vars/web1`
- `echo "script_files: /usr/local/scripts" >> /home/ansible/host_vars/web1`

## Create Ansible Plays and Playbooks
### Introduction to Playbooks and Common Modules
This less provides an overview of the section and reviews some of the common modules that will continue showing up as the playbook discussion occurs.

#### Overview:
- Know how to work with commonly used Ansible modules
- Create playbooks to configure systems to a specified state
- Use variables to retrieve the results of running commands
- Use conditionals to control play execution
- Configure error handling 
- Selectively run specified tasks in playbooks using tags

#### Know how to work with Commonly Used Ansible Modules
- Core modules to be familiar with:
  - Working with files: copy, archive, unarchive, get_url
  - user, group
  - ping
  - service
  - yum
- Lineinfile module
- htpasswd
- Shell and command modules
- Script module
- Debug module
- https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

### Create Playbooks to Configure Systems to a Specified State

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img11.png)

### Basic Playbook Syntax Demonstration
Let's write some simple playbook. 

--- #to mention that this is a playbook

Use Variables to Retrieve the Results of Running Commands

img

Use Conditionals to Control Play Execution Part 1

img

Playbook with handler:

---
- hosts: labservers
  become: yes
  handlers:
    - name: restart apache
      service: name="httpd" state="restarted"
      listen: "restart web"
  tasks:
    - name: change config
      replace:
        path: /etc/httpd/conf/httpd.conf
        regexp: '^DocumentRoot.*$'
        replace: 'DocumentRoot "/opt/www"'
        backup: yes
      notify: "restart web"

Explanation for playbook:

Use Conditionals to Control Play Execution Part 2

img

Demonstration of how to use a loop in playbooks:

---
- hosts: labservers
  become: yes
  tasks:
    - name: create users
      user:
        name: "{{item}}"
      with_items:
        - sam
        - john
        - bob

Demonstration of how to use when condition in playbooks:

---
- hosts: labservers
  become: yes
  tasks:
    - name: edit index
      lineinfile:
        path: /var/www/html/index.html
        line: "I'm back!!!"
      when:
        - ansible_hostname == "innaghiyev1c"

Configure Error Handling

Demo: Error Handling – Ignore Errors

Demonstration of playbook:

---
- hosts: labservers
  tasks:
    - name: get files
      get_url:
        url: "http://{{item}}/index.html"
        dest: "/tmp/{{item}}"
      ignore_errors: yes
      with_items:
        - innaghiyev1c
        - innaghiyev3c
        - innaghiyev2c

img

Demo: Error Handling – Block Groups

Block groups and rescues - like a try and catch.

---
- hosts: labservers
  tasks:
    - name: get file
      block:
        - get_url:
            url: "http://innaghiyev3c/index.html"
            dest: "/tmp/index_file"
      rescue:
        - debug: msg="The file doesn't exists!"
      always:
        - debug: msg="Play done!"

Here how rescue block is working: img

Selectively Run Specific Tasks In Playbooks Using Tags

How Ansible uses tags

---
- hosts: web
  become: yes
  tasks:
  - name: deploy app binary
    copy:
      src: /home/cloud_user/apps/hello
      dest: /var/www/html/hello
    tags:
      - webdeploy
- hosts: db
  become: yes
  tasks:
  - name: deploy db script
    copy:
      src: /home/cloud_user/apps/script.sql
      dest: /opt/deb/scripts/script.sql
    tags:
      - dbdeploy

LAB: Ansible Playbooks: The Basics

Additional Information and Resources

Your company has been increasing the deployment of small broacher-style websites for clients. The head of IT has decided that each client should have their own web servers for better client isolation and has tasked you with creating concept automation to quickly deploy web-nodes with simple static website content.

You have been provided an ansible control node and 2 test lab servers (node1 and node2) that have been preconfigured with the ansible user and key.

You must create an ansible inventory in /home/ansible/inventory containing a host group named web. The web group should contain node1 and node2.

Furthermore, you must design an Ansible playbook that will execute the following tasks on your configured inventory: install httpd, start and enable the httpd service, and install a simple website provided on a repo server. Create the playbook in /home/ansible/web.yml. The simple website may be accessed from http://repo.example.com/website.tgz.

Summary tasks list:

  1. Create an inventory in /home/ansible/inventory containing a host group named web. The web group should contain node1 and node2.
  2. Create a playbook in /home/ansible/web.yml.
  3. Configure the playbook to install httpd on the web group.
  4. Configure the playbook to start and enable the httpd service on the web group.
  5. Configure the playbook to retrieve the website from http://repo.example.com/website.tgz on each server in the web group.
  6. Configure the playbook to unarchive the website into /var/www/html on all servers in the web group.
  7. Execute the playbook you created using the inventory you created to verify your work.

Important notes:

Learning Objectives

Create an Inventory in /home/ansible/inventory. That Contains a Host Group Named web. The web Group Should Contain node1 and node2
Create a Playbook in /home/ansible/web.yml
Configure the Playbook to Install httpd on the web Group

Using a text editor, such as vim, edit /home/ansible/web.yml to contain the following text block below the line containing "---":

- hosts: web
  become: yes
  tasks:
    - name: install httpd
      yum: name=httpd state=latest
Configure the Playbook to Start and Enable the httpd Service on the web Group

Using a text editor such as vim, edit /home/ansible/web.yml to contain the following task block after the "install httpd task":

    - name: start and enable httpd
      service: name=httpd state=started enabled=yes
Configure the Playbook to Retrieve the Website from http://repo.example.com/website.tgz on Each Server in the web Group

Using a text editor such as vim, edit /home/ansible/web.yml to contain the following task block after the "start and enable httpd" task:

    - name: retrieve website from repo
      get_url: url=http://repo.example.com/website.tgz dest=/tmp/website.tgz
Configure the Playbook to Unarchive the Website into /var/www/html on All Servers in the web Group

Using a text editor such as vim, edit /home/ansible/web.yml to contain the following task block after the "retrieve website from repo" task:

    - name: install website
      unarchive: remote_src=yes src=/tmp/website.tgz dest=/var/www/html/
Verify the Work by Executing the Playbook Using the Inventory**

LAB: Ansible Playbooks - Error Handling

Additional Information and Resources

We have to set up automation to pull down a data file, from a notoriously unreliable third-party system, for integration purposes. Create a playbook that attempts to pull down http://apps.l33t.com/transaction_list to localhost. The playbook should gracefully handle the site being down by outputting the message "l33t.com appears to be down. Try again later." to stdout. If the task succeeds, the playbook should write "File downloaded." to stdout. No matter if the playbook errors or not, it should always output "Attempt completed." to stdout.

If the report is collected, the playbook should write and edit the file to replace all occurrences of #BLANKLINE with a line break \n.

Tasks list summary:

Important notes:

Learning Objectives

Create a playbook: /home/ansible/report.yml

Using a text editor, such as vim, edit /home/ansible/report.yml to contain the following text block below the line containing "---":

- hosts: localhost
  tasks:
    - name: download tranaction_list
      get_url:
        url: http://apps.l33t.com/transaction_list 
        dest: /home/ansible/transaction_list
    - debug: msg="File downloaded"
Configure the Playbook to Handle Connection Failure by Outputting "l33t.com appears to be down. Try again later." to stdout

Using a text editor, such as vim, edit the tasks section in /home/ansible/report.yml to contain the new lines as shown below. Note that the get_url line was changed to include a leading hyphen:

---
- hosts: localhost
  tasks:
    - name: download transction_list
      block:
        - get_url:
            url: http://apps.l33t.com/transaction_list
            dest: /home/ansible/transaction_list
        - debug: msg="File downloaded"
      rescue:
        - debug: msg="l33t.com appears to be down.  Try again later."
Configure the Playbook to Output "Attempt Completed" to stdout, Whether It Was Successful or Not

Using a text editor, such as vim, edit /home/ansible/report.yml to contain the following text block below the line containing "---":

---
- hosts: localhost
  tasks:
    - name: download transction_list
      block:
        - get_url:
            url: http://apps.l33t.com/transaction_list
            dest: /home/ansible/transaction_list
        - debug: msg="File downloaded"
      rescue:
        - debug: msg="l33t.com appears to be down.  Try again later."
      always:
        - debug: msg="Attempt completed."
Configure the Playbook to Replace All Instances of #BLANKLINE with the Line Break Character \n

Using a text editor, such as vim, edit /home/ansible/report.yml to contain the following text block below the line containing "---":

---
- hosts: localhost
  tasks:
    - name: download transction_list
      block:
        - get_url:
            url: http://apps.l33t.com/transaction_list
            dest: /home/ansible/transaction_list
        - replace: 
            path: /home/ansible/transaction_list 
            regexp: "#BLANKLINE"
            replace: '\n'
        - debug: msg="File downloaded"
      rescue:
        - debug: msg="l33t.com appears to be down.  Try again later."
      always:
        - debug: msg="Attempt completed."
Verify Configuration by Running the Playbook

Create and Use Templates to Create Customized Configuration Files

Using Ansible Templates Lecture

This lecture covers how templates are used, why they are used, and how they are created. A successful Ansible Specialist must have an understanding of these concepts.

Overview:

Template basics

Template Module

img

Template File

img

Demo: Using Ansible Templates

Our template network.j2 file will look like this:

My IP address is {{ ansible_default_ipv4.address }}.

{{ ansible_distribution }} is my OS version.

Playbook for calling our template will look like this:

---
- hosts: labservers
  tasks:
  - name: deploy local net file
    template:
      src: /home/cloud_user/template/network.j2
      dest: /home/cloud_user/template/network.txt

Created file /home/cloud_user/template/network.txt after playbook run will be:

My IP address is 142.21.46.232.

RedHat is my OS version.

Work with Ansible Variables and Facts

Ansible Variables Lecture

This lecture broadly covers how to work with Ansible variables. Variable conventions, dictionary variables, magic variables and jinja2 filters are all covered conceptually as well as syntactically.

Updated Link https://jinja.palletsprojects.com/en/2.10.x/templates/

Overview:

img

img

Demo: Ansible Variables - Magic Variables and Jinja Filters

Cookbook with variables usage:

---
- hosts: labservers
  vars:
    inv_file: /home/cloud_user/vars/inv.txt
  tasks:
  - name: create file
    file:
      path: "{{inv_file}}"
      state: touch
  - name: generate inventory
    lineinfile:
      path: "{{inv_file}}"
      line: "{{ groups['labservers']|join(' ') }}"

Content of the file after playbook run:

[cloud_user@innaghiyev2c playbook]$ cat ../vars/inv.txt 
innaghiyev1c.mylabserver.com innaghiyev2c.mylabserver.com innaghiyev3c.mylabserver.com

Demo: Ansible Variables - Variable Files

Possible ways to define variable files:

Here how users.lst file looks like:

[cloud_user@innaghiyev2c playbook]$ cat ../vars/users.lst
staff:
  - joe
  - john
  - bob
  - sam
  - mark
faculty:
  - matt
  - alex
  - frank
other:
  - will
  - jack

Cookbook with variable file usage:

---
- hosts: labservers
  vars:
    userFile: /home/cloud_user/vars/list
  tasks:
  - name: create file #going to create file with defined path
    file:
      state: touch
      path: "{{ userFile }}"
  - name: list users #add inside of file users name looping through items
    lineinfile:
      path: "{{ userFile }}"
      line: "{{ item }}"
    with_items:
      - "{{ staff }}"
      - "{{ faculty }}"
      - "{{ other }}"

Ansible Facts Lecture

What are facts?

How to use facts

img

Facts.d - custome facts

img

Demo: Working with Ansible Facts

Custom facts set up:

LAB: Working with Ansible Templates, Variables, and Facts

Additional Information and Resources

A colleague of yours was the unfortunate victim of a scam email, and their network account was compromised. Shortly after you finished helping them pack up their desk, your boss gave you the assignment to promote system security through deploying a hardened sudoers file. You will need to create an Ansible template of the sudoers file that meets the following criteria:

You will need to create an accompanying playbook in /home/ansible/security.yml that will deploy this template to all servers in the default inventory.

Summary tasks list:

Learning Objectives

Create a Template sudoers File in /home/ansible/hardened.j2 That Produces a File with Appropriate Output for Each Host
The Deployed File Should Resemble the Example File Except with the IP and hostnames Customized Appropriately
Create a Playbook in /home/ansible/security.yml That Uses the Template Module to Deploy the Template on All Servers in the Default Ansible Inventory After Validating the Syntax of the Generated File
Run the Playbook and Ensure the Files Are Correctly Deployed

Check the local /etc/sudoers.d/hardened on the ansible control node for the correct contents.

Create and Work with Roles

Working with Ansible Roles Lecture

img

img

Best practice dictates that you properly namespace your variables when working with a role to avoid conflicts.

Demo: Creating and Applying a Role in Ansible

In this terminal-side demonstration, a new role is created and then applied to a target host.

Applying In-Line Roles and Role Dependencies

Working with roles is further covered in a discussion on static vs dynamic roles followed by a lecture on how to create and work with role dependencies in Ansible. This lesson concludes with a demonstration of creating a new role that is dependent on another role.

We can put some conditions and tags to involve a roles inside of playbook:

---
- hosts: webservers
  tasks:
  - include_role:
      name: apache
    tags:
    - RH_HTTPD
    when "ansible_os_family == 'RedHat'"

You can configure roles to use dependencies:

---
dependencies:
  - role: common
    vars:
      some_parameter: 3
  - role: apache
    vars:
      apache_port: 80    

From output it can be seen that dependency apache role run first and then our php-webserver role.

PLAY [labservers] ********************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************
ok: [innaghiyev2c.mylabserver.com]

TASK [apache : install apache] ********************************************************************************************************************************************
ok: [innaghiyev2c.mylabserver.com]

TASK [apache : copy httpd.conf template] ***********************************************************************************************************************************
ok: [innaghiyev2c.mylabserver.com]

TASK [apache : enable and start service] ***********************************************************************************************************************************
ok: [innaghiyev2c.mylabserver.com]

TASK [php-webserver : install php] ***********************************************************************************************************************************
ok: [innaghiyev2c.mylabserver.com] => (item=php)
ok: [innaghiyev2c.mylabserver.com] => (item=php-gd)
ok: [innaghiyev2c.mylabserver.com] => (item=php-pear)
ok: [innaghiyev2c.mylabserver.com] => (item=php-mysql)

PLAY RECAP ************************************************************************************************************************
innaghiyev2c.mylabserver.com : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

LAB: Working with Ansible Roles

Additional Information and Resources

You have just started a new job as the operations lead at a small company. There is currently no formal server baseline, and it makes for a mixed configuration environment that is consuming more support and maintenance than it should. You have decided to create a baseline process using Ansible by creating a baseline role. You have noted the following commonalities that should be included in the baseline role:

The role should be called "baseline" and should reside in /etc/ansible/roles on the ansible control node.

You will test your role on some newly requested webservers. A playbook called web.yml has been provided for you and deploys httpd to all servers in the web group (defined in your default inventory). You will need to edit the playbook to deploy the baseline role to the servers in the web group as well.

You will find the motd template, Nagios server IP information, the noc user's public key, and the web.yml playbook in /home/ansible/resources on the ansible control node.

Summary tasks list:

Important notes:

Learning Objectives

Create a Role Called baseline in /etc/ansible/roles

Run the following commands to create the structure needed for the role:

Configure the Role to Deploy the /etc/motd Template
Configure the Role to Install the Latest Nagios Client
Configure the Role to Add an Entry to /etc/hosts for the Nagios Server
Configure the Role to Create the noc User and Deploy the Provided Public Key for the noc User on Target Systems
Edit web.yml to Deploy the baseline Role

Edit /home/ansible/resources/web.yml to the following:

---
- hosts: webservers
  become: yes
  roles:
    - baseline
  tasks:
    - name: install httpd
      yum: name=httpd state=latest
    - name: start and enable httpd
      service: name=httpd state=started enabled=yes
Run Your Playbook Using the Default Inventory

Run ansible-playbook /home/ansible/resources/web.yml.

Download roles from an Ansible Galaxy

Download Roles from Ansible Galaxy

Ansible Galaxy - galaxy.ansible.com or github.com:

Managing Parallelism

Parallelism in Ansible

This lecture covers how to configure Ansible for higher performance using Ansible Forks. There is also a demonstration on how to use the serial keyword to batch host operations.

For number:

PLAY [labservers] **

TASK [Gathering Facts] ***** ok: [innaghiyev1c.mylabserver.com]

TASK [add host entry] ** changed: [innaghiyev1c.mylabserver.com]

PLAY [labservers] **

TASK [Gathering Facts] ***** ok: [innaghiyev2c.mylabserver.com] ok: [innaghiyev3c.mylabserver.com]

TASK [add host entry] ** changed: [innaghiyev2c.mylabserver.com] changed: [innaghiyev3c.mylabserver.com]

PLAY RECAP ***** innaghiyev1c.mylabserver.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
innaghiyev2c.mylabserver.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
innaghiyev3c.mylabserver.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


- `max_fail_percentage: 30` - we can use this key to provide percentage of failure during cookbook run. If 1/3 of our cookbook run will fail, then whole playbook gonna stop and concidered as **failed**

## Use Ansible Vault in Playbooks to Protect Sensitive Data
### The Ansible-Vault Command
- The `ansible-vault` command allows file encryption, and requires a password to unencrypt
- Command: `ansible-vault encrypt <file>`
- The ansible-vault rekey command will allow you to re-encrypt a file and reset the password.
- To supply the vault password during play execution, you must use either of the `--ask-vault-password` or `--ask-vault-file` flags.
- Ansible 2.4 introduces the `--vault-id` feature.
- It is also possible to set `no_log` within a module to censor sensitive log output

- `vault-id` feature
  - going to replace `--ask-vault-password` or `--ask-vault-file` flags
  - before you can only specify one password for whole vault
  - `vault-id` provides a possibility to set several passwords for a single play. 
  - `vault-id` will go through each password stored in `vault` for encypted file to find proper one.
  - it's possible to set up `label` for `vault-id`

As a demonstration let's create simple text file:
- `echo "Super secret word stored here" > secret.txt`
- `ansible-vault encrypt secret.txt` - simply encrypt our file

[cloud_user@innaghiyev2c ~]$ ansible-vault encrypt secret.txt New Vault password: Confirm New Vault password: Encryption successful


- `[cloud_user@innaghiyev2c ~]$ cat secret.txt` - as an output we have this now

$ANSIBLE_VAULT;1.1;AES256 38643439333433636239326461326234386361306331366666636534623065343237393662363538 3635633736663639663162326166636561666639653930650a303762393030663230386438393361 64336461643063383564306230313037363166623735386164363964323265366332626138663266 3638643239626366660a613162316565303936396437393133336631346166636538336533653637 31396364666430653163306164336535333562343464376438663361663436643765


- `ansible-vault edit secret.txt` - if you want to edit encrypted file
- `ansible-vault decrypt secret.txt` - decrypt your file
- `ansible-vault encrypt_string 'The answer is 42' -n meaning` - you can encrypt pieces of your playbook, rather all files
- `ansible-vault encrypt_string 'The answer is 42' -n meaning --vault-id dev@prompt` - provide vault-id with a label `dev`

[cloud_user@innaghiyev2c ~]$ ansible-vault encrypt_string 'The answer is 42' -n meaning --vault-id dev@prompt New vault password (dev): Confirm new vault password (dev): meaning: !vault | $ANSIBLE_VAULT;1.2;AES256;dev 36333866373732363065613065643062383936656461626235326238643162303863343465373166 6431633033383432396638383463636636666364386165370a326337653336613564623363633362 31666264646662633365333237366631343130316136353939386131396432393233383732356261 6133353264626234630a353233366234343564653737383637633565623364633466343565623435 37393137383861373631636135616265613166323361356266353836626265356135 Encryption successful


### Using Vaults in Playbooks
- We have following a playbook for testing:

LAB: Working with Confidential Data in Ansible

Additional Information and Resources

In an effort to improve security, you have been tasked with securing an Ansible variable file. The variable file is to be used in an ansible job that creates a secure website. To do this, complete the following:

  1. Encrypt the file /home/ansible/secret using ansible-vault.
  2. Then configure a vault password file named /home/ansible/vault to be used to run the Ansible playbook /home/ansible/secPage.yml successfully with the encrypted secrets file.
  3. Verify your work by running the secPage.yml playbook using ansible-playbook and specifying your vault password file.
  4. Test that the site deployed correctly by trying to access http://node1/secure/classified.html using the user bond with the password james.

Summary tasks list:

Learning Objectives

Encrypt /home/ansible/secret using the ansible-vault command.

Install Ansible Tower and Use it to Manage Systems

Introduction to Ansible Tower

Installing Ansible Tower

Steps to install ansible Tower:

This collection of files provides a complete set of playbooks for deploying the Ansible Tower software to a single-server installation. It is also to install Tower to the local machine, or to a remote machine reachable by SSH.

For quickly getting started with installation and setup instructions, refer to:

For more indepth documentation, refer to:

To install or upgrade, start by editing the inventory file in this directory. Uncomment and change the password from 'password' for the 3 variables below.

Tower can be installed in 3 different modes:

  1. On a single machine. This is the default, and will install in this mode with no modifications to the inventory file.
  2. On a single machine with a remote PostgreSQL database. Supplying the pg_host and pg_port variables will trigger this mode of installation.
  3. Cluster/High Availability, multiple machines with a remote PostgreSQL database. Adding multiple hosts to the [tower] inventory group will trigger this mode of installation. Note that pg_host and pg_port are also required.

- Next one is ansible tower **inventory** file:

[tower] localhost ansible_connection=local

[database]

[all:vars] admin_password=''

pg_host='' pg_port=''

pg_database='awx' pg_username='awx' pg_password='' pg_sslmode='prefer' # set to 'verify-full' for client-side enforced SSL

rabbitmq_username=tower rabbitmq_password='' rabbitmq_cookie=cookiemonster

Isolated Tower nodes automatically generate an RSA key for authentication;

To disable this behavior, set this value to false

isolated_key_generation=true

SSL-related variables

If set, this will install a custom CA certificate to the system trust store.

custom_ca_cert=/path/to/ca.crt

Certificate and key to install in nginx for the web UI and API

web_server_ssl_cert=/path/to/tower.cert

web_server_ssl_key=/path/to/tower.key

Use SSL for RabbitMQ inter-node communication. Because RabbitMQ never

communicates outside the cluster, a private CA and certificates will be

created, and do not need to be supplied.

rabbitmq_use_ssl=False

Server-side SSL settings for PostgreSQL (when we are installing it).

postgres_use_ssl=False

postgres_ssl_cert=/path/to/pgsql.crt

postgres_ssl_key=/path/to/pgsql.key


- some of the basic configuration stored in `/etc/tower/settings.py`

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img25.png)

### Demo: Working with Ansible Tower
- You can create a new project and select SCM type (Manual, Git, Mercirial etc)
- **Inventories** - in this tab we can manage our invetory files, editing and adding new hosts inside of inventory files. 
  - groups can be added inside of inventories tab
  - ad-hoc commands can be executed from hosts tab
- **Credential** - from this tab you can manage your users, access type, import your private key, prompt for password/passphrase and so on
- **Execute ad-hoc command** 
![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img26.png)

- **Templates** - the same as in ansible playbook 
- **Jobs** - you can see the status of your jobs from this tab

![img](https://github.com/Bes0n/EX407-Ansible-Automation/blob/master/images/img27.png)

## Use Documentation to Look Up Specific Information About Ansible Modules and Commands
### Finding Documentation
Two main ways to find documentation:
- built-in ansible commands
- http://docs.ansible.com/

- `ansible-doc` - by using this command we can search for any ansible module documentation
  - `ansible-doc lineinfile` - get help about `lineinfile` module

LINEINFILE (/usr/lib/python2.7/site-packages/ansible/modules/files/lineinfile.py)

    This module ensures a particular line is in a file, or replace an existing line using a back-referenced regular expression. This is primarily useful when you
    want to change a single line in a file only. See the [replace] module if you want to change multiple, similar lines or check [blockinfile] if you want to
    insert/update/remove a block of lines in a file. For other cases, see the [copy] or [template] modules.

Ansible 2.7 Exam Update

Install and Configure Control Node and Ansible Nodes

The new exam now mentions, as an objective, needing to know how to install and configure an Ansible control node:

This lesson will help you to learn how to:

Following commands have been used during this process:

Shell Scripts to Run Ad-Hoc Commands

Why shell scripts?

img

Firewall Rules

Ansible and Firewall Rules

Archiving

The Archive Module

The Unarchive module

Scheduled Tasks: Cron

The Cron Module

The Cron Module - Extra Parameters

Scheduled Tasks: at

at software

at software - Service Details

Security

Ansible Security Tasks

Some Ansible Modules for Security

Let's us consider some examples.

Software packages and repositories

Services

File Systems

Storage Devices

File content

Users and groups