Why DevSecOps?
Finding vulnerabilities in production is 100x more expensive than finding them during development. DevSecOps integrates security into every stage of the development lifecycle.
The Security Pipeline
Complete GitHub Actions Pipeline
name: DevSecOps Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Dependency vulnerability scanning
- name: Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
path: '.'
format: 'HTML'
# SAST - Static Analysis
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Secret scanning
- name: Gitleaks
uses: gitleaks/gitleaks-action@v2
# Container scanning
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
severity: 'CRITICAL,HIGH'SAST - Static Application Security Testing
# SonarQube configuration (sonar-project.properties)
sonar.projectKey=my-project
sonar.organization=my-org
sonar.sources=src
sonar.tests=test
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# Security rules
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=javascript:S2068
sonar.issue.ignore.multicriteria.e1.resourceKey=**/*.test.jsCustom Security Rules
// ESLint security plugin configuration
module.exports = {
plugins: ['security'],
extends: ['plugin:security/recommended'],
rules: {
'security/detect-object-injection': 'error',
'security/detect-non-literal-regexp': 'warn',
'security/detect-unsafe-regex': 'error',
'security/detect-buffer-noassert': 'error',
'security/detect-eval-with-expression': 'error'
}
};DAST - Dynamic Application Security Testing
# OWASP ZAP in CI pipeline
dast:
stage: test
image: owasp/zap2docker-stable
script:
- mkdir -p /zap/wrk/
- zap-baseline.py -t $APP_URL -r zap_report.html
artifacts:
paths:
- zap_report.htmlDependency Scanning
# Snyk integration
name: Snyk Security
jobs:
snyk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
command: test
args: --severity-threshold=high// package.json audit script
{
"scripts": {
"audit": "npm audit --production",
"audit:fix": "npm audit fix",
"security:check": "snyk test && snyk monitor"
}
}Infrastructure as Code Security
# Terraform security scanning with Checkov
security-iac:
stage: security
image: bridgecrew/checkov:latest
script:
- checkov -d ./terraform --framework terraform
allow_failure: falseContainer Security
# Dockerfile best practices
FROM node:18-alpine AS builder
# Use non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Install dependencies only
COPY package*.json ./
RUN npm ci --only=production
# Copy app
COPY --chown=nextjs:nodejs . .
# Switch to non-root user
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]Security Gates
// Quality gate configuration
const securityGate = {
critical: 0, // Zero critical vulnerabilities allowed
high: 5, // Max 5 high vulnerabilities
medium: 20, // Max 20 medium vulnerabilities
codeSmells: 50, // Max 50 code smells
coverage: 80 // Minimum 80% code coverage
};
function evaluateGate(scanResults) {
if (scanResults.critical > securityGate.critical) {
throw new Error('Critical vulnerabilities found - blocking deployment');
}
// Additional checks...
}Secrets Management
# Pre-commit hooks for secret detection
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.16.1
hooks:
- id: gitleaksCompliance as Code
# Open Policy Agent (OPA) policy
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Deployment"
not input.request.object.spec.template.spec.securityContext.runAsNonRoot
msg := "Containers must not run as root"
}
deny[msg] {
input.request.kind.kind == "Deployment"
container := input.request.object.spec.template.spec.containers[_]
not container.resources.limits
msg := "Container must have resource limits"
}Conclusion
DevSecOps is about making security everyone's responsibility. Automate security checks, fail fast, and continuously improve your security posture.