From f24ee37762c6f72f515ef22ac28efade2b334457 Mon Sep 17 00:00:00 2001 From: Harald Nagel Date: Thu, 13 Nov 2025 20:31:55 -0700 Subject: [PATCH 1/2] Add Dockerfile; add GitHub Actions build --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++++ CI.md | 39 +++++++++++++++++++++++++++++++++++++++ DOCKER.md | 35 +++++++++++++++++++++++++++++++++++ Dockerfile | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 CI.md create mode 100644 DOCKER.md create mode 100644 Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..109f9db --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: ci +run-name: ${{ github.actor }} is running ci + +on: + push: + workflow_dispatch: + pull_request: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Authenticate with container registry + uses: docker/login-action@v3 + with: + username: ${{ vars.CR_USER }} + registry: ${{ vars.CR_REGISTRY }} + password: ${{ secrets.CR_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + push: true + tags: ${{ vars.CR_REGISTRY }}/${{ vars.CR_OWNER }}/seal-c:latest + diff --git a/CI.md b/CI.md new file mode 100644 index 0000000..e205fd4 --- /dev/null +++ b/CI.md @@ -0,0 +1,39 @@ +# Continuous Integration + +In order to build the project automatically in GitHub follow these steps: + +1. Fork the project +2. In your fork select the "Settings" option +3. On the left, expand "Secrets and variables" +4. Select "Actions" +5. Choose the "Variables" tab +6. Create the following "repository variables": + 1. `CR_OWNER` - the value of this should be what's before the slash in the GitHub repository name, either your GitHub username or the name of the organization which owns the repository + 2. `CR_REGISTRY` - the container registry to push to, in this case ghcr.io for the GitHub Container Registry + 3. `CR_USER` - the user who owns the Personal Access Token with rights to upload the container (likely your GitHub username, this might be the same as `CR_OWNER` if this repo is not part of an organization) +7. Click on the "Secrets" tab +8. In another tab or browser window, open the [Classic Personal Access Tokens](https://github.com/settings/tokens) settings page (for more information on this process you can see GitHub's [Creating a personal access token (classic)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) guidance). +9. Click "Generate a new token" and choose "Generate a new token (classic)" +10. Put something meaningful in the note (such as: _Project name_ deployment token) +11. Choose an expiration date - you'll have to create a new token and update the value in the repo as frequently as you select here. "No expiration" is obviously most convenient and least secure. +12. For scopes, select the following: + 1. `repo` + 2. `write:packages` + 3. `read:packages` + 4. `delete:packages` +13. Choose "Generate token" +14. Optionally: save the token in your secure password manager in case you lose it +15. Go back to your other tab/browser window and click "New repository secret" +16. Name this secret `CR_TOKEN` and put enter your token into the Secret box +17. Click "Add secret" +18. Kick off a manual workflow run: + 1. Navigate to the repo + 2. Click the "Actions" tab at the top + 3. Select the "ci" workflow from the left nav + 4. Click the "Run workflow" dropdown on the right + 5. Choose the green "Run workflow" button +19. Once the build has succeded it pushes a container into the GitHub Container Registry - though it may not be linked to the project. To link it: + 1. Navigate to your GitHub profile page (click your icon in the top right and choose "Profile") + 2. Choose the "Packages" tab at the top + 3. You should see a container registry named after the project, click it + diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..f73fb93 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,35 @@ +# SEAL-C in docker + +SEAL-C has a Dockerfile and you are able to build the project in a container and use it directly from Docker. + +## Building + +Once you clone the repository, with Docker or similar (e.g. Podman) you shoudl be able to build the Docker container with: + +`docker build -t sealtool .` + +## Using the container + +You can replace wherever you would use the `sealtool` command with the following in Linux/macOS: + +- Using your locally-built image: `docker run --rm -v ${PWD}:/root sealtool:latest` +- Using the image from the GitHub Container Registry: `docker run --rm -v ${PWD}:/root ghcr.io/hackerfactor/seal-c:latest` + +In this command: + +1. Docker is running the container +2. `--rm` means to delete the container after use +3. `-v ${PWD}:/root` says to map the current directory to `/root` inside the container. That way if you have files to SEAL or configuration files in your current directory they are accessible inside the container. + +### Example + +Starting from scratch, you can perform the following (this follows the steps under "Local Signing" in BUILD.md): + +1. Make a new directory. In that directory place a file to sign (e.g. banana.jpg). +2. Run: `docker run --rm -v ${PWD}:/root ghcr.io/hackerfactor/seal-c:latest -g -K rsa -k seal-rsa.key -D seal-rsa.dns` +3. Once the container exits, you'll see the two files (`seal-rsa.key` and `seal-rsa.dns`) in your current directory. +4. Add the contents of the `seal-rsa.dns` to a `TXT` record under your domain. +5. Now sign your image file: `docker run --rm -v ${PWD}:/root ghcr.io/hackerfactor/seal-c:latest -s -d example.com -K rsa -k seal-rsa.key banana.jpg` +6. You should now see your signed file in the directory +7. Verify your signed file with `docker run --rm -v ${PWD}:/root ghcr.io/hackerfactor/seal-c:latest banana-seal.jpg` + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3d64e19 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM debian:stable AS build + +WORKDIR /usr/local/src + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + g++ \ + libcurl4-openssl-dev \ + libperl-dev \ + libssl-dev \ + make + +RUN curl -L https://sourceforge.net/projects/exiftool/files/Image-ExifTool-13.41.tar.gz/download > exiftool.tgz \ + && tar -xf exiftool.tgz \ + && cd Image-ExifTool-* \ + && perl Makefile.PL \ + && make install + +WORKDIR /app + +COPY . ./ + +RUN make all + +#RUN cd tests \ +# && /bin/bash ./test-all.sh + +FROM debian:stable-slim AS publish + +WORKDIR /root + +RUN apt-get update \ + && apt-get install --no-install-recommends -y libcurl4-openssl-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=build "/app/bin/sealtool" "/usr/local/bin/" + +ENTRYPOINT ["/usr/local/bin/sealtool"] From 56a3c7bf4863ddddc7979cc3153b26edefd18b67 Mon Sep 17 00:00:00 2001 From: Harald Nagel Date: Fri, 14 Nov 2025 17:10:25 -0700 Subject: [PATCH 2/2] Incorporate tests into CI builds --- .github/workflows/ci.yml | 5 ++- CI.md | 5 ++- Dockerfile | 7 +++- tests/config.sample | 9 +++++ tests/test-all-ci.sh | 84 ++++++++++++++++++++++++++++++++++++++++ tests/test-all.sh | 0 6 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 tests/config.sample create mode 100755 tests/test-all-ci.sh mode change 100644 => 100755 tests/test-all.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 109f9db..9a5e428 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: ci run-name: ${{ github.actor }} is running ci on: + pull_request: push: workflow_dispatch: - pull_request: jobs: docker: @@ -22,4 +22,7 @@ jobs: with: push: true tags: ${{ vars.CR_REGISTRY }}/${{ vars.CR_OWNER }}/seal-c:latest + secrets: | + signid=${{ secrets.SIGNMYDATA_ID }} + apikey=${{ secrets.SIGNMYDATA_APIKEY }} diff --git a/CI.md b/CI.md index e205fd4..9145dc2 100644 --- a/CI.md +++ b/CI.md @@ -26,13 +26,14 @@ In order to build the project automatically in GitHub follow these steps: 15. Go back to your other tab/browser window and click "New repository secret" 16. Name this secret `CR_TOKEN` and put enter your token into the Secret box 17. Click "Add secret" -18. Kick off a manual workflow run: +18. If you want to run all of the tests on each build, add secrets named `SIGNMYDATA_APIKEY` and `SIGNMYDATA_ID` so that you can use [signmydata.com](https://signmydata.com/) for remote tests. +19. Kick off a manual workflow run: 1. Navigate to the repo 2. Click the "Actions" tab at the top 3. Select the "ci" workflow from the left nav 4. Click the "Run workflow" dropdown on the right 5. Choose the green "Run workflow" button -19. Once the build has succeded it pushes a container into the GitHub Container Registry - though it may not be linked to the project. To link it: +20. Once the build has succeded it pushes a container into the GitHub Container Registry - though it may not be linked to the project. To link it: 1. Navigate to your GitHub profile page (click your icon in the top right and choose "Profile") 2. Choose the "Packages" tab at the top 3. You should see a container registry named after the project, click it diff --git a/Dockerfile b/Dockerfile index 3d64e19..e98bd39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,8 +24,10 @@ COPY . ./ RUN make all -#RUN cd tests \ -# && /bin/bash ./test-all.sh +RUN --mount=type=secret,id=apikey,env=SIGNMYDATA_APIKEY \ + --mount=type=secret,id=signid,env=SIGNMYDATA_ID \ + cd tests \ + && ./test-all-ci.sh FROM debian:stable-slim AS publish @@ -38,3 +40,4 @@ RUN apt-get update \ COPY --from=build "/app/bin/sealtool" "/usr/local/bin/" ENTRYPOINT ["/usr/local/bin/sealtool"] + diff --git a/tests/config.sample b/tests/config.sample new file mode 100644 index 0000000..29c80e5 --- /dev/null +++ b/tests/config.sample @@ -0,0 +1,9 @@ +# Sample config file for running remote tests +# Add "apikey" and "id" and populate them +domain=signmydata.com +digestalg=sha256 +keyalg=rsa +kv=1 +sf=date:hex +apiurl=https://signmydata.com/?sign +outfile=./%b-seal%e diff --git a/tests/test-all-ci.sh b/tests/test-all-ci.sh new file mode 100755 index 0000000..4b8d30f --- /dev/null +++ b/tests/test-all-ci.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# Runs all test scripts in the tests folder. + +readonly CI_STARTAT=$SECONDS + +# Everything is relative to this test directory. +cd $(dirname "$0") + +MISSING_CONFIG=false + +if [[ -n ${XDG_CONFIG_HOME} && -f "${XDG_CONFIG_HOME}/seal/config" ]]; then + echo "*** Using configuration file in ${XDG_CONFIG_HOME} for tests" +elif [[ -f "${HOME}/.config/seal/config" ]]; then + echo "*** Using configuration file for tests" +elif [[ -n "${SIGNMYDATA_APIKEY}" && -n "${SIGNMYDATA_ID}" ]]; then + echo "*** Building configuration file with environment data" + mkdir -p "${HOME}/.config/seal" + cp config.sample "${HOME}/.config/seal/config" + echo "apikey=${SIGNMYDATA_APIKEY}" >> "${HOME}/.config/seal/config" + echo "id=${SIGNMYDATA_ID}" >> "${HOME}/.config/seal/config" +else + MISSING_CONFIG=true +fi + +if [[ "$MISSING_CONFIG" == true ]]; then + echo "***************************************" + echo "Missing configuration, local tests only" + echo "***************************************" + readonly TEST_SCRIPTS=( + "test-local.sh:Local Signing" + "test-inline.sh:Inline Signing" + "test-revoke.sh:Revocation" + ) +else + readonly TEST_SCRIPTS=( + "test-local.sh:Local Signing" + "test-remote.sh:Remote Signing" + "test-inline.sh:Inline Signing" + "test-revoke.sh:Revocation" + "test-manual.sh:Manual" + ) +fi + +PASSED_TESTS=() +FAILED_TESTS=() +OVERALL_STATUS=0 + +for test_info in "${TEST_SCRIPTS[@]}"; do + script="${test_info%%:*}" + description="${test_info#*:}" + + TEST_STARTAT=$SECONDS + echo "===========================" + echo "Running ${description} Tests" + echo "===========================" + output=$(./"$script" 2>&1) + status=$? + if [ $status -ne 0 ]; then + OVERALL_STATUS=1 + FAILED_TESTS+=("$script") + echo "ERROR: $script failed in $((SECONDS - TEST_STARTAT)) seconds." + echo "------- SCRIPT OUTPUT -------" + echo "$output" + echo "-----------------------------" + else + PASSED_TESTS+=("$script") + echo "Completed Successfully in $((SECONDS - TEST_STARTAT)) seconds" + fi + echo "" +done + +echo "" +echo "=====================" +echo "Test Execution Summary" +echo "=====================" +echo "Passed: ${#PASSED_TESTS[@]}" +echo "Failed: ${#FAILED_TESTS[@]}" +if [ ${#FAILED_TESTS[@]} -gt 0 ]; then + echo "Failed tests: ${FAILED_TESTS[*]}" +fi +echo "Total elapsed: $((SECONDS - CI_STARTAT)) seconds" +echo "=====================" + +exit $OVERALL_STATUS diff --git a/tests/test-all.sh b/tests/test-all.sh old mode 100644 new mode 100755