<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shivanshu Sharma</title>
    <description>The latest articles on DEV Community by Shivanshu Sharma (@shivanshu-sharma).</description>
    <link>https://dev.to/shivanshu-sharma</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3046859%2F0732d9b3-58be-44ff-8bbf-684fcd13bf68.png</url>
      <title>DEV Community: Shivanshu Sharma</title>
      <link>https://dev.to/shivanshu-sharma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shivanshu-sharma"/>
    <language>en</language>
    <item>
      <title>Building an Enterprise-Grade AWS CI/CD Pipeline with Terraform</title>
      <dc:creator>Shivanshu Sharma</dc:creator>
      <pubDate>Sun, 11 May 2025 12:57:01 +0000</pubDate>
      <link>https://dev.to/aws-builders/building-an-enterprise-grade-aws-cicd-pipeline-with-terraform-3fg3</link>
      <guid>https://dev.to/aws-builders/building-an-enterprise-grade-aws-cicd-pipeline-with-terraform-3fg3</guid>
      <description>&lt;h3&gt;
  
  
  How I automated AWS deployments with CodePipeline, CodeCommit, and CodeBuild for under $5/month
&lt;/h3&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;The DevOps Challenge&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Let me take you on a technical adventure that recently consumed my weekends and late nights. While I’ve mastered the arts of Jenkins, GitHub Actions, and Azure DevOps over the years, AWS’s native CI/CD services remained unexplored territory in my professional journey. When tasked with implementing a fully AWS-native DevOps pipeline for a crucial enterprise SSO project, I knew I was in for both a challenge and a revelation.&lt;/p&gt;

&lt;p&gt;Truth be told, I approached this mission with equal parts excitement and skepticism. Would AWS’s homegrown CI/CD solutions match the maturity of the standalone counterparts I’ve grown to love? Spoiler alert: they don’t — at least not yet — but they certainly bring their own flavor of magic to the table.&lt;/p&gt;

&lt;p&gt;The goal seemed straightforward at first: automate the deployment of AWS SSO configurations through a fully managed CI/CD pipeline. But as with most interesting DevOps problems, the devil was in the details. I would need to navigate the peculiarities of AWS’s native services, overcome their integration quirks, and piece together a solution that was both robust and maintainable. The journey took me through CodeCommit’s sparse interface, CodeBuild’s container idiosyncrasies, and CodePipeline’s rather opinionated workflow design — all while maintaining Terraform as my infrastructure orchestration tool of choice.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;The Mission: Infrastructure as Code Automation&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Before diving into code snippets and configuration files, let’s understand what I was building. My task centered around AWS Single Sign-On (SSO) automation for a large enterprise with dozens of AWS accounts and multiple teams requiring different levels of access:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a system to provision Permission Sets (essentially IAM roles on steroids) into AWS SSO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Establish automated linking between these Permission Sets, user Groups, and AWS accounts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up a CI/CD pipeline to deploy changes automatically whenever configurations are updated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Package everything neatly as infrastructure-as-code using Terraform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the entire process was auditable, reproducible, and compliant with security best practices&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In essence, I needed to build a self-service platform where different teams could access their assigned AWS accounts with appropriate permission levels, all managed through a central AWS SSO portal. This would replace our existing manual process where identity and access management changes required tickets, manual approvals, and direct console work — a process that typically took days and was prone to human error.&lt;/p&gt;

&lt;p&gt;The catch? Making this process as automated and hands-off as possible while maintaining appropriate security controls. As AWS SSO lacks certain API capabilities for user and group provisioning (as of this writing), this part would remain a console operation performed by our security team. However, everything else was fair game for automation.&lt;/p&gt;

&lt;p&gt;The challenge was further complicated by our organization’s strict security requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All infrastructure changes must be tracked and auditable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployments must require explicit approvals&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The entire solution must be version-controlled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No permanent admin credentials should be used in the pipeline&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is precisely the type of complex, multi-faceted DevOps problem I live for.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Assembling My AWS DevOps Arsenal&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;For this operation, I enlisted four core AWS services to create a seamless CI/CD experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CodeCommit&lt;/strong&gt;: My code repository (AWS’s equivalent of GitHub)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CodeBuild&lt;/strong&gt;: My execution environment for running Terraform commands&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CodePipeline&lt;/strong&gt;: The orchestrator connecting all the pieces&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;S3&lt;/strong&gt;: My artifact storage system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these services has its own strengths and limitations that influenced my architectural decisions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CodeCommit&lt;/strong&gt; offers tight integration with other AWS services but lacks many developer-friendly features found in GitHub or GitLab. While it supports branch policies and approval rules, its web interface for code reviews is quite basic. However, it does provide IAM-based access control, which aligns perfectly with our security requirements and eliminates the need for SSH keys or personal access tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CodeBuild&lt;/strong&gt; runs your build commands in isolated Docker containers, which is excellent for consistency but introduces challenges with filesystem operations like symbolic links (which I’ll discuss later). It supports various compute types ranging from 3GB to 64GB of memory, though I found the smallest tier more than sufficient for our Terraform operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CodePipeline&lt;/strong&gt; orchestrates the entire process but follows a linear execution model with limited branching capabilities. It allows for manual approval steps, which was crucial for our compliance requirements, but lacks some advanced features like parallel execution paths or conditional stages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3&lt;/strong&gt; serves as a simple yet effective artifact repository, with versioning capabilities that create an audit trail of all our infrastructure changes.&lt;/p&gt;

&lt;p&gt;Let’s see how I assembled these pieces into a coherent infrastructure automation puzzle.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;First Steps: Setting Up CodeCommit&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While my organization already uses GitHub for most projects, this particular project needed to live within our AWS ecosystem for security and compliance reasons. Setting up a CodeCommit repository is straightforward through the AWS console — much simpler than configuring a full-featured GitHub organization with proper permissions.&lt;/p&gt;

&lt;p&gt;After creating a new repository (I named mine &lt;code&gt;sso-permission-sets&lt;/code&gt;), the critical step is capturing the Clone URL for local development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click on the repository name in the CodeCommit console&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the “Clone URL” dropdown in the upper right&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select “Clone HTTPS (GRC)” — this is important as it uses the git-remote-codecommit helper&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The resulting URL contains your region and repository name, looking something like &lt;code&gt;https://git-codecommit.eu-west-2.amazonaws.com/v1/repos/sso-permission-sets&lt;/code&gt;. This format threw me off initially - it's not the standard Git URL format you might be used to. Later, you'll notice we use a different format altogether with the git-remote-codecommit helper.&lt;/p&gt;

&lt;p&gt;One nice aspect of CodeCommit is that it leverages your existing AWS authentication mechanisms rather than requiring separate SSH keys or personal access tokens. This simplifies credential management, especially in enterprise environments where key rotation policies are strictly enforced.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Creating My Local Development Environment&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;To effectively work with this setup, I needed a well-configured local development environment with several tools properly installed and configured. Here’s my detailed setup process:&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Installing and Configuring Required Tools&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;First, I made sure I had AWS CLI v2 installed, as v1 lacks some of the SSO functionality needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re on macOS, you can install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install awscli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next came the most crucial part — configuring SSO access for seamless authentication. This was essential as my organization had moved away from long-lived IAM access keys to temporary credentials via SSO:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure sso --profile terraform-deployer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interactive command prompted me for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The SSO start URL (our company portal)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS region for SSO (ap-south-1 in our case)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default output format (json)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Default AWS account and permission set (I selected our infrastructure account and PowerUser role)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once completed, a browser window opened for SSO authentication. With this configuration saved, I could now authenticate simply by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws sso login --profile terraform-deployer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates temporary credentials valid for 8 hours — perfect for a development session without compromising security.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Setting Up Terraform and Version Management&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;For Terraform, I needed version 0.15 or higher to leverage newer features like improved plan file handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform --version
# Should return: Terraform v0.15.5 or higher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I juggle multiple client projects with different Terraform version requirements, I use tfenv, which is essentially nvm but for Terraform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install tfenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install specific Terraform version
tfenv install 0.15.5# Set as default
tfenv use 0.15.5# Verify installed versions
tfenv list
# Shows: * 0.15.5 (set by /Users/shivanshu.sharma/.tfenv/version)
#        0.14.11
#        0.13.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Connecting to CodeCommit&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Finally, to work with CodeCommit, I needed Git and the specialized CodeCommit helper that integrates with AWS authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Verify Git version
git --version
# Should be 1.7.9 or higher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install the CodeCommit helper
python3 -m pip install git-remote-codecommit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The git-remote-codecommit package is critical — it enables Git to understand and use the special codecommit:// URL scheme that integrates with AWS authentication. Without it, connecting to CodeCommit repositories becomes much more complicated.&lt;/p&gt;

&lt;p&gt;With VS Code (plus the HashiCorp Terraform extension) as my IDE, I cloned the empty repository using the special codecommit format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone codecommit::ap-south-1://terraform-deployer@sso-permission-sets
cd sso-permission-sets &amp;amp;&amp;amp; code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the URL format: &lt;code&gt;codecommit::&amp;lt;region&amp;gt;://&amp;lt;profile&amp;gt;@&amp;lt;repository&amp;gt;&lt;/code&gt;. This leverages the AWS credentials associated with the specified profile, eliminating the need for separate Git credentials.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Validating My Setup&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;To ensure everything was working correctly, I created a simple README.md file and pushed it to the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "# AWS SSO Permission Sets" &amp;gt; README.md
git add README.md
git commit -m "Initial commit"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After refreshing the CodeCommit console, I could see my README appeared correctly — confirmation that my local development environment was properly configured and ready for the real work ahead.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Repository Structure and Organization&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Let me share how I organized my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sso-permission-sets/
├── configurations/
│   ├── permission_sets_pipeline/
│   │   ├── codepipeline.tf
│   │   ├── iam.tf
│   │   ├── codebuild.tf
│   │   ├── s3.tf
│   │   ├── buildspec-plan.yml
│   │   └── buildspec-apply.yml
│   ├── global.tf
│   ├── output.tf
│   ├── provider.tf
│   ├── version.tf
│   └── state.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I placed common configuration files at the root level and linked them into specific configuration directories. One quirk I discovered: AWS CodeBuild doesn’t handle symbolic links well, so I ultimately copied these files directly instead of linking them.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Orchestrating the CI/CD Pipeline&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The heart of my solution lives in &lt;code&gt;codepipeline.tf&lt;/code&gt;, where I defined a four-stage pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_codepipeline" "codepipeline" {
  name     = var.pipeline_name
  role_arn = aws_iam_role.codepipeline_role.arn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  artifact_store {
    location = aws_s3_bucket.codepipeline_bucket.bucket
    type     = "S3"
  }  # Stage 1: Clone the repository
  stage {
    name = "Clone"    action {
      name             = "Source"
      category         = "Source"
      owner            = "AWS"
      provider         = "CodeCommit"
      version          = "1"
      output_artifacts = ["CodeWorkspace"]      configuration = {
        RepositoryName       = var.repository_name
        BranchName           = var.branch_name
        PollForSourceChanges = "true"
      }
    }
  }  # Stage 2: Run terraform plan
  stage {
    name = "Plan"    action {
      name             = "Plan"
      category         = "Build"
      owner            = "AWS"
      provider         = "CodeBuild"
      input_artifacts  = ["CodeWorkspace"]
      output_artifacts = ["TerraformPlanFile"]
      version          = "1"      configuration = {
        ProjectName = aws_codebuild_project.plan_project.name
        EnvironmentVariables = jsonencode([
          {
            name  = "PIPELINE_EXECUTION_ID"
            value = "#{codepipeline.PipelineExecutionId}"
            type  = "PLAINTEXT"
          }
        ])
      }
    }
  }  # Stage 3: Require manual approval
  stage {
    name = "Manual-Approval"    action {
      name     = "Approval"
      category = "Approval"
      owner    = "AWS"
      provider = "Manual"
      version  = "1"
    }
  }  # Stage 4: Apply the terraform changes
  stage {
    name = "Apply"    action {
      name            = "Deploy"
      category        = "Build"
      owner           = "AWS"
      provider        = "CodeBuild"
      input_artifacts = ["CodeWorkspace", "TerraformPlanFile"]
      version         = "1"      configuration = {
        ProjectName     = aws_codebuild_project.apply_project.name
        PrimarySource   = "CodeWorkspace"
        EnvironmentVariables = jsonencode([
          {
            name  = "PIPELINE_EXECUTION_ID"
            value = "#{codepipeline.PipelineExecutionId}"
            type  = "PLAINTEXT"
          }
        ])
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline flow is elegantly simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clone&lt;/strong&gt;: Fetch the latest code from CodeCommit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt;: Run &lt;code&gt;terraform plan&lt;/code&gt; and save the output as an S3 artifact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual-Approval&lt;/strong&gt;: Allow human verification of proposed changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apply&lt;/strong&gt;: Run &lt;code&gt;terraform apply&lt;/code&gt; using the saved plan file&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A few implementation insights I discovered along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Artifact names should avoid hyphens to prevent ambiguous Terraform errors (use camelCase or snake_case instead)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CodePipeline variables can be accessed using the &lt;code&gt;#{codepipeline.VariableName}&lt;/code&gt; syntax&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the Apply stage, since it uses multiple input artifacts, I had to specify which one should be the primary source&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Setting Up CodeBuild Projects&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;For each CodeBuild stage (Plan and Apply), I needed to define a build project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_codebuild_project" "plan_project" {
  name          = "${var.pipeline_name}-plan"
  description   = "Plan stage for ${var.pipeline_name}"
  build_timeout = "5"
  service_role  = aws_iam_role.codebuild_role.arn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  artifacts {
    type = "CODEPIPELINE"
  }  environment {
    compute_type                = var.build_compute_type
    image                       = var.build_image
    type                        = var.build_container_type
    image_pull_credentials_type = "CODEBUILD"
  }  source {
    type      = "CODEPIPELINE"
    buildspec = file("${path.module}/buildspec-plan.yml")
  }
}resource "aws_codebuild_project" "apply_project" {
  name          = "${var.pipeline_name}-apply"
  description   = "Apply stage for ${var.pipeline_name}"
  build_timeout = "5"
  service_role  = aws_iam_role.codebuild_role.arn  artifacts {
    type = "CODEPIPELINE"
  }  environment {
    compute_type                = var.build_compute_type
    image                       = var.build_image
    type                        = var.build_container_type
    image_pull_credentials_type = "CODEBUILD"
  }  source {
    type      = "CODEPIPELINE"
    buildspec = file("${path.module}/buildspec-apply.yml")
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The environment variables in my &lt;code&gt;global.tf&lt;/code&gt; defined the compute specifications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "build_compute_type" {
  description = "CodeBuild compute type"
  type        = string
  default     = "BUILD_GENERAL1_SMALL"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "build_image" {
  description = "CodeBuild container image"
  type        = string
  default     = "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
}variable "build_container_type" {
  description = "CodeBuild container type"
  type        = string
  default     = "LINUX_CONTAINER"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Crafting the BuildSpec Files&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The real magic happens in the buildspec files that tell CodeBuild what to do. Here’s my plan buildspec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env:
  variables:
    TF_VERSION: "0.15.5"
    PERMISSION_SETS_DIR: "configurations/permission_sets_pipeline"phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - echo "Installing terraform version ${TF_VERSION}"
      - curl -s -qL -o terraform.zip "https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip"
      - unzip terraform.zip
      - mv terraform /usr/bin/terraform
      - rm terraform.zip  build:
    commands:
      - echo "Starting build phase"
      - cd ${CODEBUILD_SRC_DIR}

      # Copy linked files to make sure they're available
      - cp ${CODEBUILD_SRC_DIR}/configurations/global.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/provider.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/version.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/state.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/output.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/

      - cd ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}
      - terraform init
      - terraform validate
      - terraform plan -out=tfplan_commitid_${CODEBUILD_RESOLVED_SOURCE_VERSION}_pipelineid_${PIPELINE_EXECUTION_ID}

artifacts:
  files:
    - ${PERMISSION_SETS_DIR}/tfplan_commitid_${CODEBUILD_RESOLVED_SOURCE_VERSION}_pipelineid_${PIPELINE_EXECUTION_ID}
  name: TerraformPlanFile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the apply buildspec:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env:
  variables:
    TF_VERSION: "0.15.5"
    PERMISSION_SETS_DIR: "configurations/permission_sets_pipeline"phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - echo "Installing terraform version ${TF_VERSION}"
      - curl -s -qL -o terraform.zip "https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip"
      - unzip terraform.zip
      - mv terraform /usr/bin/terraform
      - rm terraform.zip  build:
    commands:
      - echo "Starting build phase"
      - cd ${CODEBUILD_SRC_DIR}

      # Copy linked files to make sure they're available
      - cp ${CODEBUILD_SRC_DIR}/configurations/global.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/provider.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/version.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/state.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/
      - cp ${CODEBUILD_SRC_DIR}/configurations/output.tf ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}/

      - cd ${CODEBUILD_SRC_DIR}/${PERMISSION_SETS_DIR}
      - terraform init
      - cp ${CODEBUILD_SRC_DIR_TerraformPlanFile}/configurations/permission_sets_pipeline/tfplan_commitid_${CODEBUILD_RESOLVED_SOURCE_VERSION}_pipelineid_${PIPELINE_EXECUTION_ID} .
      - terraform apply -auto-approve tfplan_commitid_${CODEBUILD_RESOLVED_SOURCE_VERSION}_pipelineid_${PIPELINE_EXECUTION_ID}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A critical discovery I made: when dealing with multiple artifacts in CodeBuild, you need to use &lt;code&gt;CODEBUILD_SRC_DIR_ArtifactName&lt;/code&gt; to access secondary artifacts. This was the trickiest part of the whole setup!&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Creating the S3 Artifact Bucket&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Finally, I needed a place to store my pipeline artifacts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "codepipeline_bucket" {
  bucket = var.artifact_bucket
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket_acl" "codepipeline_bucket_acl" {
  bucket = aws_s3_bucket.codepipeline_bucket.id
  acl    = "private"
}resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
  bucket = aws_s3_bucket.codepipeline_bucket.id  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy here — just a private, encrypted bucket for storing our Terraform plans and other artifacts.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Final Result and Cost Analysis&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;After applying all these configurations, I had a fully functional AWS-native CI/CD pipeline that would:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Detect changes to the repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Plan the Terraform changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait for human approval&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply the changes automatically&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The best part? The entire solution costs approximately $3.01 per month if you run it once daily. That’s less than a fancy coffee!&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Overcoming Unexpected Challenges&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While the solution appears straightforward now, I encountered several unexpected obstacles along the way:&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Dynamic State Management&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;My first attempt used a local state file, which quickly proved problematic in a CI/CD environment. I pivoted to using S3 backend with DynamoDB locking to ensure state consistency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket         = "terraform-state-xxcloud-infra"
    key            = "sso-permission-sets/terraform.tfstate"
    region         = "ap-south-1"
    dynamodb_table = "terraform-state-lock"
    encrypt        = true
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Handling Permission Boundaries&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Our organization requires permission boundaries on all IAM roles. The IAM roles created by CodeBuild and CodePipeline needed these boundaries applied, which required some additional configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "codebuild_role" {
  name                 = "${var.pipeline_name}-codebuild-role"
  assume_role_policy   = data.aws_iam_policy_document.codebuild_assume_policy.json
  permissions_boundary = "arn:aws:iam::${local.account_id}:policy/StandardPermissionsBoundary"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Cross-Account Pipeline Considerations&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While my initial implementation worked within a single account, we later expanded it to deploy permission sets across multiple accounts. This required adjusting the trust relationships and adding cross-account role assumptions to the pipeline.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Security Considerations&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Security was paramount in this implementation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Least Privilege Access&lt;/strong&gt;: The IAM roles for CodeBuild and CodePipeline have tightly scoped permissions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Artifact Encryption&lt;/strong&gt;: All pipeline artifacts are encrypted at rest in S3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Approval Gates&lt;/strong&gt;: Changes require explicit human approval before deployment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auditable History&lt;/strong&gt;: Every change is trackable through Git history and pipeline execution logs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Credentials&lt;/strong&gt;: No long-lived access keys are used in the pipeline&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Cost Analysis and Optimization&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;One pleasant surprise was the cost-effectiveness of this solution. The entire infrastructure costs approximately $4 to $5 per month with daily executions.&lt;/p&gt;

&lt;p&gt;We could further optimize by using EventBridge to trigger the pipeline only on actual changes rather than polling for changes, but the cost savings would be minimal.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion and Key Takeaways&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Building this AWS-native CI/CD pipeline was a fascinating journey that expanded my DevOps toolkit. While AWS’s CI/CD services don’t yet match the polish of dedicated solutions like Jenkins or GitHub Actions, they integrate beautifully with other AWS services and provide a cost-effective approach to automating infrastructure deployments.&lt;/p&gt;

&lt;p&gt;The most valuable lessons I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Filesystem Quirks&lt;/strong&gt;: CodeBuild has peculiar behavior with symbolic links and secondary artifacts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environment Variable Magic&lt;/strong&gt;: Use pipeline execution IDs and commit hashes to create unique artifact names&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This infrastructure-as-code approach to managing AWS SSO permission sets has dramatically improved our operational efficiency. What used to take days of manual work and coordination now happens automatically in minutes with full traceability and security controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you built similar pipelines with AWS’s native services? What challenges did you encounter?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’d love to hear about your experiences and any optimization tips you might have!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Unlocking Event-Driven Architectures with Amazon EventBridge</title>
      <dc:creator>Shivanshu Sharma</dc:creator>
      <pubDate>Thu, 17 Apr 2025 05:56:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/unlocking-event-driven-architectures-with-amazon-eventbridge-5455</link>
      <guid>https://dev.to/aws-builders/unlocking-event-driven-architectures-with-amazon-eventbridge-5455</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As modern applications shift towards microservices and serverless architectures, decoupled systems and real-time event processing become critical. Enter &lt;strong&gt;Amazon EventBridge&lt;/strong&gt;, AWS’s event bus service that connects application data from your services, integrated SaaS applications, and AWS services to enable real-time, event-driven workflows.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll take a technical deep dive into EventBridge, explore how it differs from SNS and SQS, examine its architecture, and build a simple event-driven pipeline to demonstrate its capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What is Amazon EventBridge?
&lt;/h2&gt;

&lt;p&gt;Amazon EventBridge is a &lt;strong&gt;serverless event bus&lt;/strong&gt; that makes it easy to connect applications using data from your own applications, integrated SaaS providers (like Auth0, Zendesk, Shopify), and AWS services.&lt;/p&gt;

&lt;p&gt;It routes events &lt;strong&gt;based on rules&lt;/strong&gt; to targets like Lambda, Step Functions, SQS, Kinesis, and more — without needing to write custom polling or filtering logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔄 EventBridge vs SNS vs SQS
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;EventBridge&lt;/th&gt;
&lt;th&gt;SNS&lt;/th&gt;
&lt;th&gt;SQS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Event routing&lt;/td&gt;
&lt;td&gt;Rule-based with content filtering&lt;/td&gt;
&lt;td&gt;Fan-out pub/sub&lt;/td&gt;
&lt;td&gt;Message queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Message retention&lt;/td&gt;
&lt;td&gt;24 hours&lt;/td&gt;
&lt;td&gt;No retention&lt;/td&gt;
&lt;td&gt;14 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dead-letter queue&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Event Buses&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SaaS integration&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🏗️ Architecture: Under the Hood
&lt;/h2&gt;

&lt;p&gt;An EventBridge setup consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event Sources&lt;/strong&gt;: AWS services, your apps, or SaaS apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Bus&lt;/strong&gt;: Default, Partner, or Custom.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rules&lt;/strong&gt;: JSON pattern-based filters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targets&lt;/strong&gt;: AWS services like Lambda, SQS, Step Functions, or even HTTP APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You send events to a bus, which evaluates them against rules and sends them to matched targets.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Hands-On: Building an Event-Driven Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario
&lt;/h3&gt;

&lt;p&gt;You have an e-commerce app. When a new order is placed (via a Lambda function), an event is published to EventBridge. Based on that event, EventBridge triggers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Lambda to update inventory.&lt;/li&gt;
&lt;li&gt;A Step Function to initiate fulfillment.&lt;/li&gt;
&lt;li&gt;Sends the event to an SQS queue for async analytics processing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Event Schema
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom.ecommerce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OrderPlaced"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sku-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sku-2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;49.99&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create a Custom Event Bus
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws events create-event-bus &lt;span class="nt"&gt;--name&lt;/span&gt; ecommerce-bus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Add a Rule to Route Events
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;event-rule.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"custom.ecommerce"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"DetailType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"OrderPlaced"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws events put-rule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; OrderPlacedRule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--event-bus-name&lt;/span&gt; ecommerce-bus &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--event-pattern&lt;/span&gt; file://event-rule.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Add Targets
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws events put-targets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rule&lt;/span&gt; OrderPlacedRule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--event-bus-name&lt;/span&gt; ecommerce-bus &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--targets&lt;/span&gt; file://targets.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;targets.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"InventoryLambda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:123456789012:function:UpdateInventory"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FulfillmentStepFunction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:states:us-east-1:123456789012:stateMachine:FulfillOrder"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AnalyticsQueue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sqs:us-east-1:123456789012:analytics-queue"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Send a Test Event
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws events put-events &lt;span class="nt"&gt;--entries&lt;/span&gt; file://event.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;event.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"custom.ecommerce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"DetailType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"OrderPlaced"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;orderId&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;1234&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;items&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: [&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;sku-1&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;sku-2&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;], &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;total&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 49.99}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"EventBusName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ecommerce-bus"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✅ Key Benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Loose coupling&lt;/strong&gt; between producers and consumers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Registry&lt;/strong&gt; and schema discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native support&lt;/strong&gt; for SaaS and AWS integrations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and durability&lt;/strong&gt; with at-least-once delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔐 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;custom event buses&lt;/strong&gt; to isolate domains&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;dead-letter queues&lt;/strong&gt; (DLQs) to handle failures&lt;/li&gt;
&lt;li&gt;Leverage &lt;strong&gt;schema validation&lt;/strong&gt; to prevent malformed events&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;event replay&lt;/strong&gt; to reprocess past events (available via Archive &amp;amp; Replay)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Amazon EventBridge is a cornerstone for building resilient, scalable, event-driven applications in AWS. Whether you’re decoupling microservices, responding to external triggers, or handling complex workflows, EventBridge offers a clean, powerful, and highly integrative approach.&lt;/p&gt;

&lt;p&gt;If you’re not already using it in your architecture, now’s the time to consider where EventBridge can help simplify your systems.&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>aws</category>
      <category>serverless</category>
      <category>devops</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Shivanshu Sharma</dc:creator>
      <pubDate>Wed, 16 Apr 2025 08:26:59 +0000</pubDate>
      <link>https://dev.to/shivanshu-sharma/-2hb8</link>
      <guid>https://dev.to/shivanshu-sharma/-2hb8</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa" class="crayons-story__hidden-navigation-link"&gt;Implementing AWS SSO Integration with Jenkins&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/aws-builders"&gt;
            &lt;img alt="AWS Community Builders  logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2794%2F88da75b6-aadd-4ea1-8083-ae2dfca8be94.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/shivanshu-sharma" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3046859%2F0732d9b3-58be-44ff-8bbf-684fcd13bf68.png" alt="shivanshu-sharma profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/shivanshu-sharma" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Shivanshu Sharma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Shivanshu Sharma
                
              
              &lt;div id="story-author-preview-content-2403950" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/shivanshu-sharma" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3046859%2F0732d9b3-58be-44ff-8bbf-684fcd13bf68.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Shivanshu Sharma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/aws-builders" class="crayons-story__secondary fw-medium"&gt;AWS Community Builders &lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 13 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa" id="article-link-2403950"&gt;
          Implementing AWS SSO Integration with Jenkins
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/security"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;security&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cicd"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cicd&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;15&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>aws</category>
      <category>security</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Implementing AWS SSO Integration with Jenkins</title>
      <dc:creator>Shivanshu Sharma</dc:creator>
      <pubDate>Sun, 13 Apr 2025 10:14:05 +0000</pubDate>
      <link>https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa</link>
      <guid>https://dev.to/aws-builders/implementing-aws-sso-integration-with-jenkins-18oa</guid>
      <description>&lt;h2&gt;
  
  
  Configuring SAML authentication to integrate AWS Single Sign-On with Jenkins, enhancing secure user access management and authentication processes.
&lt;/h2&gt;

&lt;p&gt;Integration of tools and platforms is an absolute must nowadays in the fast-paced world of DevOps. A good example would be the integration of AWS SSO with Jenkins, an open-source automation server that’s world-famous. AWS SSO enhances login processes by providing a unique point of authentication for AWS services and Jenkins allows automation processes to build up CI/CD Pipelines. Pairing the two gives peace of mind.&lt;/p&gt;

&lt;p&gt;This blog explains the process of integrating AWS SSO with Jenkins and emphasizes the steps and advantages while explaining the best practices.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Pre-requisites&lt;/strong&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A Running Jenkins Server (in any AWS account).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IAM Identity Center Enabled.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Let’s Begin&lt;/strong&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Start by searching &lt;strong&gt;AWS Identity Center&lt;/strong&gt; in the search and open this service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjdytuwk121sc04z1a1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjdytuwk121sc04z1a1h.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2. You will be redirected to the AWS Identity Center &lt;strong&gt;Dashboard.&lt;/strong&gt; Here you can see the Organization ID, AWS access portal URL and Issue URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fompg0e46b1q17k2j2v55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fompg0e46b1q17k2j2v55.png" alt="Image description" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3. Click &lt;strong&gt;Applications&lt;/strong&gt; under the Application assignments section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vpz70doblsbfj3cvzz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vpz70doblsbfj3cvzz4.png" alt="Image description" width="800" height="712"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4. Once on the &lt;strong&gt;Applications&lt;/strong&gt; page, click on &lt;strong&gt;Add Application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeayjokkbu1d5ohjjp4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbeayjokkbu1d5ohjjp4m.png" alt="Image description" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5. On the configurations page, start by selecting the &lt;strong&gt;Application type.&lt;/strong&gt; Under the &lt;strong&gt;Setup preference&lt;/strong&gt; select “&lt;strong&gt;I want to select an application from the catalog”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56t4w4kbiyt28887rq9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56t4w4kbiyt28887rq9j.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6. Now in the &lt;strong&gt;Application Catalog,&lt;/strong&gt; search “&lt;em&gt;Jenkins&lt;/em&gt;” and select the application and click &lt;strong&gt;Next.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5fuz33swn0t1h6hpi79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5fuz33swn0t1h6hpi79.png" alt="Image description" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7. On the next page, make sure to note down the details under section &lt;strong&gt;IAM Identity Center metadata.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytbnrb76dv8irjn87112.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytbnrb76dv8irjn87112.png" alt="Image description" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8. Now scroll down and under the &lt;strong&gt;Application metadata&lt;/strong&gt; section, add below details and click submit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf1pmvixuooyw3bbmajf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcf1pmvixuooyw3bbmajf.png" alt="Image description" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The URL mentioned corresponds to your Jenkins server's IP address, followed by &lt;code&gt;/securityRealm/finishLogin&lt;/code&gt; in the path.&lt;/p&gt;

&lt;p&gt;9. You will see that the &lt;strong&gt;Jenkins&lt;/strong&gt; has been added to the &lt;strong&gt;Applications.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;10. Now, select your &lt;strong&gt;Jenkins&lt;/strong&gt; application and click on &lt;strong&gt;Action -&amp;gt; Edit Attribute Mappings.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbvqde0r33ljla26332o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbvqde0r33ljla26332o.png" alt="Image description" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;11. Update the attributes and formats as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnq0usbh8qopt26dn6dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnq0usbh8qopt26dn6dd.png" alt="Image description" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;12. Now, login to you &lt;strong&gt;Jenkins&lt;/strong&gt; using the Public IP of the Jenkins Server.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Manage Jenkins.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27rr42uf6oqkesggqstj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27rr42uf6oqkesggqstj.png" alt="Image description" width="800" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;13. Now select the &lt;strong&gt;Plugins.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2utl3zdl0gw7j7apc5ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2utl3zdl0gw7j7apc5ju.png" alt="Image description" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;14. Under &lt;strong&gt;Plugins,&lt;/strong&gt; select the &lt;strong&gt;Available Plugins,&lt;/strong&gt; then search for &lt;strong&gt;SAML.&lt;br&gt;&lt;br&gt;
**Select the first SAML plugin and click **Install.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbmqwedb6setw4uhk2wr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbbmqwedb6setw4uhk2wr.png" alt="Image description" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;15. Once the Plugin is installed, go back to &lt;strong&gt;Manage Jenkins&lt;/strong&gt; and select &lt;strong&gt;Security.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpun9o31sbx8kiqlpuu3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpun9o31sbx8kiqlpuu3o.png" alt="Image description" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;16. Now under &lt;strong&gt;Authentication,&lt;/strong&gt; change the &lt;strong&gt;Security Realm&lt;/strong&gt; type to &lt;strong&gt;SAML 2.0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9kycgsbd6qeadwg355o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9kycgsbd6qeadwg355o.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;17. Scroll down and under &lt;strong&gt;IdP Metadata URL&lt;/strong&gt; add the &lt;strong&gt;IAM Identity Center metadata file&lt;/strong&gt; URL from the data copied in &lt;strong&gt;Step 7.&lt;/strong&gt; Once done click on &lt;strong&gt;Validate IdP Metadata URL.&lt;/strong&gt; You will get a success response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ukw7du9dmtwmjwg5dbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ukw7du9dmtwmjwg5dbp.png" alt="Image description" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;18. Scroll down, under &lt;strong&gt;Email attribute&lt;/strong&gt; add as per below image and under &lt;strong&gt;Logout URL&lt;/strong&gt; add the &lt;strong&gt;IAM Identity Center sign-out URL&lt;/strong&gt; from &lt;strong&gt;Step 7&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7f0dw3em52q6q2m4dek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7f0dw3em52q6q2m4dek.png" alt="Image description" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;19. Similarly to Email attribute, add &lt;strong&gt;group&lt;/strong&gt; in the &lt;strong&gt;Group Attribute&lt;/strong&gt; field and click &lt;strong&gt;Save.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;20. Now, we have our AWS SSO setup for Jenkins. We just need to assign it our &lt;strong&gt;Users&lt;/strong&gt; in the &lt;strong&gt;IAM Identity Center.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Select your Application in the &lt;strong&gt;IAM Identity Center&lt;/strong&gt; and click &lt;strong&gt;Assign Users and Groups&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8cidir2qbnh33jg7nve3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8cidir2qbnh33jg7nve3.png" alt="Image description" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;21. Search and select the user and click &lt;strong&gt;Assign.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnp5c0hjlb1ja540xzpx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnp5c0hjlb1ja540xzpx.png" alt="Image description" width="800" height="795"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, your users can access this &lt;strong&gt;Application&lt;/strong&gt; once they login via the SSO.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1ovk1pl72xoaaakvifs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1ovk1pl72xoaaakvifs.png" alt="Image description" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Integrating AWS SSO with Jenkins streamlines secure user access while simplifying authentication management. By leveraging SAML authentication, you can centralize identity management, enhance security with features like MFA, and reduce the overhead of managing multiple credentials. This setup ensures that your Jenkins workflows are not only secure but also aligned with best practices in modern DevOps environments.&lt;/p&gt;

&lt;p&gt;With the power of AWS SSO and Jenkins combined, your teams can focus on building, deploying, and scaling applications with peace of mind.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
