-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Image Signing #8371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Image Signing #8371
Conversation
|
[test] |
9c24be0 to
e0901a0
Compare
| ImagePusherRoleName = "system:image-pusher" | ||
| ImageBuilderRoleName = "system:image-builder" | ||
| ImagePrunerRoleName = "system:image-pruner" | ||
| ImageSignerRoleName = "system:image-signer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want project admins to be able to manage image signatures. Since this is so related to registry should we also grant privs to registry-admin role?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want project admins to be able to manage image signatures. Since this is so related to registry should we also grant privs to registry-admin role?
You can't do that with a cluster-scoped resource, you'll need to project (proJECT) access at a project (PROject) scope. (english is weird).
You need to expose this via a synthetic project-scoped resource that can create the cluster-scoped resources in a controlled way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want project admins to be able to manage image signatures.
How does that work when a single image is shared between several projects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does that work when a single image is shared between several projects?
I think that update is the wrong verb. It seems like signatures are an additive affair. If liggitt signs it, deads can still sign too.
I think the get case is a little interesting. I don't know that we want to automatically allow someone in ns-1 to see signatures created via the resource in ns-2. The ability to do that would be good, but I haven't thought about whether it should always be that way. You could end up in cases where you're seeing all sorts of signatures you know nothing about.
|
Maybe I'm missing something but I'm only seeing a 'put' API call and permissions. Where's the 'get' story to validate a signature locally? |
|
@aweiteka you can get the image object already using API calls like |
Ok. Makes sense.
Yes, I think so. |
|
Thanks, makes sense.
Re: We will probably eventually need to add more fields to |
|
Addressed some review items.
I share your opinion, but that's the best I can do right now.
Do we need the type at all then? What if we later decide to change the signature algorithm/encoding? During a migration, shall we take an old image and recreate the signatures with the desired type or throw them away?
Shouldn't be a problem to add later. Fingerprint sounds reasonable, can we be more specific right now? |
Sorry, that comment was completely nonsensical (and I deleted it instead of saying so): I have overlooked that
Ideally the signature library (currently in skopeo) should be able to deal with format changes/alternatives/detection transparently; the current code does not need the
In general the registry may not (should not?) have access to the private keys necessary to resign everything; during a migration, either old signatures, and support for them, and the data needed to verify them, can be preserved unmodified, or they will become invalid and can at best be thrown away. |
d30fe3c to
908027f
Compare
|
Flake #8397. |
|
Is there a standard convention for describing the type of a signature? An RFC? A mime-type? A convention in use in wide standard in linux? If none of those exist, I would expect us to probably choose a mime type or similar with the appropriate qualifications, especially if the signature is itself in a standard format. |
Kind of. At the moment the cryptographic signature is GPG-generated, i.e. RFC 4880 should apply (though GPG might be deviating, I don’t know). OTOH:
Overall I think saying “this is GPG” is not really the semantics we want. I expect there are two kinds of clients:
|
|
/cc |
|
Shall we perhaps split the metadata into a descriptor identifying the signare and have additional |
|
Could you elaborate? I can’t see what is the difference between “identifying the signature” and “additional metadata”. (FWIW I’d prefer not exposing the signature metadata in plaintext objects by default just because the metadata exists; until the signature is verified per the current policy (which may be different than the policy at the time of adding the signature), none of the metadata is reliable.) |
|
FWIW the blob itself uniquely identifies the blob :-) OTOH neither the issuer name, issuer key fingerprint, nor the name claimed by the signature are obviously unique. |
Probably the (signer identification, signed image identification) pair could be a good identification (it is not trivially unique but if there are collisions, the valid and latest-expiring signature should work as a substitute for any others). Then, the tradeoff would be whether to do this as a pair of strings with internal, vaguely defined structure like or whether to have the full structure codified in JSON: or something similar. Also, I guess we will eventually need a “signature applies to this image”/“signature applies to one of the base images” flag so that the UI doesn’t confuse users by showing various derived images all signed as |
I don't feel pleasant about an idea of having 200 images, each having the same signature blobs created for the rhel image they're based on. I'd rather require an import of all the base images into etcd with their signatures and refer to them.
Right, but comparing them might is expensive.
I we are pretty sure these attributes won't change, I'd reflect it in signature's structure which is serializable into json. |
It is kind of ugly, yes, but also cheap enough, and it allows for a better user workflow because it removes interdependencies. With this, an ISV can publish their application, built on top of a RHEL base image:
|
The signatures are a few hundred of bytes long at the moment; even if it were a few kilobytes, that would be cheap enough — and we can always compute a cryptograhic hash to use as an ID. The UI issues of identifying blobs by meaningless binary data seem to be a bigger concern. |
It sounds like we would benefit from a design discussion on how we expect users to interact with these signatures. |
|
Can we proceed with discussing/designing how signatures are described and presented to the user? Per #8371 (comment) , I think the major options are:
|
|
I'd prefer the 1st option. It's in analogy to image digests ( |
908027f to
f1a127e
Compare
|
I've updated the fields. @mltrmac, could you please confirm the final shape? @openshift/api-review, this needs your attention. |
f1a127e to
74c0de3
Compare
pkg/image/api/v1/types.go
Outdated
| // SignatureSubject holds information about a person or entity who created the signature. | ||
| type SignatureSubject struct { | ||
| SignatureGenericEntity `json:",inline"` | ||
| // If present, it is a fingerprint of public key belonging to the subject used to verify image signature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an example of a fingerprint, and any other detail that is required to understand why it is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not PublicKeyFingerprint if it's a fingerprint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an example of a fingerprint, and any other detail that is required to understand why it is used.
Added an example.
Why is this not PublicKeyFingerprint if it's a fingerprint?
I corrected the godoc. Since this serves solely an informative purpose, I find whole fingerprint too long to display. The long key ID (64bits) prefixed with 0x should be appropriate for this purpose. (e.g. 0x685ebe62bf278440).
1d45892 to
eaabf65
Compare
|
@smarterclayton, @deads2k: thank you for the review. Items have been addressed. |
|
|
||
| var trustedCondition, forImageCondition *api.SignatureCondition | ||
| for i := range signature.Conditions { | ||
| cond := &signature.Conditions[i] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doing this that way and not using for-each loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because in that way I'd be taking reference to a temporary cond value which is reassigned in each iteration. So in the end both trustedCondition and forImageCondition would point to the same value equal to the last item of signature.Conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, my bad. Sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for-each loops unfortunately suck hard. I've been bitten a bunch of times
eaabf65 to
055e8f6
Compare
|
Comments addressed. @smarterclayton, @soltysh, thanks for the review! Anything else? |
055e8f6 to
bb3d370
Compare
Which is an array of signatures with mostly opaque data. There are
two mandatory fields of each signature:
- Type - the only supported value for now is "atomic"
- Content - opaque binary string
There's one known signature type "atomic" with two mandatory
and one optional attributes:
- ImageHash - hash of a signed image
- ImageIdentity - signed claim representing an origin of the image
- Created - optional; the time of signarure's creation
Following attributes are added for future signing extensions:
- SignedClaims - a map of interesting signed claims that maybe added
later to the signature format but not that important
to become first-class fields
- IssuedBy - issuer of signing certificate if any
- IssuedTo - subject of signing certificate or an image signer
Signed-off-by: Michal Minar <[email protected]>
bb3d370 to
57d134c
Compare
|
Evaluated for origin test up to 57d134c |
|
continuous-integration/openshift-jenkins/test FAILURE (https://ci.openshift.redhat.com/jenkins/job/test_pr_origin/4593/) |
|
LGTM |
|
@smarterclayton merge? |
| // If present, it is a human readable key id of public key belonging to the subject used to verify image | ||
| // signature. It should contain at least 64 lowest bits of public key's fingerprint (e.g. | ||
| // 0x685ebe62bf278440). | ||
| PublicKeyID string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why this would be ID vs Fingerprint? Is ID in common use to describe this field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just trying to establish what someone familiar with signatures would expect in the usage here - fingerprint vs id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key ID is a shortened key fingerprint. Usually its lowest 32 or 64 bits. My reasoning for including ID instead of fingerprint is that this field is meant to be for diplaying. Not for verification. Clients that want to verify the signature should deal with Content field. What you usually see while working with gpg keys is just key ids because they are relatively short.
$ gpg2 --list-keys
/home/miminar/.gnupg/pubring.gpg
--------------------------------
pub rsa2048/71445503 2014-01-13 [SC] [expired: 2016-01-13]
uid [ expired] Michal Minar <[email protected]>
...
$ gpg --fingerprint 0x71445503
pub rsa2048/71445503 2014-01-13 [SC] [expired: 2016-01-13]
Key fingerprint = BF4A E972 503B 49BC A6D2 6836 F7B3 5329 7144 5503
uid [ expired] Michal Minar <[email protected]>
The full fingerprint may be very long depending on algorithm used. It this were PublicKeyFingerprint, I'd rather store it in binary format []byte and let the rendering client choose whatever formating it prefers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that's the clarity I wanted.
|
API approved, [merge] |
|
continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pr_origin/4707/) (Image: devenv-rhel7_4348) |
|
Evaluated for origin merge up to 57d134c |
|
|
||
| // SignatureCondition describes an image signature condition of particular kind at particular probe time. | ||
| type SignatureCondition struct { | ||
| // Type of job condition, Complete or Failed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cp error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cp error
Thanks! Addressed in #9181
Allow to add signatures to image objects. They are treated as opaque blobs.
Added a new cluster resource
images/signatures.Added
system:image-signerrole that athorizes to update image signatures.TODOs:
gpg/base64or justbase64).