What are we doing here?

This blog includes a series of videos and references to help new users or enthusiasts better understand how to use open source and free technology tools. The quick links includes more information for accessing many of the tools covered along with other references to learn more for taking advantage of these tools.

Click HERE to see the full list of topics covered!
Showing posts with label Ansible. Show all posts
Showing posts with label Ansible. Show all posts

More Advanced Scripting with Ansible

Working more and more in a sysadmin capacity recently has forced me to double down on learning more with Ansible, and thought I'd share some learnings. 

As previously written in other posts - one can filter those using the Ansible label on the right-hand side - Ansible is a great tool for helping to automate tasks to a fleet of hosts. Ansible is agentless, meaning the managed nodes do not need to install any particular software other than Python which is normally available on most Linux hosts. The scripts, called playbooks, are written in a .yaml format to make them easily readable with little study. Hosts can be dynamically added to the Ansible host node by adding them in the host file, or if accessible to the Ansible management node via DNS. What I have recently learned and found eye-opening is the ability to prompt and to add conditionals to create more dynamic and reusable playbooks (Ansible scripts) and enhance the usability of Ansible. 

Making a prompt

Ansible can prompt for user input before running and making changes to a selection of hosts. This is quite powerful because it allows a script to be written, and reused by other sysadmins or managers without having to even really understand the script syntax (never a good thing, but a thing). 

---
- name: User onboarding
  hosts: localhost

  vars_prompt:
    - name: uid
      prompt: Enter the users UID
      private: false
    - name: userpasswd
      prompt: Enter the general password
      private: false

  tasks:
    - name: Add user account
      become: true
      ansible.builtin.user:
        name: "{{ uid }}"
        password: "{{ userpasswd | password_hash('sha512') }}"
      delegate_to: targetservername
...

The above will prompt the admin to enter in the User account ID and provide a password for the user. The prompt structure has a name which identifies the variable for which the prompt result (entered by the admin/user running the playbook). An example of the output for the admin would be as follows:

[root@6e5abc86b9fb scripts]# ansible-playbook sample.yml 
Enter the users UID: Bob
Enter the general password: bob1234


Clicking enter after entering the values will then go off and perform the assigned task, which in the above example will create a user on the target system.

If we wanted to double check the entered values before running the tasks, it is possible to also use the same prompt method to verify values. 

---
- name: User onboarding
  hosts: localhost

  vars_prompt:
    - name: uid
      prompt: Enter the users UID
      private: false
    - name: userpasswd
      prompt: Enter the general password
      private: false

  tasks:
    - name: Confirm values
      pause:
        prompt: |
          Please confirm the below information is correct!
          Press return to continue. Press Ctrl+c and then "a" to abort.
          User UID: {{ uid }}
          User password: {{ userpasswd }}

    - name: Add user account
      become: true
      ansible.builtin.user:
        name: "{{ uid }}"
        password: "{{ userpasswd | password_hash('sha512') }}"
      delegate_to: targetservername
...


The task references to the prompt to display the values for the user to double check. The pause value in the above script will stop the tasks from proceeding one after the other and await the user to confirm by hitting 'Enter'. Sample output:

[root@6e5abc86b9fb scripts]# ansible-playbook sample.yml
Enter the users UID: bob 
Enter the general password: bob1234

PLAY [User onboarding] ***********************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: [localhost]

TASK [Confirm values] ************************************************************************************************************************************************
[Confirm values]
Please confirm the below information is correct!
Press return to continue. Press Ctrl+c and then "a" to abort.
User UID: bob
User password: bob1234
 

Using conditionals

Ansible handles conditionals - i.e. if statements - using the term when. In the task adding a when: allows for conditionals to then be added with options such as a few below:

- if equal - ==

- if not equal - !=

- Is defined - is defined

- Is not defined - is not defined

- great than - >

- less than - < 

More information can be found here:

https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_conditionals.html 

Example of changing the user password hash level based on high or low security prompt. 

---
- name: User onboarding
  hosts: localhost

  vars_prompt:
    - name: uid
      prompt: Enter the users UID
      private: false
    - name: userpasswd
      prompt: Enter the general password
      private: false
    - name: securitylevel
      prompt: Does the user require a higher security for his/her password (Yes/No)?
      private: false

  tasks:
    - name: Confirm values
      pause:
        prompt: |
          Please confirm the below information is corect!
          Press return to continue. Press Ctrl+c and then "a" to abort.
          User UID: {{ uid }}
          User password: {{ userpasswd }}
          High security: {{ securitylevel }}

    - name: Add user account
      become: true
      ansible.builtin.user:
        name: "{{ uid }}"
        password: "{{ userpasswd | password_hash('sha256') }}"
      when: securitylevel == "No"
      delegate_to: localhost

    - name: Add user account
      become: true
      ansible.builtin.user:
        name: "{{ uid }}"
        password: "{{ userpasswd | password_hash('sha512') }}"
      when: securitylevel == "Yes"
      delegate_to: localhost

...

 

And a sample of the full output:

[root@6e5abc86b9fb scripts]# ansible-playbook sample.yml
Enter the users UID: katherine
Enter the general password: kat1234
Does the user require a higher security for his/her password (Yes/No)?: No

PLAY [User onboarding] ***********************************************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************************************************
ok: [localhost]

TASK [Confirm values] ************************************************************************************************************************************************
[Confirm values]
Please confirm the below information is correct!
Press return to continue. Press Ctrl+c and then "a" to abort.
User UID: katherine
User password: kat1234
High security: No
:
ok: [localhost]

TASK [Add user account] **********************************************************************************************************************************************
changed: [localhost]

TASK [Add user account] **********************************************************************************************************************************************
skipping: [localhost]

PLAY RECAP ***********************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
 

In the above the task flagged as skipping is passed over because the conditional - set security level to high - is false hence the task is skipped and the playbook continues. 

Hope it helps for users to get more out of the great tool that is Ansible! 

Nextcloud and Ansible

 

This tutorial is really more of a proof of concept of using Ansible and other scripts to more easily deploy Nextcloud from scratch. 

Ansible is an interesting tool for deploying and maintaining server systems. Very much like Docker, it uses YAML to build configuration files called Playbooks, and these Playbooks can be used to automate actions on the managed nodes in the cluster. 

In the deployment, as mentioned in the video, I do not deploy everything that's needed for Nextcloud. The Ansible Playbook doesn't even download and install Nextcloud. This is deliberate because I would think that nodes can be added, taken away, replaced, etc. and the Nextcloud config may want to reside in a more permanent storage environment. For this reason I offer a reference for getting NFS set up in Debian 12, and then mounting it to the web server. 

After the initial web server and Nextcloud install are complete, and the config.php file is modified as needed for Redis, Memcache, etc., subsequent updates and changes to web server nodes can be made. I even noticed, while recording, that I had missed memcached package in the yaml, but a quick change and re-running the configuration brought it in. 

The source for the Ansible playbook, as well as single-node scripts for installing Nextcloud from scratch is available on Github. 

https://github.com/JoeMrCoffee/AutomateManualNextcloudInstall/

Getting Started with Ansible


Ansible is a very popular management tool for all sorts of systems. Linux servers, Windows systems, networking equipment, and more can all be managed and provisioned on mass using Ansible. 

I had to investigate some more with Ansible for work, and I wanted to share some of those findings. 

The video covers the basic install, host setup, ping, and running a sample playbook. The playbooks are really the most important tool, because by using a simple yaml file, administrators can perform routine provisioning or updates to dozens to thousands of servers with a single command. 

The sample below shows how to create a file on all of the managed devices, run a package manager update, and even install and application (openjdk is used as an example, but any valid package would work). 


The reference file is located here.

Troubleshooting:

In the making of the video, because I installed Ansible on a somewhat older host for demo purposes, the version 2.5.1 wanted to use Python 2, but the clients default to Python 3. To work around this the Group Variables need to add the below line in the hosts file. I've not seen this using newer versions 2.9, but something to watch for.

ansible_python_interpreter=/usr/bin/python3

Also important is that the ssh keys of the clients need to be in the host running Ansible. That can be most easily setup by connecting to the clients over ssh. If there is a lot of hosts, good key management can also allow for the keys to all be exported and updated into the ssh known_hosts file.

More information:

Getting started

Run a playbook command

Python3