paketo-buildpacks / ca-certificates

A Cloud Native Buildpack that adds custom CA certificates to a build and a created image
Apache License 2.0
24 stars 10 forks source link

Allow to avoid certificates splitting into multiple files #207

Open Infra-Red opened 7 months ago

Infra-Red commented 7 months ago

Describe the Enhancement

Currently, builpdack splits the certificate into multiple files when a .pem file contains multiple entries. I would like to introduce an option that will allow us to preserve the original .pem format and ignore splitting behavior.

Possible Solution

The proposed solution is to introduce a new environment variable BP_EMBED_CERTS_SKIP_SPLITTING which will ignore certificate splitting when supplied in the build parameters. I noticed that multi-certificates file is not supported by helper (https://github.com/paketo-buildpacks/ca-certificates/issues/100) so we can always ignore BP_EMBED_CERTS_SKIP_SPLITTING value unless BP_RUNTIME_CERT_BINDING_DISABLED is set a true value.

Motivation

In my scenario, I'm using ca-certificates buildpack to only add certificates to a layer and make them available during runtime (BP_EMBED_CERTS=true and BP_RUNTIME_CERT_BINDING_DISABLED=true) which is later specified in sslrootcert PostgreSQL connection parameters. Current splitting behavior makes it difficult to execute certificate rotation as sslrootcert accepts only a single file value so preserving multiple certificates will make it easier to perform certificate rotation.


Please let me know if the proposed solution is fine with you. I'm going to work on PR If this is something you are ready to accept.

dmikusa commented 7 months ago

The ca-certificates buildpack is intended to import and format certificates in a way that OpenSSL can natively read them. Can you expand on your use case? Is your application using system certificates? or is it referencing a certificate file specifically? I'm trying to understand if you care that your certs are part of the system certificates or if you are just trying to embed certs into the container. Thanks

Infra-Red commented 7 months ago

Hi @dmikusa!

or if you are just trying to embed certs into the container

This ☝️ My goal is to embed the certs into a container and make them available during the runtime as my application configuration does not rely on the system keystore but reads a .pem file from the filesystem.

dmikusa commented 7 months ago

Hi @dmikusa!

or if you are just trying to embed certs into the container

This ☝️ My goal is to embed the certs into a container and make them available during the runtime as my application configuration does not rely on the system keystore but reads a .pem file from the filesystem.

This particular buildpack is focused on putting certs into the system cert chain. I worry that this would be getting away from that core purpose. I'm not saying we can't add this, but I'd like to explore other options first.

Is there a reason you need it in a layer or were you just using that because ca-certificates put the certs there? Could you put it in the app directory instead? Getting files into the app directory is going to be easier and they will end up in the image too.

Also, what language is your app?

Thanks

itachigit commented 7 months ago

Hey @dmikusa,

Also, what language is your app?

it's a Java app, we run its jar archive and we have little to no control over making a change in the archive. That's why we sought this buildpack.

were you just using that because ca-certificates put the certs there

☝️ this. We just need the .pem file as it is available in the binding, and inject it in some directory (layers directory in this case).

dmikusa commented 7 months ago

Sorry for the delay. One thing you might try here is to just create a small custom buildpack. The buildpack can add the cert files you need in the location you need them. You could even embed your certs into the buildpack, so the buildpack is self contained and just writes out the certs.

It might seem difficult, but you can put one together with just a couple bash scripts. There is a nice walk through available here.

You can also use an inline buildpack which will be very similar but it's placed in the application's project.toml file. It's a little less overhead, but it's a little more pain if you need to use it across multiple apps.

doddisam commented 2 months ago

@dmikusa - I know today by using BP_EMBED_CERTS during the build, all the certs will be in layers directory (/layers/paketo-buildpacks_ca-certificates/ca-certificates/ca-certificates). By using SSL_CERT_DIR variable in my k8's deployment i am able to add these certs into trust store. I would like to add these certs as part of default system certs directory (/etc/ssl/certs). Is this possible today ?

dmikusa commented 2 months ago

I would like to add these certs as part of default system certs directory (/etc/ssl/certs). Is this possible today ?

@doddisam Not with a buildpack. Buildpacks won't have access to that directory because you need to be root.

That said, you can do this. You just need to add the certs you want into the stack and publish your own stack/builders.

If you only need the certs to be trusted at runtime, then it can be a little easier. You can add the certs to your runtime image only and publish a custom runtime image. Then when you pack build, you can override the runtime image with your custom runtime image.

The other option, which is newer, is to create a custom extension. Extensions can have elevated permissions so they would be able to write to that directory. However, there are downsides to extensions. They can break your ability to rebase images safely because they modify the image dynamically.

doddisam commented 2 months ago

@dmikusa Thanks for your input. Much appreciated!