Skip to content

Conversation

@mikn
Copy link
Contributor

@mikn mikn commented May 18, 2025

I promise, I have run both clippy and fmt before submitting this!

An interesting observation, which you may or may not be aware of, is that because the disk image is generated and the vendor.crt is embedded into the shim, as well as that the gpg key for the grub config signature and both of these are written into the EFI-A partition, even if you disable Secure Boot on the server - the deployment of an update downloaded from a TUF repository, using a different PKI chain for the code-sign.key and a different gpg key for config-sign.key, will fail on both the shim validation and grub validation (these are done always despite Secure Boot status).

Of course, completely theoretical - I would never have been reckless enough to encounter the above situation.

Issue number:

Closes #542

Description of changes:
This introduces three new environment variables to the build process BUILDSYS_SBKEY_SHIM_SIGN_KEY_CONTENT, BUILDSYS_SBKEY_CODE_SIGN_KEY_CONTENT and BUILDSYS_SBKEY_CONFIG_SIGN_KEY_CONTENT.
This allows you to pass in the signing keys needed to sign the artefacts both inside the full disk image, but also the update images.

The primary use-case for this would be to more conveniently enable CI builds without having to manage secrets as files (which few CI systems support in any larger extent).

Testing done:
I tested building both with a local profile and with the environment variables (we use these in building our own images in CI currently).

Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

This allows you to pass in the signing keys needed to sign the artefacts
both inside the full disk image, but also the update images.

The two relevant for the update artefacts are: code_sign and config_sign,
which signs the kernel image and the grub config respectively.
Comment on lines +703 to +706
# Environment variables case - check if all required env vars are set
elif [ -n "${BUILDSYS_SBKEY_SHIM_SIGN_KEY_CONTENT}" ] && \
[ -n "${BUILDSYS_SBKEY_CODE_SIGN_KEY_CONTENT}" ] && \
[ -n "${BUILDSYS_SBKEY_CONFIG_SIGN_KEY_CONTENT}" ] && \
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be better to associate these variables with the profile somehow, since otherwise the wrong keys could be used if the profile is changed.

Rough example:

SHIM_SIGN_KEY_CONTENT="BUILDSYS_SBKEYS_${BUILDSYS_SBKEYS_PROFILE^^}_SHIM_SIGN_KEY_CONTENT"
CODE_SIGN_KEY_CONTENT="BUILDSYS_SBKEYS_${BUILDSYS_SBKEYS_PROFILE^^}_CODE_SIGN_KEY_CONTENT"
CONFIG_SIGN_KEY_CONTENT="BUILDSYS_SBKEYS_${BUILDSYS_SBKEYS_PROFILE^^}_CONFIG_SIGN_KEY_CONTENT"

if [ -n "${!SHIM_SIGN_KEY_CONTENT}" ] && \
   [ -n "${!CODE_SIGN_KEY_CONTENT}" ] && \
   [ -n "${!CONFIG_SIGN_KEY_CONTENT}" ] ; then
  echo "FOUND KEYS"
fi

Comment on lines +697 to +698
[ -s "${profile}/code-sign.crt" ] && \
[ -s "${profile}/config-sign.key" ] ; then
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not thrilled with this interface since it creates ambiguity as to what keys will be used if both the environment variable and the file are present for a profile.

Here, we'd pass this first set of checks but silently end up using the environment variables instead of the files, assuming that the last value for a particular secret on the docker build command line is what ends up being used.

This isn't really a new issue, but the more types of signing profiles we have, the more potential for confusion that exists.

It might be better to have a different "type" of profile, with a file like sign.env that gave the variables that are expected to be set, e.g.:

SHIM_SIGN_KEY_ENV_VAR=...
CODE_SIGN_KEY_ENV_VAR=...
CONFIG_SIGN_KEY_ENV_VAR=...

Then a check could assert that we have only one type for our set of signing keys:

  • kms-sign.json
  • shim-sign.key, code-sign.key, and config-sign.key
  • sign.env

(In the KMS path, config-sign.key is a public key, not a private key, so it doesn't fit cleanly.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems like perhaps a larger project, to cleanly separate the profiles also in the builder docker stage.

It was actually the initial approach I took, but realised that it increased the code required significantly for little benefit (without an understanding of the longer roadmap of signing key support), hence I decided to limit the PR to outside of the docker build stage.

I think the two modifications you mention, correcting the prefix to BUILDSYS_SBKEYS_ instead of BUILDSYS_SBKEY_ and injecting the profile name into the env variable name are very good improvements, but I am wary of injecting logic into the docker build stage also unless there are other benefits you see?

Putting the profile name into the environment variables should be a reasonable defence against confusion of which keys are being used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow secureboot secret material (shim-sign, code-sign and config-sign) to come from env

2 participants