Skip to main content

GitLab CI Integration

Integrate Cloudgeni security scanning into your GitLab CI/CD pipelines to automatically check Infrastructure as Code for security issues on every push and merge request.

What You'll Get

  • Automated security scanning in your CI/CD pipeline
  • Merge request gates that block insecure code
  • SAST integration with GitLab Security Dashboard
  • Fail-on-severity configuration for quality gates
  • Detailed reports in merge request widgets

Prerequisites

  • GitLab repository with CI/CD enabled
  • Cloudgeni account and API key
  • Repository containing IaC files (.tf, .bicep, .hcl, .yaml, etc.)

Quick Start

Step 1: Create API Key

  1. Go to SettingsAPI Keys in Cloudgeni
  2. Click Create API Key
  3. Name it gitlab-ci
  4. Copy the generated key

Step 2: Add CI/CD Variable

  1. Go to your GitLab project
  2. Navigate to SettingsCI/CDVariables
  3. Click Add variable
  4. Configure:
    • Key: CLOUDGENI_API_KEY
    • Value: Your API key
    • Type: Variable
    • Flags: Mask variable, Protect variable
  5. Click Add variable

Step 3: Add Pipeline Job

Add to your .gitlab-ci.yml:
stages:
  - security

cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Configuration Options

Scanner Options

OptionDescriptionDefault
--api-keyCloudgeni API keyRequired
--fail-on-criticalExit 1 on critical findingsfalse
--fail-on-highExit 1 on high findingsfalse
--fail-on-mediumExit 1 on medium findingsfalse
--pathDirectory to scan.
--excludePaths to excludeNone
--outputOutput format (text, json, sarif)text

Basic Job

cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY

Strict Mode

cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --fail-on-critical --fail-on-high
  allow_failure: false

Custom Path

cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --path ./infrastructure --exclude ./infrastructure/test

Pipeline Examples

Basic Pipeline

stages:
  - security

cloudgeni:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Production Pipeline

stages:
  - validate
  - security
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/infrastructure

.terraform:
  image: hashicorp/terraform:latest
  before_script:
    - cd ${TF_ROOT}
    - terraform init

security-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan
        --api-key $CLOUDGENI_API_KEY
        --path $TF_ROOT
        --fail-on-critical
        --fail-on-high
        --output json > cloudgeni-report.json
  artifacts:
    reports:
      sast: cloudgeni-report.json
    paths:
      - cloudgeni-report.json
    when: always
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

terraform-plan:
  extends: .terraform
  stage: plan
  script:
    - terraform plan -out=plan.tfplan
  artifacts:
    paths:
      - ${TF_ROOT}/plan.tfplan
  needs:
    - security-scan
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

Multi-Environment Pipeline

stages:
  - security

.scan-template:
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --path $SCAN_PATH --fail-on-critical

scan-dev:
  extends: .scan-template
  variables:
    SCAN_PATH: ./environments/dev
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^feature\//

scan-staging:
  extends: .scan-template
  variables:
    SCAN_PATH: ./environments/staging
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"

scan-production:
  extends: .scan-template
  variables:
    SCAN_PATH: ./environments/production
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --path $SCAN_PATH --fail-on-critical --fail-on-high
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Only Scan Changed Files

cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - |
      if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
        CHANGED_FILES=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD -- '*.tf' '*.bicep' '*.hcl')
        if [ -n "$CHANGED_FILES" ]; then
          cloudgeni scan --api-key $CLOUDGENI_API_KEY --files "$CHANGED_FILES"
        else
          echo "No IaC files changed"
        fi
      else
        cloudgeni scan --api-key $CLOUDGENI_API_KEY
      fi
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - "**/*.tf"
        - "**/*.bicep"
        - "**/*.hcl"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Merge Request Integration

MR Widget

Security findings appear in the merge request:
  • Security widget shows findings summary
  • Click to expand detailed view
  • Links to Cloudgeni dashboard

Blocking Merges

Configure merge request approvals:
  1. Go to SettingsMerge requests
  2. Enable Pipelines must succeed
  3. Security job will block merge on failures

SARIF Reports

Enable GitLab Security Dashboard integration:
cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --output sarif > gl-sast-report.json
  artifacts:
    reports:
      sast: gl-sast-report.json

Group-Level Variables

For multiple projects:
  1. Go to Group SettingsCI/CDVariables
  2. Add CLOUDGENI_API_KEY at group level
  3. All projects in group can use the variable
  4. Override at project level if needed

Caching

Speed up scans with caching:
cloudgeni-scan:
  stage: security
  image: cloudgeni/scanner:latest
  cache:
    key: cloudgeni-${CI_COMMIT_REF_SLUG}
    paths:
      - .cloudgeni-cache/
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY --cache-dir .cloudgeni-cache

Scheduled Scans

Run regular security scans:
cloudgeni-scheduled:
  stage: security
  image: cloudgeni/scanner:latest
  script:
    - cloudgeni scan --api-key $CLOUDGENI_API_KEY
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
Configure schedule in CI/CDSchedules.

Troubleshooting

Variable Not Found:
  • Check variable name matches exactly
  • Verify variable is not protected (for unprotected branches)
  • Check variable scope (project vs group)
Authentication Failed:
  • Verify API key is correct
  • Check key hasn’t expired
  • Ensure variable is masked but accessible
Image Pull Failed:
  • Verify Docker is enabled for CI/CD
  • Check container registry access
  • Try docker pull cloudgeni/scanner:latest locally
Scan Timeout:
  • Large repositories take longer
  • Add timeout: 30m to job
  • Consider scanning specific paths
No SARIF Report:
  • Ensure --output sarif is specified
  • Check artifact path is correct
  • Verify job completed successfully