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

ca-certificates does not require buildpacks who provide ca-certificates paths #215

Open
braunsonm opened this issue Feb 21, 2024 · 2 comments

Comments

@braunsonm
Copy link

braunsonm commented Feb 21, 2024

Expected Behavior

Based on the documentation in the README, specifically this section:

If another buildpack provides an entry of type ca-certificates in the build plan with metadata.paths containing an array of certificate paths, it adds all CA certificates from the given paths to the system truststore.

I would expect a buildpack who provides a build plan during the detection phase, to become required by this buildpack. (note that the docs are wrongly stating that it requires a type when the code expects name)
https://github.com/paketo-buildpacks/ca-certificates/blob/main/cacerts/build.go#L58

Build Plan:

[[provides]]
name = "ca-certificates"
[provides.metadata]
paths = ["my-cert.pem"]

Unfortunately this doesn't seem to be the case and you get an error from the Pack CLI during detect that no buildpacks require ca-certificates.

Current Behavior

You get an error that ca-certificates is not required by any buildpacks

Possible Solution

I noticed that detection seems to only add a require if a platform binding is provided, which would not be the case here unless I'm misunderstanding the docs: https://github.com/paketo-buildpacks/ca-certificates/blob/main/cacerts/detect.go#L55

Steps to Reproduce

  1. Create a simple buildpack with a detect phase of
#!/bin/bash

cat >${CNB_BUILD_PLAN_PATH} <<EOF
[[provides]]
name = "ca-certificates"
[provides.metadata]
paths = ["my-cert.pem"]
EOF
  1. Run pack build example --path ./sample-app --buildpack ./example-buildpack --buildpack paketobuildpacks/ca-certificates
  2. Note the error during detect phase

Motivations

I am creating a custom meta buildpack and would like to include custom CA's during the build phase that are bundled within the buildpack itself rather than at runtime.

I'm fairly new to creating buildpacks so it's possible I misunderstood something about the docs.

@braunsonm
Copy link
Author

I thought that perhaps because I am providing the cert I would need to also have a [[requires]] block but this prevents it from getting passed to the build phase of the ca-certificates buildpack.

#!/bin/bash

cat >${CNB_BUILD_PLAN_PATH} <<EOF
[[provides]]
name = "ca-certificates"
[provides.metadata]
paths = ["/layers/my-buildpacks_example/certs/my-cert.pem"]
[[requires]]
name = "ca-certificates"
[requires.metadata]
paths = ["/layers/my-buildpacks_example/certs/my-cert.pem"]
EOF

This allows it to complete the detect phase but the ca-certificates buildpack downstream doesn't receive the entry in the build plan when BP_LOG_LEVEL=debug is enabled. So I'm assuming that Pack "consumes" the requires as my example buildpack also provides it.

Hate to tag but just seeing if @dmikusa has any ideas since you seem to actively maintain this project.

@dmikusa
Copy link
Contributor

dmikusa commented Jul 14, 2024

Sorry for the delay. Here's how this is supposed to work.

  1. You have a custom buildpack. It should requires ca-certificates. This logically sounds backwards cause your custom buildpack is providing ca-certificates, but the buildplan entry ca-certificates is not the certificates itself, you're saying that you require the ca-certificates buildpack to process some custom CA certificates (i.e. you require the processing of custom ca-certs).

  2. Your custom buildpack needs to be listed AFTER the ca-certificates buildpack. This is critical because you can only require something that has been provided by a previous buildpack in the order group.

When you do this, detect should pass because you're requiring ca-certificates and the ca-certificates buildpack provides ca-certificates (even if you don't have any bindings). At build time, the ca-certificates buildpack will check the buildplan and you'll see it read the paths you specified in the buildplan metadata.

The limitation that is present here is that you cannot dynamically generate CA certificates with your custom buildpack.

This is because your custom buildpack MUST come after the ca-certificates buildpack in the order group to pass detection, but that means that your custom buildpack's build script will not run until after the ca-certificates build binary runs. This unfortunately negates some of the things you can do here. For example, you can't load CA certificates from an external resource because that would need to be done during build time.

If you want to provide CA certs through a custom buildpack, that means you can either do:

  1. Embed the custom ca certs into the buildpack image itself. That way they're always present. This means you need to rebuild the buildpack image whenever you need to change certificates.

  2. If you need dynamically loaded certificates, then you need two buildpacks. One buildpack has its own buildplan entry and one that will require ca-certificates. The former can just provide/require itself, so that's easy. This buildpack should go before ca-certificates in the order group, and since it's first, it can dynamically download/fetch CA certificates. The latter buildpack is basically there to add the buildplan requirement/metadata. It will need to put paths to the CA certificates that the former buildpack generated.

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

No branches or pull requests

2 participants