> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CodePipeline Deployment Limit Check Should Be Reviewed

### More Info:

This rule checks if the first deployment stage of AWS CodePipeline performs more than one deployment. Optionally checks if each of the subsequent remaining stages deploy to more than the specified number of deployments (deploymentLimit).

### Risk Level

Medium

### Address

Configuration

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* Cloudanix Best Practice
* DPDPA
* Digital Operational Resilience Act (EU)
* Essential 8
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        For this finding, there’s nothing to “flip” in a single setting. The AWS managed control **CodePipeline deployment limit should be reviewed** (Config rule: `codepipeline-deployment-limit-check`) is **manual**: you must review how often your pipelines (and underlying CodeBuild projects) deploy and put proper controls in place.

        Below is how to do that for **CodeBuild-based pipelines using the AWS Console**.

        ***

        ### 1. Identify the affected pipeline(s) and CodeBuild project(s)

        1. In the AWS Console, go to **Security Hub**.
        2. In the left menu, choose **Findings**.
        3. Filter:
           * **Product name**: `Security Hub`
           * **Resource type**: `AWS::CodePipeline::Pipeline`
           * **Title / Rule ID** contains: `CodePipeline deployment limit should be reviewed` or `codepipeline-deployment-limit-check`.
        4. Open a finding and note:
           * The **pipeline name**.
           * The **region**.
        5. Go to **CodePipeline** (same region) → find and open the pipeline.
        6. For each **Build** action, note the **CodeBuild project name**.

        ***

        ### 2. Review and control deployment frequency using approvals

        If the issue is that deployments are happening too frequently (e.g., straight to a shared/test/prod environment):

        1. In **CodePipeline**, open the pipeline.
        2. Click **Edit** (top right).
        3. Between the **build** stage and the “risky” stage (e.g., deploy-to-shared, deploy-to-prod), add an approval:
           1. Click **+ Add stage** (or **+ Add action group** in an existing stage).
           2. Name it something like `Manual-Approval` or `Change-Review`.
           3. Choose **Action provider**: `Manual approval`.
           4. Configure:
              * **SNS topic**: an existing topic that notifies approvers, or create one.
              * **Comments** / **URL**: link to your change ticketing system (optional).
           5. Save the action.
        4. Click **Save** at the top, then **Release change** if required to re-run.

        This creates a gate so that not every pipeline execution will automatically deploy.

        ***

        ### 3. Use CodeBuild project settings to avoid excessive or uncontrolled builds

        1. Go to **CodeBuild** → **Build projects** → open the affected project.
        2. Click **Edit**:
           * Confirm that **Environment** settings (privileged mode, IAM role) are appropriate and not allowing overly broad actions in downstream stages that increase deployment risk.
        3. Under **Buildspec** / build commands, ensure you are not:
           * Triggering additional **nested pipelines**.
           * Manually invoking **deployments** to multiple environments from one build in an uncontrolled way.
        4. If necessary, split the build into:
           * One build project for **build and test**.
           * Another separate, more controlled pipeline for **deployment**, with approvals.

        ***

        ### 4. Control triggers so deployments don’t happen too often

        1. In **CodePipeline** → your pipeline → **Edit**.
        2. At the **Source** stage:
           * If using **CloudWatch Events / EventBridge** or **Git webhooks**, consider:
             * Enabling **filtering** (branch, directory).
             * Configuring your repo (GitHub/CodeCommit) to only trigger on specific events.
        3. Or, switch some pipelines to **manual** trigger (click **Release change** on demand instead of on every commit) for non-critical or noisy branches.

        ***

        ### 5. (Optional) Restrict who can start/approve deployments

        1. Go to **IAM** → **Roles / Users**.
        2. Find the role or user groups that:
           * Run the pipeline (`codepipeline` service role).
           * Have **StartPipelineExecution** or **PutApprovalResult** permissions.
        3. Tighten policies so only appropriate users/groups can:
           * Manually start the pipeline.
           * Approve the manual approval steps.

        ***

        ### 6. Mark the finding as addressed (if using Security Hub)

        1. Once you’ve implemented the controls above and are satisfied with the deployment behavior:
           * In **Security Hub → Findings**, open the finding.
           * Set the **Workflow status** to **Resolved**, or add a **note** indicating:
             * What controls you added (manual approval, trigger changes, IAM restrictions).
             * That deployment frequency and limits have been reviewed.

        ***

        In summary, the remediation is to **review how often your CodePipeline+CodeBuild combination can deploy and add gates (approvals, restricted triggers, IAM)** so that deployments are intentionally controlled rather than unconstrained.
      </Accordion>

      <Accordion title="Using CLI">
        For the “CodePipeline Deployment Limit Check Should Be Reviewed” finding, the remediation is **not** a change on a specific CodeBuild project; it’s about making sure you’re not too close to (or exceeding) AWS service quotas for CodePipeline/CodeBuild and cleaning up or increasing those limits.

        Below are step‑by‑step AWS CLI actions you can take to remediate from the CodeBuild side.

        ***

        ## 1. Identify which limit you are close to

        This Trusted Advisor check generally warns when you’re close to CodePipeline/CodeBuild quotas (e.g., number of pipelines, actions, concurrent builds, etc.).

        List relevant CodeBuild quotas via Service Quotas:

        ```bash theme={null}
        aws service-quotas list-service-quotas \
          --service-code codebuild \
          --region <REGION>
        ```

        Common CodeBuild-related quotas include:

        * `CODEBUILD_CONCURRENT_BUILDS`
        * `CODEBUILD_PROJECTS_PER_ACCOUNT`

        Similarly, for CodePipeline (for context):

        ```bash theme={null}
        aws service-quotas list-service-quotas \
          --service-code codepipeline \
          --region <REGION>
        ```

        Locate the quota whose `UsageMetric` or description matches what you’re nearing (e.g., concurrent builds, number of projects, etc.).

        ***

        ## 2. Reduce current usage (clean up unused CodeBuild resources)

        ### 2.1. List all CodeBuild projects

        ```bash theme={null}
        aws codebuild list-projects --region <REGION>
        ```

        Get details to identify unused projects:

        ```bash theme={null}
        aws codebuild batch-get-projects \
          --names project1 project2 ... \
          --region <REGION>
        ```

        ### 2.2. Delete unused projects

        ```bash theme={null}
        aws codebuild delete-project \
          --name <PROJECT_NAME> \
          --region <REGION>
        ```

        Repeat for all obsolete projects.

        ***

        ## 3. Adjust how many builds run concurrently

        If the issue is around concurrent builds or load on CodeBuild:

        ### 3.1. Reduce parallel builds via batch builds or scheduling

        You can reduce parallelism by controlling how many builds are triggered at once (e.g., from CodePipeline or CI system), but directly on a project you can change `timeoutInMinutes`, environment, etc., not the hard limit. From CLI, update project configuration for better queue handling:

        ```bash theme={null}
        aws codebuild update-project \
          --name <PROJECT_NAME> \
          --source <JSON_SOURCE> \
          --artifacts <JSON_ARTIFACTS> \
          --environment <JSON_ENVIRONMENT> \
          --service-role <ROLE_ARN> \
          --region <REGION>
        ```

        (Use the current project config as a template: `aws codebuild batch-get-projects` → edit → `update-project`.)

        The actual **quota** of concurrent builds itself is an account‑level limit, not per project.

        ***

        ## 4. Request a quota increase (if needed)

        If cleanup/optimization isn’t enough, request a higher limit with Service Quotas.

        1. Find the specific quota code:

        ```bash theme={null}
        aws service-quotas list-service-quotas \
          --service-code codebuild \
          --region <REGION> \
          --output table
        ```

        Note the `QuotaCode` for the quota you need to raise (e.g., `L-XXXXXXX`).

        2. Request an increase:

        ```bash theme={null}
        aws service-quotas request-service-quota-increase \
          --service-code codebuild \
          --quota-code <QUOTA_CODE> \
          --desired-value <NEW_NUMERIC_VALUE> \
          --region <REGION>
        ```

        You can then track the request:

        ```bash theme={null}
        aws service-quotas list-requested-service-quota-change-history \
          --service-code codebuild \
          --region <REGION>
        ```

        ***

        ## 5. Re-run/check the finding

        Once you’ve:

        * Deleted unused projects,
        * Reduced parallelism where practical,
        * And/or increased the service quota,

        re‑run your auditing tool (Security Hub / Trusted Advisor / Config integration) or wait for the next evaluation cycle. The “CodePipeline Deployment Limit Check” should move to a passing or informational state once you’re back under safe utilization of the limit.
      </Accordion>

      <Accordion title="Using Python">
        “CodePipeline Deployment Limit Check Should Be Reviewed” is an AWS Config *managed rule* (`CODEPIPELINE_DEPLOYMENT_LIMIT_CHECK`).\
        It flags CodePipelines whose **Deploy stage has no safe deployment limit** (for example, a CodeDeploy action pushing to too many instances at once).

        Below is how to remediate this specifically for **pipelines that use CodeBuild + CodeDeploy**, using Python (`boto3`).

        ***

        ## 1. Understand what you must change

        For pipelines that deploy via **CodeDeploy**, the “deployment limit” is effectively controlled by the **deployment configuration** on the CodeDeploy *deployment group*:

        * `CodeDeployDefault.OneAtATime` – safest (deploy to one instance at a time).
        * `CodeDeployDefault.HalfAtATime` – deploy to 50% at a time.
        * `CodeDeployDefault.AllAtOnce` – deploy to all at once (usually what the Config rule flags as risky).

        So the usual remediation is:

        1. Identify the CodeDeploy deployment groups your pipeline’s Deploy stage uses.
        2. Change those deployment groups to use a safer `deploymentConfigName`
           (typically `CodeDeployDefault.OneAtATime` or a custom config with suitably low percentages).

        CodeBuild itself does not hold the “deployment limit”; it just builds artifacts. The *Deploy* action in CodePipeline (backed by CodeDeploy) does.

        ***

        ## 2. Find noncompliant CodePipelines from AWS Config (Python)

        ```python theme={null}
        import boto3

        config = boto3.client('config')

        def list_noncompliant_pipelines():
            rule_name = 'CODEPIPELINE_DEPLOYMENT_LIMIT_CHECK'
            paginator = config.get_paginator('get_compliance_details_by_config_rule')

            noncompliant_arns = set()

            for page in paginator.paginate(
                ConfigRuleName=rule_name,
                ComplianceTypes=['NON_COMPLIANT']
            ):
                for result in page['EvaluationResults']:
                    arn = result['EvaluationResultIdentifier']['EvaluationResultQualifier']['ResourceId']
                    noncompliant_arns.add(arn)

            return list(noncompliant_arns)

        print(list_noncompliant_pipelines())
        ```

        This gives you the pipeline names/IDs that the rule is flagging.

        ***

        ## 3. For each pipeline, locate the Deploy action and its CodeDeploy deployment group

        ```python theme={null}
        import boto3

        codepipeline = boto3.client('codepipeline')

        def get_deploy_actions(pipeline_name):
            response = codepipeline.get_pipeline(name=pipeline_name)
            stages = response['pipeline']['stages']

            deploy_actions = []
            for stage in stages:
                if stage['name'].lower() == 'deploy':
                    for action in stage['actions']:
                        if action['actionTypeId']['category'] == 'Deploy' and \
                           action['actionTypeId']['provider'] == 'CodeDeploy':
                            deploy_actions.append(action)
            return deploy_actions

        pipeline_name = 'your-pipeline-name'
        deploy_actions = get_deploy_actions(pipeline_name)
        for a in deploy_actions:
            print(a['name'], a['configuration'])
        ```

        In the Deploy action configuration you should see keys similar to:

        * `ApplicationName`
        * `DeploymentGroupName`

        These map to the CodeDeploy deployment group whose deployment configuration you must change.

        ***

        ## 4. Update the CodeDeploy deployment group to a safer deployment config (Python)

        Example: change `deploymentConfigName` to `CodeDeployDefault.OneAtATime`.

        ```python theme={null}
        import boto3

        codedeploy = boto3.client('codedeploy')

        def set_safer_deployment_config(application_name, deployment_group_name,
                                        deployment_config_name='CodeDeployDefault.OneAtATime'):
            # Get existing group
            dg = codedeploy.get_deployment_group(
                applicationName=application_name,
                deploymentGroupName=deployment_group_name
            )['deploymentGroupInfo']

            # Update only the deploymentConfigName (other required params must be preserved)
            codedeploy.update_deployment_group(
                applicationName=application_name,
                currentDeploymentGroupName=deployment_group_name,
                deploymentConfigName=deployment_config_name,
                # You must re‑pass any fields that are required in your setup
                # e.g. serviceRoleArn, autoScalingGroups, etc., if you modify more fields.
            )

        # Example usage from one pipeline's deploy action
        application_name = 'my-codedeploy-app'
        deployment_group_name = 'my-codedeploy-dg'

        set_safer_deployment_config(application_name, deployment_group_name)
        ```

        Notes:

        * In practice, `update_deployment_group` may require additional parameters if you want to modify other aspects; the minimal example above focuses on `deploymentConfigName`.
        * If you need a more tailored rollout (e.g., 10% at a time), create a custom deployment configuration first (`create_deployment_config`) and then reference it here.

        ***

        ## 5. Optional: End‑to‑end automation for all noncompliant pipelines

        Sketch:

        ```python theme={null}
        def remediate_all_noncompliant():
            pipelines = list_noncompliant_pipelines()
            for pipeline in pipelines:
                deploy_actions = get_deploy_actions(pipeline)
                for action in deploy_actions:
                    app = action['configuration']['ApplicationName']
                    dg  = action['configuration']['DeploymentGroupName']
                    print(f"Remediating {pipeline} → {app}/{dg}")
                    set_safer_deployment_config(app, dg, 'CodeDeployDefault.OneAtATime')

        remediate_all_noncompliant()
        ```

        ***

        If you can paste one of the actual noncompliant pipeline definitions (or the AWS Config rule message), I can tailor the Python exactly to your case (e.g., ECS, CloudFormation, Lambda deployments instead of CodeDeploy).
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_codepipeline" "PIPELINE_NAME" {
          name     = "PIPELINE_NAME"            # replace with your pipeline name
          role_arn = "PIPELINE_SERVICE_ROLE_ARN" # replace with pipeline IAM role

          artifact_store {
            type     = "S3"
            location = "ARTIFACT_BUCKET_NAME"   # replace with S3 bucket name
          }

          # First stage must NOT perform more than the allowed number of deployments.
          # This example shows a single deploy action in the first deployment stage.
          stage {
            name = "DeployToDev"

            action {
              name             = "DeployToDevSingle"   # single deployment
              category         = "Deploy"
              owner            = "AWS"
              provider         = "CodeDeploy"
              version          = "1"
              input_artifacts  = ["BuildOutput"]
              region           = "DEPLOY_REGION"       # replace with region for deployment
              run_order        = 1

              configuration = {
                ApplicationName     = "CODEDEPLOY_APP_NAME"           # replace
                DeploymentGroupName = "CODEDEPLOY_DEPLOYMENT_GROUP"   # replace
              }
            }

            # REMOVE any additional deploy actions here that would exceed the
            # allowed deploymentLimit for this first stage.
            # Example of what to avoid (commented out):
            # action {
            #   name             = "DeployToAnotherEnv"
            #   category         = "Deploy"
            #   owner            = "AWS"
            #   provider         = "CodeDeploy"
            #   version          = "1"
            #   input_artifacts  = ["BuildOutput"]
            #   region           = "ANOTHER_REGION"
            #   run_order        = 1
            #   configuration = {
            #     ApplicationName     = "ANOTHER_CODEDEPLOY_APP"
            #     DeploymentGroupName = "ANOTHER_DEPLOYMENT_GROUP"
            #   }
            # }
          }

          # Subsequent stages must also respect the deploymentLimit if you use it:
          # keep the number of Deploy actions in each stage <= your chosen limit.
          stage {
            name = "DeployToProd"

            action {
              name             = "DeployToProdSingle"
              category         = "Deploy"
              owner            = "AWS"
              provider         = "CodeDeploy"
              version          = "1"
              input_artifacts  = ["BuildOutput"]
              region           = "PROD_REGION"         # replace
              run_order        = 1

              configuration = {
                ApplicationName     = "PROD_CODEDEPLOY_APP"           # replace
                DeploymentGroupName = "PROD_DEPLOYMENT_GROUP"         # replace
              }
            }

            # If your policy allows more than one deployment per stage (deploymentLimit > 1),
            # you can add up to that many Deploy actions here, but not more.
          }

          # other stages (Source, Build, etc.) as needed...
        }
        ```

        This AWS Config rule is evaluated against the CodePipeline pipeline (AWS::CodePipeline::Pipeline), not the `aws_codedeploy_deployment_group` or CodeBuild project, so the remediation is to reduce the number of `Deploy` actions per stage in `aws_codepipeline`, especially in the first deployment stage, to be at or below your chosen `deploymentLimit`.

        This change normally does not force replacement of the pipeline resource itself, but it will update stages and actions in place; expect `terraform plan` to show modifications to the `stage` blocks (removal or reduction of extra `Deploy` actions) and no changes to unrelated resources.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://docs.aws.amazon.com/config/latest/developerguide/codepipeline-deployment-count-check.html](https://docs.aws.amazon.com/config/latest/developerguide/codepipeline-deployment-count-check.html)
