CI/CD Pipeline Security Gates
Integrate security scanning into GitHub Actions, GitLab CI, or Jenkins to block insecure deployments.
Overview
Shift security left by integrating automated security scanning directly into your CI/CD pipeline. This tutorial shows you how to use reNgine Cloud API to scan staging environments, block deployments with critical vulnerabilities, and track security debt over time.
What You'll Learn
- API-based scan triggering from CI/CD workflows
- Fail pipelines on critical security findings
- Parallel scanning of staging environments
- Generate security badges for README files
- Track security debt metrics over time
Step 1: API-Based Scan Triggering
Use the reNgine Cloud API to trigger scans automatically when code is pushed to staging or production branches. Store your API key as a CI/CD secret for secure authentication.
# GitHub Actions Workflow
name: Security Scan
on:
push:
branches: [staging, main]
pull_request:
branches: [main]
jobs:
security_scan:
runs-on: ubuntu-latest
steps:
- name: Trigger reNgine Scan
env:
RENGINE_API_KEY: ${{ secrets.RENGINE_API_KEY }}
RENGINE_URL: ${{ secrets.RENGINE_URL }}
run: |
SCAN_ID=$(curl -X POST "$RENGINE_URL/api/scans" \
-H "Authorization: Bearer $RENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "staging.example.com",
"scan_type": "full",
"notify_on_completion": true
}' | jq -r '.scan_id')
echo "SCAN_ID=$SCAN_ID" >> $GITHUB_ENV
echo "Started scan: $SCAN_ID"Step 2: Fail Pipelines on Critical Findings
Poll the scan status API until completion, then check for critical or high-severity vulnerabilities. Fail the pipeline if security thresholds are exceeded.
- name: Wait for Scan Completion
run: |
while true; do
STATUS=$(curl -s "$RENGINE_URL/api/scans/$SCAN_ID/status" \
-H "Authorization: Bearer $RENGINE_API_KEY" \
| jq -r '.status')
if [ "$STATUS" = "completed" ]; then
break
fi
echo "Scan status: $STATUS. Waiting 30s..."
sleep 30
done
- name: Check Security Findings
run: |
RESULTS=$(curl -s "$RENGINE_URL/api/scans/$SCAN_ID/results" \
-H "Authorization: Bearer $RENGINE_API_KEY")
CRITICAL=$(echo $RESULTS | jq '.findings.critical // 0')
HIGH=$(echo $RESULTS | jq '.findings.high // 0')
echo "Critical: $CRITICAL, High: $HIGH"
# Fail if critical findings exist
if [ "$CRITICAL" -gt 0 ]; then
echo "❌ CRITICAL vulnerabilities found! Blocking deployment."
exit 1
fi
# Warn if high findings exist
if [ "$HIGH" -gt 3 ]; then
echo "⚠️ Warning: $HIGH HIGH severity findings detected"
exit 1
fi
echo "✅ Security scan passed"Step 3: Parallel Staging Environment Scans
For microservices architectures, scan multiple staging endpoints in parallel to reduce total pipeline time. Use matrix builds to scale across services.
GitLab CI Configuration
stages:
- deploy
- security
deploy_staging:
stage: deploy
script:
- deploy_to_staging.sh
environment:
name: staging
security_scan:
stage: security
parallel:
matrix:
- SERVICE: [api, web, admin, mobile-api]
script:
- |
curl -X POST "$RENGINE_URL/api/scans" \
-H "Authorization: Bearer $RENGINE_API_KEY" \
-d "{\"target\": \"$SERVICE.staging.example.com\"}"
only:
- staging
- mainStep 4: Generate Security Badges
Create visual security status badges for your README to communicate security posture to stakeholders. Use shields.io or generate custom SVG badges via API.
- name: Generate Security Badge
run: |
SCORE=$(curl -s "$RENGINE_URL/api/scans/$SCAN_ID/score" \
-H "Authorization: Bearer $RENGINE_API_KEY" \
| jq -r '.security_score')
# Determine badge color
if [ "$SCORE" -gt 90 ]; then COLOR="brightgreen"
elif [ "$SCORE" -gt 70 ]; then COLOR="yellow"
else COLOR="red"; fi
# Generate badge URL
BADGE_URL="https://img.shields.io/badge/security-$SCORE%25-$COLOR"
echo "" >> security-badge.md
- name: Update README
run: |
# Replace security badge in README
sed -i "s|!\[Security\].*|$(cat security-badge.md)|" README.md
- name: Commit Badge Update
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "Update security badge [skip ci]"
file_pattern: README.mdStep 5: Track Security Debt Over Time
Store scan results as CI/CD artifacts and track security metrics across deployments. Use dashboards to visualize trends and measure security improvement.
Jenkins Pipeline Example
pipeline {
agent any
stages {
stage('Deploy to Staging') {
steps {
sh 'deploy_staging.sh'
}
}
stage('Security Scan') {
steps {
script {
def scanId = sh(
script: """curl -X POST ${env.RENGINE_URL}/api/scans \
-H 'Authorization: Bearer ${env.RENGINE_API_KEY}' \
-d '{"target": "staging.example.com"}' \
| jq -r '.scan_id'""",
returnStdout: true
).trim()
env.SCAN_ID = scanId
}
}
}
stage('Wait & Validate') {
steps {
script {
timeout(time: 30, unit: 'MINUTES') {
waitUntil {
def status = sh(
script: "curl -s ${env.RENGINE_URL}/api/scans/${env.SCAN_ID}/status | jq -r '.status'",
returnStdout: true
).trim()
return status == 'completed'
}
}
def critical = sh(
script: "curl -s ${env.RENGINE_URL}/api/scans/${env.SCAN_ID}/results | jq '.findings.critical'",
returnStdout: true
).trim().toInteger()
if (critical > 0) {
error("Critical vulnerabilities found! Deployment blocked.")
}
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'security-report.json', allowEmptyArchive: true
publishHTML([
reportDir: 'security',
reportFiles: 'report.html',
reportName: 'Security Scan Report'
])
}
}
}Best Practices
- Scan Staging First: Never run destructive scans against production
- Define Thresholds: Set clear severity thresholds for pipeline failures
- Cache Results: Avoid re-scanning identical deployments
- Timeout Protection: Set maximum wait times to prevent hung pipelines
- Exception Workflow: Allow security team to approve exceptions for known issues
- Notifications: Alert security team on pipeline failures
Next Steps
- Deploy reNgine Cloud on AWS or Azure
- Review API documentation for advanced options
- Learn about SIEM integration for centralized monitoring
- Get support from our team via contact page