-
Notifications
You must be signed in to change notification settings - Fork 547
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
fix for issue 3476 #3486
fix for issue 3476 #3486
Conversation
Signed-off-by: Mukuls77 <[email protected]>
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3486 +/- ##
==========================================
+ Coverage 40.07% 40.10% +0.02%
==========================================
Files 155 155
Lines 10040 10044 +4
==========================================
+ Hits 4024 4028 +4
Misses 5530 5530
Partials 486 486 ☔ View full report in Codecov by Sentry. |
pkg/cosign/verify.go
Outdated
// as it uses a common reference of CheckOpts so in multi thread invocation co.intermediateCert object | ||
// can get overwritten my multiple threads. So to solve this ValidateAndUnpackCertWithIntermediates | ||
// is created which has a separate argument for Intermediate certs. | ||
|
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.
nit: remove this blank line
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.
Thanks for the review i will remove the empty line
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.
there is any tests that we can add or the existing ones cover this change?
The new function written ValidateAndUnpackCertWithIntermediates() also test function TestVerifyImageSignature() The only logic which existing function can not test is that we need to invoke verification on Multiple Signature case. i am not sure if we can create a unit test for the same. But if required i can create an end to end test where we can attach multiple signatures with different root chains and do verification using any of the root certificate. Pls suggest shall we create an end to end test case for this. |
i propose to enhance existing end to end test case |
Signed-off-by: Mukuls77 <[email protected]>
I have enhanced end to end attach test case to attach two signatures with different root chains and tested the verification using root certificate only. attached are the logs of the testing done. |
Signed-off-by: Mukuls77 <[email protected]>
@haydentherapper ; @cpanato |
pkg/cosign/verify.go
Outdated
} | ||
|
||
// Now verify the cert, then the signature. | ||
if intermediateCerts == nil { |
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.
I would remove this conditional, as the purpose of this function is to pass in the intermediates that should be used for chain building.
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.
This check is important and should be present.
we will reach the new function ValidateAndUnpackCertWithIntermediates() via two paths
- ValidateAndUnpackCert()
- verifyInternal()
verifyInternal is called in some cases where we dont have an intermediate present in signature but we pass that as an argument in verification in those cases co.IntermediateCerts will have a valid intermediate cert but we will not be able to set the intermediatePool argument. one scenario is verification of Blob signatures.
so we need to have this condition if the intermediate Argument is Null that set the value from co.IntermediateCerts
I tested this by removing this condition and i could see verify blob signature test cases were failing so i put this condition back.
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.
Ah I think I understand the issue. Correct me if I misunderstand, you're saying that co.IntermediateCerts may have been set by one of the functions that calls verifyInternal.
I think the fix would just be to pass co.IntermediateCerts
to ValidateAndUnpackCertWithIntermediates
on line 745 if co.IntermediateCerts != nil
. Then you could remove this check.
pkg/cosign/verify.go
Outdated
@@ -721,19 +803,19 @@ func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash, | |||
return false, err | |||
} | |||
// If there is no chain annotation present, we preserve the pools set in the CheckOpts. | |||
var pool = (*x509.CertPool)(nil) | |||
if len(chain) > 0 { | |||
if len(chain) == 1 { | |||
co.IntermediateCerts = nil |
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.
This line needs to be updated too, we can't overwrite co.IntermediateCerts
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.
Agreed i will incorporate this comment
pkg/cosign/verify.go
Outdated
@@ -721,19 +803,19 @@ func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash, | |||
return false, err | |||
} | |||
// If there is no chain annotation present, we preserve the pools set in the CheckOpts. | |||
var pool = (*x509.CertPool)(nil) |
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.
var pool = (*x509.CertPool)(nil) | |
var pool *x509.CertPool |
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.
This should be sufficient to create a pointer.
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.
Agreed i will incorporate this comment
Signed-off-by: Mukuls77 <[email protected]>
Signed-off-by: Mukuls77 <[email protected]>
@haydentherapper i have implemented the review comments. kindly review |
pkg/cosign/verify.go
Outdated
@@ -216,9 +216,16 @@ func verifyOCISignature(ctx context.Context, verifier signature.Verifier, sig pa | |||
return verifier.VerifySignature(bytes.NewReader(signature), bytes.NewReader(payload), options.WithContext(ctx)) | |||
} | |||
|
|||
// ValidateAndUnpackCert creates a Verifier from a certificate. Veries that the certificate | |||
// chains up to a trusted root. Optionally verifies the subject and issuer of the certificate. | |||
// ValidateAndUnpackCert calls ValidateAndUnpackCertWithIntermediates() by passing intermediate |
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.
I'd keep the previous comment, just adding the detail that the intermediate certificate chain comes from CheckOpts. You can omit the detail that it calls another function.
pkg/cosign/verify.go
Outdated
} | ||
|
||
// Now verify the cert, then the signature. | ||
if intermediateCerts == nil { |
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.
Ah I think I understand the issue. Correct me if I misunderstand, you're saying that co.IntermediateCerts may have been set by one of the functions that calls verifyInternal.
I think the fix would just be to pass co.IntermediateCerts
to ValidateAndUnpackCertWithIntermediates
on line 745 if co.IntermediateCerts != nil
. Then you could remove this check.
Signed-off-by: Mukuls77 <[email protected]>
@haydentherapper i have incorporated the review comments pls review |
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.
Thanks for the fix!
Signed-off-by: Mukuls77 <[email protected]>
@haydentherapper i have incorporated the review comment. please check |
@@ -25,6 +25,10 @@ cp ./test/testdata/test_attach_private_key $tmp/private_key | |||
cp ./test/testdata/test_attach_leafcert.pem $tmp/leafcert.pem | |||
cp ./test/testdata/test_attach_certchain.pem $tmp/certchain.pem | |||
cp ./test/testdata/test_attach_rootcert.pem $tmp/rootcert.pem | |||
cp ./test/testdata/test_attach_second_private_key $tmp/secondprivate_key |
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.
@Mukuls77 What is the purpose of this extra set of certificates? It looks like this is testing the same behavior, are these e2e test changes needed?
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.
This test case creates the scenario when multiple signatures are attached to a artifact with different root chains and we want to verify the artifact with any one of the root certificate. because there are more than one signatures attached so multiple threads will be created during verification and each thread will verify the allocated signature. During this operation previously when threads were modifying co.intermediates sometime verification use to fail, now with this fix it will not fail. so in my view this is an important test cases of verifying multiple signatures.
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.
Thanks, that makes sense. Can you add a comment about this in the test file?
LGTM, just one comment about tests |
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.
lgtm
@haydentherapper @hectorj2f |
@@ -25,6 +25,10 @@ cp ./test/testdata/test_attach_private_key $tmp/private_key | |||
cp ./test/testdata/test_attach_leafcert.pem $tmp/leafcert.pem | |||
cp ./test/testdata/test_attach_certchain.pem $tmp/certchain.pem | |||
cp ./test/testdata/test_attach_rootcert.pem $tmp/rootcert.pem | |||
cp ./test/testdata/test_attach_second_private_key $tmp/secondprivate_key |
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.
Thanks, that makes sense. Can you add a comment about this in the test file?
test/e2e_test_attach.sh
Outdated
@@ -59,24 +67,22 @@ echo "Payload: $PAYLOAD" | |||
|
|||
## Attach Signature, payload, cert and cert-chain | |||
./cosign attach signature --signature ./payloadbase64.sig --payload ./payload.json --cert ./leafcert.pem --cert-chain ./certchain.pem $IMAGE_URI_DIGEST | |||
./cosign attach signature --signature ./secondpayloadbase64.sig --payload ./payload.json --cert ./secondleafcert.pem --cert-chain ./secondcertchain.pem $IMAGE_URI_DIGEST |
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 we modify this test so that we still test verification with a single attached cert, then after verification, attach another and try verification?
Signed-off-by: Mukuls77 <[email protected]>
Signed-off-by: Mukuls77 <[email protected]>
@haydentherapper i have incorporated the review comments. kindly check |
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.
Thanks @Mukuls77!
What is the difference between the new |
Main difference is Function ValidateAndUnpackCertWithChain() uses
intermediate cert from co.Intermediatecerts to construct the verification
chain to verify the certificates. Function
ValidateAndUnpackCertWithIntermediates()
provide the caller to pass intermediate cert as a separate argument and use
that for constructing the certificate chain for cert verification.
Function ValidateAndUnpackCertWithChain() internally calls
ValidateAndUnpackCertWithIntermediates() by passing co.Intermediatecerts in
the Intermediatecert Argument of the function.
…On Fri, Jan 26, 2024 at 7:15 PM Riccardo Schirone ***@***.***> wrote:
What is the difference between the new
ValidateAndUnpackCertWithIntermediates and ValidateAndUnpackCertWithChain?
—
Reply to this email directly, view it on GitHub
<#3486 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/A46KPVI6BITZUKXWUGGBZWTYQOXQRAVCNFSM6AAAAABB7YF77KVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMJSGA4TGMJWG4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Purpose was a nonbreaking API change. Long term there's a larger refactor to do to pass a set of read-only CA cert metadata to the verification function. |
@haydentherapper thanks for Merging the pull request. I suppose this fix will be available in 2.3.0 release, i wanted to check what is the expected timeframe of next cosign release. when i checked further i see cross build to macOS is failing in upload artifact step so wanted to check if there is some action i can do to solve this issue, |
I'll likely cut a release next week or so, there's a few open PRs we should get in first. I've been noticing that failure too, I'm not sure the root cause, but it's not related to this PR specifically. |
Summary
The PR fixes the issue "Closes #3476"
Use case Impacted:
A company sign the artifact using its PKI using
companyRootCA->companyIntermediateCrt->CompanyLeafcert
Client download the software and want to sign it again using client PKI before it can be used using
ClientRootCA->clientIntermediatecrt->Clientleafcrt
so in this case we will have multiple signatures attached to the artifact with different Root->intermediate->leaf chains.
Now if client verify the artifact just passing the client RootCA, the verification fails randomly.
The main issue identified is that
func verifySignatures(ctx context.Context, sigs oci.Signatures, h v1.Hash, co *CheckOpts) (checkedSignatures []oci.Signature, bundleVerified bool, err error)
function invokes multiple worker thread and call the function VerifyImageSignature() by passing common CheckOpts reference.
now in downstream the function
func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash,
verifyFn signatureVerificationFn, co *CheckOpts)
try to update the co.IntermediateCerts if it is null. ( which will be the case in this scenario as we are just passing root certificate for verification)
since this function is being executed by multiple threads so it can corrupt the co.IntermediateCerts (which ever thread find it Null)
This can corrupt the verification chain , so sometime verification fails.
To solve this issue a new function is introduced
func ValidateAndUnpackCertWithIntermediates(cert *x509.Certificate, co *CheckOpts, intermediateCerts *x509.CertPool) (signature.Verifier, error)
this has intermediate as separate argument. this new function is now called inside verifyInternal()
Release Note
File modified:
cosign/pkg/cosign/verify.go
Documentation
no change in existing API