Container Scanning in DevSecOps
Why Container Scanning Became My Non-Negotiable Security Practice
My Container Scanning Approach in GitLab CI/CD
stages:
- build
- test
- scan
- review
- deploy
variables:
DOCKER_DRIVER: overlay2
CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
TRIVY_NO_PROGRESS: "true"
TRIVY_CACHE_DIR: ".trivycache/"
SCAN_KUBERNETES_MANIFESTS: "true"
# Build the container image
build:
stage: build
image: docker:20.10.16
services:
- docker:20.10.16-dind
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- docker build --pull -t $CONTAINER_IMAGE .
- docker push $CONTAINER_IMAGE
cache:
paths:
- .npm/
- node_modules/
tags:
- docker
# Run application tests
test:
stage: test
image: $CONTAINER_IMAGE
script:
- npm test
cache:
paths:
- node_modules/
# GitLab built-in container scanning
container_scanning:
stage: scan
image:
name: registry.gitlab.com/gitlab-org/security-products/container-scanning:latest
variables:
DOCKER_IMAGE: $CONTAINER_IMAGE
GIT_STRATEGY: fetch
allow_failure: false
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
expire_in: 1 week
# Custom Trivy scan with detailed configuration
trivy-scan:
stage: scan
image:
name: aquasec/trivy:latest
entrypoint: [""]
variables:
TRIVY_USERNAME: "$CI_REGISTRY_USER"
TRIVY_PASSWORD: "$CI_REGISTRY_PASSWORD"
TRIVY_AUTH_URL: "$CI_REGISTRY"
TRIVY_NO_PROGRESS: "true"
TRIVY_FORMAT: "template"
TRIVY_OUTPUT: "trivy-results.json"
TRIVY_SEVERITY: "CRITICAL,HIGH"
TRIVY_EXIT_CODE: "1"
TRIVY_VULN_TYPE: "os,library"
TRIVY_TEMPLATE: "@/contrib/gitlab.tpl"
script:
- trivy image --cache-dir .trivycache/ --exit-code $TRIVY_EXIT_CODE --format $TRIVY_FORMAT --output $TRIVY_OUTPUT --template "$TRIVY_TEMPLATE" --vuln-type $TRIVY_VULN_TYPE --severity $TRIVY_SEVERITY $CONTAINER_IMAGE
cache:
paths:
- .trivycache/
artifacts:
reports:
container_scanning: trivy-results.json
expire_in: 1 week
allow_failure: false
# Scan manifest files for misconfigurations
kube-scan:
stage: scan
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy config --severity HIGH,CRITICAL --exit-code 1 ./kubernetes/
rules:
- exists:
- kubernetes/**/*.yaml
- kubernetes/**/*.yml
allow_failure: true
# Manual review for findings before production deployment
security-review:
stage: review
script:
- echo "Review security findings before proceeding to production"
allow_failure: false
when: manual
only:
- main
# Deploy to production
deploy-production:
stage: deploy
script:
- kubectl set image deployment/my-app container=$CONTAINER_IMAGE
environment:
name: production
only:
- main
when: manual
needs:
- security-reviewGitLab's Built-in Container Scanning vs. Trivy: Why I Use Both
GitLab Container Scanning
Aquasec Trivy
Real-world Lessons from Container Scanning
1. Base Image Selection is Critical
2. Multi-stage Builds Reduce Attack Surface
3. False Positives Need Management
Managing Container Vulnerabilities in Production
The ROI of Container Scanning
Getting Started with Container Scanning
Conclusion: Shifting Container Security Left
Last updated