Daniel López Azaña

Tema

Social Media

Blog

GNU/Linux, Open Source, Cloud Computing, DevOps y más...

Cómo compartir una AMI entre 2 cuentas de AWS

Sin categorizar
Copy-AMI-using-customer-managed-key-for-encryption

Si tenemos una AMI que no está encriptada podremos compartirla con otra cuenta de forma directa sin hacer nada especial. Pero si la AMI está cifrada, la cosa se complica, ya que la cuenta de destino no dispondrá de la clave de cifrado para poder descifrar sus snapshots y no podremos compartirla.

Por ello, si necesitamos compartir una AMI cifrada de una instancia EC2 de una cuenta a otra en AWS llevaremos a cabo el siguiente procedimiento:

1.- Crear una nueva clave gestionada por el cliente (Customer managed key) en el servicio AWS KMS siguiendo los siguientes pasos:

Si necesitamos añadir permisos especiales a la clave KMS, podremos editar directamente su código JSON. Por ejemplo, en el siguiente ejemplo añadimos permisos para usar la clave para encriptar y desencriptar con ella a un role IAM específico. En el ejemplo la cuenta aaaaaaaaaaaa es la origen y la bbbbbbbbbbbbb es la de destino:

{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aaaaaaaaaaaa:root",
                    "arn:aws:iam::bbbbbbbbbbbbb:role/bbbbbbbbbbbbb-admin"                    
                ]
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aaaaaaaaaaaa:user/username_with_admin_privileges_from_aaaaaaaaaaaa_account"
                ]
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion",
                "kms:ReplicateKey",
                "kms:UpdatePrimaryRegion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aaaaaaaaaaaa:root",
                    "arn:aws:iam::aaaaaaaaaaaa:role/aaaaaaaaaaaa-admin",
                    "arn:aws:iam::aaaaaaaaaaaa:user/username_with_admin_privileges_from_aaaaaaaaaaaa_account",
                    "arn:aws:iam::bbbbbbbbbbbb:root",
                    "arn:aws:iam::bbbbbbbbbbbb:role/bbbbbbbbbbbb-admin"
                ]
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow attachment of persistent resources",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::aaaaaaaaaaaa:root",
                    "arn:aws:iam::aaaaaaaaaaaa:role/aaaaaaaaaaaa-admin",
                    "arn:aws:iam::aaaaaaaaaaaa:user/username_with_admin_privileges_from_aaaaaaaaaaaa_account",
                    "arn:aws:iam::bbbbbbbbbbbb:root",
                    "arn:aws:iam::bbbbbbbbbbbb:role/bbbbbbbbbbbb-admin"
                ]
            },
            "Action": [
                "kms:CreateGrant",
                "kms:ListGrants",
                "kms:RevokeGrant"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "kms:GrantIsForAWSResource": "true"
                }
            }
        }
    ]
}

2.- Hacer una copia de la AMI que queramos compartir con la otra cuenta de AWS, pero usando la nueva clave de cifrado creada en el punto anterior. Para ello iremos a la sección AMI’s del servicio EC2 de Amazon, seleccionaremos la AMI que queramos y con el botón derecho seleccionaremos la opción «Copiar AMI». Como se puede ver en la captura siguiente, seleccionaremos la clave KMS multi-account-shared-aws-key que acabamos de crear:

Copy-AMI-using-customer-managed-key-for-encryption

3.- Una vez copiada, modificaremos los permisos de la nueva AMI para añadir el identificador de la cuenta con la que queremos compartirla (botón Add account ID):

Edit-AMI-permissions-to-add-shared-account

4.- Tras esto, si accedemos a la consola de la cuenta de destino, ya podremos ver la AMI compartida en el listado de AMI’s. Pero es importante seleccionar las imágenes privadas, ya que si no no se mostrará al sólo mostrarse por defecto las imágenes de las cuales somos propietarios. Pero en este caso el propietario es la cuenta origen.

Shared-AMI-from-destination-account

5.- Por último, si queremos conservar una copia de la AMI en la cuenta de destino cifrada con sus propias claves y que en el propietario aparezca el ID de dicha cuenta de destino, realizaremos una copia de la misma igual que hicimos en el punto 2, pero esta vez seleccionando la clave de cifrado por defecto de la cuenta de destino o alguna otra que hayamos creado.

Daniel López Azaña

Sobre el autor

Daniel López Azaña

Emprendedor tecnológico y arquitecto cloud con más de 20 años de experiencia transformando infraestructuras y automatizando procesos.

Especialista en integración de IA/LLM, desarrollo con Rust y Python, y arquitectura AWS & GCP. Mente inquieta, generador de ideas y apasionado por la innovación tecnológica y la IA.

Artículos relacionados

Script para cambiar automáticamente todos los volúmenes gp2 a gp3 con aws-cli

Script para cambiar automáticamente todos los volúmenes gp2 a gp3 con aws-cli

El pasado diciembre Amazon anunció sus nuevos volúmenes EBS gp3, los cuales ofrecen mejores prestaciones y un ahorro en el coste del 20% respecto a los que se venían utilizando hasta ahora, los gp2. Pues bien, tras probar satisfactoriamente estos nuevos volúmenes en varios clientes, no puedo hacer otra cosa más que recomendar su utilización, pues son todo ventajas y en estos 2 meses y medio que han transcurrido desde el anuncio no he apreciado ningún problema ni efecto secundario.

16 de febrero de 2021
AWS security groups

Cómo actualizar automáticamente todos nuestros grupos de seguridad EC2 de AWS cuando nuestra IP dinámica cambia

Uno de los mayores fastidios cuando trabajamos con AWS y nuestra conexión a Internet tiene IP dinámica es que cuándo ésta cambia, automáticamente dejamos de tener acceso a todos los servidores y servicios que habíamos protegido mediante un grupo de seguridad EC2 cuyas reglas sólo permiten el tráfico a ciertas IP’s específicas en lugar de abrir las conexiones a todo el mundo (0.0.0.0/0).Ciertamente lo más sencillo es siempre indicar en el grupo de seguridad que permitimos el tráfico en un puerto a todo el mundo, de modo que aunque tengamos IP dinámica en nuestra conexión a Internet siempre podremos continuar accediendo aunque ésta cambie. Pero abrir el tráfico a un puerto a todo el mundo no es la forma correcta de proceder desde el punto de vista de la seguridad, pues entonces cualquier atacante podrá tener acceso a ese puerto sin restricciones, y eso no es lo que queremos.

12 de enero de 2021
Diagrama de una instancia EC2 con múltiples interfaces de red compartiendo la misma subred dentro de la misma zona de disponibilidad en AWS

Cómo conectar en Linux 2 interfaces de red a la misma subred de AWS

El siguiente procedimiento describe cómo permitir en Linux el uso simultáneo de 2 interfaces de red conectadas a la misma subred de AWS y que la comunicación funcione tanto a nivel interno (máquinas en la misma subred) como externo (ambas interfaces visibles desde Internet). Esto puede ser útil por ejemplo cuando queremos que una misma instancia aloje un servidor web que sirva peticiones http ó https y al mismo tiempo disponga de un servidor de websockets ws:// o wss:// que escuche en el mismo puerto 80 ó 443 respectivamente. Aunque hay otras formas de conseguirlo como configurar Nginx para que sea capaz de discriminar el tráfico web (http) del tráfico de websockets (ws) y actuar como proxy para redirigir las peticiones correspondientes al servidor de websockets, esta otra solución que planteo me parece más sencilla y en cierta medida más eficiente porque no es necesario redirigir el tráfico, lo cual siempre introducirá una pequeña latencia, y permite mantener ambos servidores totalmente independientes dentro de la misma máquina. La única pega es que necesitaremos asignar 2 direcciones IP elásticas (Elastic IP) a la misma máquina en lugar de 1, pero al mismo tiempo esto nos aportará mayor flexibilidad a la hora de establecer reglas en los grupos de seguridad o en las reglas NAT de la subred.

6 de octubre de 2017

Comentarios

Sé el primero en comentar

Enviar comentario