# EC2 Image Builder Construct Library

<!--BEGIN STABILITY BANNER-->---


![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)

> The APIs of higher level constructs in this module are experimental and under active development.
> They are subject to non-backward compatible changes or removal in any future version. These are
> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be
> announced in the release notes. This means that while you may use them, you may need to update
> your source code when upgrading to a newer version of this package.

---
<!--END STABILITY BANNER-->

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.

## README

[Amazon EC2 Image Builder](https://docs.aws.amazon.com/imagebuilder/latest/userguide/what-is-image-builder.html) is a
fully managed AWS service that helps you automate the creation, management, and deployment of customized, secure, and
up-to-date server images. You can use Image Builder to create Amazon Machine Images (AMIs) and container images for use
across AWS Regions.

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. It allows you to define
Image Builder pipelines, images, recipes, components, workflows, and lifecycle policies.
A component defines the sequence of steps required to customize an instance during image creation (build component) or
test an instance launched from the created image (test component). Components are created from declarative YAML or JSON
documents that describe runtime configuration for building, validating, or testing instances. Components are included
when added to the image recipe or container recipe for an image build.

EC2 Image Builder supports AWS-managed components for common tasks, AWS Marketplace components, and custom components
that you create. Components run during specific workflow phases: build and validate phases during the build stage, and
test phase during the test stage.

### Image Pipeline

An image pipeline provides the automation framework for building secure AMIs and container images. The pipeline
orchestrates the entire image creation process by combining an image recipe or container recipe with infrastructure
configuration and distribution configuration. Pipelines can run on a schedule or be triggered manually, and they manage
the build, test, and distribution phases automatically.

#### Image Pipeline Basic Usage

Create a simple AMI pipeline with just an image recipe:

```python
image_recipe = imagebuilder.ImageRecipe(self, "MyImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64")
)

image_pipeline = imagebuilder.ImagePipeline(self, "MyImagePipeline",
    recipe=example_image_recipe
)
```

Create a simple container pipeline with just a container recipe:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "MyContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)

container_pipeline = imagebuilder.ImagePipeline(self, "MyContainerPipeline",
    recipe=example_container_recipe
)
```

#### Image Pipeline Scheduling

##### Manual Pipeline Execution

Create a pipeline that runs only when manually triggered:

```python
manual_pipeline = imagebuilder.ImagePipeline(self, "ManualPipeline",
    image_pipeline_name="my-manual-pipeline",
    description="Pipeline triggered manually for production builds",
    recipe=example_image_recipe
)

# Grant Lambda function permission to trigger the pipeline
manual_pipeline.grant_start_execution(lambda_role)
```

##### Automated Pipeline Scheduling

Schedule a pipeline to run automatically using cron expressions:

```python
weekly_pipeline = imagebuilder.ImagePipeline(self, "WeeklyPipeline",
    image_pipeline_name="weekly-build-pipeline",
    recipe=example_image_recipe,
    schedule=imagebuilder.ImagePipelineSchedule(
        expression=events.Schedule.cron(
            minute="0",
            hour="6",
            week_day="MON"
        )
    )
)
```

Use rate expressions for regular intervals:

```python
daily_pipeline = imagebuilder.ImagePipeline(self, "DailyPipeline",
    recipe=example_container_recipe,
    schedule=imagebuilder.ImagePipelineSchedule(
        expression=events.Schedule.rate(Duration.days(1))
    )
)
```

##### Pipeline Schedule Configuration

Configure advanced scheduling options:

```python
advanced_schedule_pipeline = imagebuilder.ImagePipeline(self, "AdvancedSchedulePipeline",
    recipe=example_image_recipe,
    schedule=imagebuilder.ImagePipelineSchedule(
        expression=events.Schedule.rate(Duration.days(7)),
        # Only trigger when dependencies are updated (new base images, components, etc.)
        start_condition=imagebuilder.ScheduleStartCondition.EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE,
        # Automatically disable after 3 consecutive failures
        auto_disable_failure_count=3
    ),
    # Start enabled
    status=imagebuilder.ImagePipelineStatus.ENABLED
)
```

#### Image Pipeline Configuration

##### Infrastructure and Distribution in Image Pipelines

Configure custom infrastructure and distribution settings:

```python
infrastructure_configuration = imagebuilder.InfrastructureConfiguration(self, "Infrastructure",
    infrastructure_configuration_name="production-infrastructure",
    instance_types=[
        ec2.InstanceType.of(ec2.InstanceClass.COMPUTE7_INTEL, ec2.InstanceSize.LARGE)
    ],
    vpc=vpc,
    subnet_selection=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS)
)

distribution_configuration = imagebuilder.DistributionConfiguration(self, "Distribution")
distribution_configuration.add_ami_distributions(
    ami_name="production-ami-{{ imagebuilder:buildDate }}",
    ami_target_account_ids=["123456789012", "098765432109"]
)

production_pipeline = imagebuilder.ImagePipeline(self, "ProductionPipeline",
    recipe=example_image_recipe,
    infrastructure_configuration=infrastructure_configuration,
    distribution_configuration=distribution_configuration
)
```

##### Pipeline Logging Configuration

Configure custom CloudWatch log groups for pipeline and image logs:

```python
pipeline_log_group = logs.LogGroup(self, "PipelineLogGroup",
    log_group_name="/custom/imagebuilder/pipeline/logs",
    retention=logs.RetentionDays.ONE_MONTH
)

image_log_group = logs.LogGroup(self, "ImageLogGroup",
    log_group_name="/custom/imagebuilder/image/logs",
    retention=logs.RetentionDays.ONE_WEEK
)

logged_pipeline = imagebuilder.ImagePipeline(self, "LoggedPipeline",
    recipe=example_image_recipe,
    image_pipeline_log_group=pipeline_log_group,
    image_log_group=image_log_group
)
```

##### Workflow Integration in Image Pipelines

Use AWS-managed workflows for common pipeline phases:

```python
workflow_pipeline = imagebuilder.ImagePipeline(self, "WorkflowPipeline",
    recipe=example_image_recipe,
    workflows=[imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.build_image(self, "BuildWorkflow")), imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.test_image(self, "TestWorkflow"))
    ]
)
```

For container pipelines, use container-specific workflows:

```python
container_workflow_pipeline = imagebuilder.ImagePipeline(self, "ContainerWorkflowPipeline",
    recipe=example_container_recipe,
    workflows=[imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.build_container(self, "BuildContainer")), imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.test_container(self, "TestContainer")), imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.distribute_container(self, "DistributeContainer"))
    ]
)
```

##### Advanced Features in Image Pipelines

Configure image scanning for container pipelines:

```python
scanning_repository = ecr.Repository(self, "ScanningRepo")

scanned_container_pipeline = imagebuilder.ImagePipeline(self, "ScannedContainerPipeline",
    recipe=example_container_recipe,
    image_scanning_enabled=True,
    image_scanning_ecr_repository=scanning_repository,
    image_scanning_ecr_tags=["security-scan", "latest"]
)
```

Control metadata collection and testing:

```python
controlled_pipeline = imagebuilder.ImagePipeline(self, "ControlledPipeline",
    recipe=example_image_recipe,
    enhanced_image_metadata_enabled=True,  # Collect detailed OS and package info
    image_tests_enabled=False
)
```

#### Image Pipeline Events

##### Pipeline Event Handling

Handle specific pipeline events:

```python
# Monitor CVE detection
example_pipeline.on_cVEDetected("CVEAlert",
    target=targets.SnsTopic(topic)
)

# Handle pipeline auto-disable events
example_pipeline.on_image_pipeline_auto_disabled("PipelineDisabledAlert",
    target=targets.LambdaFunction(lambda_function)
)
```

#### Importing Image Pipelines

Reference existing pipelines created outside CDK:

```python
# Import by name
existing_pipeline_by_name = imagebuilder.ImagePipeline.from_image_pipeline_name(self, "ExistingPipelineByName", "my-existing-pipeline")

# Import by ARN
existing_pipeline_by_arn = imagebuilder.ImagePipeline.from_image_pipeline_arn(self, "ExistingPipelineByArn", "arn:aws:imagebuilder:us-east-1:123456789012:image-pipeline/imported-pipeline")

# Grant permissions to imported pipelines
automation_role = iam.Role(self, "AutomationRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)

existing_pipeline_by_name.grant_start_execution(automation_role)
existing_pipeline_by_arn.grant_read(lambda_role)
```

### Image

An image is the output resource created by Image Builder, consisting of an AMI or container image plus metadata such as
version, platform, and creation details. Images are used as base images for future builds and can be shared across AWS
accounts. While images are the output from image pipeline executions, they can also be created in an ad-hoc manner
outside a pipeline, defined as a standalone resource.

#### Image Basic Usage

Create a simple AMI-based image from an image recipe:

```python
image_recipe = imagebuilder.ImageRecipe(self, "MyImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64")
)

ami_image = imagebuilder.Image(self, "MyAmiImage",
    recipe=image_recipe
)
```

Create a simple container image from a container recipe:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "MyContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)

container_image = imagebuilder.Image(self, "MyContainerImage",
    recipe=container_recipe
)
```

#### AWS-Managed Images

##### Pre-defined OS Images

Use AWS-managed images for common operating systems:

```python
# Amazon Linux 2023 AMI for x86_64
amazon_linux2023_ami = imagebuilder.AmazonManagedImage.amazon_linux2023(self, "AmazonLinux2023",
    image_type=imagebuilder.ImageType.AMI,
    image_architecture=imagebuilder.ImageArchitecture.X86_64
)

# Ubuntu 22.04 AMI for ARM64
ubuntu2204_ami = imagebuilder.AmazonManagedImage.ubuntu_server2204(self, "Ubuntu2204",
    image_type=imagebuilder.ImageType.AMI,
    image_architecture=imagebuilder.ImageArchitecture.ARM64
)

# Windows Server 2022 Full AMI
windows2022_ami = imagebuilder.AmazonManagedImage.windows_server2022_full(self, "Windows2022",
    image_type=imagebuilder.ImageType.AMI,
    image_architecture=imagebuilder.ImageArchitecture.X86_64
)

# Use as base image in recipe
managed_image_recipe = imagebuilder.ImageRecipe(self, "ManagedImageRecipe",
    base_image=amazon_linux2023_ami.to_base_image()
)
```

##### Custom AWS-Managed Images

Import AWS-managed images by name or attributes:

```python
# Import by name
managed_image_by_name = imagebuilder.AmazonManagedImage.from_amazon_managed_image_name(self, "ManagedImageByName", "amazon-linux-2023-x86")

# Import by attributes with specific version
managed_image_by_attributes = imagebuilder.AmazonManagedImage.from_amazon_managed_image_attributes(self, "ManagedImageByAttributes",
    image_name="ubuntu-server-22-lts-x86",
    image_version="2024.11.25"
)
```

#### Image Configuration

##### Infrastructure and Distribution in Images

Configure custom infrastructure and distribution settings:

```python
infrastructure_configuration = imagebuilder.InfrastructureConfiguration(self, "Infrastructure",
    infrastructure_configuration_name="production-infrastructure",
    instance_types=[
        ec2.InstanceType.of(ec2.InstanceClass.COMPUTE7_INTEL, ec2.InstanceSize.LARGE)
    ],
    vpc=vpc,
    subnet_selection=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS)
)

distribution_configuration = imagebuilder.DistributionConfiguration(self, "Distribution")
distribution_configuration.add_ami_distributions(
    ami_name="production-ami-{{ imagebuilder:buildDate }}",
    ami_target_account_ids=["123456789012", "098765432109"]
)

production_image = imagebuilder.Image(self, "ProductionImage",
    recipe=example_image_recipe,
    infrastructure_configuration=infrastructure_configuration,
    distribution_configuration=distribution_configuration
)
```

##### Logging Configuration

Configure custom CloudWatch log groups for image builds:

```python
log_group = logs.LogGroup(self, "ImageLogGroup",
    log_group_name="/custom/imagebuilder/image/logs",
    retention=logs.RetentionDays.ONE_MONTH
)

logged_image = imagebuilder.Image(self, "LoggedImage",
    recipe=example_image_recipe,
    log_group=log_group
)
```

##### Workflow Integration in Images

Use workflows for custom build, test, and distribution processes:

```python
image_with_workflows = imagebuilder.Image(self, "ImageWithWorkflows",
    recipe=example_image_recipe,
    workflows=[imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.build_image(self, "BuildWorkflow")), imagebuilder.WorkflowConfiguration(workflow=imagebuilder.AmazonManagedWorkflow.test_image(self, "TestWorkflow"))
    ]
)
```

##### Advanced Features in Images

Configure image scanning, metadata collection, and testing:

```python
scanning_repository = ecr.Repository(self, "ScanningRepository")

advanced_container_image = imagebuilder.Image(self, "AdvancedContainerImage",
    recipe=example_container_recipe,
    image_scanning_enabled=True,
    image_scanning_ecr_repository=scanning_repository,
    image_scanning_ecr_tags=["security-scan", "latest"],
    enhanced_image_metadata_enabled=True,
    image_tests_enabled=False
)
```

#### Importing Images

Reference existing images created outside CDK:

```python
# Import by name
existing_image_by_name = imagebuilder.Image.from_image_name(self, "ExistingImageByName", "my-existing-image")

# Import by ARN
existing_image_by_arn = imagebuilder.Image.from_image_arn(self, "ExistingImageByArn", "arn:aws:imagebuilder:us-east-1:123456789012:image/imported-image/1.0.0")

# Import by attributes
existing_image_by_attributes = imagebuilder.Image.from_image_attributes(self, "ExistingImageByAttributes",
    image_name="shared-base-image",
    image_version="2024.11.25"
)

# Grant permissions to imported images
role = iam.Role(self, "ImageAccessRole",
    assumed_by=iam.ServicePrincipal("lambda.amazonaws.com")
)

existing_image_by_name.grant_read(role)
existing_image_by_arn.grant(role, "imagebuilder:GetImage", "imagebuilder:ListImagePackages")
```

### Image Recipe

#### Image Recipe Basic Usage

Create an image recipe with the required base image:

```python
image_recipe = imagebuilder.ImageRecipe(self, "MyImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64")
)
```

#### Image Recipe Base Images

To create a recipe, you have to select a base image to build and customize from. This base image can be referenced from
various sources, such as from SSM parameters, AWS Marketplace products, and AMI IDs directly.

##### SSM Parameters

Using SSM parameter references:

```python
image_recipe = imagebuilder.ImageRecipe(self, "SsmImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64")
)

# Using an SSM parameter construct
parameter = ssm.StringParameter.from_string_parameter_name(self, "BaseImageParameter", "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base")
windows_recipe = imagebuilder.ImageRecipe(self, "WindowsImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter(parameter)
)
```

##### AMI IDs

When you have a specific AMI to use:

```python
image_recipe = imagebuilder.ImageRecipe(self, "AmiImageRecipe",
    base_image=imagebuilder.BaseImage.from_ami_id("ami-12345678")
)
```

##### Marketplace Images

For marketplace base images:

```python
image_recipe = imagebuilder.ImageRecipe(self, "MarketplaceImageRecipe",
    base_image=imagebuilder.BaseImage.from_marketplace_product_id("prod-1234567890abcdef0")
)
```

#### Image Recipe Components

Components from various sources, such as custom-owned, AWS-owned, or AWS Marketplace-owned, can optionally be included
in recipes. For parameterized components, you are able to provide the parameters to use in the recipe, which will be
applied during the image build when executing components.

##### Custom Components in Image Recipes

Add your own components to the recipe:

```python
custom_component = imagebuilder.Component(self, "MyComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_json_object({
        "schema_version": imagebuilder.ComponentSchemaVersion.V1_0,
        "phases": [{
            "name": imagebuilder.ComponentPhaseName.BUILD,
            "steps": [{
                "name": "install-app",
                "action": imagebuilder.ComponentAction.EXECUTE_BASH,
                "inputs": {
                    "commands": ["yum install -y my-application"]
                }
            }
            ]
        }
        ]
    })
)

image_recipe = imagebuilder.ImageRecipe(self, "ComponentImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64"),
    components=[imagebuilder.ComponentConfiguration(
        component=custom_component
    )
    ]
)
```

##### AWS-Managed Components in Image Recipes

Use pre-built AWS components:

```python
image_recipe = imagebuilder.ImageRecipe(self, "AmazonManagedImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64"),
    components=[imagebuilder.ComponentConfiguration(
        component=imagebuilder.AmazonManagedComponent.update_os(self, "UpdateOS",
            platform=imagebuilder.Platform.LINUX
        )
    ), imagebuilder.ComponentConfiguration(
        component=imagebuilder.AmazonManagedComponent.aws_cli_v2(self, "AwsCli",
            platform=imagebuilder.Platform.LINUX
        )
    )
    ]
)
```

##### Component Parameters in Image Recipes

Pass parameters to components that accept them:

```python
parameterized_component = imagebuilder.Component.from_component_name(self, "ParameterizedComponent", "my-parameterized-component")

image_recipe = imagebuilder.ImageRecipe(self, "ParameterizedImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64"),
    components=[imagebuilder.ComponentConfiguration(
        component=parameterized_component,
        parameters={
            "environment": imagebuilder.ComponentParameterValue.from_string("production"),
            "version": imagebuilder.ComponentParameterValue.from_string("1.0.0")
        }
    )
    ]
)
```

#### Image Recipe Configuration

##### Block Device Configuration

Configure storage for the build instance:

```python
image_recipe = imagebuilder.ImageRecipe(self, "BlockDeviceImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64"),
    block_devices=[ec2.BlockDevice(
        device_name="/dev/sda1",
        volume=ec2.BlockDeviceVolume.ebs(100,
            encrypted=True,
            volume_type=ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3
        )
    )
    ]
)
```

##### AMI Tagging

Tag the output AMI:

```python
image_recipe = imagebuilder.ImageRecipe(self, "TaggedImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64"),
    ami_tags={
        "Environment": "Production",
        "Application": "WebServer",
        "Owner": "DevOps Team"
    }
)
```

### Container Recipe

A container recipe is similar to an image recipe but specifically for container images. It defines the base container
image and components applied to produce the desired configuration for the output container image. Container recipes work
with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points.

#### Container Recipe Basic Usage

Create a container recipe with the required base image and target repository:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "MyContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)
```

#### Container Recipe Base Images

##### DockerHub Images

Using public Docker Hub images:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "DockerHubContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)
```

##### ECR Images

Using images from your own ECR repositories:

```python
source_repo = ecr.Repository.from_repository_name(self, "SourceRepo", "my-base-image")
target_repo = ecr.Repository.from_repository_name(self, "TargetRepo", "my-container-repo")

container_recipe = imagebuilder.ContainerRecipe(self, "EcrContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_ecr(source_repo, "1.0.0"),
    target_repository=imagebuilder.Repository.from_ecr(target_repo)
)
```

##### ECR Public Images

Using images from Amazon ECR Public:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "EcrPublicContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_ecr_public("amazonlinux", "amazonlinux", "2023"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)
```

#### Container Recipe Components

##### Custom Components in Container Recipes

Add your own components to the container recipe:

```python
custom_component = imagebuilder.Component(self, "MyComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_json_object({
        "schema_version": imagebuilder.ComponentSchemaVersion.V1_0,
        "phases": [{
            "name": imagebuilder.ComponentPhaseName.BUILD,
            "steps": [{
                "name": "install-app",
                "action": imagebuilder.ComponentAction.EXECUTE_BASH,
                "inputs": {
                    "commands": ["yum install -y my-container-application"]
                }
            }
            ]
        }
        ]
    })
)

container_recipe = imagebuilder.ContainerRecipe(self, "ComponentContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo")),
    components=[imagebuilder.ComponentConfiguration(
        component=custom_component
    )
    ]
)
```

##### AWS-Managed Components in Container Recipes

Use pre-built AWS components:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "AmazonManagedContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo")),
    components=[imagebuilder.ComponentConfiguration(
        component=imagebuilder.AmazonManagedComponent.update_os(self, "UpdateOS",
            platform=imagebuilder.Platform.LINUX
        )
    ), imagebuilder.ComponentConfiguration(
        component=imagebuilder.AmazonManagedComponent.aws_cli_v2(self, "AwsCli",
            platform=imagebuilder.Platform.LINUX
        )
    )
    ]
)
```

#### Container Recipe Configuration

##### Custom Dockerfile

Provide your own Dockerfile template:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "CustomDockerfileContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo")),
    dockerfile=imagebuilder.DockerfileData.from_inline("""
        FROM {{{ imagebuilder:parentImage }}}
        CMD ["echo", "Hello, world!"]
        {{{ imagebuilder:environments }}}
        {{{ imagebuilder:components }}}
        """)
)
```

##### Instance Configuration

Configure the build instance:

```python
container_recipe = imagebuilder.ContainerRecipe(self, "InstanceConfigContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo")),
    # Custom ECS-optimized AMI for building
    instance_image=imagebuilder.ContainerInstanceImage.from_ssm_parameter_name("/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id"),
    # Additional storage for build process
    instance_block_devices=[ec2.BlockDevice(
        device_name="/dev/xvda",
        volume=ec2.BlockDeviceVolume.ebs(50,
            encrypted=True,
            volume_type=ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3
        )
    )
    ]
)
```

### Component

A component defines the sequence of steps required to customize an instance during image creation (build component) or
test an instance launched from the created image (test component). Components are created from declarative YAML or JSON
documents that describe runtime configuration for building, validating, or testing instances. Components are included
when added to the image recipe or container recipe for an image build.

EC2 Image Builder supports AWS-managed components for common tasks, AWS Marketplace components, and custom components
that you create. Components run during specific workflow phases: build and validate phases during the build stage, and
test phase during the test stage.

#### Basic Component Usage

Create a component with the required properties: platform and component data.

```python
component = imagebuilder.Component(self, "MyComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_json_object({
        "schema_version": imagebuilder.ComponentSchemaVersion.V1_0,
        "phases": [{
            "name": imagebuilder.ComponentPhaseName.BUILD,
            "steps": [{
                "name": "install-app",
                "action": imagebuilder.ComponentAction.EXECUTE_BASH,
                "inputs": {
                    "commands": ["echo \"Installing my application...\"", "yum update -y"]
                }
            }
            ]
        }
        ]
    })
)
```

#### Component Data Sources

##### Inline Component Data

Use `ComponentData.fromInline()` for existing YAML/JSON definitions:

```python
component = imagebuilder.Component(self, "InlineComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_inline("""
        name: my-component
        schemaVersion: 1.0
        phases:
          - name: build
            steps:
              - name: update-os
                action: ExecuteBash
                inputs:
                  commands: ['yum update -y']
        """)
)
```

##### JSON Object Component Data

Most developer-friendly approach using objects:

```python
component = imagebuilder.Component(self, "JsonComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_json_object({
        "schema_version": imagebuilder.ComponentSchemaVersion.V1_0,
        "phases": [{
            "name": imagebuilder.ComponentPhaseName.BUILD,
            "steps": [{
                "name": "configure-app",
                "action": imagebuilder.ComponentAction.CREATE_FILE,
                "inputs": {
                    "path": "/etc/myapp/config.json",
                    "content": "{\"env\": \"production\"}"
                }
            }
            ]
        }
        ]
    })
)
```

##### Structured Component Document

For type-safe, CDK-native definitions with enhanced properties like `timeout` and `onFailure`.

###### Defining a component step

You can define steps in the component which will be executed in order when the component is applied:

```python
step = imagebuilder.ComponentDocumentStep(
    name="configure-app",
    action=imagebuilder.ComponentAction.CREATE_FILE,
    inputs=imagebuilder.ComponentStepInputs.from_object({
        "path": "/etc/myapp/config.json",
        "content": "{\"env\": \"production\"}"
    })
)
```

###### Defining a component phase

Phases group steps together, which run in sequence when building, validating or testing in the component:

```python
phase = imagebuilder.ComponentDocumentPhase(
    name=imagebuilder.ComponentPhaseName.BUILD,
    steps=[imagebuilder.ComponentDocumentStep(
        name="configure-app",
        action=imagebuilder.ComponentAction.CREATE_FILE,
        inputs=imagebuilder.ComponentStepInputs.from_object({
            "path": "/etc/myapp/config.json",
            "content": "{\"env\": \"production\"}"
        })
    )
    ]
)
```

###### Defining a component

The component data defines all steps across the provided phases to execute during the build:

```python
component = imagebuilder.Component(self, "StructuredComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_component_document_json_object(
        schema_version=imagebuilder.ComponentSchemaVersion.V1_0,
        phases=[imagebuilder.ComponentDocumentPhase(
            name=imagebuilder.ComponentPhaseName.BUILD,
            steps=[imagebuilder.ComponentDocumentStep(
                name="install-with-timeout",
                action=imagebuilder.ComponentAction.EXECUTE_BASH,
                timeout=Duration.minutes(10),
                on_failure=imagebuilder.ComponentOnFailure.CONTINUE,
                inputs=imagebuilder.ComponentStepInputs.from_object({
                    "commands": ["./install-script.sh"]
                })
            )
            ]
        )
        ]
    )
)
```

##### S3 Component Data

For those components you want to upload or have uploaded to S3:

```python
# Upload a local file
component_from_asset = imagebuilder.Component(self, "AssetComponent",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_asset(self, "ComponentAsset", "./my-component.yml")
)

# Reference an existing S3 object
bucket = s3.Bucket.from_bucket_name(self, "ComponentBucket", "my-components-bucket")
component_from_s3 = imagebuilder.Component(self, "S3Component",
    platform=imagebuilder.Platform.LINUX,
    data=imagebuilder.ComponentData.from_s3(bucket, "components/my-component.yml")
)
```

#### Encrypt component data with a KMS key

You can encrypt component data with a KMS key, so that only principals with access to decrypt with the key are able to
access the component data.

```python
component = imagebuilder.Component(self, "EncryptedComponent",
    platform=imagebuilder.Platform.LINUX,
    kms_key=kms.Key(self, "ComponentKey"),
    data=imagebuilder.ComponentData.from_json_object({
        "schema_version": imagebuilder.ComponentSchemaVersion.V1_0,
        "phases": [{
            "name": imagebuilder.ComponentPhaseName.BUILD,
            "steps": [{
                "name": "secure-setup",
                "action": imagebuilder.ComponentAction.EXECUTE_BASH,
                "inputs": {
                    "commands": ["echo \"This component data is encrypted with KMS\""]
                }
            }
            ]
        }
        ]
    })
)
```

#### AWS-Managed Components

AWS provides a collection of managed components for common tasks:

```python
# Install AWS CLI v2
aws_cli_component = imagebuilder.AmazonManagedComponent.aws_cli_v2(self, "AwsCli",
    platform=imagebuilder.Platform.LINUX
)

# Update the operating system
update_component = imagebuilder.AmazonManagedComponent.update_os(self, "UpdateOS",
    platform=imagebuilder.Platform.LINUX
)

# Reference any AWS-managed component by name
custom_aws_component = imagebuilder.AmazonManagedComponent.from_amazon_managed_component_name(self, "CloudWatchAgent", "amazon-cloudwatch-agent-linux")
```

#### AWS Marketplace Components

You can reference AWS Marketplace components using the marketplace component name and its product ID:

```python
marketplace_component = imagebuilder.AwsMarketplaceComponent.from_aws_marketplace_component_attributes(self, "MarketplaceComponent",
    component_name="my-marketplace-component",
    marketplace_product_id="prod-1234567890abcdef0"
)
```

### Infrastructure Configuration

Infrastructure configuration defines the compute resources and environment settings used during the image building
process. This includes instance types, IAM instance profile, VPC settings, subnets, security groups, SNS topics for
notifications, logging configuration, and troubleshooting settings like whether to terminate instances on failure or
keep them running for debugging. These settings are applied to builds when included in an image or an image pipeline.

```python
infrastructure_configuration = imagebuilder.InfrastructureConfiguration(self, "InfrastructureConfiguration",
    infrastructure_configuration_name="test-infrastructure-configuration",
    description="An Infrastructure Configuration",
    # Optional - instance types to use for build/test
    instance_types=[
        ec2.InstanceType.of(ec2.InstanceClass.STANDARD7_INTEL, ec2.InstanceSize.LARGE),
        ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.LARGE)
    ],
    # Optional - create an instance profile with necessary permissions
    instance_profile=iam.InstanceProfile(self, "InstanceProfile",
        instance_profile_name="test-instance-profile",
        role=iam.Role(self, "InstanceProfileRole",
            assumed_by=iam.ServicePrincipal.from_static_service_principle_name("ec2.amazonaws.com"),
            managed_policies=[
                iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMManagedInstanceCore"),
                iam.ManagedPolicy.from_aws_managed_policy_name("EC2InstanceProfileForImageBuilder")
            ]
        )
    ),
    # Use VPC network configuration
    vpc=vpc,
    subnet_selection=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
    security_groups=[ec2.SecurityGroup.from_security_group_id(self, "SecurityGroup", vpc.vpc_default_security_group)],
    key_pair=ec2.KeyPair.from_key_pair_name(self, "KeyPair", "imagebuilder-instance-key-pair"),
    terminate_instance_on_failure=True,
    # Optional - IMDSv2 settings
    http_tokens=imagebuilder.HttpTokens.REQUIRED,
    http_put_response_hop_limit=1,
    # Optional - publish image completion messages to an SNS topic
    notification_topic=sns.Topic.from_topic_arn(self, "Topic",
        self.format_arn(service="sns", resource="image-builder-topic")),
    # Optional - log settings. Logging is enabled by default
    logging=imagebuilder.InfrastructureConfigurationLogging(
        s3_bucket=s3.Bucket.from_bucket_name(self, "LogBucket", f"imagebuilder-logging-{Aws.ACCOUNT_ID}"),
        s3_key_prefix="imagebuilder-logs"
    ),
    # Optional - host placement settings
    ec2_instance_availability_zone=Stack.of(self).availability_zones[0],
    ec2_instance_host_id=dedicated_host.attr_host_id,
    ec2_instance_tenancy=imagebuilder.Tenancy.HOST,
    resource_tags={
        "Environment": "production"
    }
)
```

### Distribution Configuration

Distribution configuration defines how and where your built images are distributed after successful creation. For AMIs,
this includes target AWS Regions, KMS encryption keys, account sharing permissions, License Manager associations, and
launch template configurations. For container images, it specifies the target Amazon ECR repositories across regions.
A distribution configuration can be associated with an image or an image pipeline to define these distribution settings
for image builds.

#### AMI Distributions

AMI distributions can be defined to copy and modify AMIs in different accounts and regions, and apply them to launch
templates, SSM parameters, etc.:

```python
distribution_configuration = imagebuilder.DistributionConfiguration(self, "DistributionConfiguration",
    distribution_configuration_name="test-distribution-configuration",
    description="A Distribution Configuration",
    ami_distributions=[imagebuilder.AmiDistribution(
        # Distribute AMI to us-east-2 and publish the AMI ID to an SSM parameter
        region="us-east-2",
        ssm_parameters=[imagebuilder.SSMParameterConfigurations(
            parameter=ssm.StringParameter.from_string_parameter_attributes(self, "CrossRegionParameter",
                parameter_name="/imagebuilder/ami",
                force_dynamic_reference=True
            )
        )
        ]
    )
    ]
)

# For AMI-based image builds - add an AMI distribution in the current region
distribution_configuration.add_ami_distributions(
    ami_name="imagebuilder-{{ imagebuilder:buildDate }}",
    ami_description="Build AMI",
    ami_kms_key=kms.Key.from_lookup(self, "ComponentKey", alias_name="alias/distribution-encryption-key"),
    # Copy the AMI to different accounts
    ami_target_account_ids=["123456789012", "098765432109"],
    # Add launch permissions on the AMI
    ami_launch_permission=imagebuilder.AmiLaunchPermission(
        organization_arns=[
            self.format_arn(region="", service="organizations", resource="organization", resource_name="o-1234567abc")
        ],
        organizational_unit_arns=[
            self.format_arn(
                region="",
                service="organizations",
                resource="ou",
                resource_name="o-1234567abc/ou-a123-b4567890"
            )
        ],
        is_public_user_group=True,
        account_ids=["234567890123"]
    ),
    # Attach tags to the AMI
    ami_tags={
        "Environment": "production",
        "Version": "{{ imagebuilder:buildVersion }}"
    },
    # Optional - publish the distributed AMI ID to an SSM parameter
    ssm_parameters=[imagebuilder.SSMParameterConfigurations(
        parameter=ssm.StringParameter.from_string_parameter_attributes(self, "Parameter",
            parameter_name="/imagebuilder/ami",
            force_dynamic_reference=True
        )
    ), imagebuilder.SSMParameterConfigurations(
        ami_account="098765432109",
        data_type=ssm.ParameterDataType.TEXT,
        parameter=ssm.StringParameter.from_string_parameter_attributes(self, "CrossAccountParameter",
            parameter_name="imagebuilder-prod-ami",
            force_dynamic_reference=True
        )
    )
    ],
    # Optional - create a new launch template version with the distributed AMI ID
    launch_templates=[imagebuilder.LaunchTemplateConfiguration(
        launch_template=ec2.LaunchTemplate.from_launch_template_attributes(self, "LaunchTemplate",
            launch_template_id="lt-1234"
        ),
        set_default_version=True
    ), imagebuilder.LaunchTemplateConfiguration(
        account_id="123456789012",
        launch_template=ec2.LaunchTemplate.from_launch_template_attributes(self, "CrossAccountLaunchTemplate",
            launch_template_id="lt-5678"
        ),
        set_default_version=True
    )
    ],
    # Optional - enable Fast Launch on an imported launch template
    fast_launch_configurations=[imagebuilder.FastLaunchConfiguration(
        enabled=True,
        launch_template=ec2.LaunchTemplate.from_launch_template_attributes(self, "FastLaunchLT",
            launch_template_name="fast-launch-lt"
        ),
        max_parallel_launches=10,
        target_snapshot_count=2
    )
    ],
    # Optional - license configurations to apply to the AMI
    license_configuration_arns=["arn:aws:license-manager:us-west-2:123456789012:license-configuration:lic-abcdefghijklmnopqrstuvwxyz"
    ]
)
```

#### Container Distributions

##### Container repositories

Container distributions can be configured to distribute to ECR repositories:

```python
ecr_repository = ecr.Repository.from_repository_name(self, "ECRRepository", "my-repo")
image_builder_repository = imagebuilder.Repository.from_ecr(ecr_repository)
```

##### Defining a container distribution

You can configure the container repositories as well as the description and tags applied to the distributed container
images:

```python
ecr_repository = ecr.Repository.from_repository_name(self, "ECRRepository", "my-repo")
container_repository = imagebuilder.Repository.from_ecr(ecr_repository)
container_distribution_configuration = imagebuilder.DistributionConfiguration(self, "ContainerDistributionConfiguration")

container_distribution_configuration.add_container_distributions(
    container_repository=container_repository,
    container_description="Test container image",
    container_tags=["latest", "latest-1.0"]
)
```

### Workflow

Workflows define the sequence of steps that Image Builder performs during image creation. There are three workflow
types: BUILD (image building), TEST (testing images), and DISTRIBUTION (distributing container images).

#### Basic Workflow Usage

Create a workflow with the required properties: workflow type and workflow data.

```python
workflow = imagebuilder.Workflow(self, "MyWorkflow",
    workflow_type=imagebuilder.WorkflowType.BUILD,
    data=imagebuilder.WorkflowData.from_json_object({
        "schema_version": imagebuilder.WorkflowSchemaVersion.V1_0,
        "steps": [{
            "name": "LaunchBuildInstance",
            "action": imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "wait_for": "ssmAgent"
            }
        }, {
            "name": "ExecuteComponents",
            "action": imagebuilder.WorkflowAction.EXECUTE_COMPONENTS,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "instance_id": "i-123"
            }
        }, {
            "name": "CreateImage",
            "action": imagebuilder.WorkflowAction.CREATE_IMAGE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "instance_id": "i-123"
            }
        }, {
            "name": "TerminateInstance",
            "action": imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.CONTINUE,
            "inputs": {
                "instance_id": "i-123"
            }
        }
        ],
        "outputs": [{
            "name": "ImageId",
            "value": "$.stepOutputs.CreateImage.imageId"
        }
        ]
    })
)
```

#### Workflow Data Sources

##### Inline Workflow Data

Use `WorkflowData.fromInline()` for existing YAML/JSON definitions:

```python
workflow = imagebuilder.Workflow(self, "InlineWorkflow",
    workflow_type=imagebuilder.WorkflowType.TEST,
    data=imagebuilder.WorkflowData.from_inline("""
        schemaVersion: 1.0
        steps:
          - name: LaunchTestInstance
            action: LaunchInstance
            onFailure: Abort
            inputs:
              waitFor: ssmAgent
          - name: RunTests
            action: RunCommand
            onFailure: Abort
            inputs:
              instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"
              commands: ['./run-tests.sh']
          - name: TerminateTestInstance
            action: TerminateInstance
            onFailure: Continue
            inputs:
              instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"
        """)
)
```

##### JSON Object Workflow Data

Most developer-friendly approach using JavaScript objects:

```python
workflow = imagebuilder.Workflow(self, "JsonWorkflow",
    workflow_type=imagebuilder.WorkflowType.BUILD,
    data=imagebuilder.WorkflowData.from_json_object({
        "schema_version": imagebuilder.WorkflowSchemaVersion.V1_0,
        "steps": [{
            "name": "LaunchBuildInstance",
            "action": imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "wait_for": "ssmAgent"
            }
        }, {
            "name": "ExecuteComponents",
            "action": imagebuilder.WorkflowAction.EXECUTE_COMPONENTS,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "instance_id": "i-123"
            }
        }, {
            "name": "CreateImage",
            "action": imagebuilder.WorkflowAction.CREATE_IMAGE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "instance_id": "i-123"
            }
        }, {
            "name": "TerminateInstance",
            "action": imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.CONTINUE,
            "inputs": {
                "instance_id": "i-123"
            }
        }
        ],
        "outputs": [{
            "name": "ImageId",
            "value": "$.stepOutputs.CreateImage.imageId"
        }
        ]
    })
)
```

##### S3 Workflow Data

For those workflows you want to upload or have uploaded to S3:

```python
# Upload a local file
workflow_from_asset = imagebuilder.Workflow(self, "AssetWorkflow",
    workflow_type=imagebuilder.WorkflowType.BUILD,
    data=imagebuilder.WorkflowData.from_asset(self, "WorkflowAsset", "./my-workflow.yml")
)

# Reference an existing S3 object
bucket = s3.Bucket.from_bucket_name(self, "WorkflowBucket", "my-workflows-bucket")
workflow_from_s3 = imagebuilder.Workflow(self, "S3Workflow",
    workflow_type=imagebuilder.WorkflowType.BUILD,
    data=imagebuilder.WorkflowData.from_s3(bucket, "workflows/my-workflow.yml")
)
```

#### Encrypt workflow data with a KMS key

You can encrypt workflow data with a KMS key, so that only principals with access to decrypt with the key are able to
access the workflow data.

```python
workflow = imagebuilder.Workflow(self, "EncryptedWorkflow",
    workflow_type=imagebuilder.WorkflowType.BUILD,
    kms_key=kms.Key(self, "WorkflowKey"),
    data=imagebuilder.WorkflowData.from_json_object({
        "schema_version": imagebuilder.WorkflowSchemaVersion.V1_0,
        "steps": [{
            "name": "LaunchBuildInstance",
            "action": imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "wait_for": "ssmAgent"
            }
        }, {
            "name": "CreateImage",
            "action": imagebuilder.WorkflowAction.CREATE_IMAGE,
            "on_failure": imagebuilder.WorkflowOnFailure.ABORT,
            "inputs": {
                "instance_id": "i-123"
            }
        }, {
            "name": "TerminateInstance",
            "action": imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
            "on_failure": imagebuilder.WorkflowOnFailure.CONTINUE,
            "inputs": {
                "instance_id": "i-123"
            }
        }
        ],
        "outputs": [{
            "name": "ImageId",
            "value": "$.stepOutputs.CreateImage.imageId"
        }
        ]
    })
)
```

#### AWS-Managed Workflows

AWS provides a collection of workflows for common scenarios:

```python
# Build workflows
build_image_workflow = imagebuilder.AmazonManagedWorkflow.build_image(self, "BuildImage")
build_container_workflow = imagebuilder.AmazonManagedWorkflow.build_container(self, "BuildContainer")

# Test workflows
test_image_workflow = imagebuilder.AmazonManagedWorkflow.test_image(self, "TestImage")
test_container_workflow = imagebuilder.AmazonManagedWorkflow.test_container(self, "TestContainer")

# Distribution workflows
distribute_container_workflow = imagebuilder.AmazonManagedWorkflow.distribute_container(self, "DistributeContainer")
```

### Lifecycle Policy

Lifecycle policies help you manage the retention and cleanup of Image Builder resources automatically. These policies
define rules for deprecating or deleting old image versions, managing AMI snapshots, and controlling resource costs by
removing unused images based on age, count, or other criteria.

#### Lifecycle Policy Basic Usage

Create a lifecycle policy to automatically delete old AMI images after 30 days:

```python
lifecycle_policy = imagebuilder.LifecyclePolicy(self, "MyLifecyclePolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(age_filter=imagebuilder.LifecyclePolicyAgeFilter(age=Duration.days(30)))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Environment": "development"}
    )
)
```

Create a lifecycle policy to keep only the 10 most recent container images:

```python
container_lifecycle_policy = imagebuilder.LifecyclePolicy(self, "ContainerLifecyclePolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.CONTAINER_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(count_filter=imagebuilder.LifecyclePolicyCountFilter(count=10))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Application": "web-app"}
    )
)
```

#### Lifecycle Policy Resource Selection

##### Tag-Based Resource Selection

Apply lifecycle policies to images with specific tags:

```python
tag_based_policy = imagebuilder.LifecyclePolicy(self, "TagBasedPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(age_filter=imagebuilder.LifecyclePolicyAgeFilter(age=Duration.days(90)))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={
            "Environment": "staging",
            "Team": "backend"
        }
    )
)
```

##### Recipe-Based Resource Selection

Apply lifecycle policies to specific image or container recipes:

```python
image_recipe = imagebuilder.ImageRecipe(self, "MyImageRecipe",
    base_image=imagebuilder.BaseImage.from_ssm_parameter_name("/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64")
)

container_recipe = imagebuilder.ContainerRecipe(self, "MyContainerRecipe",
    base_image=imagebuilder.BaseContainerImage.from_docker_hub("amazonlinux", "latest"),
    target_repository=imagebuilder.Repository.from_ecr(
        ecr.Repository.from_repository_name(self, "Repository", "my-container-repo"))
)

recipe_based_policy = imagebuilder.LifecyclePolicy(self, "RecipeBasedPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(count_filter=imagebuilder.LifecyclePolicyCountFilter(count=5))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        recipes=[image_recipe, container_recipe]
    )
)
```

#### Lifecycle Policy Rules

##### Age-Based Rules

Delete images older than a specific time period:

```python
age_based_policy = imagebuilder.LifecyclePolicy(self, "AgeBasedPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(
            type=imagebuilder.LifecyclePolicyActionType.DELETE,
            include_amis=True,
            include_snapshots=True
        ),
        filter=imagebuilder.LifecyclePolicyFilter(
            age_filter=imagebuilder.LifecyclePolicyAgeFilter(
                age=Duration.days(60),
                retain_at_least=3
            )
        )
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Environment": "testing"}
    )
)
```

##### Count-Based Rules

Keep only a specific number of the most recent images:

```python
count_based_policy = imagebuilder.LifecyclePolicy(self, "CountBasedPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.CONTAINER_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(count_filter=imagebuilder.LifecyclePolicyCountFilter(count=15))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Application": "microservice"}
    )
)
```

##### Multiple Lifecycle Rules

Implement a graduated approach with multiple actions:

```python
graduated_policy = imagebuilder.LifecyclePolicy(self, "GraduatedPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        # First: Deprecate images after 30 days
        action=imagebuilder.LifecyclePolicyAction(
            type=imagebuilder.LifecyclePolicyActionType.DEPRECATE,
            include_amis=True
        ),
        filter=imagebuilder.LifecyclePolicyFilter(
            age_filter=imagebuilder.LifecyclePolicyAgeFilter(
                age=Duration.days(30),
                retain_at_least=5
            )
        )
    ), imagebuilder.LifecyclePolicyDetail(
        # Second: Disable images after 60 days
        action=imagebuilder.LifecyclePolicyAction(
            type=imagebuilder.LifecyclePolicyActionType.DISABLE,
            include_amis=True
        ),
        filter=imagebuilder.LifecyclePolicyFilter(
            age_filter=imagebuilder.LifecyclePolicyAgeFilter(
                age=Duration.days(60),
                retain_at_least=3
            )
        )
    ), imagebuilder.LifecyclePolicyDetail(
        # Finally: Delete images after 90 days
        action=imagebuilder.LifecyclePolicyAction(
            type=imagebuilder.LifecyclePolicyActionType.DELETE,
            include_amis=True,
            include_snapshots=True
        ),
        filter=imagebuilder.LifecyclePolicyFilter(
            age_filter=imagebuilder.LifecyclePolicyAgeFilter(
                age=Duration.days(90),
                retain_at_least=1
            )
        )
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Environment": "production"}
    )
)
```

#### Lifecycle Policy Exclusion Rules

##### AMI Exclusion Rules

Exclude specific AMIs from lifecycle actions based on various criteria:

```python
exclude_amis_policy = imagebuilder.LifecyclePolicy(self, "ExcludeAmisPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(age_filter=imagebuilder.LifecyclePolicyAgeFilter(age=Duration.days(30))),
        exclusion_rules=imagebuilder.LifecyclePolicyExclusionRules(
            ami_exclusion_rules=imagebuilder.LifecyclePolicyAmiExclusionRules(
                is_public=True,  # Exclude public AMIs
                last_launched=Duration.days(7),  # Exclude AMIs launched in last 7 days
                regions=["us-west-2", "eu-west-1"],  # Exclude AMIs in specific regions
                shared_accounts=["123456789012"],  # Exclude AMIs shared with specific accounts
                tags={
                    "Protected": "true",
                    "Environment": "production"
                }
            )
        )
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Team": "infrastructure"}
    )
)
```

##### Image Exclusion Rules

Exclude Image Builder images with protective tags:

```python
exclude_images_policy = imagebuilder.LifecyclePolicy(self, "ExcludeImagesPolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.CONTAINER_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(count_filter=imagebuilder.LifecyclePolicyCountFilter(count=20)),
        exclusion_rules=imagebuilder.LifecyclePolicyExclusionRules(
            image_exclusion_rules=imagebuilder.LifecyclePolicyImageExclusionRules(
                tags={
                    "DoNotDelete": "true",
                    "Critical": "baseline"
                }
            )
        )
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Application": "frontend"}
    )
)
```

#### Advanced Lifecycle Configuration

##### Custom Execution Roles

Provide your own IAM execution role with specific permissions:

```python
execution_role = iam.Role(self, "LifecycleExecutionRole",
    assumed_by=iam.ServicePrincipal("imagebuilder.amazonaws.com"),
    managed_policies=[
        iam.ManagedPolicy.from_aws_managed_policy_name("service-role/EC2ImageBuilderLifecycleExecutionPolicy")
    ]
)

custom_role_policy = imagebuilder.LifecyclePolicy(self, "CustomRolePolicy",
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    execution_role=execution_role,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(age_filter=imagebuilder.LifecyclePolicyAgeFilter(age=Duration.days(45)))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Environment": "development"}
    )
)
```

##### Lifecycle Policy Status

Control whether the lifecycle policy is active:

```python
disabled_policy = imagebuilder.LifecyclePolicy(self, "DisabledPolicy",
    lifecycle_policy_name="my-disabled-policy",
    description="A lifecycle policy that is temporarily disabled",
    status=imagebuilder.LifecyclePolicyStatus.DISABLED,
    resource_type=imagebuilder.LifecyclePolicyResourceType.AMI_IMAGE,
    details=[imagebuilder.LifecyclePolicyDetail(
        action=imagebuilder.LifecyclePolicyAction(type=imagebuilder.LifecyclePolicyActionType.DELETE),
        filter=imagebuilder.LifecyclePolicyFilter(age_filter=imagebuilder.LifecyclePolicyAgeFilter(age=Duration.days(30)))
    )
    ],
    resource_selection=imagebuilder.LifecyclePolicyResourceSelection(
        tags={"Environment": "testing"}
    ),
    tags={
        "Owner": "DevOps",
        "CostCenter": "Engineering"
    }
)
```

##### Importing Lifecycle Policies

Reference lifecycle policies created outside CDK:

```python
# Import by name
imported_by_name = imagebuilder.LifecyclePolicy.from_lifecycle_policy_name(self, "ImportedByName", "existing-lifecycle-policy")

# Import by ARN
imported_by_arn = imagebuilder.LifecyclePolicy.from_lifecycle_policy_arn(self, "ImportedByArn", "arn:aws:imagebuilder:us-east-1:123456789012:lifecycle-policy/my-policy")

imported_by_name.grant_read(lambda_role)
imported_by_arn.grant(lambda_role, "imagebuilder:UpdateLifecyclePolicy")
```
