From 2067157ce4bd9f76ea097d24c5bb9dc15ccfe13b Mon Sep 17 00:00:00 2001 From: Mari Date: Sat, 10 Jan 2026 02:03:38 -0500 Subject: [PATCH] Add Containerfile for Podman/Docker This adds a simple Containerfile to run Tang within a Fedora-based container. In this PR, the image is not published anywhere, but it is built and tested. Also updates the README to remove the dead link to the external image. Progress on #107. --- .github/workflows/build.yml | 40 ++++++++++++++++++++++++++ .github/workflows/install-dependencies | 10 +++---- Containerfile | 17 +++++++++++ README.md | 20 +++++++++---- tests/adv | 4 ++- tests/adv-podman | 30 +++++++++++++++++++ tests/adv-podman-endpoint | 30 +++++++++++++++++++ tests/adv-socat | 2 +- tests/adv-socat-endpoint | 2 +- tests/helpers | 20 ++++++++++++- tests/meson.build | 13 +++++++++ tests/rec-podman | 30 +++++++++++++++++++ tests/rec-podman-endpoint | 30 +++++++++++++++++++ tests/rec-socat | 2 +- tests/rec-socat-endpoint | 2 +- tests/rec-standalone | 2 -- tests/rec-standalone-endpoint | 2 -- 17 files changed, 235 insertions(+), 21 deletions(-) create mode 100644 Containerfile create mode 100644 tests/adv-podman create mode 100644 tests/adv-podman-endpoint create mode 100755 tests/rec-podman create mode 100755 tests/rec-podman-endpoint diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d9d655..98d806f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,4 +71,44 @@ jobs: env: DISTRO: ${{matrix.os}} + build-podman: + runs-on: ubuntu-24.04 + env: + DISTRO: ubuntu:noble + steps: + - uses: actions/checkout@v6 + + - name: Show OS information + run: cat /etc/os-release 2>/dev/null || \ + echo /etc/os-release not available + + - name: Install build dependencies + run: sudo --preserve-env bash .github/workflows/install-dependencies + + - name: Build tang + run: | + mkdir -p build && cd build + export ninja=$(command -v ninja) + [ -z "${ninja}" ] && export ninja=$(command -v ninja-build) + meson setup .. || cat meson-logs/meson-log.txt >&2 + ${ninja} + export podman=$(command -v podman) + [ -n "${podman}" ] && ${podman} build -t tangd .. + + - name: Run tests + run: | + cd build + if ! meson test ; then + cat meson-logs/testlog.txt >&2 + exit -1 + fi + + - name: Show full test logs + run: | + if [ -r build/meson-logs/testlog.txt ]; then + cat build/meson-logs/testlog.txt >&2 + else + echo "No test log available" >&2 + fi + # vim:set ts=2 sw=2 et: diff --git a/.github/workflows/install-dependencies b/.github/workflows/install-dependencies index c8729ac..822a947 100755 --- a/.github/workflows/install-dependencies +++ b/.github/workflows/install-dependencies @@ -6,7 +6,7 @@ ubuntu:focal) apt clean apt update apt -y install gcc pkg-config libjose-dev jose libhttp-parser-dev \ - systemd gcovr curl socat iproute2 asciidoc git python3-pip ninja-build + systemd gcovr curl socat iproute2 asciidoc git python3-pip ninja-build apt remove -y meson pip3 install --upgrade meson ;; @@ -16,7 +16,7 @@ debian:*|ubuntu:*) apt clean apt update apt -y install gcc meson pkg-config libjose-dev jose libhttp-parser-dev \ - systemd gcovr curl socat iproute2 asciidoc git + systemd gcovr curl socat iproute2 asciidoc git podman ;; *fedora:*) @@ -24,7 +24,7 @@ debian:*|ubuntu:*) dnf -y clean all dnf -y --setopt=deltarpm=0 update dnf -y install gcc meson pkgconfig libjose-devel jose llhttp-devel \ - systemd gcovr curl socat iproute asciidoc git + systemd gcovr curl socat iproute asciidoc git podman ;; centos:7) @@ -33,7 +33,7 @@ centos:7) yum install -y yum-utils epel-release yum config-manager -y --set-enabled PowerTools \ || yum config-manager -y --set-enabled powertools || : - yum -y install meson socat iproute asciidoc git + yum -y install meson socat iproute asciidoc git podman yum-builddep -y tang ;; @@ -43,7 +43,7 @@ centos:7) dnf install -y dnf-plugins-core epel-release dnf config-manager -y --set-enabled powertools \ || dnf config-manager -y --set-enabled crb || : - dnf -y install meson socat iproute git + dnf -y install meson socat iproute git podman dnf builddep -y tang --allowerasing --skip-broken --nobest ;; esac diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..c3cf0d9 --- /dev/null +++ b/Containerfile @@ -0,0 +1,17 @@ +FROM quay.io/fedora/fedora:latest AS build +RUN dnf -y --setopt=deltarpm=0 update && \ + dnf -y install gcc pkgconfig meson libjose-devel jose llhttp-devel +RUN mkdir -p /build/in /build/out +COPY . /build/in/ +WORKDIR /build/out +RUN meson setup ../in && ninja-build + +FROM quay.io/fedora/fedora:latest AS runtime +RUN dnf -y install jose llhttp +COPY src/tang-show-keys /bin/ +COPY --from=build /build/out/src/tangd /build/out/src/tangd-rotate-keys /build/out/src/tangd-keygen /bin/ + +VOLUME [ "/jwkdir" ] +EXPOSE 9090 + +CMD [ "/bin/tangd", "-l", "-p", "9090", "/jwkdir" ] \ No newline at end of file diff --git a/README.md b/README.md index 0106a69..545ef8b 100644 --- a/README.md +++ b/README.md @@ -124,14 +124,22 @@ and start the server: # service tangd enable # service tangd start -#### Docker Container +#### Docker/Podman Container -Tang is also available as a [Docker -Container](https://gitlab.com/AdrianKoshka/tang-docker-container/). +Tang can also be built as a Docker or Podman image using the included +Containerfile. -Care should be taken to ensure that, when deploying in a container cluster, -that the Tang keys are not stored on the same physical medium that you wish to -protect. +When deploying in a container cluster, care should be taken to ensure that the +Tang keys are not stored on the same physical medium that you wish to protect. + +By default, this container starts in listen mode on port 9090 of all addresses +within the container, with the key directory set to the container's `/jwkdir`. +This path should be bound to a key storage location on the container host. + +Note that socket activation is **not supported** for Tang Podman containers, as +Tang uses inetd-style socket activation (`Accept=yes`) rather than systemd-style +socket activation (`Accept=no`), and Podman quadlets do not support inetd-style +socket activation due to containers/podman#22874 (among other reasons). ### Building and Installing from Source diff --git a/tests/adv b/tests/adv index 416dc6e..c21c42e 100755 --- a/tests/adv +++ b/tests/adv @@ -75,7 +75,9 @@ adv_second_phase () { test "$(tang-show-keys $PORT $ENDPOINT)" = "$(jose jwk thp -a "${THP_DEFAULT_HASH}" -i $TMP/db/sig.jwk)" # Check that new keys will be created if none exist. - rm -rf "${TMP}/db" && mkdir -p "${TMP}/db" + # Use find to delete the contents here because deleting the directory + # breaks the container-volume link in Podman tests, which is a problem. + find "${TMP}/db" -mindepth 1 -depth -delete fetch "${ENDPOINT}"/adv # Now let's make sure the new keys were named using our default thumbprint diff --git a/tests/adv-podman b/tests/adv-podman new file mode 100644 index 0000000..51ec789 --- /dev/null +++ b/tests/adv-podman @@ -0,0 +1,30 @@ +#!/bin/sh -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2026 Marissa Lyndon +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +. adv + +sanity_check_podman + +adv_startup + +export PORT=$(random_port) +export CONTAINER=$(start_podman_server "${PORT}") +wait_for_port "${PORT}" + +adv_second_phase diff --git a/tests/adv-podman-endpoint b/tests/adv-podman-endpoint new file mode 100644 index 0000000..f15b95d --- /dev/null +++ b/tests/adv-podman-endpoint @@ -0,0 +1,30 @@ +#!/bin/sh -ex +# +# Copyright (c) 2026 Marissa Lyndon +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +. adv + +sanity_check_podman + +adv_startup + +export PORT=$(random_port) +export ENDPOINT="/api/dee-hms" +export CONTAINER=$(start_podman_server_endpoint "${PORT}" "${ENDPOINT}") +wait_for_port "${PORT}" + +adv_second_phase diff --git a/tests/adv-socat b/tests/adv-socat index 02c9037..3349a50 100755 --- a/tests/adv-socat +++ b/tests/adv-socat @@ -20,7 +20,7 @@ . adv -sanity_check +sanity_check_socat adv_startup diff --git a/tests/adv-socat-endpoint b/tests/adv-socat-endpoint index c4deb88..aa7f3e2 100644 --- a/tests/adv-socat-endpoint +++ b/tests/adv-socat-endpoint @@ -19,7 +19,7 @@ . adv -sanity_check +sanity_check_socat adv_startup diff --git a/tests/helpers b/tests/helpers index ebce966..c707352 100755 --- a/tests/helpers +++ b/tests/helpers @@ -83,11 +83,22 @@ start_standalone_server_endpoint() { ${VALGRIND} tangd -p ${1} -l ${TMP}/db -e ${2} & } +start_podman_server() { + "${PODMAN}" run -d -p "${1}":9090 -v "${TMP}"/db:/jwkdir localhost/tangd +} + +start_podman_server_endpoint() { + "${PODMAN}" run -d -p "${1}":9090 -v "${TMP}"/db:/jwkdir localhost/tangd /bin/tangd -p 9090 -l -e "${2}" /jwkdir +} + on_exit() { if [ "${PID}" ]; then kill "${PID}" || true wait "${PID}" || true fi + if [ -n "${PODMAN}" ] && [ -n "${CONTAINER}" ]; then + "${PODMAN}" stop --time 1 "${CONTAINER}" + fi [ -d "${TMP}" ] && rm -rf "${TMP}" } @@ -114,11 +125,18 @@ validate_exc() { --use deriveKey 2>/dev/null } -sanity_check() { +sanity_check_socat() { # Skip test if socat is not available. [ -n "${SOCAT}" ] || exit 77 } +sanity_check_podman() { + # Skip test if podman is not available or the image does not exist. + if [ -z "${PODMAN}" ] || ! podman image exists localhost/tangd; then + exit 77 + fi +} + die() { echo "${1}" >&2 exit 1 diff --git a/tests/meson.build b/tests/meson.build index e2e9924..0a898f0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -23,6 +23,11 @@ socat = find_program( required: false ) +podman = find_program( + 'podman', + required: false +) + env = environment() env.prepend('PATH', join_paths(meson.source_root(), 'src'), @@ -40,10 +45,18 @@ if socat.found() env.set('SOCAT', socat.path()) endif +if podman.found() + env.set('PODMAN', podman.path()) +endif + +test('adv-podman', find_program('adv-podman'), env: env, timeout: 360) +test('adv-podman-endpoint', find_program('adv-podman-endpoint'), env: env, timeout: 360) test('adv-standalone', find_program('adv-standalone'), env: env, timeout: 360) test('adv-standalone-endpoint', find_program('adv-standalone-endpoint'), env: env, timeout: 360) test('adv-socat', find_program('adv-socat'), env: env, timeout: 360) test('adv-socat-endpoint', find_program('adv-socat-endpoint'), env: env, timeout: 360) +test('rec-podman', find_program('rec-podman'), env: env, timeout: 360) +test('rec-podman-endpoint', find_program('rec-podman-endpoint'), env: env, timeout: 360) test('rec-standalone', find_program('rec-standalone'), env: env, timeout: 360) test('rec-standalone-endpoint', find_program('rec-standalone-endpoint'), env: env, timeout: 360) test('rec-socat', find_program('rec-socat'), env: env, timeout: 360) diff --git a/tests/rec-podman b/tests/rec-podman new file mode 100755 index 0000000..f41ac75 --- /dev/null +++ b/tests/rec-podman @@ -0,0 +1,30 @@ +#!/bin/sh -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2026 Marissa Lyndon +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +. rec + +sanity_check_podman + +rec_startup + +export PORT=$(random_port) +export CONTAINER=$(start_podman_server "${PORT}") +wait_for_port "${PORT}" + +rec_second_phase diff --git a/tests/rec-podman-endpoint b/tests/rec-podman-endpoint new file mode 100755 index 0000000..73e8e4b --- /dev/null +++ b/tests/rec-podman-endpoint @@ -0,0 +1,30 @@ +#!/bin/sh -ex +# +# Copyright (c) 2026 Marissa Lyndon +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +. rec + +sanity_check_podman + +rec_startup + +export PORT=$(random_port) +export ENDPOINT="api/dee-hms" +export CONTAINER=$(start_podman_server_endpoint "${PORT}" "${ENDPOINT}") +wait_for_port "${PORT}" + +rec_second_phase_endpoint diff --git a/tests/rec-socat b/tests/rec-socat index 2b1483d..4ffc05f 100755 --- a/tests/rec-socat +++ b/tests/rec-socat @@ -20,7 +20,7 @@ . rec -sanity_check +sanity_check_socat rec_startup diff --git a/tests/rec-socat-endpoint b/tests/rec-socat-endpoint index f62d919..d2273ff 100644 --- a/tests/rec-socat-endpoint +++ b/tests/rec-socat-endpoint @@ -19,7 +19,7 @@ . rec -sanity_check +sanity_check_socat rec_startup diff --git a/tests/rec-standalone b/tests/rec-standalone index 0538f12..609d975 100755 --- a/tests/rec-standalone +++ b/tests/rec-standalone @@ -20,8 +20,6 @@ . rec -sanity_check - rec_startup # Start the server diff --git a/tests/rec-standalone-endpoint b/tests/rec-standalone-endpoint index 2e7e1b8..67eb88b 100755 --- a/tests/rec-standalone-endpoint +++ b/tests/rec-standalone-endpoint @@ -19,8 +19,6 @@ . rec -sanity_check - rec_startup # Start the server