By: Eliana Perez
Si tienes que desplegar o administrar imágenes de máquinas virtuales con EC2 Image Builder desde novato a experto, este tutorial te va a servir. ¡Guárdalo!
Builder nivel 100
¿Qué es una AMI?
Una AMI (Amazon Machine Image) es una plantilla de virtualización utilizada para crear instancias de máquinas virtuales (VM) en Amazon Web Services (AWS). Una AMI proporciona la información necesaria para lanzar una instancia EC2 (Elastic Compute Cloud) que puede ser una máquina virtual de Windows o Linux, junto con el software preinstalado, configuraciones del sistema o personalizadas y datos asociados.
Con las AMIs podremos desplegar entornos de computación en la nube de manera rápida y consistente.
Hay AMIs ofrecidas por AWS y podemos crear AMIs propias.
En este video se muestra como lanzar una instancia de EC2 con una AMI personalizada. Es el mismo proceso para imágenes de Amazon o de terceros.
https://www.youtube.com/watch?v=Kg1XRjOHqFY
En este video se muestra como lanzar una instancia EC2 con AMI de Windows
https://www.youtube.com/watch?v=DshwCN2twuE
Builder nivel 200
Inicialmente la gestión y actualización de imágenes puede realizarse de forma manual. Pero bien podría automatizarse este proceso utilizando el creador de imágenes EC2 que simplifica la creación, el mantenimiento, la validación, el intercambio y la implementación de imágenes de Linux o Windows para usarlas con Amazon EC2 y en las premisas. Así habrá mayor productividad, soporte integrado y conformidad con la postura de seguridad de la organización.
Este tutorial técnico ayudará con la automatización de la creación de imágenes utilizando EC2 Image Builder
https://www.youtube.com/watch?v=YP2hPUq-VAc&t=15s
Este workshop te llevará paso a paso en la automatización para creación de imágenes en Windows. Aplica igualmente para Linux
https://catalog.us-east-1.prod.workshops.aws/workshops/d6c7ecdc-c75f-4ad1-910f-fdd994cc4aed/en-US
Builder nivel 300
Caso de Uso
El equipo de seguridad, libera una nueva imagen (AMI) con las últimas actualizaciones de seguridad para los sistemas operativos Windows y Linux.
De forma automatizada debe crearse una nueva AMI que, a partir de la AMI entregada por el equipo de seguridad, agregue datos, software pre-instalado y configuraciones de sistema o personalizada, para posteriormente activar el despliegue de un nuevo pipeline que cree las nuevas instancias, con la nueva configuración y apague las instancias que ya no son conformes.
El objetivo es que el equipo de pruebas trabaje en un sistema operativo conforme con la postura de seguridad de la organización, sin perder eficiencia en los recursos, productividad en los equipos o elevar los costos.
Solución
Cada vez que se genera una nueva actualización del equipo de seguridad, se detectará el evento que viene a través de Amazon Eventbridge, automáticamente se creará una nueva versión de la imagen (ya conforme y con las configuraciones necesarias) con EC2 Image Builder y se notificará al pipeline que activará la creación de las nuevas instancias de EC2 sobre las que debe trabajar el equipo de pruebas. Se notificará del proceso a través del canal de slack correspondiente con AWS chatbot.
Arquitectura de la solución
Amazon Eventbridge es un enrutador de eventos que se encarga en este caso de llevar a quien lo solicite la información de que una nueva AMI de seguridad está disponible. Para ello se debe crear la siguiente regla.
En este contexto solo el equipo de seguridad crea las AMIs
1. {
2. "source": ["aws.ec2"],
3. "detail-type": ["EC2 AMI State Change"],
4. "detail": {
5. "State": ["available"]
6. }
7. }
Una Función Lambda se encargará de procesar el evento. Básicamente, una función Lambda es una pieza de código que se ejecuta en la nube de AWS en respuesta a eventos específicos, como cambios en la creación de AMIs, cambio en los datos, solicitudes HTTP, actualizaciones de bases de datos, cargas de archivos, etc. Puedes escribir funciones Lambda en varios lenguajes de programación, como Python, Node.js, Java, C#, entre otros.
La función lambda recibe como entrada el evento que se generó desde Eventbridge con el siguiente payload
1. {
2. "version": "0",
3. "id": "123f456f-7b89-c012-d3cb-e4567de8901e",
4. "detail-type": "EC2 AMI State Change",
5. "source": "aws.ec2",
6. "account": "123456789012",
7. "time": "2024-01-09T14:46:28Z",
8. "region": "us-east-x",
9. "resources": [
10. "arn:aws:ec2:us-east-x::image/ami-1c2df3456fe78901b"
11. ],
12. "detail": {
13. "RequestId": "1a2c345a-fdd6-78b9-01bf-2eedb345678b",
14. "State": "available",
15. "ImageId": "ami-1c2df3456fe78901b",
16. "ErrorMessage": ""
17. }
18. }
La función lambda está hecha en Python por lo que utilizaremos la librería boto3 v 1.34.69. Utilizas el SDK de AWS para Python (Boto3) para crear, configurar y gestionar servicios de AWS, como Amazon Elastic Compute Cloud (Amazon EC2) y Amazon Simple Storage Service (Amazon S3). El SDK proporciona una API orientada a objetos, así como acceso de bajo nivel a los servicios de AWS. Aquí está el enlace que te llevará a la documentación de EC2 Image Builder
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/imagebuilder.html
Retomando EC2 Image Builder
Un pipeline de imagen para automatizar la creación de AMIs, necesita al menos una Receta de Imagen y una Configuración de Infraestructura. Las recetas de Imagen son un recurso versionado que contiene una imagen Padre y unos componentes.
La versión de la receta de imagen debemos obtenerla en la función lambda
La imagen padre es la imagen enviada por el equipo de seguridad de la que debemos tener su ARN.
Los componentes son los bloques de construcción que son consumidos por una receta de imagen, por ejemplo, paquetes para instalación, pasos de endurecimiento de seguridad y pruebas.
Son básicamente 3 pasos
Una receta de imagen es un documento que define los componentes que se van a aplicar a las imágenes base para crear la configuración deseada para la imagen de salida. Luego de crear la receta, no es posible modificarla. Se debe crear una nueva versión para cambiar los componentes.
Los componentes de compilación y las pruebas forman parte de una receta. Los componentes de compilación contienen software, ajustes y configuraciones que se instalan o aplican durante el proceso de creación de imágenes personalizadas. Las pruebas se ejecutan después de crear una imagen personalizada para validar la funcionalidad, la seguridad, el rendimiento, etc.
La creación de estos componentes también puede automatizarse utilizando AWS CloudFormation y entregarlos a la función Lambda como variables de entorno. AWS CloudFormation es un servicio de infraestructura como código (IaC) que te permite modelar, aprovisionar y gestionar fácilmente recursos de AWS y de terceros.
Aquí un ejemplo de como crear una carpeta. Se define como componente, se le da un nombre un sistema operativo, descripción, versión, pasos y acciones a tomar para la creación de esa carpeta.
CreateFolderComponent:
Type: 'AWS::ImageBuilder::Component'
Properties:
Name: 'folderssTestingHubCreation'
Platform: 'Linux'
Version: '1.0.2'
Description: 'This component create a folder called TestingHub in the ubuntu user folder and delete the .m2 folder'
SupportedOsVersions:
- 'Ubuntu 20'
# Require one of 'Data' or 'Uri' for Component template
Data: |
name: CreationOfTestingHubFolder
description: This is to create TestingHub folder on the root path
schemaVersion: 1.0
phases:
- name: build
steps:
- name: CreatingFolderLinux
action: CreateFolder
inputs:
- path: /home/ubuntu/TestingHubDeepak3
- name: DeletingFolderM2
action: DeleteFolder
inputs:
- path: /home/ubuntu/.m2
force: true
Dado que la función lambda donde se va a procesar el evento es stateless, se debe guardar la información de la versión de la receta de imagen en un sitio seguro. AWS proporciona ese sitio en el servicio AWS System Manager Parameter store. El Parameter Store se utiliza comúnmente para almacenar datos de configuración que necesitan ser compartidos entre diferentes servicios o instancias de EC2, como configuraciones de aplicaciones, credenciales, rutas de conexión a bases de datos, etc. Proporciona integraciones con otros servicios de AWS, como AWS Lambda, Amazon ECS, Amazon EC2, entre otros, lo que facilita el acceso seguro a los datos de configuración desde diferentes partes de tu infraestructura.
Ya con los recursos necesarios para crear la receta de imagen procedemos a crear la función Lambda
Lógica de la función Lambda
- Se recibe el evento
- Si el nombre de la ami que esta disponible comienza con un prefijo especifico continuamos
- Se carga en la función la lista de componentes que van a ejecutarse en la receta de imagen
- Se obtiene y actualiza la ultima versión de la receta de Imagen
- Se actualiza esta nueva versión en el pipeline de EC2 Image Builder
- Se crea la nueva imagen
- Se activa el pipeline de creación de la nueva receta de imagen
- Inicia el proceso de notificación con aws chatbot y publica el tópicon con SNS
Cuando se actualiza el ID de la nueva AMI, el pipeline que despliega las instancias EC2 ya conformes, detecta el evento a través de una regla de Eventbridge, activa la ejecución del Pipeline, se crean las nuevas instancias, se apagan las que ya estaban y ya el equipo de pruebas puede continuar sin problema.
Con esta automatización se puede reducir a horas la aplicación de políticas de conformidad, así como la carga operativa necesaria para mantener la postura de seguridad de la organización.
Función Lambda
import json
import boto3
import os
#Boto3 Clients
imageBuilder = boto3.client('imagebuilder')
ec2 = boto3.client('ec2')
ssm = boto3.client('ssm')
#environment variables
testRecipeArn= os.environ['testRecipeArn']
infrastructureConfigurationArn= os.environ['infrastructureConfigurationArn']
imagepipelineArn = os.environ['imagepipelineArn']
ssmPath = os.environ['ssmPath']
components= os.environ['components']
def lambda_handler(event, context):
# Image Id delivers by Event Bridge event
amiId= event['detail']['ImageId']
# Get the name associated with the Ami ID
amiInformation= ec2.describe_images(ImageIds=[ amiId, ],)
amiName= amiInformation['Images'][0]['Name']
# Compare if the name Ami starts with the specific pattern
if amiName.startswith('testRecipe') :
try:
print('Correct Image')
#create components array
componentsRecipe= components.split(',')
component = [{"componentArn": arn} for arn in componentsRecipe]
print(component)
# get Actual version
version = ssm.get_parameter(Name=ssmPath)['Parameter']['Value']
values = version.split('.')
nextVersion = int(values[2]) + 1
# Convert nextVersion to string before concatenating
newValueVersion = values[0]+"."+ values[1]+"."+ str(nextVersion)
print(newValueVersion)
#update new value version
ssm.put_parameter(Name=ssmPath, Value=newValueVersion, Type="String", Overwrite=True)
# Create the new Image Recipe with the new AMI
newImageRecipe = imageBuilder.create_image_recipe(
name='testRecipe',
description='newversion' + newValueVersion,
semanticVersion=newValueVersion,
components=component,
parentImage=amiId
)
# Get the new recipe Arn
newImageRecipeArn = newImageRecipe['imageRecipeArn']
# Update the Image Pipeline with the new Image Recipe
response = imageBuilder.update_image_pipeline(
imagePipelineArn=imagepipelineArn,
description='new version for imagepipeline' + newValueVersion,
imageRecipeArn=newImageRecipeArn,
infrastructureConfigurationArn=infrastructureConfigurationArn
)
except Exception as e:
print("Error:", e)
Template CloudFormation para automatizar todo el proceso
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::Serverless-2016-10-31'
Resources:
# Create an S3 Bucket for logs.
# When deleting the stack, make sure to empty the bucket first.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html
ImageBuilderLogBucket:
Type: AWS::S3::Bucket
# If you want to delete the stack, but keep the bucket, set the DelectionPolicy to Retain.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html
# DeletionPolicy: Retain
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
IgnorePublicAcls: true
BlockPublicPolicy: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
# By default, AWS Services do not have permission to perform actions on your instances. This grants
# AWS Systems Manager (SSM) and EC2 Image Builder the necessary permissions to build an image.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
# https://docs.aws.amazon.com/imagebuilder/latest/userguide/image-builder-setting-up.html
InstanceRole:
Type: AWS::IAM::Role
Metadata:
Comment: Role to be used by instance during image build.
Properties:
ManagedPolicyArns:
- Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore
- Fn::Sub: arn:${AWS::Partition}:iam::aws:policy/EC2InstanceProfileForImageBuilder
AssumeRolePolicyDocument:
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- !Sub 'ec2.${AWS::URLSuffix}'
Version: '2012-10-17'
Path: /executionServiceEC2Role/
# Policy to allow the instance to write to the S3 bucket (via instance role / instance profile).
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html
InstanceRoleLoggingPolicy:
Type: AWS::IAM::Policy
Metadata:
Comment: Allows the instance to save log files to an S3 bucket.
Properties:
PolicyName: ImageBuilderLogBucketPolicy
Roles:
- Ref: InstanceRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- s3:PutObject
Effect: Allow
Resource:
- Fn::Sub:
- arn:${AWS::Partition}:s3:::${BUCKET}/*
- BUCKET:
Ref: ImageBuilderLogBucket
# To pass the InstanceRole to an EC2 instance, we need an InstanceProfile.
# This profile will be used during the image build process.
# https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html
InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /executionServiceEC2Role/
Roles:
- Ref: InstanceRole
# Specifies the infrastructure within which to build and test your image.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-infrastructureconfiguration.html
Ubuntu2004ImageInfrastructureConfiguration:
Type: AWS::ImageBuilder::InfrastructureConfiguration
Properties:
InstanceTypes:
- 'm4.large'
- 'm5.large'
Name: Ubuntu-2004-with-latest-SSM-Agent-Infrastructure-Configuration
InstanceProfileName:
Ref: InstanceProfile
# Specify an S3 bucket and EC2 Image Builder will save logs to the bucket.
Logging:
S3Logs:
S3BucketName:
Ref: ImageBuilderLogBucket
# S3KeyPrefix: 'my-imagebuilder-bucket-prefix'
# If you would like to keep the instance running after a failed build, set TerminateInstanceOnFailure to false.
# TerminateInstanceOnFailure: false
# If you do not have a default VPC or want to use a different VPC, you must specify the subnet ID to use
# SubnetId: 'subnet-id'
# The CloudWatch LogGroup for the image build logs is provided to ensure the LogGroup is cleaned up if the stack is deleted.
Ubuntu2004LogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
LogGroupName: /aws/imagebuilder/Ubuntu-2004-with-latest-SSM-Agent
RetentionInDays: 3
# Recipe which references the latest (x.x.x) version of the Amazon Linux 2 AMI).
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-imagerecipe.html
Ubuntu2004ImageRecipe:
Type: AWS::ImageBuilder::ImageRecipe
Properties:
Name: Ubuntu-2004-with-latest-SSM-Agent
Version: 1.0.1
# ${AWS::Partition} returns the partition where you are running the CloudFormation template. For standard AWS regions, the
# partition is aws. For resources elsewhere, the partition is aws-partitionname. For example, China (Beijing and Ningxia)
# regions use aws-cn and AWS GovCloud (US) regions are aws-us-gov.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
ParentImage:
Fn::Sub: arn:${AWS::Partition}:imagebuilder:${AWS::Region}:aws:image/ubuntu-server-20-lts-x86/x.x.x
Components:
- ComponentArn:
Fn::Sub: arn:aws:imagebuilder:${AWS::Region}:aws:component/amazon-cloudwatch-agent-linux/x.x.x
- ComponentArn:
Fn::Sub: arn:aws:imagebuilder:${AWS::Region}:aws:component/amazon-corretto-11-apt-generic/x.x.x
- ComponentArn:
Fn::Sub: arn:aws:imagebuilder:${AWS::Region}:aws:component/powershell-linux/x.x.x
- ComponentArn: !Ref CreateFolderComponent
- ComponentArn: !Ref MavenInstallationComponent
# Create an SSM Parameter Store entry with our resulting ImageId.
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html
Ubuntu2004WithLatestSSMAgentParameter:
Type: AWS::SSM::Parameter
Properties:
Description: image recipe latest version for image build pipeline
Name: /ec2ImageBuilder/imageRecipeVersion
Type: String
Value: '0.0.1'
ImagePipelineBami:
Type: 'AWS::ImageBuilder::ImagePipeline'
Properties:
Name: 'golden-image-for-BAMI'
Description: 'description'
ImageRecipeArn: !Ref Ubuntu2004ImageRecipe
InfrastructureConfigurationArn: !Ref Ubuntu2004ImageInfrastructureConfiguration
ImageTestsConfiguration:
ImageTestsEnabled: false
TimeoutMinutes: 90
CreateFolderComponent:
Type: 'AWS::ImageBuilder::Component'
Properties:
Name: 'folderssTestingHubCreation'
Platform: 'Linux'
Version: '1.0.2'
Description: 'This component create a folder called TestingHub in the ubuntu user folder and delete the .m2 folder'
SupportedOsVersions:
- 'Ubuntu 20'
# Require one of 'Data' or 'Uri' for Component template
Data: |
name: CreationOfTestingHubFolder
description: This is to create TestingHub folder on the root path
schemaVersion: 1.0
phases:
- name: build
steps:
- name: CreatingFolderLinux
action: CreateFolder
inputs:
- path: /home/ubuntu/TestingHubDeepak3
- name: DeletingFolderM2
action: DeleteFolder
inputs:
- path: /home/ubuntu/.m2
force: true
MavenInstallationComponent:
Type: 'AWS::ImageBuilder::Component'
Properties:
Name: 'MavenComponent'
Platform: 'Linux'
Version: '1.0.0'
Description: 'This component is to install maven'
SupportedOsVersions:
- 'Ubuntu 20'
# Require one of 'Data' or 'Uri' for Component template
Data: |
name: Maven
description: This is to install Maven
schemaVersion: 1.0
phases:
- name: build
steps:
- name: Install_Maven
action: ExecuteBash
inputs:
commands:
- sudo apt update
- sudo apt install maven -y
## Lambdas Event Management
StartImagePipelineLambda:
Type: 'AWS::Serverless::Function'
Properties:
Handler: startImagePipeline.lambda_handler
Runtime: python3.8
# CodeUri: ../functions/startImagePipeline
InlineCode: |
import json
import boto3
import os
#Boto3 Clients
imageBuilder = boto3.client('imagebuilder')
ec2 = boto3.client('ec2')
ssm = boto3.client('ssm')
#environment variables
testRecipeArn= os.environ['testRecipeArn']
infrastructureConfigurationArn= os.environ['infrastructureConfigurationArn']
imagepipelineArn = os.environ['imagepipelineArn']
ssmPath = os.environ['ssmPath']
components= os.environ['components']
def lambda_handler(event, context):
# Image Id delivers by Event Bridge event
amiId= event['detail']['ImageId']
# Get the name associated with the Ami ID
amiInformation= ec2.describe_images(ImageIds=[ amiId, ],)
amiName= amiInformation['Images'][0]['Name']
# Compare if the name Ami starts with the specific pattern
if amiName.startswith('testRecipe') :
try:
print('Correct Image')
#create components array
componentsRecipe= components.split(',')
component = [{"componentArn": arn} for arn in componentsRecipe]
# get Actual version
version = ssm.get_parameter(Name=ssmPath)['Parameter']['Value']
values = version.split('.')
nextVersion = int(values[2]) + 1
# Convert nextVersion to string before concatenating
newValueVersion = values[0]+"."+ values[1]+"."+ str(nextVersion)
print(newValueVersion)
#update new value version
ssm.put_parameter(Name=ssmPath, Value=newValueVersion, Type="String", Overwrite=True)
# Delete the last 5 characters
# modifyVersionImageRecipe = testRecipeArn[:-5]
# actualVersionImageRecipe = modifyVersionImageRecipe + version
# Get the last Image Recipe components
# getImageRecipe= imageBuilder.get_image_recipe(imageRecipeArn=actualVersionImageRecipe)
# components= getImageRecipe['imageRecipe']['components']
# Create the new Image Recipe with the new AMI
newImageRecipe = imageBuilder.create_image_recipe(
name='testRecipe',
description='newversion' + newValueVersion,
semanticVersion=newValueVersion,
components=component,
parentImage=amiId
)
# Get the new recipe Arn
newImageRecipeArn = newImageRecipe['imageRecipeArn']
# Update the Image Pipeline with the new Image Recipe
response = imageBuilder.update_image_pipeline(
imagePipelineArn=imagepipelineArn,
description='new version for imagepipeline' + newValueVersion,
imageRecipeArn=newImageRecipeArn,
infrastructureConfigurationArn=infrastructureConfigurationArn
)
#
# response = imageBuilder.start_image_pipeline_execution(
# imagePipelineArn='arn:aws:imagebuilder:us-east-1:012983038368:image-pipeline/golden-image-for-bami'
# )
# print("Image pipeline execution started successfully.")
# print("Execution ID:", response.get('clientToken'))
except Exception as e:
print("Error:", e)
Description: Lamdba function to trigger Image Build when a new DAMI is created
Environment:
Variables:
testRecipeArn: !Ref 'Ubuntu2004ImageRecipe'
infrastructureConfigurationArn: !Ref 'Ubuntu2004ImageInfrastructureConfiguration'
imagepipelineArn: !Ref 'ImagePipelineBami'
ssmPath: !Ref 'Ubuntu2004WithLatestSSMAgentParameter'
components:
Fn::Sub: arn:aws:imagebuilder:${AWS::Region}:aws:component/amazon-cloudwatch-agent-linux/x.x.x,arn:aws:imagebuilder:${AWS::Region}:aws:component/amazon-corretto-11-apt-generic/x.x.x,${CreateFolderComponent.Arn},${MavenInstallationComponent.Arn}
MemorySize: 128
Timeout: 300
Role: !GetAtt 'StartImagePipelineRole.Arn'
StartImagePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
Policies:
- PolicyName: StartImagePipelineLambdaPolicy
PolicyDocument:
Statement:
- Effect: Allow
Resource: "*"
Action:
- 'ssm:DescribeParameters'
- 'ssm:GetParameter'
- 'ssm:PutParameter'
- 'ssm:GetParameters'
- Effect: Allow
Resource: "*"
Action:
- 'ec2:DescribeImages'
- Effect: Allow
Action:
- 'imagebuilder:GetWorkflow'
- 'imagebuilder:GetComponent'
- 'imagebuilder:TagResource'
- 'imagebuilder:GetImagePipeline'
- 'imagebuilder:GetImageRecipe'
- 'imagebuilder:CreateImageRecipe'
- 'imagebuilder:GetContainerRecipe'
- 'imagebuilder:GetDistributionConfiguration'
- 'imagebuilder:GetImage'
- 'iam:PassRole'
- 'iam:CreateServiceLinkedRole'
- 'imagebuilder:GetInfrastructureConfiguration'
- 'imagebuilder:UpdateImagePipeline'
Resource: "*"
AmiAvailableEventRule:
Type: AWS::Events::Rule
Properties:
Description: "Event rule that captures when a new AMI is available"
State: "ENABLED"
EventPattern:
source:
- aws.ec2
detail-type:
- EC2 AMI State Change
detail:
state:
- available
Targets:
- Arn: !GetAtt 'StartImagePipelineLambda.Arn'
Id: !Ref 'StartImagePipelineLambda'
SlackNotificationJavaPipelinepEventsRulePermissions:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref 'StartImagePipelineLambda'
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt 'AmiAvailableEventRule.Arn'
######## AWS CHATBOT NOTIFICATIONS RESOURCES #########
AwsChatbotNotification:
Type: AWS::Chatbot::SlackChannelConfiguration
Properties:
ConfigurationName: codePipelineStartnotificationJavaCode
IamRoleArn: !GetAtt 'AwsChatBotIamRole.Arn'
LoggingLevel: 'ERROR'
SlackChannelId: "xxxxxxxxxxxx" #!Ref SlackChannelId
SlackWorkspaceId: "xxxxxxxxxx" #!Ref SlackWorkspaceId
SnsTopicArns:
- !Ref 'AwsChatbotSnsTopicLambda'
AwsChatbotSnsTopicLambda:
Type: AWS::SNS::Topic
Properties:
TopicName: AwsChatbotSnsTopicLambda
KmsMasterKeyId:
Ref: SNSKmsAlias
SNSKmsAlias:
Type: 'AWS::KMS::Alias'
Properties:
AliasName:
'Fn::Join':
- '-'
- - alias/SnsServiceKmsKey
- 'Fn::Sub': '${AWS::StackName}'
TargetKeyId:
Ref: SNSKmsKey
SNSKmsKey:
Type: 'AWS::KMS::Key'
Properties:
Description: This is used to encrypt-decrypt the SNS.
EnableKeyRotation: 'true'
KeyPolicy:
Statement:
- Action:
- 'kms:Create*'
- 'kms:Describe*'
- 'kms:Enable*'
- 'kms:List*'
- 'kms:Put*'
- 'kms:Update*'
- 'kms:Revoke*'
- 'kms:Disable*'
- 'kms:Get*'
- 'kms:Delete*'
- 'kms:ScheduleKeyDeletion'
- 'kms:CancelKeyDeletion'
- 'kms:UntagResource'
- 'kms:TagResource'
Effect: Allow
Principal:
AWS:
- 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:root'
Resource: '*'
Sid: Allow access for Key Administrators
- Action:
- 'kms:Encrypt'
- 'kms:Decrypt'
- 'kms:ReEncrypt*'
- 'kms:GenerateDataKey*'
- 'kms:DescribeKey'
Effect: Allow
Principal:
AWS:
- 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:root'
- 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/imagebuilder.amazonaws.com/AWSServiceRoleForImageBuilder'
Service: cloudwatch.amazonaws.com
Resource: '*'
Sid: Allow use of the key
- Action:
- 'kms:CreateGrant'
- 'kms:ListGrants'
- 'kms:RevokeGrant'
Condition:
Bool:
'kms:GrantIsForAWSResource': true
Effect: Allow
Principal:
AWS:
- 'Fn::Sub': 'arn:aws:iam::${AWS::AccountId}:root'
Resource: '*'
Sid: Allow attachment of persistent resources
- Effect: Allow
Principal:
Service: events.amazonaws.com
Action:
- 'kms:Decrypt'
- 'kms:GenerateDataKey*'
Resource: '*'
- Action:
- 'kms:GenerateDataKey*'
- 'kms:Decrypt'
Condition:
StringEquals:
'kms:ViaService': sns.us-east-1.amazonaws.com
Effect: Allow
Principal:
Service: codestar-notifications.amazonaws.com
Resource: '*'
Sid: Allow codepiple to push message to encrypted sns
Version: '2012-10-17'
EventTopicPolicy:
Type: 'AWS::SNS::TopicPolicy'
Properties:
PolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- codestar-notifications.amazonaws.com
Action:
- 'sns:Publish'
Resource: !Ref AwsChatbotSnsTopicLambda
Topics:
- !Ref AwsChatbotSnsTopicLambda
AwsChatBotIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action:
- sts:AssumeRole
Policies:
- PolicyName: AwsChatBotIamPolicyName
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- s3:PutObject*
Resource:
- arn:aws:s3:::bucket-name/*
Effect: Allow
Condition:
StringLike:
s3:x-amz-acl: bucket-owner-full-control
- Action:
- s3:GetBucketAcl
Resource:
- arn:aws:s3:::bucketname
Effect: Allow
- Effect: Allow
Action:
- kms:Encrypt
- kms:Decrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
- kms:DescribeKey
Resource:
- !GetAtt SNSKmsKey.Arn
Espero te sea de mucha utilidad! Disfrutalo!
Top comments (0)