Introduction:
As containerized applications become integral to modern DevOps workflows, ensuring the security of container images is paramount. This guide explores a GitLab CI pipeline setup that seamlessly integrates security scanning using the SNYK API, validation with Conftest, and artifact management on Docker Hub and linting the Dockerfile using Dockerlinter.
Key Components and Tools:
Conftest: Policy as Code (PaC) tool for validating configuration files against Rego policies.
SNYK Secure API: Leveraging Snyk for vulnerability scanning and image security.
Docker Hub: Centralized container image registry for storing and managing Docker images.
DockerLinter: Dockerlinter is a Dockerfile linter that focuses on best practices and recommendations from the official Docker documentation
DockerFile Sample
# Use an official Python runtime as a parent image
FROM python:3.8-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
Sample Rego Code to Validate DockerFile
package main
suspicious_env_keys = [
"passwd",
"password"
]
# Looking for suspicious environment variable settings
deny[msg] {
dockerenvs := [val | input[i].Cmd == "env"; val := input[i].Value]
dockerenv := dockerenvs[_]
envvar := dockerenv[_]
lower(envvar) == suspicious_env_keys[_]
msg = sprintf("Potential secret in ENV found: %s", [envvar])
}
You can create your own Rego code to enforce granular restrictions or policies in a more fine-grained manner, you can customize the Rego policy accordingly.
Here is the pipeline
---
variables:
IMAGE_CONFTEST: "omvedi25/conftest:v0.2"
IMAGE_SNYK: "omvedi25/snyk:v0.1"
IMAGE_LINTER: "omvedi25/dockerlinter:v0.0"
stages:
- lint
- validation
- scan
- push
linting:Dockerfile:
image: "$IMAGE_LINTER"
stage: lint
script:
- dockerlinter -f Dockerfile -e
validation:Dockerfile:
image: "$IMAGE_CONFTEST"
stage: validation
script:
- conftest test -p /policy Dockerfile
scanning:Image:
image: "$IMAGE_SNYK"
stage: scan
script:
- podman build -t test .
- image_id=`podman images --format "table {{.Repository}}\t{{.ID}}" | awk '$1 == "localhost/test" {print $2}'`
- podman save $image_id -o test.tar
- snyk auth $SNYK_TOKEN
- snyk container test docker-archive:test.tar --json > results.json || true
- snyk-to-html -i results.json -o results.html
artifacts:
paths:
- results.html
expire_in: 1 week
pushing:Image:
image: "$IMAGE_SNYK"
stage: push
script:
- podman login -u $USERNAME -p $PASSWORD docker.io
- podman build -t test .
- podman tag localhost/test:latest omvedi25/$CI_PROJECT_NAME:$CI_COMMIT_SHA
- podman images
- podman push omvedi25/$CI_PROJECT_NAME:$CI_COMMIT_SHA
when: manual
Pipeline Stages
Linting Output
Validation Output
SNKY HTML REPORT
PUSH IMAGE
Top comments (0)