Published: 2026-06-01 ‱ Updated: 2026-06-17

AWS DevOps Masterclass: Orchestrating Continuous Delivery with AWS CodePipeline

A comprehensive, enterprise-grade guide to designing, building, securing, and scaling automated continuous delivery pipelines on AWS.


Table of Contents


1. Introduction to Enterprise Continuous Delivery

Continuous Delivery (CD) is the backbone of modern software engineering. It represents the capability to deploy software updates of all types—including features, configuration changes, bug fixes, and experiments—into production or into the hands of users safely, quickly, and sustainably. In an enterprise environment, continuous delivery cannot be a simple script that copies files to a server. It must be a highly resilient, secure, audited, and observable process.

On AWS, the primary tool for orchestrating this process is AWS CodePipeline. AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates. It models, visualizes, and automates the steps required to release your software.

Featured Snippet Definition:
AWS CodePipeline is a fully managed, continuous delivery service that automates the release pipelines for application and infrastructure updates. It operates as a workflow engine that coordinates the flow of software changes through various phases—such as Source, Build, Test, and Deploy—integrating with AWS services (like CodeCommit, CodeBuild, CodeDeploy, ECS, EKS, and CloudFormation) as well as third-party tools (like GitHub, Jenkins, and Snyk) to deliver software fast, securely, and with high predictability.

Unlike traditional self-hosted CI/CD servers, AWS CodePipeline is serverless. This means you do not need to provision, configure, patch, or scale any underlying infrastructure to manage your release workflows. It scales dynamically with your deployment frequency, provides native integrations with AWS Identity and Access Management (IAM), and natively encrypts artifacts at rest using AWS Key Management Service (KMS).

In this guide, we will move beyond basic "Hello World" pipelines. We will explore how to architect production-grade pipelines that span multiple AWS accounts, cross physical AWS regions, implement zero-downtime deployment strategies, and enforce strict enterprise compliance rules.

2. What You Will Learn

By the end of this comprehensive guide, you will be able to:

  • Architect multi-account, cross-region continuous delivery pipelines using AWS CodePipeline.
  • Implement infrastructure as code (IaC) definitions for pipelines using both Terraform and AWS CloudFormation.
  • Understand and configure complex IAM permission models, cross-account assume-roles, and KMS key policies for secure artifact sharing.
  • Design advanced deployment strategies including Blue/Green, Canary, and rolling updates across ECS, EKS, Lambda, and EC2.
  • Implement real-time monitoring, alerting, and event-driven automation for your pipeline lifecycle events.
  • Diagnose and remediate complex pipeline failures, including artifact decryption errors, IAM role mismatches, and deployment timeouts.

3. Prerequisites

To get the most out of this masterclass lesson, you should possess the following foundational knowledge:

  • AWS Core Services: Familiarity with IAM, S3, KMS, CloudWatch, and EventBridge.
  • CI/CD Concepts: Understanding of version control (Git), continuous integration (compiling, linting, testing), and continuous deployment.
  • Infrastructure as Code (IaC): Basic knowledge of Terraform syntax or AWS CloudFormation template structures.
  • Containerization: Understanding of Docker, Amazon ECS, or Amazon EKS is highly beneficial for the deployment sections of this guide.

If you need a refresher on basic AWS DevOps concepts, we highly recommend reading our previous lesson on Introduction to AWS CodePipeline before continuing.

4. AWS CodePipeline Architecture & Core Concepts

To build reliable pipelines, you must master the building blocks of AWS CodePipeline. The service operates on a structured hierarchical model consisting of Pipelines, Stages, Actions, Transitions, Artifacts, and Variables.

Pipelines

A pipeline is a workflow construct that describes how software changes go through a release process. It is uniquely named within an AWS account and region, and it is associated with a service role that gives CodePipeline permission to orchestrate the resources involved in the workflow.

Stages

A pipeline is divided into logical segments called stages. Examples of stages include Source, Build, Staging-Deploy, Manual-Approval, and Production-Deploy. Every stage must contain at least one action, and all actions within a stage must complete successfully before the pipeline execution can progress to the next stage.

Actions

An action is a highly specific task performed on your application code or infrastructure in a given stage. Actions can run sequentially or in parallel. You configure execution order using the RunOrder parameter. For example, you can run three unit test suites in parallel by assigning them all a RunOrder of 1, and then run an integration test suite only after they succeed by assigning it a RunOrder of 2.

Transitions

Stages are connected by transitions, represented visually as arrows between stages. Transitions can be enabled or disabled. Disabling a transition prevents executions from progressing past that point. This is an excellent operational tool when you need to freeze deployments to an environment (e.g., during a major database migration or holiday code freeze) without stopping the source-control integration and build stages.

Artifacts

CodePipeline passes data between stages using artifacts. An artifact can be a ZIP file containing source code, compiled binaries, deployment manifests, or environment configurations. Every pipeline must be configured with an Artifact Store, which is an Amazon S3 bucket. CodePipeline automatically uploads, downloads, and manages the versioning of these artifacts in the background. When an action runs, it specifies one or more InputArtifacts and produces one or more OutputArtifacts. CodePipeline handles the retrieval of the input artifact from the S3 bucket and presents it to the action provider, and then captures the output artifact and writes it back to S3.

Variables

CodePipeline supports dynamic variables. Actions can emit variables during execution (such as the Git commit hash, build ID, or output variables from a CloudFormation stack deployment). Subsequent stages and actions can reference these variables using the syntax #{namespace.variable_name}, enabling dynamic configuration changes during execution.

Execution Modes

CodePipeline supports different execution modes that dictate how concurrent changes are handled:

  • SUPERSEDED (Default): If a new execution starts while an older execution is still running in an earlier stage, the newer execution will "catch up" and supersede the older one at the transition point. The older execution is stopped. This ensures that you are always deploying the latest code and saves compute resources.
  • QUEUED: Executions are processed sequentially in the order they are triggered. This is critical for deployments that modify persistent state (like database schemas) where concurrent or skipped executions could cause data corruption.
  • PARALLEL: Allows multiple executions to run concurrently through the pipeline stages. This is useful for high-throughput testing pipelines but requires careful isolation of target environments to prevent resource conflicts.

5. Architectural Blueprints & Workflows

To visualize how these components interact in an enterprise environment, let us look at two architecture diagrams. The first diagram shows an event-driven, single-region pipeline. The second diagram shows a highly secure, multi-account deployment pipeline spanning three AWS accounts (Tooling, Staging, and Production).

Workflow 1: Event-Driven Single-Region Pipeline

+-------------------------------------------------------------------------------------------------------------------------+
|                                                  AWS Region (us-east-1)                                                 |
|                                                                                                                         |
|  +------------------+      +--------------------+      +----------------------+      +-------------------------------+  |
|  |   GitHub Repo    |      |  EventBridge Rule  |      |   AWS CodePipeline   |      |        S3 Artifact Store      |  |
|  |  (CodeStar Conn) | ---> | (Trigger on Push)  | ---> | (Orchestration Flow) | <==> | (Encrypted with KMS CMK Key)  |  |
|  +------------------+      +--------------------+      +----------------------+      +-------------------------------+  |
|                                                                   |                                                     |
|                                                                   | (Coordinates Stages)                                |
|                                                                   v                                                     |
|                                                     +----------------------------+                                      |
|                                                     | Stage 1: Source            |                                      |
|                                                     | - Pull from GitHub         |                                      |
|                                                     +----------------------------+                                      |
|                                                                   |                                                     |
|                                                                   v                                                     |
|                                                     +----------------------------+                                      |
|                                                     | Stage 2: Build & Test      |                                      |
|                                                     | - AWS CodeBuild (Unit Tests)                                      |
|                                                     +----------------------------+                                      |
|                                                                   |                                                     |
|                                                                   v                                                     |
|                                                     +----------------------------+                                      |
|                                                     | Stage 3: Manual Approval   |                                      |
|                                                     | - SNS Notification to SecOps                                      |
|                                                     +----------------------------+                                      |
|                                                                   |                                                     |
|                                                                   v                                                     |
|                                                     +----------------------------+                                      |
|                                                     | Stage 4: Deploy            |                                      |
|                                                     | - ECS / Lambda Deployment  |                                      |
|                                                     +----------------------------+                                      |
+-------------------------------------------------------------------------------------------------------------------------+
    

Workflow 2: Multi-Account Pipeline Architecture

This diagram illustrates an enterprise pattern where the pipeline resides in a central Tooling/Shared Services Account and deploys applications safely to isolated Staging and Production accounts using IAM role assumption and cross-account KMS decryption key permissions.

+-------------------------------------------------------------------------------------------------------------------------+
|                                              AWS ORGANIZATIONS STRUCTURE                                                |
|                                                                                                                         |
|  +-------------------------------------------------------------------------------------------------------------------+  |
|  |  [TOOLING ACCOUNT] (111111111111)                                                                                 |  |
|  |                                                                                                                   |  |
|  |  +--------------------+      +--------------------------+                                                          |  |
|  |  |  AWS CodePipeline  | ---> |  S3 Artifact Store       |                                                          |  |
|  |  |  (Pipeline Role)   |      |  (KMS CMK Encrypted)     |                                                          |  |
|  |  +--------------------+      +--------------------------+                                                          |  |
|  |           |                               |                                                                       |  |
|  |           | (Assume Cross-Account Role)   | (Grants Read Access via Bucket & Key Policies)                        |  |
|  +-----------|-------------------------------|-----------------------------------------------------------------------+  |
|              |                               |                                                                          |
|              |                               |                                                                          |
|              v                               v                                                                          |
|  +-------------------------------------------------------+   +-------------------------------------------------------+  |
|  |  [STAGING ACCOUNT] (222222222222)                     |   |  [PRODUCTION ACCOUNT] (333333333333)                  |  |
|  |                                                       |   |                                                       |  |
|  |  +----------------------------+                       |   |  +----------------------------+                       |  |
|  |  |  Deployment IAM Role       |                       |   |  |  Deployment IAM Role       |                       |  |
|  |  |  (Trusts Tooling Account)  |                       |   |  |  (Trusts Tooling Account)  |                       |  |
|  |  +----------------------------+                       |   |  +----------------------------+                       |  |
|  |               |                                       |   |               |                                       |  |
|  |               v                                       |   |               v                                       |  |
|  |  +----------------------------+                       |   |  +----------------------------+                       |  |
|  |  |  Target Resources          |                       |   |  |  Target Resources          |                       |  |
|  |  |  (ECS, Lambda, S3)         |                       |   |  |  (ECS, Lambda, S3)         |                       |  |
|  |  +----------------------------+                       |   |  +----------------------------+                       |  |
|  +-------------------------------------------------------+   +-------------------------------------------------------+  |
+-------------------------------------------------------------------------------------------------------------------------+
    

6. Action Types & Execution Models

AWS CodePipeline classifies workflow actions into six distinct categories. Understanding the configuration properties and best practices for each category is essential for designing high-performance pipelines.

Action Category Common Providers Key Input Parameters Typical Output Artifacts Enterprise Best Practice
Source GitHub (via CodeStar), S3, CodeCommit, ECR RepositoryName, BranchName, ConnectionArn SourceArtifact Use CodeStar Source Connections instead of legacy GitHub OAuth webhooks. Turn on EventBridge-based triggering.
Build AWS CodeBuild, Jenkins ProjectName, EnvironmentVariables BuildArtifact Run security scans (Snyk, SonarQube) inside your CodeBuild step. Keep build timeouts short.
Test AWS CodeBuild, AWS Device Farm ProjectName, TestType TestReports Run multiple test suites in parallel using the same RunOrder to speed up feedback loops.
Deploy AWS CodeDeploy, CloudFormation, ECS, S3 StackName, ClusterName, ServiceName None (or DeployResult) Use CloudFormation change sets to preview infrastructure changes before executing them.
Approval Manual (SNS integration) NotificationArn, ExternalEntityLink None Set up custom IAM permissions to restrict approval actions to authorized operations personnel.
Invoke AWS Lambda, Step Functions FunctionName, UserParameters FunctionResult Use Step Functions to orchestrate complex database migrations and rollbacks during deployment.

Deep Dive on CodeStar Connections (GitHub v2 Integration)

Historically, connecting AWS CodePipeline to GitHub required generating personal access tokens (PATs) and storing them as plain-text secrets or using S3-based polling. This approach had serious security and scalability drawbacks. The modern, secure approach is AWS CodeStar Source Connections. CodeStar Connections use OAuth app permissions managed directly inside your GitHub Organization settings. This ensures:

  • No long-lived GitHub tokens are stored in AWS.
  • Finer-grained access control can be applied at the GitHub organization level.
  • Automatic, event-driven webhooks are configured under the hood without manual API setup.

Dynamic Pipeline Variables

Variables allow you to build dynamic, parameter-driven workflows. For example, when using a GitHub source action, CodePipeline automatically generates variables like CommitId, BranchName, and AuthorDate. You can reference these variables in downstream actions. For example, you can pass the Git commit ID as an environment variable to CodeBuild to tag your Docker images:

# Example snippet of referencing a variable in a downstream action
EnvironmentVariables: !Sub |
  [
    {"Name": "GIT_COMMIT_HASH", "Type": "PLAINTEXT", "Value": "#{SourceVariables.CommitId}"}
  ]

7. Advanced Enterprise Patterns: Multi-Account & Cross-Region

In a production-ready enterprise AWS setup, resource isolation is paramount. Deploying dev, staging, and production environments inside a single AWS account is an anti-pattern. If a developer accidentally runs a destructive command or misconfigures an IAM policy, it could compromise or take down production systems. The industry standard is to use AWS Organizations to separate workloads into distinct accounts.

To orchestrate deployments across these boundaries, CodePipeline must be configured for multi-account access. This design relies on three security pillars: Cross-Account IAM Roles, Cross-Account KMS Cryptographic Keys, and Cross-Account S3 Bucket Policies.

1. Cross-Account IAM Roles

The pipeline runs in the Tooling Account (e.g., 111111111111). When it reaches a deployment stage targeting the Production Account (e.g., 333333333333), CodePipeline does not call production APIs directly using its own pipeline role. Instead, it assumes a pre-existing deployment role in the Production Account.

This deployment role must have a trust policy that allows the Tooling Account's CodePipeline service role to assume it:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/tooling-codepipeline-service-role"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

2. Cross-Account KMS Cryptographic Keys

By default, S3 buckets use SSE-S3 encryption or the default AWS-managed KMS key (aws/s3). However, AWS-managed keys cannot be shared across AWS accounts. To allow the Production Account to read artifacts from the Tooling Account's S3 bucket, you must encrypt the S3 bucket using a Customer Managed Key (CMK) in the Tooling Account, and configure a key policy that grants decryption rights to the Production deployment role.

Here is the KMS Key Policy template that must be applied to the CMK in the Tooling Account:

{
  "Version": "2012-10-17",
  "Id": "cross-account-kms-key-policy",
  "Statement": [
    {
      "Sid": "AllowLocalAdministration",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowCrossAccountAccessToTargetRoles",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::222222222222:role/staging-deployment-role",
          "arn:aws:iam::333333333333:role/production-deployment-role"
        ]
      },
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey",
        "kms:Encrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*"
      ],
      "Resource": "*"
    }
  ]
}

3. Cross-Account S3 Bucket Policies

The S3 bucket in the Tooling Account must also grant explicit read/write access to the cross-account deployment roles. Without this, even with valid KMS permissions, S3 will block access.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCrossAccountReadWriteAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::222222222222:role/staging-deployment-role",
          "arn:aws:iam::333333333333:role/production-deployment-role"
        ]
      },
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:PutObject",
        "s3:GetBucketLocation",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::tooling-codepipeline-artifacts-bucket",
        "arn:aws:s3:::tooling-codepipeline-artifacts-bucket/*"
      ]
    }
  ]
}

8. Production-Grade IaC: Complete Terraform Implementation

In this section, we present a complete, production-grade Terraform configuration file. This file provisions an AWS CodePipeline with three stages: Source (GitHub via CodeStar Connection), Build (AWS CodeBuild), and Deploy (ECS). It includes a dedicated S3 bucket, custom KMS key, and secure IAM service roles with strict least-privilege permissions.

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}

# Local variables for resource naming
locals {
  project_name = "enterprise-app"
  environment  = "production"
}

# KMS Key for encrypting S3 Artifacts
resource "aws_kms_key" "pipeline_key" {
  description             = "KMS Key for CodePipeline S3 Artifacts Encryption"
  deletion_window_in_days = 30
  enable_key_rotation     = true

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "Enable IAM User Permissions"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
        }
        Action   = "kms:*"
        Resource = "*"
      },
      {
        Sid    = "Allow CodePipeline and CodeBuild Access"
        Effect = "Allow"
        Principal = {
          AWS = [
            aws_iam_role.pipeline_role.arn,
            aws_iam_role.build_role.arn
          ]
        }
        Action = [
          "kms:Encrypt",
          "kms:Decrypt",
          "kms:ReEncrypt*",
          "kms:GenerateDataKey*",
          "kms:DescribeKey"
        ]
        Resource = "*"
      }
    ]
  })

  tags = {
    Name        = "${local.project_name}-pipeline-key"
    Environment = local.environment
  }
}

# Fetch metadata about the current AWS account
data "aws_caller_identity" "current" {}

# S3 Bucket for Pipeline Artifacts
resource "aws_s3_bucket" "artifacts_bucket" {
  bucket        = "${local.project_name}-artifacts-bucket-${data.aws_caller_identity.current.account_id}"
  force_destroy = true

  tags = {
    Name        = "${local.project_name}-artifacts-bucket"
    Environment = local.environment
  }
}

# Block all public access to the S3 bucket
resource "aws_s3_bucket_public_access_block" "artifacts_bucket_block" {
  bucket = aws_s3_bucket.artifacts_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# Enable versioning on the S3 bucket
resource "aws_s3_bucket_versioning" "artifacts_bucket_versioning" {
  bucket = aws_s3_bucket.artifacts_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

# Enable server-side encryption with the custom KMS key
resource "aws_s3_bucket_server_side_encryption_configuration" "artifacts_bucket_encryption" {
  bucket = aws_s3_bucket.artifacts_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      kms_master_key_id = aws_kms_key.pipeline_key.arn
      sse_algorithm     = "aws:kms"
    }
  }
}

# IAM Role for CodePipeline Service
resource "aws_iam_role" "pipeline_role" {
  name = "${local.project_name}-pipeline-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Service = "codepipeline.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      }
    ]
  })
}

# IAM Policy for CodePipeline Service Role
resource "aws_iam_role_policy" "pipeline_policy" {
  name = "${local.project_name}-pipeline-policy"
  role = aws_iam_role.pipeline_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:GetObjectVersion",
          "s3:GetBucketLocation",
          "s3:PutObject",
          "s3:ListBucket"
        ]
        Resource = [
          aws_s3_bucket.artifacts_bucket.arn,
          "${aws_s3_bucket.artifacts_bucket.arn}/*"
        ]
      },
      {
        Effect = "Allow"
        Action = [
          "codebuild:BatchGetBuilds",
          "codebuild:StartBuild"
        ]
        Resource = [aws_codebuild_project.app_build.arn]
      },
      {
        Effect = "Allow"
        Action = [
          "codestar-connections:UseConnection"
        ]
        Resource = [var.codestar_connection_arn]
      },
      {
        Effect = "Allow"
        Action = [
          "kms:Decrypt",
          "kms:Encrypt",
          "kms:GenerateDataKey"
        ]
        Resource = [aws_kms_key.pipeline_key.arn]
      }
    ]
  })
}

# IAM Role for CodeBuild Service
resource "aws_iam_role" "build_role" {
  name = "${local.project_name}-build-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Service = "codebuild.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      }
    ]
  })
}

# IAM Policy for CodeBuild Service Role
resource "aws_iam_role_policy" "build_policy" {
  name = "${local.project_name}-build-policy"
  role = aws_iam_role.build_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"
        ]
        Resource = "arn:aws:logs:*:*:*"
      },
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:GetObjectVersion",
          "s3:PutObject"
        ]
        Resource = [
          "${aws_s3_bucket.artifacts_bucket.arn}/*"
        ]
      },
      {
        Effect = "Allow"
        Action = [
          "kms:Decrypt",
          "kms:Encrypt",
          "kms:GenerateDataKey"
        ]
        Resource = [aws_kms_key.pipeline_key.arn]
      }
    ]
  })
}

# CodeBuild Project Definition
resource "aws_codebuild_project" "app_build" {
  name          = "${local.project_name}-build"
  description   = "Build project for compiling code and running tests"
  service_role  = aws_iam_role.build_role.arn
  build_timeout = "15"

  artifacts {
    type = "CODEPIPELINE"
  }

  environment {
    compute_type                = "BUILD_GENERAL1_SMALL"
    image                       = "aws/codebuild/standard:6.0"
    type                        = "LINUX_CONTAINER"
    image_pull_credentials_type = "CODEBUILD"

    environment_variable {
      name  = "ENV"
      value = "production"
    }
  }

  source {
    type      = "CODEPIPELINE"
    buildspec = "buildspec.yml"
  }

  logs_config {
    cloudwatch_logs {
      group_name  = "/aws/codebuild/${local.project_name}-build"
      status      = "ENABLED"
    }
  }
}

# CodePipeline Definition
resource "aws_codepipeline" "app_pipeline" {
  name     = "${local.project_name}-pipeline"
  role_arn = aws_iam_role.pipeline_role.arn

  artifact_store {
    location = aws_s3_bucket.artifacts_bucket.bucket
    type     = "S3"

    encryption_key {
      id   = aws_kms_key.pipeline_key.arn
      type = "KMS"
    }
  }

  stage {
    name = "Source"

    action {
      name             = "SourceAction"
      category         = "Source"
      owner            = "AWS"
      provider         = "CodeStarSourceConnection"
      version          = "1"
      output_artifacts = ["SourceOutput"]

      configuration = {
        ConnectionArn    = var.codestar_connection_arn
        FullRepositoryId = var.repository_id
        BranchName       = "main"
      }
    }
  }

  stage {
    name = "Build"

    action {
      name             = "BuildAction"
      category         = "Build"
      owner            = "AWS"
      provider         = "CodeBuild"
      version          = "1"
      input_artifacts  = ["SourceOutput"]
      output_artifacts = ["BuildOutput"]

      configuration = {
        ProjectName = aws_codebuild_project.app_build.name
      }
    }
  }
}

# Input variables definition
variable "codestar_connection_arn" {
  type        = string
  description = "The ARN of the AWS CodeStar Connection to GitHub"
}

variable "repository_id" {
  type        = string
  description = "The GitHub repository ID in the format: Organization/Repository-Name"
}

9. Production-Grade IaC: Complete CloudFormation Template

For organizations that standardize on native AWS CloudFormation, here is the equivalent production-ready YAML template. It implements best practices, including explicit parameterization, KMS encryption, and a multi-stage pipeline definition.

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Production-grade AWS CodePipeline with KMS encryption and secure IAM roles.'

Parameters:
  ProjectName:
    Type: String
    Default: 'enterprise-app'
    Description: 'Project name used for resource naming prefix'

  CodeStarConnectionArn:
    Type: String
    Description: 'ARN of the CodeStar Connection for GitHub integration'

  GitHubRepo:
    Type: String
    Description: 'Format: OrgName/RepoName'

  BranchName:
    Type: String
    Default: 'main'
    Description: 'Branch to monitor for code changes'

Resources:
  # KMS Customer Managed Key (CMK)
  PipelineKmsKey:
    Type: AWS::KMS::Key
    Properties:
      Description: !Sub 'KMS Key for ${ProjectName} Artifacts'
      EnableKeyRotation: true
      KeyPolicy:
        Version: '2012-10-17'
        Statement:
          - Sid: AdminPermissions
            Effect: Allow
            Principal:
              AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
            Action: 'kms:*'
            Resource: '*'
          - Sid: CodePipelineAccess
            Effect: Allow
            Principal:
              AWS:
                - !GetAtt PipelineServiceRole.Arn
                - !GetAtt CodeBuildServiceRole.Arn
            Action:
              - kms:Encrypt
              - kms:Decrypt
              - kms:ReEncrypt*
              - kms:GenerateDataKey*
              - kms:DescribeKey
            Resource: '*'

  # S3 Artifact Store
  PipelineS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub '${ProjectName}-artifacts-${AWS::AccountId}'
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: 'aws:kms'
              KMSMasterKeyId: !Ref PipelineKmsKey
            BucketKeyEnabled: true
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  # IAM Service Role for CodePipeline
  PipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${ProjectName}-pipeline-role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'codepipeline.amazonaws.com'
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: PipelineExecutionPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketLocation
                  - s3:PutObject
                  - s3:ListBucket
                Resource:
                  - !GetAtt PipelineS3Bucket.Arn
                  - !Sub '${PipelineS3Bucket.Arn}/*'
              - Effect: Allow
                Action:
                  - codebuild:BatchGetBuilds
                  - codebuild:StartBuild
                Resource: !GetAtt CodeBuildProject.Arn
              - Effect: Allow
                Action:
                  - codestar-connections:UseConnection
                Resource: !Ref CodeStarConnectionArn
              - Effect: Allow
                Action:
                  - kms:Decrypt
                  - kms:Encrypt
                  - kms:GenerateDataKey
                Resource: !GetAtt PipelineKmsKey.Arn

  # IAM Service Role for CodeBuild
  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub '${ProjectName}-codebuild-role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'codebuild.amazonaws.com'
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: CodeBuildExecutionPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: 'arn:aws:logs:*:*:*'
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:PutObject
                Resource: !Sub '${PipelineS3Bucket.Arn}/*'
              - Effect: Allow
                Action:
                  - kms:Decrypt
                  - kms:Encrypt
                  - kms:GenerateDataKey
                Resource: !GetAtt PipelineKmsKey.Arn

  # CodeBuild Project
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub '${ProjectName}-```html
  # CodeBuild Project
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub '${ProjectName}-build'
      Description: 'Enterprise build project'
      ServiceRole: !GetAtt CodeBuildServiceRole.Arn

      Artifacts:
        Type: CODEPIPELINE

      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/standard:7.0
        Type: LINUX_CONTAINER
        PrivilegedMode: true
        EnvironmentVariables:
          - Name: ENVIRONMENT
            Value: production

      Source:
        Type: CODEPIPELINE
        BuildSpec: buildspec.yml

      TimeoutInMinutes: 15

      LogsConfig:
        CloudWatchLogs:
          Status: ENABLED
          GroupName: !Sub '/aws/codebuild/${ProjectName}-build'

  # CodePipeline Definition
  ApplicationPipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub '${ProjectName}-pipeline'
      RoleArn: !GetAtt PipelineServiceRole.Arn

      ArtifactStore:
        Type: S3
        Location: !Ref PipelineS3Bucket
        EncryptionKey:
          Id: !GetAtt PipelineKmsKey.Arn
          Type: KMS

      Stages:

        - Name: Source
          Actions:
            - Name: GitHubSource
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeStarSourceConnection
                Version: '1'

              OutputArtifacts:
                - Name: SourceOutput

              Configuration:
                ConnectionArn: !Ref CodeStarConnectionArn
                FullRepositoryId: !Ref GitHubRepo
                BranchName: !Ref BranchName
                DetectChanges: true

              RunOrder: 1

        - Name: Build
          Actions:
            - Name: BuildApplication
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'

              InputArtifacts:
                - Name: SourceOutput

              OutputArtifacts:
                - Name: BuildOutput

              Configuration:
                ProjectName: !Ref CodeBuildProject

              RunOrder: 1

        - Name: Deploy
          Actions:
            - Name: DeployCloudFormation
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Provider: CloudFormation
                Version: '1'

              InputArtifacts:
                - Name: BuildOutput

              Configuration:
                ActionMode: CREATE_UPDATE
                StackName: !Sub '${ProjectName}-stack'
                Capabilities: CAPABILITY_NAMED_IAM
                TemplatePath: BuildOutput::infrastructure/template.yaml

              RunOrder: 1

Outputs:

  PipelineName:
    Description: CodePipeline Name
    Value: !Ref ApplicationPipeline

  PipelineRoleArn:
    Description: Pipeline Service Role ARN
    Value: !GetAtt PipelineServiceRole.Arn

  ArtifactBucket:
    Description: S3 Artifact Bucket
    Value: !Ref PipelineS3Bucket

  KmsKeyArn:
    Description: Artifact Encryption Key
    Value: !GetAtt PipelineKmsKey.Arn

  BuildProjectName:
    Description: CodeBuild Project Name
    Value: !Ref CodeBuildProject
```

10. Blue/Green, Canary, and GitOps Integrations

Modern enterprises require deployment mechanisms that minimize risk and eliminate downtime. AWS CodePipeline integrates with AWS CodeDeploy, ECS, Lambda, and EKS to support advanced deployment strategies.

Blue/Green Deployments

Blue/Green deployment creates a new environment (Green) alongside the existing production environment (Blue). After validation succeeds, traffic is shifted to Green.

Users
  |
  v
ALB
  |
  +----> Blue Environment (Current)
  |
  +----> Green Environment (New)
                  |
             Validation
                  |
            Traffic Shift

Benefits

  • Near-zero downtime
  • Instant rollback capability
  • Reduced deployment risk
  • Production validation before cutover

Canary Deployments

Canary releases gradually expose a new version to a small percentage of users before full rollout.

100% Traffic
      |
      +----> Version 1 (90%)
      |
      +----> Version 2 (10%)

After Validation

100% Traffic
      |
      +----> Version 2 (100%)

AWS Lambda Canary Example

{
  "Type": "Linear10PercentEvery1Minute"
}

GitOps Integration Pattern

Organizations running Kubernetes commonly integrate CodePipeline with GitOps tools such as ArgoCD and Flux.

GitHub
   |
CodePipeline
   |
Update Helm Charts
   |
GitOps Repository
   |
ArgoCD / Flux
   |
Amazon EKS

11. Security, Compliance, and Governance

IAM Least Privilege

Every pipeline action should execute under a dedicated IAM role with narrowly scoped permissions.

KMS Encryption

  • Encrypt artifact buckets
  • Rotate CMKs annually
  • Use customer-managed keys
  • Enable CloudTrail auditing

Compliance Controls

Framework Relevant Controls
SOC2 Change Management, Audit Trails
PCI DSS Access Control, Encryption
HIPAA Audit Logging, Encryption
ISO 27001 Release Governance

Security Scanning Stage

Source
  |
Build
  |
Security Scan
  |
Approval
  |
Deploy

12. Observability, Metrics, and Event-Driven Automation

CloudWatch Metrics

  • PipelineExecutionSuccessCount
  • PipelineExecutionFailureCount
  • BuildDuration
  • DeploymentDuration

EventBridge Integration

{
  "source": [
    "aws.codepipeline"
  ]
}

SNS Alerting

CodePipeline Failure
        |
    EventBridge
        |
       SNS
        |
 Email / Slack

About the Author

Naresh Kumar

Naresh Kumar

Senior Java Backend Engineer experienced in Banking, Payments, ISO 20022, Spring Boot, Microservices, Kafka, Docker, Kubernetes, AWS and Cloud Native Systems.

Built enterprise payment solutions, transaction processing systems, API platforms and scalable microservices used in production.

LinkedIn Profile