¿Cómo configurar el proceso de firma de clave SSH cada vez que se ejecuta alguna etapa de Ansible? O al menos en algún intervalo.
Tengo una canalización que crea máquinas virtuales con Terraform y luego ejecuta Ansible. En la etapa de inicio de la nube, se crean y firman las claves de host y también se configura la clave de CA de usuario pública. Las autoridades de CA de cliente/host están configuradas/ejecutándose en HashiCorp Vault. Entonces, en este punto, no importa qué máquinas virtuales estén aprovisionadas, puedo acceder mediante SSH a cada una de ellas, ya que tengo la clave pública de CA del host @cert-authority *.example.com ecdsa-sha2-nistp521 AAAAB3NzaC1yc2EAAA...
configurada globalmente en /etc/ssh/ssh_known_hosts
. Todo lo que necesito hacer es crear una nueva clave personal y firmarla porque mi TTL es bastante corto.
Pero esto no funciona en Jenkins. Jenkins almacena todas las claves SSH /var/lib/jenkins/.ssh
y, de forma predeterminada, no hay nada. Si solo por motivos de prueba copio mis claves de usuario personal (o generadas) y el archivo de configuración certificado + ssh en /var/lib/jenkins/.ssh
, entonces Jenkins puede ejecutar Ansible felizmente. Pero no puedo generar, firmar y copiar las claves de Jenkins cada vez que hago alguna confirmación en mi repositorio de infraestructura. Crear certificados de larga duración tampoco huele bien.
¿Cuál es el flujo de trabajo automatizado idiomático para la firma y rotación de claves SSH?
Respuesta1
Enumeraré la solución "MALA" yo solo. Malo, porque la rotación de claves allí es manual y lo más probable es que el TTL sea largo porque somos vagos.
En Vault, debe crear una nueva función SSH "jenkins" con el TTL como52w
Luego, idealmente en el propio host de Jenkins, es necesario crear nuevas claves.
ssh-keygen -t ecdsa -b 521 -f /var/lib/jenkins/.ssh/id_ecdsa -C "jenkins@jenkins-01"
Entonces cántalo por Vault
vault write -field=signed_key ssh-client-signer/sign/jenkinsrole public_key=/var/lib/jenkins/.ssh/id_ecdsa.pub > /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
Esto significa que Vault debería estar en el sistema. ... es un dilema: ¿quieres copiar claves ssh (incluidas las privadas) a través de la red, lo cual huele un poco, o quieres instalar Vault en la máquina Jenkins? Tu decides.
Una vez que tenga id_ecdsa-cert.pub
el certificado, puede inspeccionarlo ssh-keygen -Lf /var/lib/jenkins/.ssh/id_ecdsa-cert.pub
y ver si el período de validez, los principios, etc. son correctos.
Debido a que lo más probable es que haya desviaciones en la infraestructura, almacenar la configuración SSH estáticamente /var/lib/jenkins/.ssh/config
será doloroso.
En su lugar, puede crear ansible-ssh.cfg
un archivo con el contenido como
Host bastion
HostName bastion.example.com
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ecdsa
CertificateFile ~/.ssh/id_ecdsa-cert.pub
Port 22
Protocol 2
User ansible
LogLevel INFO
Este archivo puede (debería) ubicarse junto con el resto del código de Ansible.
Luego, en el ansible.cfg
archivo incluya la estrofa SSH.
[ssh_connection]
ssh_args = -F ./ansible-ssh.cfg
De esta manera, Ansible recogerá configuraciones SSH siempre actualizadas.
Si usa Terraform, entonces es posible actualizar dinámicamente el archivo de configuración SSH para incluir nuevos hosts y demás.
Esta solución no está vinculada únicamente a Vault. Se puede hacer bastante fácilmente con el ssh-keygen
mismo.
ACTUALIZACIÓN: Finalmente terminé con un pequeño script de shell que realiza la autorización mediante aprole y luego firma el certificado. El servicio Systemd y la unidad Timer ejecutan el script de shell que realiza la rotación de certificados todos los días. Entonces, en este punto, Jenkins usa sus propios certificados de usuario nuevos para ejecutar Terraform y Ansible. https://stackoverflow.com/a/65875997/6651080