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:
- [ ] Pre-commit hooks (secrets, linting)
- [ ] SAST in IDE
- [ ] Secure coding standards
- [ ] Security training
✅ Build:
- [ ] Dependency scanning
- [ ] SAST in pipeline
- [ ] License compliance
- [ ] Build artifact signing
✅ Test:
- [ ] Security unit tests
- [ ] DAST scanning
- [ ] Penetration testing
- [ ] Compliance validation
✅ Deploy:
- [ ] IaC security scanning
- [ ] Container image scanning
- [ ] Secret management
- [ ] Least privilege IAM
✅ Operate:
- [ ] Runtime protection
- [ ] WAF/IDS/IPS
- [ ] Logging & monitoring
- [ ] Incident response
DevSecOps consultancy: iletisim@cesayazilim.com 🚀🔒