Hardening de Servidores Linux Ubuntu con Ansible

¿Que es Ansible?

Con Ansible podemos instalar aplicaciones, orquestar servicios y tareas más avanzas. También se puede utilizar para la estandarización de sistema operativo (Estandarización de servicios instalados, de configuración de ficheros, versiones de software, etcétera) y la administración de servicios centralizados, como por ejemplo DNS.

Para este laboratorio vamos a utilizar 2 Ubuntu Server's. Tendremos un Ansible Master y un Ansible Worker.

Ansible lo encontramos, por defecto, en la mayoria de las distribuciones de linux. La instalacion es sencilla. Para ello ejecutamos:

apt install ansible
HostnameDirección TCP IP
ansiblemaster192.168.247.224
ansibleworker192.168.247.225

Vamos a utilizar estos nombres, en los hosts, con estas direcciones IP's.

Instalación Master Node

Ya hemos instalado ansbile, en el servidor, ahora vamos a realizar las configuraciones.

Ansible se conecta a su cliente a través de SSH, primero generaremos una clave pública en el servidor ansible, para copiarla en los clientes ansible.

Genere la clave usando ssh-keygen comando como se muestra a continuación.

santiago@ansiblemaster:/etc/ansible$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/santiago/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/santiago/.ssh/id_rsa.
Your public key has been saved in /home/santiago/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:AT62rfaL7zq06CUlxUP/DKDmyZH3kM/OLJEFQmhlSnw santiago@ansiblemaster
The key's randomart image is:
+---[RSA 2048]----+
| ..+= =          |
| .+oEB *         |
| ...= @ =        |
|   + * % =       |
|    = = S o      |
|     o.*         |
|    .o=.+        |
|    .+o+         |
|   .. o==.       |
+----[SHA256]-----+

Cambiamos los permisos en la llave publica y privada.

santiago@ansiblemaster:/etc/ansible$ sudo chmod 0400 /home/santiago/.ssh/id_rsa.pub
santiago@ansiblemaster:/etc/ansible$ sudo chmod 0400 /home/santiago/.ssh/id_rsa

Copiemos la clave pública al host Ansible cuya dirección IP es 192.168.247.225, con ssh-copy-id.

santiago@ansiblemaster:/etc/ansible$ ssh-copy-id -i ~/.ssh/id_rsa.pub santiago@192.168.247.225
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/santiago/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
santiago@192.168.247.225's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'santiago@192.168.247.225'"
and check to make sure that only the key(s) you wanted were added.

Vamos a configurar el inventario, en el Master. Completamos, como en el ejemplo, el /etc/ansible/hosts. Como se puede ver agregamos, dentro de [servers], nuestro worker.

servers:
  hosts:
    192.168.247.225:
    192.168.247.224:

Ahora vamos a probar la conexión.

santiago@ansiblemaster:/etc/ansible$ ansible -m ping servers
ansibleworker | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Hacemos un ping y recibimos un pong. Ya estamos llegando al Worker. ¡Podriamos tener, miles!

Algunos comandos

Vamos a consultar nuestro inventario y revisar los discos.

santiago@ansiblemaster:/etc/ansible$ ansible-inventory --list -y
all:
  children:
    servers:
      hosts:
        ansiblemaster:
          ansible_host: 192.168.247.224
          ansible_python_interpreter: /usr/bin/python3
        ansibleworker:
          ansible_host: 192.168.247.225
          ansible_python_interpreter: /usr/bin/python3
    ungrouped: {}
santiago@ansiblemaster:/etc/ansible$ ansible all -a "df -h" -u santiago
ansibleworker | SUCCESS | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
udev            955M     0  955M   0% /dev
tmpfs           198M  1,2M  196M   1% /run
/dev/sda2        20G  4,0G   15G  22% /
tmpfs           986M     0  986M   0% /dev/shm
tmpfs           5,0M     0  5,0M   0% /run/lock
tmpfs           986M     0  986M   0% /sys/fs/cgroup
/dev/loop0       89M   89M     0 100% /snap/core/7270
tmpfs           198M     0  198M   0% /run/user/1000

ansiblemaster | SUCCESS | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
udev            955M     0  955M   0% /dev
tmpfs           198M  1,3M  196M   1% /run
/dev/sda2        20G  4,3G   15G  23% /
tmpfs           986M  144K  985M   1% /dev/shm
tmpfs           5,0M     0  5,0M   0% /run/lock
tmpfs           986M     0  986M   0% /sys/fs/cgroup
/dev/loop0       89M   89M     0 100% /snap/core/7270
tmpfs           198M     0  198M   0% /run/user/1000
/dev/loop1       98M   98M     0 100% /snap/core/10444

Hardening Ubuntu

Uno de los blogs mas importantes para realizar un Hardening de Ubuntu 18.04 es el de Florian Utz. Vamos a utilizar ese playbook y aplicar los CIS Benchmark Controls. Es imporante saber que los niveles 1 y 2 se corregiran de forma predeterminada. El rol podria "romper cosas" por eso es imporante leer la documentacion.

Vamos a crear nuestro requirements.yml.

sudo sh -c "echo '- src: https://github.com/joelradon/ubuntu1804-desktop-cis.git' >> /etc/ansible/requirements.yml"

Una vez que creamos el archivo instalamos el rol con el comando ansible-galaxy.

santiago@ansiblemaster:/etc/ansible$ sudo ansible-galaxy install -p roles -r /etc/ansible/requirements.yml
- extracting ubuntu1804-desktop-cis to /etc/ansible/roles/ubuntu1804-desktop-cis
- ubuntu1804-desktop-cis was installed successfully

Ahora vamos a nuestro playbook para iniciar el Hardening. Se le dira a ansible que use el rol, que acabamos de crear, y corra la "receta" en nuestros servidores. Para ello creamos site.yml.

- name: Hardenizar Servidores Ubuntu
  hosts: servers
  become: yes
  roles:
    - ubuntu1804-desktop-cis

Vamos cambiar algunas configuraciones para no ingresar con la llave privada y revisar el potencial de Ansible. Hay varias configuraciones posibles para hacerlo, aca les dejo un instructivo que me resulto muy interesante. Pasando el password, como variable, usando Vault de Ansible. Revisenlo.

Vamos a ingresar el usuario y el password en nuestro inventario.

servers:
  hosts:
    192.168.247.225:
    192.168.247.224:
  vars:
    ansible_user: santiago
    ansible_become: True
    ansible_become_pass: TUPASSWORD

¡Vamos a correr el playbook! Y que comience la magia. Ejecutamos ansible-playbook -i hosts site.yml.

santiago@ansiblemaster:/etc/ansible$ ansible-playbook -i hosts site.yml

PLAY [Harden Server] *****************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************************
ok: [192.168.247.225]
ok: [192.168.247.224]

TASK [ubuntu1804-desktop-cis : Check OS version and family] **************************************************************************************************************************************************
skipping: [192.168.247.225]
skipping: [192.168.247.224]

TASK [ubuntu1804-desktop-cis : Check ansible version] ********************************************************************************************************************************************************
skipping: [192.168.247.225]
skipping: [192.168.247.224]

TASK [ubuntu1804-desktop-cis : PRELIM | List users accounts] *************************************************************************************************************************************************
ok: [192.168.247.225]
ok: [192.168.247.224]

TASK [ubuntu1804-desktop-cis : PRELIM | Gather accounts with empty password fields] **************************************************************************************************************************
ok: [192.168.247.225]
ok: [192.168.247.224]

TASK [ubuntu1804-desktop-cis : PRELIM | Gather UID 0 accounts other than root] *******************************************************************************************************************************
ok: [192.168.247.225]
ok: [192.168.247.224]

De esta manera vamos a tener nuestros servidores Ubuntu en compliance con CIS Controls. Se puede usar OpenSCAP para realizar Compliance As a Code, basado diferentes estandars.

Espero que les sirva para empezar a conocer el poder de Ansible.

0
Subscribe to my newsletter

Read articles from Santiago Fernandez directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Santiago Fernandez
Santiago Fernandez

I have a bachelor's degree in Technology from the University of Palermo, a Master in Information Security from the University of Murcia and different certifications such as CISSP | CISM | CDPSE | CCSK | CSX | MCSA | SMAC™️ | DSOE | DEPC | CSFPC | CSFPC | 5x AWS Certified. He is currently CISO at Klar, a Mexican Fintech. He was fortunate to be awarded as CISO of the Year in Argentina in 2021 and was among the Top 100 CISO's in the World in 2022. A lover of new technologies, he has developed a career in DevSecOps and Cloud Security at Eko Party, the largest security conference in Latin America.