Uninstalling DevGuard
Digital sovereignty is crucial in today’s world where control over your own data and software is essential. By maintaining digital sovereignty, you ensure that you have full control over your digital assets and can protect your privacy and security. Thus it is mandatory to have a clear understanding of how to uninstall DevGuard from your system and software development environment that you do not depend on DevGuard as well.
This guide provides step-by-step instructions on how to uninstall DevGuard from your system and gives an overview of alternative tools which are somewhat comparable to DevGuard.
How to Uninstall
DevGuard consists of multiple components. Precisely, it includes:
- DevGuard Server Infrastructure: The api, web frontend, authorization server and database. This component gets either used as Software as a Server, it gets manually installed or deployed in the organization infrastructure using a Helm-Chart.
- DevGuard CLI: A Command Line Interface (CLI) tool that is used inside the CI/CD Pipeline to scan the project and verify integrity as well as installed on the developer’s machine to scan the project before pushing it to the repository.
- DevGuard CI/CD Component or DevGuard Reusable Workflow: A reusable workflow (for GitHub users) or a CI/CD component (for GitLab users) that can be used in the CI/CD pipeline. This component utilizes the DevGuard CLI to scan the project and verify integrity.
Uninstalling the DevGuard Server Infrastructure
Before uninstalling the server infrastructure, make sure to backup the data if you want to keep it for future use. DevGuard stores its data in a PostgreSQL database. You can backup the database using the following command:
# exec into the pod to dump the database
kubectl exec --namespace <NAMESPACE> -it <POSTGRES POD NAME> -- bash -c "pg_dump -U <POSTGRES USER> <POSTGRES DATABASE> > /tmp/backup.sql"
# copy the backup to your local machine
kubectl cp --namespace <NAMESPACE> <POSTGRES POD NAME>:/tmp/backup.sql /tmp/backup.sql
Usually your deployment infrastructure already provides a backup mechanism for the database. Thus you do not need to backup the database manually.
Uninstalling the DevGuard Server Infrastructure is as simple as deleting the Helm-Chart or the manually installed components. If you have deployed the DevGuard Server Infrastructure using a Helm-Chart, you can delete the Helm-Chart using the following command:
helm delete <RELEASE NAME> --namespace <NAMESPACE>
Uninstalling the DevGuard CLI
The DevGuard CLI is a standalone binary that can be installed on the developer’s machine. To uninstall the DevGuard CLI, you can simply delete the binary from your machine. The binary is usually located in the /usr/local/bin
directory. You can find the path to the binary by running the following command:
which devguard-scanner
Once you have found the path to the binary, you can delete it using the following command:
rm /usr/local/bin/devguard-scanner
Uninstalling the DevGuard CI/CD Component
The DevGuard CI/CD Component is a reusable workflow (for GitHub users) or a CI/CD component (for GitLab users) that can be used in the CI/CD pipeline. To uninstall the DevGuard CI/CD Component, you can simply delete the workflow or the CI/CD component from your repository.
Alternatives
CI/CD Security Scanning Tools
Here is an example reusable workflow which can be used as an alternative to the DevGuard CI/CD Component. The definition makes use of the following tools (which devguard does as well)
Tool | Purpose |
---|---|
Gitleaks | Secret scanning |
Trivy | Software composition analysis and container scanning |
Checkov | Infrastructure as code scanning |
Semgrep | Static application security testing |
Kaniko | OCI Build without root privileges |
Crane | OCI Image Push |
Cosign | Image Signing |
# DevSecOps Workflow Definition
name: DevSecOps Workflow
on:
push:
branches:
- '*'
tags:
- '*'
permissions:
contents: read
jobs:
# Gitleaks secret scanning: Identifies potential security risks by detecting unintentionally
# exposed sensitive information within the Git repository
# like passwords, API keys, or other secrets.
secret-scanning:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Gitleaks Scan
run: |
docker run --rm -v $(pwd):/code -u $(id -u):$(id -g) zricethezav/gitleaks:v8.18.1@sha256:6945c62ca019ead32bc337ab0c9fd055e98d82961765d38b7ccccc84dae95d0f -s /code detect -f sarif -r /code/gitleaks.sarif.json
- name: Upload sarif file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: gitleaks.sarif.json
category: secret-scanning
# Software composition analysis: Conducts dependency scanning using npm's built-in audit tool.
# Note: Language-specific software-composition-analysis tools are typically preferred; consider replacing npm audit with Trivy, if the language does not provide
# a built-in software-composition-analysis tool.
software-composition-analysis:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner in fs mode
# Running Trivy to scan the filesystem for vulnerabilities
uses: aquasecurity/trivy-action@v0.19.0
with:
scan-type: "fs"
scan-ref: "."
severity: "CRITICAL,HIGH"
format: "sarif"
output: "trivy-results.sarif"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "trivy-results.sarif"
category: "software-composition-analysis"
# Scan infrastructure-as-code (infrastructure-as-code-scanning) files for security and compliance issues.
# This stage runs the Checkov tool provided by Bridgecrew to analyze infrastructure-as-code-scanning files
# (YAML, JSON, Terraform, CloudFormation, etc.) for misconfigurations and best
# practices violations.
infrastructure-as-code-scanning:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Test with Checkov
id: checkov
uses: bridgecrewio/checkov-action@v12.2731.0
with:
directory: .
# Static application security testing: Utilizes Semgrep to perform static analysis, enhancing code security by
# identifying vulnerabilities and potential security flaws within the application's source code.
static-application-security-testing:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Semgrep
# Running Semgrep for static code analysis to identify security issues
uses: docker://returntocorp/semgrep@sha256:7843a979bf88d9d16c476e9f7f547b573187f395532b1f74825fd58c6463c5b0
with:
args: semgrep scan /github/workspace --sarif -o /github/workspace/semgrep.sarif.json
- name: Upload sarif file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep.sarif.json
category: static-application-security-testing
# OCI Build: Uses Kaniko to build Docker images securely without requiring privileged access (docker in docker needs privileged access). The artifacts are not pushed to the registry until they have undergone security scanning to ensure vulnerabilities are addressed before deployment - therefore they are stored as artifacts rather than pushed to the registry.
oci-build:
permissions:
packages: write
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v4
- name: Set IMAGE_TAG if tagged
# Setting the image tag if the push is a tag push
run: |
echo "ghcr.io/${{ github.repository }}:${GITHUB_REF#refs/tags/}" > image-tag.txt
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/')
- name: Set IMAGE_TAG if not tagged
run: |
branch=${GITHUB_REF##*/}
sha=${GITHUB_SHA::8}
ts=$(date +%s)
echo "ghcr.io/${{ github.repository }}:${branch}-${sha}-${ts}" > image-tag.txt
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
if: github.ref == 'refs/heads/main'
- name: Build Docker image with Kaniko
# Building the Docker image using Kaniko
id: build_image
uses: docker://gcr.io/kaniko-project/executor:v1.9.2@sha256:034f15e6fe235490e64a4173d02d0a41f61382450c314fffed9b8ca96dff66b2
with:
args: --destination=${{ env.IMAGE_TAG }} --context=/github/workspace --dockerfile=/github/workspace/Dockerfile --no-push --tarPath /github/workspace/image.tar
- name: Setup crane
uses: imjasonh/setup-crane@v0.1
- name: Use crane to get the digest
run: crane digest --tarball=image.tar > digest.txt
- name: Upload artifact
# Uploading the built Docker image as an artifact
uses: actions/upload-artifact@v4
with:
name: docker-image
path: image.tar
- name: Upload digest
# Uploading the built Docker image digest as an artifact
uses: actions/upload-artifact@v4
with:
name: digest
path: digest.txt
- name: Upload image tag
uses: actions/upload-artifact@v4
with:
name: image-tag
path: image-tag.txt
# Container scanning: Utilizes Trivy to perform vulnerability scanning on the built container image
container-scanning:
needs: oci-build
permissions:
security-events: write
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: docker-image
path: .
- name: Run Trivy vulnerability scanner in tarball mode
# Running Trivy to scan the Docker image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
input: /github/workspace/image.tar
severity: "CRITICAL,HIGH"
format: "sarif"
output: "trivy-results.sarif"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: "trivy-results.sarif"
category: "container-scanning"
# OCI Image Push: Publishes the built container image to the container registry, ensuring it is available for deployment.
# Dependencies include successful completion of the 'oci:build', 'container-scanning', 'secret-scanning', 'static-application-security-testing', 'software-composition-analysis', and 'tag' stages, ensuring that the image is built securely and meets quality standards before publication.
publish:
needs: [oci-build, container-scanning, secret-scanning, software-composition-analysis, static-application-security-testing, infrastructure-as-code-scanning]
runs-on: ubuntu-latest
permissions:
packages: write
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/download-artifact@v4
with:
name: docker-image
path: .
- uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: set IMAGE_TAG env
run: |
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- uses: imjasonh/setup-crane@v0.1
- name: Push Docker image to GitHub image Registry
# Pushing the Docker image to GitHub Container Registry
run: crane push image.tar ${{ env.IMAGE_TAG }}
# SBOM (Software Bill of Materials) generation: Utilizes Syft to create a Software Bill of Materials in CycloneDX JSON format from the built container image, providing a comprehensive inventory of software components and their dependencies for improved transparency and vulnerability management.
sbom:
runs-on: ubuntu-latest # Specify the runner
needs: [oci-build]
container:
image: alpine:3.19.1@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b
steps:
- name: Install curl
run: apk add --update curl
- name: Install Syft
run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Download artifact from previous build
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Generate SBOM with Syft
run: syft ./image.tar -o cyclonedx-json=sbom.json
- name: Upload SBOM as an artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
# Image Signing: Signs the container image using Cosign to provide cryptographic verification of its integrity and authenticity. The signing process involves authentication, followed by the application of a digital signature using the provided private key.
sign-image:
permissions:
packages: write
runs-on: ubuntu-latest
needs: publish
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- name: cosign-installer
uses: sigstore/cosign-installer@v3.3.0
with:
cosign-release: 'v2.2.3' # optional
- name: Download digest
uses: actions/download-artifact@v4
with:
name: digest
path: .
- name: Download image tag
uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: Read digest and image tag from file
run: |
export IMAGE_DIGEST=$(cat digest.txt)
echo "IMAGE_DIGEST=$IMAGE_DIGEST" >> $GITHUB_ENV
export IMAGE_TAG=$(cat image-tag.txt)
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Write signing key to disk (only needed for `cosign sign --key`)
run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key
- name: Sign the published Docker image
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
run: cosign sign --yes --key cosign.key "$(cat image-tag.txt)@${{ env.IMAGE_DIGEST }}"
# SBOM Signing: Signs the Software Bill of Materials (SBOM) using Cosign to provide cryptographic verification of its integrity and authenticity.
sign-sbom:
runs-on: ubuntu-latest
permissions:
packages: write
needs: publish
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
steps:
- name: cosign-installer
uses: sigstore/cosign-installer@v3.3.0
with:
cosign-release: 'v2.2.3' # optional
- name: Download digest
uses: actions/download-artifact@v4
with:
name: digest
path: .
- name: Download image tag
uses: actions/download-artifact@v4
with:
name: image-tag
path: .
- name: Download sbom tag
uses: actions/download-artifact@v4
with:
name: sbom
path: .
- name: Login to GitHub Container Registry
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Write signing key to disk (only needed for `cosign sign --key`)
run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key
- name: Sign SBOM
run: cosign attest --yes --predicate ./sbom.json --key cosign.key "$(cat image-tag.txt)@$(cat digest.txt)"
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}