Cesa Yazılım
TR EN DE

AMP • TR

DevSecOps 2025: CI/CD Pipeline'da Güvenlik Entegrasyonu

DevSecOps implementation, SAST, DAST, container security, secret management ve secure CI/CD pipeline rehberi.

DevSecOps Implementation 2025

Güvenlik artık sadece production'dan önce değil, geliştirme sürecinin her aşamasında olmalı. DevSecOps implementation rehberi.

DevSecOps Nedir?

Traditional: Dev → Ops → Security (waterfall)
DevOps: Dev + Ops (agile)
DevSecOps: Dev + Sec + Ops (security-first agile)

┌────────────────────────────────────────────┐
│  PLAN → CODE → BUILD → TEST → RELEASE →   │
│  DEPLOY → OPERATE → MONITOR                │
│         ↑                                   │
│      SECURITY (her aşamada)                │
└────────────────────────────────────────────┘

Secure CI/CD Pipeline

GitHub Actions Example

name: DevSecOps Pipeline

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    
    steps:
      # 1. Code checkout
      - uses: actions/checkout@v3
      
      # 2. Secret scanning
      - name: TruffleHog Secret Scan
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./
          base: ${{ github.event.repository.default_branch }}
          head: HEAD
      
      # 3. SAST (Static Application Security Testing)
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@master
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
      
      # 4. Dependency scanning
      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main
        with:
          project: 'my-app'
          path: '.'
          format: 'HTML'
      
      # 5. Container image scanning
      - name: Trivy Vulnerability Scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      # 6. IaC scanning
      - name: Checkov IaC Scan
        uses: bridgecrewio/checkov-action@master
        with:
          directory: ./terraform/
          framework: terraform
      
      # 7. Upload results
      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: trivy-results.sarif

Static Application Security Testing (SAST)

SonarQube Integration

# sonar-project.properties
sonar.projectKey=my-app
sonar.sources=src
sonar.tests=tests
sonar.exclusions=**/node_modules/**,**/*.test.js

# Security-specific rules
sonar.java.binaries=target/classes
sonar.security.hotspots.enableSA=true
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml

Semgrep Rules

# .semgrep.yml
rules:
  - id: sql-injection
    pattern: |
      db.query($SQL)
    message: Possible SQL injection
    severity: ERROR
    languages: [javascript]
    
  - id: hardcoded-secret
    pattern: |
      password = "..."
    message: Hardcoded password detected
    severity: ERROR
    
  - id: insecure-random
    pattern: Math.random()
    message: Use crypto.randomBytes() for security
    severity: WARNING

Dynamic Application Security Testing (DAST)

# OWASP ZAP Automated Scan
docker run -t owasp/zap2docker-stable zap-baseline.py \
  -t https://example.com \
  -r zap-report.html \
  -J zap-report.json

# Nuclei vulnerability scanner
nuclei -u https://example.com \
  -t nuclei-templates/ \
  -o nuclei-results.txt \
  -severity critical,high

Container Security

Dockerfile Security

# 1. Use specific, minimal base image
FROM node:18-alpine3.18 AS builder

# 2. Don't run as root
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

# 3. Use multi-stage builds
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

# 4. Final minimal image
FROM node:18-alpine3.18
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

WORKDIR /app

# 5. Copy only necessary files
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules

# 6. Switch to non-root user
USER nodejs

# 7. Expose port
EXPOSE 3000

# 8. Health check
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node healthcheck.js

# 9. Run application
CMD ["node", "dist/server.js"]

Trivy Scanning

# Scan Docker image
trivy image myapp:latest

# Scan with severity filter
trivy image --severity HIGH,CRITICAL myapp:latest

# Scan filesystem
trivy fs /path/to/project

# Generate SARIF for GitHub
trivy image --format sarif -o results.sarif myapp:latest

Secret Management

HashiCorp Vault

const vault = require('node-vault')({
  endpoint: 'http://vault:8200',
  token: process.env.VAULT_TOKEN
});

async function getSecret(path) {
  try {
    const result = await vault.read(`secret/data/${path}`);
    return result.data.data;
  } catch (error) {
    console.error('Failed to read secret:', error);
    throw error;
  }
}

// Usage
const dbCreds = await getSecret('database/prod');
const connection = createConnection({
  host: dbCreds.host,
  user: dbCreds.username,
  password: dbCreds.password
});

AWS Secrets Manager

import boto3
import json

def get_secret(secret_name):
    client = boto3.client('secretsmanager', region_name='us-east-1')
    
    try:
        response = client.get_secret_value(SecretId=secret_name)
        return json.loads(response['SecretString'])
    except Exception as e:
        print(f"Error: {e}")
        raise

# Usage
db_creds = get_secret('prod/database')
connection = psycopg2.connect(
    host=db_creds['host'],
    user=db_creds['username'],
    password=db_creds['password']
)

Infrastructure as Code (IaC) Security

Terraform Security

# Enable encryption
resource "aws_s3_bucket" "secure_bucket" {
  bucket = "my-secure-bucket"
  
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm     = "AES256"
      }
    }
  }
  
  # Block public access
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
  
  # Versioning
  versioning {
    enabled = true
  }
  
  # Logging
  logging {
    target_bucket = aws_s3_bucket.log_bucket.id
    target_prefix = "access-logs/"
  }
}

Checkov Scanning

# Scan Terraform
checkov -d ./terraform/

# Scan Kubernetes manifests
checkov -d ./k8s/ --framework kubernetes

# Scan Dockerfile
checkov -f Dockerfile

# Output as JSON
checkov -d . -o json > checkov-results.json

Kubernetes Security

# Secure Pod configuration
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  # Security context
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  
  containers:
  - name: app
    image: myapp:1.0
    
    # Container security context
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    
    # Resource limits
    resources:
      limits:
        memory: "512Mi"
        cpu: "500m"
      requests:
        memory: "256Mi"
        cpu: "250m"
    
    # Liveness probe
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10

Security Metrics

SAST Metrics:
  - Code coverage: > 80%
  - Critical vulnerabilities: 0
  - High vulnerabilities: < 5
  - Scan time: < 10 minutes

DAST Metrics:
  - Scan coverage: > 90%
  - Critical findings: 0
  - False positive rate: < 10%
  - Scan frequency: Daily

Container Metrics:
  - Base image age: < 30 days
  - Known vulnerabilities: 0 critical
  - Image size: Minimize
  - Scan time: < 5 minutes

Pipeline Metrics:
  - Security scan success rate: > 99%
  - Mean time to fix: < 24 hours
  - Security gate pass rate: > 95%

DevSecOps Checklist

Code:

Build:

Test:

Deploy:

Operate:


DevSecOps consultancy: iletisim@cesayazilim.com 🚀🔒