Necesito activar un montón de cajas EC2 para diferentes usuarios. Cada usuario debe estar aislado de todos los demás, por lo que cada caja EC2 necesita su propia clave SSH.
¿Cuál es la mejor manera de lograr esto en Terraform?
Casi todas las instrucciones que he encontrado me piden que cree manualmente una clave SSH y la pegue en un script de terraformación.
(Malos) Ejemplos:
Dado que necesito generar mediante programación claves únicas para muchos usuarios, esto no es práctico.
Esto no parece un caso de uso difícil, pero no puedo encontrar documentos en ninguna parte.
En un apuro, podía generar scripts de Terraform e inyectar claves SSH sobre la marcha usando Bash. Pero eso parece ser exactamente el tipo de cosas que se supone que debe hacer Terraform en primer lugar.
Terraform puede generar claves privadas SSL/SSH utilizando el recurso tls_private_key .
Entonces, si quisiera generar claves SSH sobre la marcha, podría hacer algo como esto:
variable "key_name" {} resource "tls_private_key" "example" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "generated_key" { key_name = var.key_name public_key = tls_private_key.example.public_key_openssh } data "aws_ami" "ubuntu" { most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] } filter { name = "virtualization-type" values = ["hvm"] } owners = ["099720109477"] # Canonical } resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = "t2.micro" key_name = aws_key_pair.generated_key.key_name tags { Name = "HelloWorld" } } Esto creará un par de claves SSH que vive en el estado de Terraform (no se escribe en el disco en archivos que no sean los que se pueden hacer para el propio estado de Terraform cuando no se usa el estado remoto), crea un par de claves de AWS basado en la clave pública y luego crea una instancia de Ubuntu 14.04 donde se puede acceder al usuario de ubuntu con la clave privada que se generó.
Luego, tendría que extraer la clave privada del archivo de estado y proporcionarla a los usuarios. Podría usar una output para escupir esto directamente a la salida estándar cuando se aplica Terraform.
Debo señalar aquí que pasar claves privadas generalmente es una mala idea y sería mucho mejor que los desarrolladores creen sus propios pares de claves y le proporcionen la clave pública que usted (o ellos) pueden usar para generar un par de claves de AWS (potencialmente usando el recurso aws_key_pair como se usó en el ejemplo anterior) que luego se puede especificar al crear instancias.
En general, solo usaría algo como la forma anterior de generar claves SSH para entornos de desarrollo muy temporales que está controlando, por lo que no necesita pasar claves privadas a nadie. Si necesita pasar claves privadas a las personas, deberá asegurarse de hacerlo en un canal seguro y de asegurarse de que el estado de Terraform (que contiene la clave privada en texto sin formato) también esté protegido adecuadamente.
El siguiente código crea myKey para AWS y myKey.pem para your computer y myKey y myKey.pem tienen las mismas claves privadas. ( Terraform v0.15.4 )
resource "tls_private_key" "pk" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "kp" { key_name = "myKey" # Create "myKey" to AWS!! public_key = tls_private_key.pk.public_key_openssh provisioner "local-exec" { # Create "myKey.pem" to your computer!! command = "echo '${tls_private_key.pk.private_key_pem}' > ./myKey.pem" } } No olvide hacer que myKey.pem sea legible solo ejecutando el siguiente código antes de ssh a su instancia ec2.
chmod 400 myKey.pemDe lo contrario, se produce el siguiente error.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0664 for 'myKey.pem' are too open. It is required that your private key files are NOT accessible by others. This private key will be ignored. Load key "myKey.pem": bad permissions ubuntu@35.72.30.251: Permission denied (publickey).Una extensión de las respuestas anteriores, no cabe en un comentario:
Para escribir la clave generada en un archivo privado con los permisos correctos:
resource "local_file" "pem_file" { filename = pathexpand("~/.ssh/${local.ssh_key_name}.pem") file_permission = "600" directory_permission = "700" sensitive_content = tls_private_key.ssh.private_key_pem }Sin embargo, una desventaja de guardar un archivo como este es que la ruta terminará en el estado de terraformación. No es un gran problema si solo se aplica CI/CD y/o una persona que ejecuta la aplicación terraform, pero si hay más "aplicadores", el tfstate se actualizará cada vez que se ejecute una aplicación diferente de la última aplicación. Esto creará algo de ruido de "actualización". No es un gran problema, pero es algo a tener en cuenta.
Una alternativa que evita eso es guardar el archivo pem en AWS Secrets Manager, o encriptado en S3, y proporcionar un comando para buscarlo y crear un archivo local.