Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need a docker login to use debian stable? I believe you can pull the public image without a login.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Docker login step is to authenticate with the GitHub Container Registry so once the next step generates a Docker image it can be pushed up to the registry.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: ci
run-name: ${{ github.actor }} is running ci

on:
pull_request:
push:
workflow_dispatch:

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
secrets: |
signid=${{ secrets.SIGNMYDATA_ID }}
apikey=${{ secrets.SIGNMYDATA_APIKEY }}

40 changes: 40 additions & 0 deletions CI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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. 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
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

35 changes: 35 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -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`

43 changes: 43 additions & 0 deletions Dockerfile
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using the Sourceforge mirror of exiftool, doing a source build and not the Debian package?
libimage-exiftool-perl Trixie version 13.25+dfsg-1

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had originally set this up with the Debian package but since I've been consistently running into difficulties with the test suite I decided to follow the directions in BUILD.md and install the latest version of ExifTool following their instructions just to rule out an older version of ExifTool as a possible culprit. Once it passes all the tests reliably it is my intent to attempt to transition to the Debian packaged ExifTool.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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 --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

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"]

9 changes: 9 additions & 0 deletions tests/config.sample
Original file line number Diff line number Diff line change
@@ -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
84 changes: 84 additions & 0 deletions tests/test-all-ci.sh
Original file line number Diff line number Diff line change
@@ -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
Empty file modified tests/test-all.sh
100644 → 100755
Empty file.