Configurando ansible en un entorno cerrado

DISCLAIMER: Estoy aprendiendo a usar Ansible. No recomiendo seguir esto como guía. Son notas para mi uso personal.

El reto es meter ansible en un entorno de producción con máquinas corriendo con sus configuraciones de seguridad hechas y que no se pueden cambiar por políticas de auditoría.

La idea sería crear un usuario en cada servidor, instalarle las claves ssh y operar conectando desde la máquina que tiene ansible al usuario del servidor. A priori suena fácil. El problema

Básicamente el problema consiste en que las máquinas están en producción y no puedo entrar con root por ssh porque está deshabilitado. Y tampoco es una opción habilitarlo porque tardaría demasiado tiempo, son varias decenas.

Esto me impide crear fácilmente un usuario como había planeado en un principio.

El plan

El plan finalmente debería ser el siguiente:

La configuración a ejecutar:

  • Crear las claves ssh en el servidor con ansible (controlador).
  • Copiarlas a mi usuario de administración de cada servidor.
  • Crear un playbook que ejecute copie, ejecute un script y lo borre.
  • Crear un script bash que ejecute la creación de usuario e instale la clave ssh.
  • Configurar el visudo para poder usar NOPASSWD con seguridad

Para que finalmente haya:

  • Una máquina con ansible a modo de controlador.
  • Un usuario ansible con clave ssh y priviliegios de sudo suficientes para funcionar en cada servidor.

Ya tengo montada una máquina que centralizará las gestiones y los playbooks y lo que haga falta.

1. Configurando mi usuario en el controlador

Lo primero es generar las claves publica/privada desde el controlador

$ ssh-keygen -t rsa -b 4096 ~/.ssh/ansible

$ vim ~/.ssh/config

Host 192.168.2.*
    User xuacu
    IdentityFile ~/.ssh/ansible

ssh-copy-id -i ~/.ssh/ansible [email protected]
Y tras meter la contraseña ya podemos hacer login en ese servidor, a modo de test.

Si esto ha funcionado sin problemas lo automatizamos para el resto de máquinas

2. Creando el script bash

Una vez tenemos la clave de ansible instalada en los servidores hay que configurar los servidores. Crear el usuario ansible e introducir la clave para que el controlador pueda entrar.

#!/usr/bin/env bash
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ansible/.local/bin:/home/ansible/bin
export HISTIGNORE='*sudo -S*'
export PATH
PASSWORD=Pa$$w0rd
echo "$PASSWORD" | sudo -S -k useradd ansible -r -p ansible -m -G sudo -s /bin/bash
echo "$PASSWORD" | sudo -S -k mkdir -p /home/ansible/.ssh
echo "$PASSWORD" | sudo -S -k touch /home/ansible/.ssh/authorized_keys
echo "$PASSWORD" | sudo -S -k chown -R ansible:ansible /home/ansible/.ssh
echo "$PASSWORD" | sudo -S -k chmod 777 /home/ansible/.ssh/authorized_keys
echo "$PASSWORD" | sudo -S -k cat /tmp/ansible.pub >> /home/ansible/.ssh/authorized_keys
echo "$PASSWORD" | sudo -S -k chmod 600 /home/ansible/.ssh/authorized_keys
Lógicamente hay que reemplazar la variable PASSWORD por el password real del usuario. sudo -S sirve para tomar el password del stdin sudo -k para que no cachea las credenciales, por seguridad PATH es obligatorio, de lo contrario no encuentra los binarios. La otra opción es poner las rutas absolutas.

El playbook

$cat copy-config.yml

---
- hosts: SERVIDORES
  tasks:
    - name: copia archivos a remoto
      copy:
        src: /home/ansible/playbooks/preConfig/requiere/
        dest: /tmp
        mode: u+x
    - name: ejecuta el script que crea el user e instala las llaves
      shell: bash /tmp/instalador.sh
    - file:
         path: /tmp/instalador.sh
         state: absent
    - file:
         path: /tmp/ansible.pub
         state: absent

Para facilitar, en la misma carpeta que tengo el playbook creo una carpeta requiere con los archivos que requiere copiar al otro host. Esto es instalador.sh (el script de antes) y ansible.pub (la clave pública).

Ya podemos ejecutar el playbook: $ ansible-playbook copy-ssh.yml El sudo

# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults	env_reset
Defaults	mail_badpass
Defaults	secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

#Host alias specification

# User alias specification

# Cmnd alias specification
Cmnd_Alias      RESTRICTED=/usr/sbin/vipw, /bin/vi /etc/sudoers, /bin/su - root, /bin/su -, /usr/sbin/visudo

# User privilege specification
root	ALL=(ALL:ALL) ALL
ansible ALL = (ALL)ALL, !RESTRICTED

# Allow members of group sudo to execute any command
# %sudo	ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d