DEV Community

AMIT CHATURVEDI
AMIT CHATURVEDI

Posted on

Automating Container Image Security with GitLab: A Comprehensive Guide using Dockerlinter, Conftest, SNYK API, and Docker Hub

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"]

Enter fullscreen mode Exit fullscreen mode

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])
}

Enter fullscreen mode Exit fullscreen mode

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  

Enter fullscreen mode Exit fullscreen mode

Pipeline Stages

Image description

Linting Output

Image description

Validation Output

Image description

SNKY HTML REPORT

Image description

PUSH IMAGE

Image description

Top comments (0)