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

fix signature verification for oci hosted bundles #6145

Merged

Conversation

gitu
Copy link
Contributor

@gitu gitu commented Aug 8, 2023

Why the changes in this PR are needed?

Verification of bundles downloaded via OCI fail.

What are the changes in this PR?

Removes double usage of base dir.

@ashutosh-narkar
Copy link
Member

@gitu it would be helpful if you could explain why this change is needed. It's not clear from the comment. Thanks.

@gitu
Copy link
Contributor Author

gitu commented Aug 8, 2023

@ashutosh-narkar sure, when downloading a signed image from oci, the path, where the persisted bundle is stored, gets added to verify the signature.

Here an example with a signed bundle containing a data.json file it it's root, and persistence_directory: /tmp/this-is-a-test:

> {"level":"error","msg":"Bundle load failed: unexpected error file tmp/this-is-a-test/oci/data.json not included in bundle signature","name":"authz","plugin":"bundle","time":"2023-08-08T20:51:39+02:00"}

when downloading the same bundle via oras manually and loading it directly the signature comes out as valid.

the base path gets added here to the verification:

opa/bundle/bundle.go

Lines 544 to 548 in cca8197

// verify the file content
if bundle.Type() == SnapshotBundleType && !bundle.Signatures.isEmpty() {
path := f.Path()
if r.baseDir != "" {
path = f.URL()

@ashutosh-narkar
Copy link
Member

Thanks for the context. It would good to have some tests to ensure we don't break anything. The base dir would be set on modules iirc so a test or some would be useful.

@gitu
Copy link
Contributor Author

gitu commented Aug 9, 2023

The only other usage of basedir I could find is when loading the bundle from a folder, even there it only seems to be added for debugging purposes.

opa/loader/loader.go

Lines 253 to 257 in cca8197

// For bundle directories add the full path in front of module file names
// to simplify debugging.
if isDir {
br.WithBaseDir(path)
}

The question I know have maybe the verifier is wrong and it might be sensible to remove the adding of the baseDir for getting the right hash from the signature:

opa/bundle/bundle.go

Lines 543 to 549 in cca8197

// verify the file content
if bundle.Type() == SnapshotBundleType && !bundle.Signatures.isEmpty() {
path := f.Path()
if r.baseDir != "" {
path = f.URL()
}

@gitu
Copy link
Contributor Author

gitu commented Aug 9, 2023

after a bit playing that further, can a signature as such ever exist:

opa/bundle/bundle_test.go

Lines 462 to 470 in cca8197

func TestReadWithSignaturesWithBaseDir(t *testing.T) {
signedTokenHS256 := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZvbyJ9.eyJmaWxlcyI6W3sibmFtZSI6ImZvby9iYXIvLm1hbmlmZXN0IiwiaGFzaCI6IjUwN2EyYzM4YTE0NDFkYjU4ZDJjYjg3OTgyYzQyYWE5MWE0MzQyZWY0MjJhNmI1NDJlZGRlYmVlZjZmMDQxMmYiLCJhbGdvcml0aG0iOiJTSEEtMjU2In0seyJuYW1lIjoiZm9vL2Jhci9hL2IvYy9kYXRhLmpzb24iLCJoYXNoIjoiYTYxNWVlYWVlMjFkZTUxNzlkZTA4MGRlOGMzMDUyYzhkYTkwMTEzODQwNmJhNzFjMzhjMDMyODQ1ZjdkNTRmNCIsImFsZ29yaXRobSI6IlNIQS0yNTYifSx7Im5hbWUiOiJmb28vYmFyL2h0dHAvcG9saWN5L3BvbGljeS5yZWdvIiwiaGFzaCI6ImY2NjQ0NjFlMzAzYjM3YzIwYzVlMGJlMjkwMDg4MTY3OGNkZjhlODYwYWE0MzNhNWExNGQ0OTRiYTNjNjY2NDkiLCJhbGdvcml0aG0iOiJTSEEtMjU2In1dLCJpYXQiOjE1OTIyNDgwMjcsImlzcyI6IkpXVFNlcnZpY2UiLCJzY29wZSI6IndyaXRlIn0.qTHkuBDVuT-Zl5pbJdZ6LoJ9eooFOhhpRdCheauDrlA`
files := [][2]string{
{"/.manifest", `{"revision": "quickbrownfaux"}`},
{"/.signatures.json", fmt.Sprintf(`{"signatures": ["%v"]}`, signedTokenHS256)},
{"/a/b/c/data.json", "[1,2,3]"},
{"/http/policy/policy.rego", `package example`},
}

decoded signature:

  {
        "name": "foo/bar/.manifest",
        "hash": "507a2c38a1441db58d2cb87982c42aa91a4342ef422a6b542eddebeef6f0412f",
        "algorithm": "SHA-256"
      },
      {
        "name": "foo/bar/a/b/c/data.json",
        "hash": "a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4",
        "algorithm": "SHA-256"
      },
      {
        "name": "foo/bar/http/policy/policy.rego",
        "hash": "f664461e303b37c20c5e0be2900881678cdf8e860aa433a5a14d494ba3c66649",
        "algorithm": "SHA-256"
      }
    ],
    "iat": 1592248027,
    "iss": "JWTService",
    "scope": "write"
  }

when reading: https://www.openpolicyagent.org/docs/latest/management-bundles/#signature-format my understanding would be that the filename should be relative to the .signatures.json file see also #6147 that would implement that.

@ashutosh-narkar
Copy link
Member

when reading: https://www.openpolicyagent.org/docs/latest/management-bundles/#signature-format my understanding would be that the filename should be relative to the .signatures.json

That is not necessary. They could be absolute paths as well. So #6147 would possibly break existing bundle checks and loading as well. Hence for backwards compatibility let's not change that. If this is a concern for OCI bundles, we should address that in this PR.

@netlify
Copy link

netlify bot commented Aug 14, 2023

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit 0506d01
🔍 Latest deploy log https://app.netlify.com/sites/openpolicyagent/deploys/64edfc896212840008beb39f
😎 Deploy Preview https://deploy-preview-6145--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@gitu
Copy link
Contributor Author

gitu commented Aug 14, 2023

@ashutosh-narkar took me a while to get to write a proper test for only changing the behaviour for the oci downloader please have another look

@gitu gitu force-pushed the verification-oci-signatures branch from 364102d to b42b2fd Compare August 14, 2023 19:59
@gitu gitu changed the title remove double base url fix signature verification for oci hosted bundles Aug 15, 2023
@@ -271,7 +271,7 @@ func (d *OCIDownloader) download(ctx context.Context, m metrics.Metrics) (*downl
return nil, err
}
loader := bundle.NewTarballLoaderWithBaseURL(fileReader, d.localStorePath)
reader := bundle.NewCustomReader(loader).WithBaseDir(d.localStorePath).
reader := bundle.NewCustomReader(loader).
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't this break verification for some existing OCI bundles?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As there was no test for it I assume that it didn't work before.

If you want to try that just add revert the line you mentioned and rerun the test.

The test uses a bundle that is signed directly via opa:

//go:generate go run github.com/open-policy-agent/opa build -b --signing-alg HS256 --signing-key secret testdata/signed_bundle_data --output testdata/signed.tar.gz

I still consider the #6147 the more correct thing to do, although I see that might lead to not backward compatible changes. As my assumption is that I could sign a bundle in one folder for example: /home/userx/bundles/myBundle then copy that to another system into /data/bundles/myBundle and verify the signature without having to move to bundle to a specific folder. Besides that point the other usages of the bundle reader do not seem to us the WithBaseDir option.

opa/download/download.go

Lines 331 to 338 in de896d9

reader := bundle.NewCustomReader(loader).
WithMetrics(m).
WithBundleVerificationConfig(d.bvc).
WithBundleEtag(etag).
WithLazyLoadingMode(d.lazyLoadingMode).
WithBundleName(d.bundleName).
WithBundlePersistence(d.persist)
if d.sizeLimitBytes != nil {

or

r := bundle.NewCustomReader(bundle.NewTarballLoaderWithBaseURL(f, ""))
if bvc != nil {
r = r.WithBundleVerificationConfig(bvc)
}
b, err := r.Read()
if err != nil {
return nil, err
}

@ashutosh-narkar
Copy link
Member

@DerGut if you have sometime to review these changes especially anything you think that affects current behavior that would be great!

Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

Few nits and comments inline. Thanks for working on this!

download/oci_download_test.go Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

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

What is this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

my bad, that went lost while rebasing now it should be clear that is just a rename of the existing tar.layer file

download/testharness.go Outdated Show resolved Hide resolved
@gitu gitu force-pushed the verification-oci-signatures branch from 44e8d08 to b278d01 Compare August 29, 2023 11:18
@gitu
Copy link
Contributor Author

gitu commented Aug 29, 2023

Few nits and comments inline. Thanks for working on this!

@ashutosh-narkar thanks for the review, now this small stuff is also still easy to change :D

Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

Thanks @gitu! Can you please squash your commits and we can get this in.

@gitu gitu force-pushed the verification-oci-signatures branch from 0506d01 to 6c9f860 Compare August 29, 2023 17:52
@gitu
Copy link
Contributor Author

gitu commented Aug 29, 2023

@ashutosh-narkar done, thanks for you review

@ashutosh-narkar ashutosh-narkar merged commit 519eea7 into open-policy-agent:main Aug 29, 2023
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants