singularity
singularity copied to clipboard
Verification of Multiple Signatures
When singularity verify
is called on an image with a single signature, the expected behaviour is straightforward. If the signature can be verified, all is well, and otherwise there is a problem.
When singularity verify
is called on an image with multiple signatures, the expected behaviour is less clear. It could be:
- Verification is successful if all signatures are verified. This is the current behaviour.
- Verification is successful if one or more (but possibly not all) signatures were verified.
Although the first option is the current behaviour, I would argue that it likely isn't the user's expected behaviour in all cases. My intent may be "verify this image has been signed by a particular authority". In this case, I could ensure I have the public key material for the relevant authority, and call verify
. Unfortunately, if the image contains other signatures that are not relevant to me, and I don't have access the the required public key material, verification fails.
To make matters worse, in the above use case, verify
doesn't have a way for me to specify the relevant authority. The suggestion in https://github.com/apptainer/apptainer/issues/462 goes part way to helping with this by displaying "verified" or "not verified" for each signature, but still requires the user to (visually or programmatically) parse the output to determine whether a signature from the relevant authority can be verified.
In addition, singularity verify
now has a --key
option to specify non-PGP key material, which introduces yet another complexity. The user expectation of singularity verify --key
may very well be "verify this image can be verified with this key material", but at present the semantics are actually "verify all signatures in this image can be verified with this key material". As mentioned in https://github.com/sylabs/singularity/pull/1120#issuecomment-1330754059, this means that verifying an image signed with both PGP and non-PGP key material actually isn't possible, since there is no way to specify multiple key material sources:
$ singularity sign image.sif
$ singularity sign --key private.pem image.sif
This can't be successfully verified, since using --key
disables PGP key material as a source:
$ singularity verify image.sif
Verifying image: image.sif
FATAL: Failed to verify container: integrity: key material not provided for DSSE envelope signature
$ singularity verify --key public.pem image.sif
Verifying image: image.sif
FATAL: Failed to verify container: integrity: key material not provided for PGP clear-sign signature
As a proposal, I suggest the following semantics:
-
singularity verify image.sif
maintains the current semantics, i.e. all signatures inimage.sif
are verified using PGP public key material. -
singularity verify --key public.pem image.sif
verifiesimage.sif
can be verified bypublic.pem
. Same if key material is provided by environment variable (ex.VERIFY_KEY=public.pem singularity verify image.sif
). -
singularity verify --fingerprint ABCD image.sif
verifiesimage.sif
can be verified by the PGP entity with fingerprintABCD
. Same if a fingerprint is provided by environment variable (ex.VERIFY_FINGERPRINT=ABCD singularity verify image.sif
).
@tri-adam After looking at the code, I wonder if the --key
in verification is needed.
Instead, users can create self-signed certificates and use them directly in --certificate
.
https://devopscube.com/create-self-signed-certificates-openssl/
Removing the --key
not only keeps the CLI cleaner but also makes it more RFC-compliant. Plus, it keeps the semantics cleaner since verifying an officially signed image has the same flag as verifying your self-signed image.
@tri-adam After looking at the code, I wonder why the
--key
is needed.The
--certificate
already provides all the needed information to verify the signature (the public key can be extracted directly from it).
They're two different use cases:
- You generate a public/private key pair and use them directly (
singularity verify --key <public_key>
), or - You generate a private key, and then create a certificate that contains the public key (
singularity verify --certificate <certificate_with_public_key>
)
The first is simpler, with obvious tradeoffs in functionality (establishing trust through chaining, revocation checks, metadata in the certificate, etc.) For an individual or organization that doesn't have a PKI setup, they might choose to go this route.
The second is obviously more rich in functionality, with the downside being complexity.
Sidenote: I 've added support for self-signed certificates and working on the OCSP.
Awesome! Looking forward to checking that out.
Hit me up on the CE Slack if there's any way I can help (invite link on https://sylabs.io/singularity/). Thanks!
Ha ! you are fast ;p I was editing my previous answer when I saw your response.
My concern is about the first point, since it can be represented by self-signed certificates.
My concern is about the first point, since it can be represented by self-signed certificates.
Ah, gotcha. I guess the goal here is to support a variety of use cases. Raw keys are sort of the lowest common denominator, and if someone wants to re-use a bare key pair from elsewhere (cosign generate-key-pair
, for example), they can. Others will want self-signed certs or full certificate chains. And I could see others wanting other approaches like integration with cloud key management systems. At the end of the day, it'll be an individual choice.
We will need to ensure good documentation for all of this... to help guide users towards the approach that best meets their needs!
Does that make sense?