Skip to content

Build and Publish Extra UBI Packages for Hardening #368

Build and Publish Extra UBI Packages for Hardening

Build and Publish Extra UBI Packages for Hardening #368

# Copyright 2023-2024 The MathWorks, Inc.
name: Build and Publish Extra UBI Packages for Hardening
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'ubi-hardening-extras/**'
- "!ubi-hardening-extras/**.md"
schedule:
- cron: '0 0 * * *'
env:
BASE_IMAGE: almalinux-base
jobs:
build-base-image:
runs-on: ubuntu-latest
# This job builds the base image and uploads it to the artifacts.
# The following jobs all build from this base image.
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build base image and save as tar archive
uses: docker/build-push-action@v5
with:
context: ./ubi-hardening-extras/${{ env.BASE_IMAGE }}
tags: ${{ env.BASE_IMAGE }}:latest
outputs: type=docker,dest=/tmp/${{ env.BASE_IMAGE }}.tar
- name: Upload base image archive to artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ env.BASE_IMAGE }}
path: /tmp/${{ env.BASE_IMAGE }}.tar
retention-days: 1
build-and-publish-ubi-hardening-extras:
runs-on: ubuntu-latest
needs: build-base-image
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
package: [icewm, novnc, tigervnc, xterm]
tag: [ubi9.4]
include:
- package: matlab
tag: R2024b
env:
IMAGE_NAME: ghcr.io/${{ github.repository }}/ubi-hardening-extras/${{ matrix.package }}
RED: \033[0;31m
GREEN: \033[0;32m
ORANGE: \033[0;33m
NC: \033[0m
# This job builds the Docker image for a specific UBI package.
# It then checks if the package is different from the last version published.
# Finally, it updates GHCR if the package was updated.
# This runs for all packages in the matrix.
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download base image archive from artifacts
uses: actions/download-artifact@v4
with:
name: ${{ env.BASE_IMAGE }}
path: /tmp
- name: Load base image from tar archive
run: |
docker load --input /tmp/${{ env.BASE_IMAGE }}.tar
docker image ls -a
- name: Make image save location
run: |
mkdir -p /tmp/new
# Build the package Docker image locally to retrieve the new signature.
# We will only push to GHCR if the new package SHA-256 is different from the latest one.
- name: Build new UBI package Docker image to file system
uses: docker/build-push-action@v5
with:
context: ./ubi-hardening-extras/${{ matrix.package }}
build-args: BASE_IMAGE=${{ env.BASE_IMAGE }}
outputs: type=tar,dest=/tmp/new/${{ matrix.package }}.tar
push: false
- name: Login to GitHub Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# Try to retrieve the latest package pushed to GHCR.
# This will error when running this action for the first time.
- name: Pull latest UBI package Docker image from ghcr
id: pull_latest
continue-on-error: true
run: |
docker pull ${{ env.IMAGE_NAME }}:${{ matrix.tag }}
- name: Extract signature and version from latest Docker image
id: extract
run: |
# Extract signature and version files from latest docker image if pull was succesful.
if [[ ${{ steps.pull_latest.outcome }} == 'success' ]]; then
VERSION=$(bash ./ubi-hardening-extras/workflow/extract_metadata.sh ${{ env.IMAGE_NAME }}:${{ matrix.tag }})
echo -e "${{ env.GREEN }}>> Found ${{ env.IMAGE_NAME }} version ${VERSION}.${{ env.NC }}"
NEXT_VERSION=$(bash ./ubi-hardening-extras/workflow/increment_version.sh ${VERSION})
else
echo -e "${{ env.RED }}>> Image ${{ env.IMAGE_NAME }} does not exist.${{ env.NC }}"
NEXT_VERSION="v1.0"
fi
echo "next_version=${NEXT_VERSION}" >> $GITHUB_OUTPUT
- name: Check latest signature against new signature
id: check
run: |
# Compare the SHA-256 signature of the latest published package versus the new build
(cd /tmp/new && mkdir image-layers && tar -xf ${{ matrix.package }}.tar -C image-layers)
STATUS=$(cmp --silent /tmp/latest/*.sha256 /tmp/new/image-layers/*.sha256; echo $?)
if [[ "${STATUS}" == '0' ]]; then
echo -e "${{ env.GREEN }}>> ${{ matrix.package }} has not changed, nothing to do.${{ env.NC }}"
else
echo -e "${{ env.ORANGE }}>> ${{ matrix.package }} has changed, updating the artifacts.${{ env.NC }}"
fi
echo "is_identical=${STATUS}" >> $GITHUB_OUTPUT
# Rebuild the same package Docker image from step "Build new UBI package Docker image to file system"
# this time build locally storing the new version number.
# The build relies on the docker build cache to simply update the version and push.
- name: Build Docker image for UBI packages
uses: docker/build-push-action@v5
if: ${{ steps.check.outputs.is_identical != '0' }}
with:
context: ./ubi-hardening-extras/${{ matrix.package }}
build-args: |
BASE_IMAGE=${{ env.BASE_IMAGE }}
VERSION=${{ steps.extract.outputs.next_version }}
tags: |
${{ env.IMAGE_NAME }}:${{ matrix.tag }}
${{ env.IMAGE_NAME }}:${{ steps.extract.outputs.next_version }}-${{ matrix.tag }}
- name: Set up Python 3
if: ${{ steps.check.outputs.is_identical != '0' }}
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install test dependencies
if: ${{ steps.check.outputs.is_identical != '0' }}
working-directory: ubi-hardening-extras/tests
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Test new UBI package Docker image
if: ${{ steps.check.outputs.is_identical != '0' }}
working-directory: ubi-hardening-extras/tests
env:
IMAGE_UNDER_TEST: ${{ env.IMAGE_NAME }}:${{ matrix.tag }}
run: python -m unittest ${{ matrix.package }}/*.py
# Push the package Docker image built in the "Build Docker image for UBI packages" step to GHCR
# (since we now know if something has changed).
- name: Push to GitHub Container Registry if package has changed
if: ${{ steps.check.outputs.is_identical != '0' }}
run: docker push --all-tags ${{ env.IMAGE_NAME }}