Skip to content
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

Specification and Prototype - JWT based signature #2

Closed
wants to merge 2 commits into from

Conversation

shizhMSFT
Copy link
Contributor

In this PR, we propose specification for Notary v2, including the client and server side.

We also provide a client prototype as a refernece implementation of the specification.

Basically, the client nv2 is able to sign and verify a manifest-based artifact offline. Later, the result signature can be shared to others via OCI-compliant registries as OCI artifacts or as a normal file on the file system.

Copy link

@trishankatdatadog trishankatdatadog left a comment

Choose a reason for hiding this comment

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

This is a cursory review of the prototype, and I have already found some rudimentary problems that really shouldn't be there, considering that they are security problems we have fixed in Notary-v1. This is my problem with the current prototype: it looks like we are designing a custom, homegrown signature scheme, and completely throwing out security issues that we have already solved in v1. Is there a good reason for doing this?

docs/signature/README.md Outdated Show resolved Hide resolved
docs/signature/README.md Outdated Show resolved Hide resolved
docs/signature/README.md Show resolved Hide resolved
docs/signature/README.md Outdated Show resolved Hide resolved

This REQUIRED property is the *size* of the target manifest. If the actual content is fetched according the *digest*, implementations MUST verify the content against the *size*.

- **`references`** *array of strings*
Copy link
Contributor

Choose a reason for hiding this comment

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

In the meeting we discussed signature options other than x509. If these are used, how will this domain name verification be done?

Copy link
Contributor

Choose a reason for hiding this comment

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

in a word: "dunno".
It's an interesting concept that enables a number of additional, but not required scenarios.
Let's say I publish an image from wabbit-networks.io If the CN=registry.wabbit-networks.io and the referenced artifacts have the same registry name, I can simply know where they originated from. In theory, even go back to that registry as I may have gotten the images from an aggregator (docker.io), or my private registry.
More importantly, when I pull the registry.wabbit-networks.io/net-monitor:v1 image into my private repository for my production deployment, I can scan it, test it, verify it works in my acme-rockets environment. I then add another signature to the image, which is now at acme-rockets.azurecr.io/net-monitor:v1. That additional signature has the new registry url on it. My production k8s environment can be configured with OPA (Open Policy Agent) to assure that all content is signed by the acme-rockets key, and all content must be signed under the acme-rockets.azurecr.io registry and pulled from this registry.
So, it can provide extra validation/policy enforcement.
Now, this is just a riff that Shiwei came up with using x509. I wouldn't say it's a hard constraint. Think of it as a interesting tile pattern on this mocked bathroom we've been designing. It's not as important as having the bidet (that Cormack and Ralph Squillace say are requirements) . It's an idea we can keep or toss. Remember, we're sketching things out to see what we like and don't like.


- **`digest`** *string*

This REQUIRED property is the *digest* of the target manifest, conforming to the requirements outlined in [Digests](https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests). If the actual content is fetched according to the *digest*, implementations MUST verify the content against the *digest*.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be good to explicitly add that the digest must be compared to the contents of the image, to make sure that the image actually matches the digest that was signed.

docs/nv2/README.md Outdated Show resolved Hide resolved
docs/nv2/README.md Outdated Show resolved Hide resolved
docs/distribution/README.md Outdated Show resolved Hide resolved
docs/distribution/README.md Outdated Show resolved Hide resolved
docs/distribution/spec.yml Outdated Show resolved Hide resolved
docs/nv2/README.md Outdated Show resolved Hide resolved
docs/nv2/README.md Outdated Show resolved Hide resolved
## Scenarios

The current implementation focuses on x509 cert based signatures. Using this approach, the digest and references block are signed, with the cert Common Name required to match the registry references. This enables both the public registry and private registry scenarios.

Choose a reason for hiding this comment

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

the digest and references block are signed

Does this indicate that an image cannot be renamed? Or that a publisher should assign a "canonical" reference before signing the image?

Copy link
Contributor

Choose a reason for hiding this comment

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

An image can be renamed, moved to a different registry, different tag, etc.
What this block shows is: what was it when it was signed.
When you run example.com/hello-world:v1 from myregistry.io/hello-you:v1-blah, the validation would pass as long as the digest hasn't changed.
However, you can also add another registry.corp.io signature for: registry.corp.io/hello-you:v1-blah, and then limit deployments to being signed by registry.corp.io and pulled from registry.corp.io. The signature validation would come from Notary v2. The additional "policy" would be something incorporated into a policy managmenet solution like OPA or something else.
Think of it as an extra layer of security, we may like. Or, we may not. See comment above: #2 (comment)

Choose a reason for hiding this comment

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

Roughly: the signature attests that the signer (Foo) called the image by this name (foo.example.com/myimage:latest), and a validator can implement a policy such that it only trusts the name (foo.example.com/myimage:*) if it was signed by this key (Foo)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup, But, I suspect companies would more likely re-sign for themselves and trust their own registry. The main point is an x509 signature can only sign artifacts where the CN matches the registry name.
As we're discussing the larger question of key types, this may become less possible.
But, is it interesting?

Choose a reason for hiding this comment

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

@SteveLasker
I think we need clarification regarding the "re-sign" scenario you mentioned.
More specifically, should the signature by registry.corp.io be independent of the signature by example.com?
Is it reasonable that when the signature by example.com is revoked, the signature by registry.corp.io should be invalid immediately?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi Daniel,
Great question. Today, the signatures are independent. The reason a signature may get revoked may or may not have anything to do with subsequent signatures. But, the information is super important. I'd suggest this is more of a policy managmenet decision that makes use of the information, rather than a hard rule the spec would enforce.
To your point, once we've all gotten comfortable with the prototype, we should absolutely clarify this in the spec.
I think the other question buried here is the continual question of policy vs. data separation.
I'm suggesting signatures are data, enabling policy by external systems.
We must support the ability to invalidate some data - such as the wabbit-networks signature may be revoked. If acme-rockets wants to keep or invalidate their signature is a policy decision.
Thoughts?

docs/nv2/README.md Show resolved Hide resolved
docs/signature/README.md Outdated Show resolved Hide resolved
This is a joint commit of
- Shiwei Zhang
- Steve Lasker
- Aviral Takkar

Signed-off-by: Shiwei Zhang <shizh@microsoft.com>
Signed-off-by: Shiwei Zhang <shizh@microsoft.com>
@shizhMSFT
Copy link
Contributor Author

The JWT PR #3 is merged into this PR. We may discuss JWT here.

@SteveLasker SteveLasker changed the title Specification and Prototype Specification and Prototype - JWT based signature Aug 21, 2020
@shizhMSFT shizhMSFT closed this Aug 26, 2020
@shizhMSFT shizhMSFT deleted the master branch August 26, 2020 02:51
@yizha1 yizha1 mentioned this pull request Nov 8, 2022
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.