Pipeline-Based Access Control

Pipeline-Based Access Control

CI/CD pipelines introduce another access control layer between code repositories and cloud environments. Pipeline permissions determine who can trigger deployments, approve stages, and access deployment logs. Modern pipeline platforms provide sophisticated RBAC models that integrate with enterprise identity providers.

Stage-based approvals enable different teams to control different deployment phases. Security teams might approve security scanning stages, while operations teams approve production deployments. These approvals can be manual for critical changes or automated based on predefined criteria.

# Example GitLab CI/CD pipeline with RBAC controls
stages:
  - validate
  - plan
  - security-review
  - deploy-dev
  - deploy-staging
  - deploy-prod

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/infrastructure
  TF_STATE_NAME: ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}

.terraform_init: &terraform_init
  - cd ${TF_ROOT}
  - terraform init
    -backend-config="key=${TF_STATE_NAME}"
    -backend-config="bucket=${STATE_BUCKET}"
    -backend-config="region=${AWS_DEFAULT_REGION}"

validate:
  stage: validate
  script:
    - *terraform_init
    - terraform fmt -check=true
    - terraform validate
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

plan:
  stage: plan
  script:
    - *terraform_init
    - terraform plan -out=tfplan
    - terraform show -json tfplan > tfplan.json
  artifacts:
    paths:
      - ${TF_ROOT}/tfplan
      - ${TF_ROOT}/tfplan.json
    expire_in: 7 days
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

security-review:
  stage: security-review
  script:
    - checkov -f tfplan.json --framework terraform_plan
    - opa eval -d policies/ -i tfplan.json "data.terraform.deny[_]"
  artifacts:
    reports:
      terraform: ${TF_ROOT}/tfplan.json
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

deploy-dev:
  stage: deploy-dev
  environment:
    name: development
  script:
    - *terraform_init
    - terraform apply -auto-approve
  rules:
    - if: '$CI_COMMIT_BRANCH == "develop"'
      when: manual
  only:
    - develop

deploy-staging:
  stage: deploy-staging
  environment:
    name: staging
  script:
    - assume-role ${STAGING_ROLE_ARN}
    - *terraform_init
    - terraform apply -auto-approve
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual
      allow_failure: false
  only:
    - main
  needs:
    - job: deploy-dev
      optional: true

deploy-prod:
  stage: deploy-prod
  environment:
    name: production
  script:
    - assume-role ${PROD_ROLE_ARN}
    - *terraform_init
    - terraform apply -auto-approve
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual
      allow_failure: false
  only:
    - main
  needs:
    - job: deploy-staging
    - job: security-approval
  allow_failure: false

security-approval:
  stage: deploy-prod
  script:
    - echo "Security team approval required"
  when: manual
  only:
    - main
  allow_failure: false
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual
  # Restricted to security team members
  only:
    variables:
      - $GITLAB_USER_LOGIN =~ /^(security-lead|security-admin|ciso)$/

Environment-specific permissions ensure teams can only deploy to appropriate environments. Junior developers might deploy to development environments while senior engineers handle staging deployments. Production deployments often require special authorization or multiple approvals from different teams.