Introduction: Why AWS CodeCommit over GitLab?

In DevOps, Continuous Integration and Continuous Deployment (CI/CD) are essential practices for accelerating software development and ensuring high-quality code delivery. When considering a version control system for hosting your code repository, both AWS CodeCommit and GitLab offer potent solutions. However, AWS CodeCommit, a fully managed source control service, offers seamless integration with other AWS services, making it an attractive option for teams already invested in the AWS ecosystem. This blog post will guide you through building a primary CI/CD pipeline using AWS CodeCommit and CodeBuild, leveraging Terraform for infrastructure as code (IaC).

Terraform Backend Configuration: S3 and DynamoDB for State Management

Before diving into the pipeline setup, it’s crucial to establish a reliable Terraform backend for state management. Using Amazon S3 to store the Terraform state files and DynamoDB to store state locking ensures consistency and prevents conflicts during concurrent Terraform executions.

Steps to Configure the Terraform Backend:

  1. Create an S3 Bucket:
    • The Terraform state files will be stored in the S3 bucket. To prevent accidental deletions or overwrites, ensure that versioning is enabled.


resource “aws_s3_bucket” “terraform_state” {

  bucket = “my-terraform-state-bucket”

  versioning {

    enabled = true

  }

}

  1. Create a DynamoDB Table:
    • The DynamoDB table will handle state locking to prevent simultaneous updates to the state file.

resource “aws_dynamodb_table” “terraform_locks” {

  name         = “terraform-locks”

  billing_mode = “PAY_PER_REQUEST”

  hash_key     = “LockID”

  attribute {

    name = “LockID”

    type = “S”

  }

}

  1. Configure Terraform to Use S3 and DynamoDB:
    • Modify your backend configuration to use the S3 bucket and DynamoDB table.


terraform {

  backend “s3” {

    bucket         = “my-terraform-state-bucket”

    key            = “path/to/my/terraform.tfstate”

    region         = “us-west-2”

    dynamodb_table = “terraform-locks”

  }

}

Setting Up the AWS Provider and IAM Roles

With the backend configured, the next step is to set up the AWS provider and IAM roles necessary for your CI/CD pipeline. Terraform will manage these resources, ensuring consistent and repeatable deployments.

Defining the AWS Provider:

provider “aws” {

  region = “us-west-2”

}

Creating IAM Roles:

  1. CodeCommit Role:
    • This role allows CodeCommit to access necessary AWS services.


resource “aws_iam_role” “codecommit_role” {

  name = “codecommit-role”

  assume_role_policy = <<EOF

  {

    “Version”: “2012-10-17”,

    “Statement”: [

      {

        “Action”: “sts:AssumeRole”,

        “Effect”: “Allow”,

        “Principal”: {

          “Service”: “codecommit.amazonaws.com”

        }

      }

    ]

  }

  EOF

}

  1. CodeBuild Role:
    • This role allows CodeBuild to perform build tasks and interact with other AWS services.


resource “aws_iam_role” “codebuild_role” {

  name = “codebuild-role”

  assume_role_policy = <<EOF

  {

    “Version”: “2012-10-17”,

    “Statement”: [

      {

        “Action”: “sts:AssumeRole”,

        “Effect”: “Allow”,

        “Principal”: {

          “Service”: “codebuild.amazonaws.com”

        }

      }

    ]

  }

  EOF

}

Creating an AWS CodeCommit Repository: IaaS vs. GitLab’s Managed Approach

AWS CodeCommit, unlike GitLab’s managed repositories, offers Infrastructure as a Service (IaaS) with the advantage of tighter integration with AWS services like CodeBuild, CloudWatch, and IAM. This makes it ideal for teams leveraging AWS’s extensive cloud capabilities.

Creating the CodeCommit Repository with Terraform:

resource “aws_codecommit_repository” “my_repo” {

  repository_name = “my-repo”

  description     = “My sample repository for CI/CD pipeline”

}

Defining the CI/CD Process: CodeBuild and Buildspec.yml

AWS CodeBuild is a fully managed build service that automates building and testing your code. The buildspec.yml file, which defines the build steps, is critical to this setup.

Sample buildspec.yml Configuration:

version: 0.2

phases:

  install:

    commands:

      – echo Installing dependencies…

      – pip install -r requirements.txt

  build:

    commands:

      – echo Building the project…

      – python build.py

  post_build:

    commands:

      – echo Build complete

artifacts:

  files:

    – ‘**/*’

Connecting CodeCommit and CodeBuild: The Role of CloudWatch Events

To automate the build process, you must trigger CodeBuild every time a new commit is pushed to the CodeCommit repository. Setting up CloudWatch Events can achieve this.

Creating a CloudWatch Event Rule with Terraform:

resource “aws_cloudwatch_event_rule” “codecommit_push” {

  name        = “codecommit-push-event”

  description = “Trigger CodeBuild on CodeCommit push”

  event_pattern = <<EOF

{

  “source”: [“aws.codecommit”],

  “detail-type”: [“CodeCommit Repository State Change”],

  “detail”: {

    “event”: [“referenceUpdated”],

    “referenceType”: [“branch”],

    “referenceName”: [“main”]

  }

}

EOF

}

resource “aws_cloudwatch_event_target” “trigger_codebuild” {

  rule = aws_cloudwatch_event_rule.codecommit_push.name

  arn  = aws_codebuild_project.my_build_project.arn

}

Fine-Tuning Permissions: IAM Roles for CodeBuild and CloudWatch Events

To ensure that the CI/CD pipeline operates securely, it’s crucial to fine-tune IAM roles, granting only the necessary permissions for CodeBuild and CloudWatch Events.

IAM Policy Example for CodeBuild:

resource “aws_iam_policy” “codebuild_policy” {

  name        = “codebuild-policy”

  description = “Policy for CodeBuild permissions”

  policy      = jsonencode({

    “Version”: “2012-10-17”,

    “Statement”: [

      {

        “Action”: [

          “s3:GetObject”,

          “s3:PutObject”

        ],

        “Effect”: “Allow”,

        “Resource”: “*”

      }

    ]

  })

}

resource “aws_iam_role_policy_attachment” “codebuild_attach” {

  role       = aws_iam_role.codebuild_role.name

  policy_arn = aws_iam_policy.codebuild_policy.arn

}

Conclusion: Reflections on the Terraform-Driven AWS CI/CD Setup

Building a CI/CD pipeline with AWS CodeCommit and CodeBuild, managed through Terraform, provides a robust, scalable solution that integrates seamlessly with the AWS ecosystem. This approach offers greater control over your infrastructure and enhances security and automation capabilities compared to traditional managed CI/CD solutions like GitLab.

Adopting a Terraform-driven approach ensures your infrastructure is version-controlled, repeatable, and easy to manage. This makes it ideal for teams looking to streamline their DevOps processes within the AWS environment.

References

Secure and analyze your Terraform code using AWS CodeCommit, AWS CodePipeline, AWS CodeBuild, and tfsec

Create a CI/CD pipeline to validate Terraform configurations using AWS CodePipeline.