In the next chapter, you’ll prepare for communication with nodes. It will be a question of setting up the necessary prerequisites to establish communication between the node manager and the nodes.

Table of Contents

Use Ansible to automate your configuration tasks

Prepare for communication

So you’ll automatically deploy MediaWiki to the 2 nodes, using Ansible and automation scripts from the node manager.

Ansible works with tools that are already widely used on Linux systems. This is because Ansible only needs SSH and Python to work. At the very least, these 2 tools must be installed and functional on the node manager and nodes.

To establish communication and have the right to initiate remote commands, you need:

  1. Define a node inventory.
  2. Check the SSH connection between the node manager and the nodes.
  3. Ping Ansible on nodes.
  4. Verify that Python is installed on the nodes.
  5. Create a single user on the nodes.
  6. Assign sudo rights to this user.
  7. Create an SSH key pair for this user.
  8. Copy the SSH public key to the nodes.

Define a node inventory

It’s time to name your servers:

  • Server 1 will have Apache, PHP and MediaWiki installed; So we’ll call it http1 ;
  • MariaDB will be installed on server 2; So we’ll call it BDD1.

Since you don’t have access to the company’s DNS, you decide to configure name resolution via the /etc/hosts file on the node manager.

Ideally, machine names should be used rather than IP addresses. Node names are always to be registered in a DNS. For the exercise that focuses on practicing Ansible, you take a shortcut using the /etc/hosts file. This file is used to set up matches between the names of the servers and their IP addresses.

Log in to the root node manager:

root@node-manager:~#

Add in the /etc/hosts file on the node manager the record of the 2 nodes:

127.0.0.1 localhost
127.0.1.1 node-manager
# le node http1
192.168.122.11 http1
# le node bdd1
192.168.122.12 bdd1

This action will allow you to use the names http1 and bdd1 to communicate with the nodes.

Create the Ansible inventory file

At this point, you’ll start using the Ansible commands to do the next actions.

To work, Ansible needs an inventory file. This file contains the list of nodes. So you’ll save the names of the nodes in this file.

Place yourself in your virtual environment:

root@node-manager:~# su - user-ansible
user-ansible@node-manager:~$ source ansible/bin/activate

Then edit the inventaire.ini file with the vi command:

(ansible) user-ansible@node-manager:~$ vi inventaire.ini

Put in this file the 2 names of the nodes:

http1
bdd1

Vi is not mandatory; If you’re more comfortable with another editor, use it!

The inventory file is in INI format by default, so it follows the syntax of that format. Ansible knows how to work with other data formats, you just need to activate the right plugins. You can find the list of inventory plugins here.

Verify that you are communicating with the nodes

Before using Ansible to start automating tasks, run an SSH connection on the nodes to register the fingerprint (the server fingerprint that needs to be verified to make sure you’re connecting to the correct node) on the node manager. You have to do this at least once, otherwise Ansible will grumble on the first connection, because the sshpass package doesn’t know how to handle fingerprinting.

user-ansible@node-manager:~$
ssh root@http1
root@http1's password:
Linux node-www 5.10.0-11-amd64 #1 SMP Debian 5.10.92-1 (2022-01-18) x86_64

The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.

Debian GU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law.
Last login: Mon Feb 14 12:07:26 2022

Answer yes and do the same for bdd1.

Use the ansible command in ad-hoc mode

You’ll start using Ansible (in ad-hoc mode, i.e., with manual commands rather than scripts) to set up the prerequisites. This will allow you to automate them and apply them to all nodes at the same time.

Ad-hoc commands are quick actions that don’t necessarily need to be saved for later. You can refer to Ansible’s documentation on ad-hoc commands for further information.

Now ping Ansible in your virtual work environment:

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m ping http1 --user root --ask-pass
SSH password:
http1 | SUCCESS => {
      "ansible_facts": {
      "discovered_interpreter_python": "/usr/bin/python3"
      },
      "changed": false,
      "ping": "pong"
}

You’ve just used the ansible command with several options:

  • -i: Tells Ansible the location of the inventaire file;
  • -m: Instructs Ansible to use the ping model;
  • http1: Instructs Ansible to take action on the http1 node ;
  • –user: Instructs Ansible to use the root user to connect to the node (no choice at the moment, as this is the only account you have) ;
  • –ask-pass: Instructs Ansible to prompt for the SSH password ;
  • http1: Instructs Ansible to run the command on the http1 node.

Returning the command tells you that the action is a success and responds pong to ping! The http1 node is easily reachable.

Ansible doesn’t run the ping command, it launches a module that does the same thing as the ping command.

Module icon

module is a program used to execute an Ansible task or command. Each task uses one module and only one, which can take arguments to be executed in a custom way. Ansible provides many modules, but you can create your own, customized.

All modules can be accessed on the Ansible documentation or with the command.(ansible) user-ansible@node-manager:~$ ansible-doc--list

All official Ansible modules are downloaded to your computer when you install Ansible. When you use a module, Ansible will fetch the code to run from the module’s folder on your computer. If you installed Ansible in a virtual environment with pip, the modules can be found at ../ansible/lib/python2XY/site-packages/ansible

The syntax and options for the ansible command can be found in the Ansible documentation.

Verify that Python is installed on the nodes

Sometimes Python is not installed on the node; in this case, you can use a special module: raw, which allows you to pass Ansible commands without using Python:

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m raw -a "apt install -y python3" http1 --user root --ask-pass
SSH password:
http1 | CHANGED | rc=0 >>
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances... Fait
Lecture des informations d'état... Fait
python3 est déjà la version la plus récente (3.9.2-3).
0 mis à jour, 0 nouvellement installés, 0 à enlever et 0 non mis à jour.
Shared connection to http1 closed.

You used the -m option to call the raw module with the argument “apt install -y python3”, which installs Python version 3 on the http1 node.

In reality, Ansible modules can be written in a language other than Python. The raw module, written in Shell, is proof of this! An additional advantage in favor of Ansible.

Create the user-ansible user on the nodes

You’ll follow best practices by creating a single user so that you don’t work directly with the root account.

It is not recommended to use the root account directly to do all the operations (although this is possible with Ansible and necessary to set up the prerequisites). Instead, it is better to work with a single user and give them sudo rights. Indeed, commands launched with sudo will be done with a prior password and can be limited to certain actions. In addition, since the user account is nominative, it will be much easier to trace actions in the logs to debug.

But before you create a user, you’ll generate an encrypted password (in a format recognized by Linux) with Ansible:

(ansible) user-ansible@node-manager:~$ ansible localhost -i inventaire.ini -m debug -a "msg={{'passforce'|password_hash('sha512','secretsalt')}}" localhost | SUCCESS => {
    "msg": "$6$secretsalt$X5YDmUgDphPxnMkByvHbNaiP4T5Uk0WjEZ9TukWKQnXmXN81jG3DcGZnNJiSz9ltgPhplH92HOR/RqgmyS.zN1"
} 

In this command, we used the debug module with the msg argument to turn the password “passforce” into a string encrypted with the sha512 algorithm. “Secretsalt” is what is called salt. It’s a word that helps strengthen the security of the algorithm by adding an extra unknown to the password encryption process.

The “localhost” option was used to instruct Ansible to run the command on localhost (locally on the node manager).

You will now be able to create the user-ansible user with an encrypted password, using the following command:

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m user -a 'name=user-ansible
password=$6$secretsalt$X5YDmUgDphPxnMkByvHbNaiP4T5Uk0WjEZ9TukWKQnXmXN81jG3DcGZnNJiSz9ltgPhplH92HOR/RqgmyS.zN1' --user root --ask-pass all
SSH password:
http1 | CHANGED => {
     "ansible_facts": {
     "discovered_interpreter_python": "/usr/bin/python3"
     },
     "changed": true,
     "comment": "",
     "create_home": true,
     "group": 1001,
     "home": "/home/user-ansible",
     "name": "user-ansible",
     "password": "NOT_LOGGING_PASSWORD",
     "shell": "/bin/sh",
     "state": "present",
     "system": false,
     "uid": 1001
}
bdd1 | CHANGED => {
     "ansible_facts": {
     "discovered_interpreter_python": "/usr/bin/python3"
     },
     "changed": true,
     "comment": "",
     "create_home": true,
     "group": 1001,
     "home": "/home/user-ansible",
     "name": "user-ansible",
     "password": "NOT_LOGGING_PASSWORD",
     "shell": "/bin/sh",
     "state": "present",
     "system": false,
     "uid": 1001
}

You used the user module with the name and password arguments, and you asked Ansible to run the command on all (on all nodes in the inventory file).

Give sudo rights to user-ansible

Connect to the http1 node, install the sudo package (apt get install sudo), and look at the /etc/sudoers file; It contains the configurations of SUDO:

You can see the following line:

## Allows people in group sudo to run all commands
%sudo ALL=(ALL) ALL

The sudo group has sudo rights. So you’ll add the user-ansible user in the sudo group on all nodes:

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m user -a 'name=user-ansible groups=sudo append=yes ' --user root --ask-pass all
SSH password:
http1 | CHANGED => {
     "ansible_facts": {
     "discovered_interpreter_python": "/usr/bin/python3"
     },
     "append": true,
     "changed": true,
     "comment": "",
     "group": 1001,
     "groups": "sudo",
     "home": "/home/user-ansible",
     "move_home": false,
     "name": "user-ansible",
     "shell": "/bin/sh",
     "state": "present",
     "uid": 1001
}
bdd1 | CHANGED => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": true,
    "changed": true,
    "comment": "",
    "group": 1001,
    "groups": "sudo",
    "home": "/home/user-ansible",
    "move_home": false,
    "name": "user-ansible",
    "shell": "/bin/sh",
    "state": "present",
    "uid": 1001
}

Un moyen de vérifier que user-ansible a bien les droits sudo est de relancer la commande précédente, mais en ajoutant de nouvelles options :

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m user -a 'name=user-ansible groups=sudo append=yes ' --user user-ansible --ask-pass --become --ask-become-pass all
SSH password:
BECOME password[defaults to SSH password]:
bdd1 | SUCCESS => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": true,
    "changed": false,
    "comment": "",
    "group": 1001,
    "groups": "sudo",
    "home": "/home/user-ansible",
    "move_home": false,
    "name": "user-ansible",
    "shell": "/bin/sh",
    "state": "present",
    "uid": 1001
}
http1 | SUCCESS => {
    "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": true,
    "changed": false,
    "comment": "",
    "group": 1001,
    "groups": "sudo",
    "home": "/home/user-ansible",
    "move_home": false,
    "name": "user-ansible",
    "shell": "/bin/sh",
    "state": "present",
    "uid": 1001
}

La commande s’est bien passée, car le retour est un SUCCESS ! Vous avez les privilèges sudo.

Ici, vous avez utilisé le module user pour ajouter user-ansible dans le groupe wheel et vous avez utilisé deux nouvelles options :

  • –become : Ansible vous permet de “devenir” un autre utilisateur en utilisant sudo ;
  • –ask-become-pass : Ansible demande le mot de passe sudo (qui est le même que le mot de passe de user-ansible).

Dorénavant, nous n’utiliserons plus root, mais l’utilisateur user-ansible en mode sudo pour passer les commandes Ansible

Créez les clés SSH

Pour se connecter en SSH, il est recommandé d’utiliser une paire de clés plutôt que d’utiliser un mot de passe.

La communication SSH est établie sur la base de clés SSH ; cette pratique est conseillée, car elle permet un niveau d’authentification beaucoup plus sûr que l’authentification par mot de passe.

Vous allez maintenant créer une paire de clés SSH de type ecdsa pour l’utilisateur user-ansible.

Elliptic Curve Digital Signature Algorithm (ECDSA) est un algorithme de signature numérique qu’il est conseillé d’utiliser aujourd’hui pour avoir un niveau de sécurité satisfaisant. 

Commencez par vous remettre en utilisateur user-ansible avec la commande suivante si c’est nécessaire :

# su - user-ansible
user-ansible@node-manager:~$

Et lancez la création des clés avec la commande suivante :

user-ansible@node-manager:~$ ssh-keygen -t ecdsa
Generating public/private key pair.
Enter file in which to save the key (/home/user-ansible/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user-ansible/.ssh/id_ecdsa
Your public key has been saved in /home/user-ansible/.ssh/id_ecdsa.pub
The key fingerprint is: SHA256:dJfRsev7RlWVLd4e9aUCBOdX+SqdkwaH0f9tGruLYLU
user-ansible@node-manager
They key's randomart image is:
+---[ECDSA 256]---+
|    .oo .ooo=|
|     o. .+=o=|
|    . o.++.*=|
|   . . o+ +o*|
|    S   .=.==|
|       ..oO *|
|      o Eo.B |
|     . . .o..|
|        . +=.|
The key fingerprint is:
SHA256:geBOUCBR+4ljdMOn5QVmq9R7dpgmwYsAv995BtTWCYg user-ansible@node-manager
The key's randomart image is:
+---[ECDSA 256]---+
|+o+oo.+..    |
| + =E*.= o . |
|  = B X = o  |
| . X @ * +   |
|  = B * S .  |
|   . o . B . |
|  . o o      |
|   o         |
|             |
+----[SHA256]-----+

You can leave everything by default, without changing anything. There is no need to put a passphrase. 

The passphrase is used to strengthen the SSH connection with a password. In our case, you don’t use it, which will save you time during the practical exercises.

Add the user-ansible user’s public key to the nodes

You’ll use the authorized_key module to register the user-ansible user’s public key on all nodes. This way, you will be able to log in to the nodes without entering an SSH password.

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m authorized_key -a 'user=user-ansible state=present key="{{
lookup("file", "/home/user-ansible/.ssh/id_ecdsa.pub") }}"' --user user-ansible --ask-pass --become --ask-become-pass all
SSH password:
BECOME password[defaults to SSH password]
http1 | CHANGED => {
      "ansible_facts": {
      "discovered_interpreter_python": "/usr/bin/python3"
      },
      "changed": true,
      "comment": null,
      "exclusive": false,
      "follow": false,
      "key": "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAOS9i3B7TxpPkV8a2S8DLeVX5HWYaGTl435CDy+PmKGMOCi3PnvZQ6GmaXyht+EhQUQSM0dUJ9wQC8wjwM0xes= user-ansible@node-manager",
      "key_options": null,
      "keyfile": "/home/user-ansible/.ssh/authorized_keys",
      "manage_dir": true,
      "path": null,
      "state": "present",
      "user": "user-ansible",
      "validate_certs": true
}
bdd1 | CHANGED => {
     "ansible_facts": {
     "discovered_interpreter_python": "/usr/bin/python3"
     },
     "changed": true,
     "comment": null,
     "exclusive": false,
     "follow": false,
     "key": "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAOS9i3B7TxpPkV8a2S8DLeVX5HWYaGTl435CDy+PmKGMOCi3PnvZQ6GmaXyht+EhQUQSM0dUJ9wQC8wjwM0xes= user-ansible@node-manager",
     "key_options": null,
     "keyfile": "/home/user-ansible/.ssh/authorized_keys",
     "manage_dir": true,
     "path": null,
     "state": present,
     "user": "user-ansible",
     "validate_certs": true
}

You’ve used new options:

  • -m authorized_key: module authorized_key (adds or removes SSH keys for users) ;
  • user=user-ansible: The user is user-ansible;
  • state=present: Indicates to add the file;
  • key=”{{ lookup(“file”, “/home/user-ansible/.ssh/id_ecdsa.pub”) }}”: Use the lookup command to find the file in question.

Rerun the command but this time without –ask-pass (asks for the SSH password):

(ansible) user-ansible@node-manager:~$ ansible -i inventaire.ini -m authorized_key -a 'user=user-ansible state=present key="{{lookup("file", "/home/user-ansible/.ssh/id_ecdsa.pub") }}"' --user user-ansible --become --ask-become-pass all
BECOME password:
http1 | SUCCESS => {
      "ansible_facts": {
      "discovered_interpreter_python": "/usr/bin/python3"
      },
      "changed": false,
      "comment": null,
      "exclusive": false,
      "follow": false,
      "key": "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAOS9i3B7TxpPkV8a2S8DLeVX5HWYaGTl435CDy+PmKGMOCi3PnvZQ6GmaXyht+EhQUQSM0dUJ9wQC8wjwM0xes= user-ansible@node-manager",
      "key_options": null,
      "keyfile": "/home/user-ansible/.ssh/authorized_keys",
      "manage_dir": true,
      "path": null,
      "state": "prensent,
      "user": "user-ansible",
      "validate_certs": true,
}
bdd1 | SUCCESS => {
     "ansible_facts": {
     "discovered_interpreter_python": "/usr/bin/python3"
     },
     "changed": false,
     "comment": null,
     "exclusive": false,
     "follow": false,
     "key": "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAOS9i3B7TxpPkV8a2S8DLeVX5HWYaGTl435CDy+PmKGMOCi3PnvZQ6GmaXyht+EhQUQSM0dUJ9wQC8wjwM0xes= user-ansible@node-manager",
     "key_options": null,
     "keyfile": "/home/user-ansible/.ssh/authorized_keys",
     "manage_dir": true,
     "path": null,
     "state": "prensent,
     "user": "user-ansible",
     "validate_certs": true,

You have only been asked for one password, the sudo password only.

There you have it, you can run remote commands with Ansible on nodes with sudo privilege. Limitless automation is yours!

Summary

In this chapter, you have prepared the communication with the nodes; In particular, you have:

  • Created an inventory file and added the nodes to that file.
  • used the ansible command in ad-hoc mode to check for the presence of Python on nodes and ping ;
  • Created a user-ansible user on the nodes ;
  • created SSH keys for the user-ansible user ;
  • gave sudo privileges to user-ansible to be able to execute commands as a super user on nodes;
  • Stored the user-ansible public key on nodes to secure communications.

In the next chapter, you’ll walk through deploying an application with Ansible.

Did you enjoy this article? Feel free to share it on social media and subscribe to our newsletter so you never miss a post!

And if you'd like to go a step further in supporting us, you can treat us to a virtual coffee ☕️. Thank you for your support ❤️!
Buy Me a Coffee

Categorized in:

Tagged in: