Making your landscape trust a certain certificate authority


Mathias Essenpreis <esse@...>
 

Hi,
we want to make the apps on our landscape trust a certain ca certificate of a ca we run internally. I came across the instructions on how to do this for the JRE buildpack: https://github.com/cloudfoundry/java-buildpack/blob/master/docs/jre-open_jdk_jre.md#custom-ca-certificates

I understand doing this once in the JRE buildpack will directly make all the java apps that of course need to make use of the JRE buildpack trusting our internal ca. Is that correct or do I need to change other buildpacks as well?

However this implies performing a fork of the JRE buildpack. A fork means that we always need to synchronize manually with the newer versions of the build pack.

How do you approach this problem in your organization? I suppose you also have internal certificate authorities that need to be trusted, right?

Also I am asking myself whether there is a way to enhance the default buildpack allowing an application (instead of the buildpack) to bring their own, additional certificates?

thx
Mathias


Daniel Mikusa
 

A couple options...

1.) If you only need the cert for one or a couple apps and / or you don't
want to manage a fork, you can package the CA cert with the application.
Then add a `.profile.d` script [1] that sets up the certificate that you
packaged with the app. I don't have an example off-hand, but the
.profile.d script could call keytool and import your ca cert or just move a
keystore containing your ca cert from the app files and overwrite the JVM
default.

2.) Write your application so that it can utilize it's own truststore.
It's a little more work, but most things that use a truststore in the JVM
allow you to customize the behavior specifying your own truststore. If the
app were to do this, it could then expose a configuration option through
which it's users could set their own truststore. Then users wouldn't need
to depend on what certs are installed by default.

Dan


[1] - https://devcenter.heroku.com/articles/profiled (CF honors them too)

On Tue, Sep 29, 2015 at 4:50 PM, Mathias Essenpreis <esse(a)gmx.de> wrote:

Hi,
we want to make the apps on our landscape trust a certain ca certificate
of a ca we run internally. I came across the instructions on how to do this
for the JRE buildpack:
https://github.com/cloudfoundry/java-buildpack/blob/master/docs/jre-open_jdk_jre.md#custom-ca-certificates

I understand doing this once in the JRE buildpack will directly make all
the java apps that of course need to make use of the JRE buildpack trusting
our internal ca. Is that correct or do I need to change other buildpacks as
well?

However this implies performing a fork of the JRE buildpack. A fork means
that we always need to synchronize manually with the newer versions of the
build pack.

How do you approach this problem in your organization? I suppose you also
have internal certificate authorities that need to be trusted, right?

Also I am asking myself whether there is a way to enhance the default
buildpack allowing an application (instead of the buildpack) to bring their
own, additional certificates?

thx
Mathias


Eric Westenberger
 

Hello,

I am trying to implement option 1 above but I am struggling from where to pick up the certificate files which I have packaged with my application (for experimentation I put the certificates both in the .profile.d directory and a ssl folder in my webapp).

I tried the following variants
keytool -keystore ... -storepass ... -importcert -alias MyCert -file MyCert.crt
keytool -keystore ... -storepass ... -importcert -alias MyCert -file /home/vcap/app/.java-buildpack/tomcat/webapps/ROOT/ssl/MyCert.crt
keytool -keystore ... -storepass ... -importcert -alias MyCert -file /home/vcap/app/ssl/MyCert.crt

I all cases I am getting
(No such file or directory)[App/0] OUT keytool error: java.io.FileNotFoundException: ...MyCert.crt (or similar)
( I checked using cf files myapp app/.profile.d that the files are deployed)

Does someone have an idea how to address within the profile.d script files from the deployed application?

Best,
Eric

PS: I had to put the profile.d folder into the web app root folder in order to be picked up, which makes it a public resource. The documentation is also not very clear where to put it. Any ideas in this direction would also be appreciated.


Daniel Mikusa
 

Eric,

Some comments inline...

On Fri, Oct 2, 2015 at 5:02 AM, Eric Westenberger <
eric.westenberger(a)gmail.com> wrote:

Hello,

I am trying to implement option 1 above but I am struggling from where to
pick up the certificate files which I have packaged with my application
(for experimentation I put the certificates both in the .profile.d
directory and a ssl folder in my webapp).
This is a little tricky with Java apps because of how they get packaged
up. You need to make sure that `.profile.d` is included at the root of
your WAR file. If you run `jar tf file.war` it should list `.profile.d/`
and nothing in the path before that.

When your app gets uploaded to CF, the files are extracted from the WAR and
you end up with an exploded WAR director at `/home/vcap/app`. Since
`.profile.d` is at the root of your WAR, that means
`/home/vcap/app/.profile.d` is where you should be able to find your script
and anything else you put in that directory.


I tried the following variants
keytool -keystore ... -storepass ... -importcert -alias MyCert -file
MyCert.crt
keytool -keystore ... -storepass ... -importcert -alias MyCert -file
/home/vcap/app/.java-buildpack/tomcat/webapps/ROOT/ssl/MyCert.crt
keytool -keystore ... -storepass ... -importcert -alias MyCert -file
/home/vcap/app/ssl/MyCert.crt
If I understand your comment above, I'd have expected the last one to
work. You said that you put a `ssl` director at the root of your WAR file
and that contained the certs. I'd also expect the path
`/home/vcap/app/.profile.d/MyCert.crt` to work since you said you put the
certs into the `.profile.d` folder too.



I all cases I am getting
(No such file or directory)[App/0] OUT keytool error:
java.io.FileNotFoundException: ...MyCert.crt (or similar)
( I checked using cf files myapp app/.profile.d that the files are
deployed)
A few tips for debugging `.profile.d` scripts.

1.) Put `sleep 2` as the first line of the script, right after the
`#!/bin/bash`. This works around a known issue with logging, which can
sometimes cause log entries to be lost.

2.) Add copious echo statements to your script. You can also do things
like run `ls` and `pwd` to inspect the environment. Anything that writes
to STDOUT should show up when the script runs.

3.) You can use environment variables like `$PWD` and `$HOME` so you don't
have to deal with full paths. `$HOME` points to `/home/vcap/app` and
`$PWD` points to the working directory, which should also be
`/home/vcap/app`.



Does someone have an idea how to address within the profile.d script files
from the deployed application?
You're close. Try adding some `ls` statements if you need to confirm
exactly where things are at. The output should show up when you run your
script.



Best,
Eric

PS: I had to put the profile.d folder into the web app root folder in
order to be picked up, which makes it a public resource. The documentation
is also not very clear where to put it. Any ideas in this direction would
also be appreciated.
The `.profile.d` folder has to be in the root of what you push to CF.
That's the only place it will get picked up.

It depends on your app and how it's configured to serve up public files,
but you can generally put anything that you need to protect under `WEB-INF`
since that shouldn't be publicly accessible. For example if you want to
keep someone from seeing your script you could put `.profile.d/wrapper.sh`
which will get called by CF and have it call `WEB-INF/secret-script.sh`,
which is your actual script.


Eric Westenberger
 

Hi,

thanks so much for pointing me in the right direction. The following script worked for me

#!/bin/bash
sleep 2
$HOME/.java-buildpack/open_jdk_jre/bin/keytool -keystore $HOME/.java-buildpack/open_jdk_jre/lib/security/cacerts -storepass changeit -importcert -noprompt -alias MyCert -file $HOME/WEB-INF/ssl/MyCert.crt

Cheers, Eric