Docker Container that builds Whonix Images

Yeah, start_build.sh already jumps into derivative-maker.

cd -- "${SOURCE_DIR}"

So instead of this

"${SOURCE_DIR}/derivative-maker" "$@" | tee -a -- "${BUILD_LOG}"

We just do that instead

 "$@" | tee -a -- "${BUILD_LOG}"

Then the user could pass whatever they want to run.sh, with ./derivative-maker as working directory.

Maybe some enhanced argument parsing to capture wrong format and return an info dialog.

And alias or wrapper to make the final command prettier.
Edit: Maybe even an additional option like --build-step|-b) or -dm|--derivative-maker) ? Ok lots of options, I’ll come up with something cool to make it simple and short.

Alright, I’ll do that. :+1:

1 Like

Okay, just finished testing. Working.

I added additional options to launch a specific build-step or custom command.

Default behavior launches ./derivative-maker with arguments

./derivative-maker-docker-run --flavor kicksecure-xfce --target iso --repo true --arch amd64

Launching specific build-step:

./derivative-maker-docker-run -b 1100_sanity-tests --flavor kicksecure-xfce --target iso --repo true --arch amd64

Launching custom command:

./derivative-maker-docker-run -c /bin/bash

Also did name changes and some minor fixes.

One thing that annoyed me during testing was that on container restarts, the key and git stage run every time.

git verify-tag requires the key to be imported.
But with each restart that process is of course repeated and the check always exits 1

gpg --quiet --list-keys -- "${FINGERPRINT}" &>/dev/null || { ....

To fix that I would suggest an additional option -s|--skip which allows for specific stages in derivative-maker-docker-start to be skipped.

For example:

./derivative-maker-docker-run -b 1100_sanity-tests -s git --flavor kicksecure-xfce --target iso --repo true --arch amd64

Then just set a boolean GIT="false" and condition execution of git stage.

Let me know if anything else needs to be fixed before the next pull. :+1:

1 Like

If the test result is always false, simply remove the test?

1 Like

When you’ve manually entered the container and repeat builds, the check works, because the key has been imported and gpg exits 0.

But on full container restarts, the key needs to be imported every time,
thus gpg --quiet --list-keys -- "${FINGERPRINT}" &>/dev/null exits 1 (actually 2).

gpg --quiet --list-keys -- "${FINGERPRINT}" &>/dev/null || {
  gpg --keyid-format long --import --import-options show-only --with-fingerprint -- "${KEY}"
  gpg --import -- "${KEY}"
  gpg --check-sigs -- "${FINGERPRINT}"
} 2>&1 | tee -a -- "${KEY_LOG}"

A skip or opt-in, specifically requesting key check maybe?
--key-check → KEY_CHECK="true"

"${KEY_CHECK}" && {
  gpg --keyid-format long --import --import-options show-only --with-fingerprint -- "${KEY}"
  gpg --import -- "${KEY}"
  gpg --check-sigs -- "${FINGERPRINT}"
} 2>&1 | tee -a -- "${KEY_LOG}"
1 Like

I guess key check is somewhat optional. Not useful as a security feature in that place. Either source code digital signatures have been verified prior execution of docker they haven’t.

If I wanted this functionality as a sanity test or CI test, it could be done outside of docker inside a derivative-maker build-step.

So I guess it’s best to remove this from docker. Doesn’t belong there.

1 Like

Actually since docker invocation can change the git tag, source code verification is probably desirable before switching the git tag.

1 Like

Why would one skip the test? It’s super fast, not noticeable? So best always run it?

Does this need to be in a separate key log? Just use the same log? Would be simpler.

Normal if syntax would be preferable.

1 Like

Actually since docker invocation can change the git tag, source code verification is probably desirable before switching the git tag.

Yes I actually agree, also because if removed then git verify-commit needs to be scrapped too, because it requires the key to be imported.

I originally liked that you requested this back in tbh. :upside_down_face:
It was just super in my face during repeated restarts.

Why would one skip the test? It’s super fast, not noticeable? So best always run it?

I think it was more about the git stage, because on every restart that part consumed a couple seconds because of git pull etc, which annoyed me.
I’m very sensitive to lag. :smile:

OK, I’ll pipe the key verification to build.log, check everything again and file a new pull.

1 Like

There can be opt-in environment variables to skip all sorts of things such as git pull.

Or even git pull could be removed. Or opt-in. Dunno what is best.

This is only guided on how to archive maximum security and usefulness.

Not sure what’s best. Require git pull outside of docker (additional typing) versus docker doing git pull and an option or environment variable to skip git pull.

1 Like

Yes, --env would be a more elegant solution.

--env "GIT=1" 
--env "GIT=" 
[ -n "${GIT}" ] || git pull

Edit: Or if preferred. :smile: (Hating if used to be a virtue)

if [ -z "${GIT}" ]; then
  git pull
fi 

I’ll do one for git and whatever else makes sense.

1 Like
1 Like

Hey cool! Gonna test it this evening.

I’m writing the documentation right now and wanted to make a derivative-maker-docker logo. Do you have anything specific in mind? Here are some drafts:

1 Like

Top right one is good.


Added minimal docker CI test just now.

related:


IMG=ā€œderivative-maker/derivative-maker-dockerā€

 --volume "${CACHER_VOLUME}:/var/cache/approx-derivative-maker" "${IMG}" \

Please explain.


Another todo:

  • Use sudo with --non-interactive in as many places as possible. (This is to avoid long timeouts on CI in case of sudo issues in the future.)
1 Like

I got confused because "${IMG}" wasn’t on its own separate line. Fixed.

1 Like

That’s awesome!
Hmm, failed.
I’ll take a closer look later.

gpg: can't open '/home/user/derivative-maker/packages/kicksecure/repository-dist/usr/share/keyrings/derivative.asc': No such file or directory
Sending SIGTERM to remaining processes...

Done. I’ll make changes today or tomorrow. Gonna take a look at your latest commits. Damn, I like it when you don’t have to change much after a pull. Gotta be cleaner.

You can track the progress on the doc here. (I’m writing it in a private repo, but will update the official one when new parts are done )

Yeah, maybe this should be IMAGE_ID anyway. In case the user creates multiple images. I’ll try to improve that. And yes, needed a backspace, thank you.

1 Like

Cannot import the gpg key before cloning the git submodules.

I think the gpg verification code needs to be moved to prepare build machine build step after git submodule fetching.

It cannot be a security feature anyhow. It can only be a sanity test.

It cannot be a security feature because one would have the verify source code digital signatures prior execution of docker.

1 Like

Cannot import the gpg key before cloning the git submodules.

So that’s why it failed.

Placing it under the run_git function with sync?

Otherwise underneath this in prepare-build-machine?

  true "INFO: Updating git sub modules..."

   ## Safe.
   ## Ensures submodules' remote URL configuration matches the values specified in .gitmodules.
   git submodule sync --recursive

   ## Caution.
   ## This command updates Git submodules to the commit recorded in the parent repository. (derivative-maker)
   ## It modifies the submodule's Git HEAD, potentially overriding local changes.
   #git submodule update --init --recursive --jobs=200
   git -c merge.verifySignatures=true submodule update --init --recursive --jobs=200 --merge

   true "INFO: Updated git sub modules."

Adding.

1 Like

Just tested, minor fixes.

1 Like
[kicksecure-shield]: https://img.shields.io/badge/HOME-KICKSECURE-blue?style=for-the-badge&link=https%3A%2F%2Fgithub.com%2Fderivative-maker%2Fderivative-maker

[kicksecure-url]: https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://www.kicksecure.com/&ved=2ahUKEwjCvNiA0vaNAxXq9bsIHYaTPQsQFnoECCAQAQ&usg=AOvVaw21yYxPqNL29HjKNEgjGlM8

I don’t understand this. In any case, such functionality relying on third-party domain names is probably best avoided for security (in case shields.io gets compromised) and for privacy (avoiding links to google.com).


{
  [ -z "${GIT}" ] || git pull
  git checkout --recurse-submodules "${TAG}"
  [ "$TAG" = "master" ] || git describe
  git status
} 2>&1 | tee -a -- "${GIT_LOG}"

This syntax is problematic because error handling does not apply in subshell. Please avoid subshells whenever possible due to error handling issues. Shell functions are preferable.


Kicksecure and Whonix by extension source code and documentation follows System Security Level Always use software signatures verification.

Quote:

  1. Host preparation.
  2. Get Kicksecure source code (which includes Kicksecure build script).
  3. Verify digital software signatures.
  4. Run Kicksecure build script
  5. Done, build of Kicksecure has been completed.

This is not yet implemented in this docker pull request. Documentation should recommend to verify software signatures prior execution of any build scripts.

derivative-maker-docker-start as is now supports git fetch, git checkout and execution of unverified source code.

The probably unsolvable problem is, that derivative-maker-docker-start cannot support git fetch, digital software verification at first execution, because

  • there is no signing key yet. (The signing key issue could maybe be simplified a bit by shipping a copy of the signing key inside derivative-maker repository.)
  • the script cannot verify itself. The user needs to do a manual initial digital software signatures verification first. [1]

Anything that automates git checkout should probably only be done after the first manual verification.

So maybe we can let derivative-maker-docker-start do git checkout, git verify, but only if the signing key has already been imported? And document to do the first verification manually.


[1] Unless the user can review that script to be non-malicious by scanning for Invisible Malicious Unicode Risks as well as doing a source code review.

1 Like

Removed.

I also made these badges myself in svg format. If you like the look I could re-insert them as image uploads.

Done.
This part can’t be inside the function either though, or export won’t work.

export TAG="$(git describe --tags -- "$(git rev-list --tags --max-count=1)")"

I keep tag fetch and export out. Then run residual git commands.
Personally prefer this, because git fetch pollutes the git.log

git fetch --tags --depth=1
[ -n "${TAG}" ] || export TAG="$(git describe --tags -- "$(git rev-list --tags --max-count=1)")"

run_git 2>&1 | tee -a -- "${GIT_LOG}"

Another way would be to make TAG an --env and no longer allow empty → latest tag search.
If it’s empty in derivative-maker-docker-run then TAG="master". But then again, this would force the user to assign --tag @ build cmd.

Sure thing. I’ll put the if back and add checkout, but why does it have to be manual? Couldn’t the verification + key grab be executed in a script that runs prior to derivative-maker-docker-start?
Basically, you just add derivative-maker-docker-key to $@ in derivative-maker-docker-run which handles pre-verification, no?

1 Like