images #42
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
name: images | |
# build, test and scan latest image/tag created from main | |
# https://docs.github.com/en/developers/webhooks-and-events/events/github-event-types | |
# https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule | |
on: | |
push: | |
tags: | |
- 'v[0-9]+.[0-9]+.[0-9]+' # yamllint disable-line rule:quoted-strings | |
schedule: | |
- cron: '0 0 1 * *' # yamllint disable-line rule:quoted-strings | |
env: | |
IMAGE_NAME: jsloan117/docker-openvpn-client | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
scan: | |
name: vulnerability scan | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write # dependency submission API | |
security-events: write # upload sarif report to Github | |
steps: | |
# https://github.com/marketplace/actions/checkout | |
- name: Checkout | |
uses: actions/checkout@v4 | |
# https://github.com/marketplace/actions/docker-metadata-action | |
- name: Docker Metadata | |
uses: docker/metadata-action@v5.2.0 | |
id: meta | |
with: | |
images: ${{ env.IMAGE_NAME }} | |
flavor: latest=false | |
tags: | | |
type=ref,event=tag | |
type=schedule,pattern={{date 'YYYYMMDD'}} | |
# https://github.com/marketplace/actions/docker-setup-buildx | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3.0.0 | |
with: | |
install: true | |
version: latest | |
# https://github.com/marketplace/actions/build-and-push-docker-images | |
- name: Build Image | |
uses: docker/build-push-action@v5.1.0 | |
with: | |
tags: ${{ steps.meta.outputs.tags }} | |
push: false | |
load: true | |
cache-from: type=gha,scope=${{ github.workflow}} | |
cache-to: type=gha,mode=max,scope=${{ github.workflow}} | |
# https://github.com/marketplace/actions/anchore-sbom-action | |
- name: Anchore SBOM Action | |
uses: anchore/sbom-action@v0.15.0 | |
with: | |
image: ${{ steps.meta.outputs.tags }} | |
dependency-snapshot: true | |
# https://github.com/marketplace/actions/anchore-container-scan | |
- name: Anchore Container Scan | |
uses: anchore/scan-action@v3.3.7 | |
id: scan | |
with: | |
image: ${{ steps.meta.outputs.tags }} | |
fail-build: true | |
severity-cutoff: critical | |
# https://github.com/github/codeql-action | |
# https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning | |
- name: Upload Anchore scan SARIF report | |
uses: github/codeql-action/upload-sarif@v2 | |
with: | |
sarif_file: ${{ steps.scan.outputs.sarif }} | |
wait-for-processing: true | |
- name: Set Sarif Report artifact variable | |
run: | | |
echo "sarif_artifact=$(echo ${image_tag} | sed -e 's|/|-|g' -e 's|:|_|g').sarif" >> $GITHUB_ENV | |
env: | |
image_tag: ${{ steps.meta.outputs.tags }} | |
# https://github.com/marketplace/actions/upload-a-build-artifact | |
- name: Upload Sarif Report | |
uses: actions/upload-artifact@v3.1.3 | |
with: | |
name: ${{ env.sarif_artifact }} | |
path: ${{ steps.scan.outputs.sarif }} | |
if-no-files-found: warn | |
build-push: | |
runs-on: ubuntu-latest | |
needs: scan | |
permissions: | |
packages: write # push image to ghcr | |
steps: | |
# https://github.com/marketplace/actions/checkout | |
- name: Checkout | |
uses: actions/checkout@v4 | |
# https://github.com/marketplace/actions/cosign-installer | |
- name: Install Cosign | |
uses: sigstore/cosign-installer@v3.2.0 | |
# https://github.com/marketplace/actions/docker-metadata-action | |
- name: Docker Metadata | |
uses: docker/metadata-action@v5.2.0 | |
id: meta | |
with: | |
images: | | |
${{ env.IMAGE_NAME }} | |
ghcr.io/${{ env.IMAGE_NAME }} | |
flavor: | | |
latest=auto | |
prefix=v,onlatest=false | |
tags: | | |
type=semver,pattern={{version}} | |
type=semver,pattern={{major}}.{{minor}} | |
type=semver,pattern={{major}} | |
type=schedule,pattern={{date 'YYYYMMDD'}} | |
# https://github.com/marketplace/actions/docker-setup-qemu | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3.0.0 | |
# https://github.com/marketplace/actions/docker-setup-buildx | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3.0.0 | |
with: | |
install: true | |
version: latest | |
# https://github.com/marketplace/actions/docker-login | |
- name: Login to Docker Hub | |
if: github.event_name != 'pull_request' | |
uses: docker/login-action@v3.0.0 | |
with: | |
username: jsloan117 | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
# https://github.com/marketplace/actions/docker-login | |
- name: Login to GitHub Container Registry | |
if: github.event_name != 'pull_request' | |
uses: docker/login-action@v3.0.0 | |
with: | |
registry: ghcr.io | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
# https://github.com/marketplace/actions/build-and-push-docker-images | |
- name: Build and push | |
uses: docker/build-push-action@v5.1.0 | |
id: build | |
with: | |
file: ./Dockerfile | |
platforms: linux/amd64,linux/arm64 | |
build-args: | | |
BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} | |
REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | |
push: ${{ github.event_name != 'pull_request' }} | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
cache-from: type=gha,scope=${{ github.workflow}} | |
cache-to: type=gha,mode=max,scope=${{ github.workflow}} | |
- name: Sign Image | |
run: | | |
cosign sign -y --key env://COSIGN_KEY --recursive \ | |
-a "repo=${{ github.repository }}" \ | |
-a "workflow=${{ github.workflow }}" \ | |
-a "ref=${{ github.sha }}" \ | |
-a "ref=${{ github.ref_name }}" \ | |
${{ env.IMAGE_NAME }}@${DIGEST} \ | |
ghcr.io/${{ env.IMAGE_NAME }}@${DIGEST} | |
env: | |
DIGEST: ${{ steps.build.outputs.digest }} | |
COSIGN_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }} | |
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} | |
- name: Verify Image | |
run: | | |
printf '%s' "${COSIGN_PUBLIC_KEY}" > cosign.pub && \ | |
cosign verify --key env://COSIGN_PUBLIC_KEY \ | |
${{ env.IMAGE_NAME }}@${DIGEST} \ | |
ghcr.io/${{ env.IMAGE_NAME }}@${DIGEST} | jq | |
env: | |
DIGEST: ${{ steps.build.outputs.digest }} | |
COSIGN_PUBLIC_KEY: ${{ secrets.COSIGN_PUBLIC_KEY }} | |
# https://github.com/marketplace/actions/upload-a-build-artifact | |
- name: Upload public key | |
uses: actions/upload-artifact@v3.1.3 | |
with: | |
name: cosign.pub | |
path: cosign.pub | |
if-no-files-found: warn | |