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]
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
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