Skip to content

Commit

Permalink
Update the Quarkus SSL guide to reflect the latest state
Browse files Browse the repository at this point in the history
Co-authored-by: Guillaume Smet <[email protected]>
  • Loading branch information
geoand and gsmet committed Jun 15, 2020
1 parent bc861de commit aa5820e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ private void handleAdditionalProperties(NativeConfig nativeConfig, List<String>
String trimmedBuildArg = buildArg.trim();
if (trimmedBuildArg.contains(TRUST_STORE_SYSTEM_PROPERTY_MARKER) && isContainerBuild) {
/*
* When the native binary is being built with a docker container, because a volume is create,
* When the native binary is being built with a docker container, because a volume is created,
* we need to copy the trustStore file into the output directory (which is the root of volume)
* and change the value of 'javax.net.ssl.trustStore' property to point to this value
*
Expand Down
81 changes: 23 additions & 58 deletions docs/src/main/asciidoc/native-and-ssl.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ As long as you have one of those extensions in your project, the SSL support wil

Now, let's just check the size of our native executable as it will be useful later:
```
$ ls -lh target/rest-client-1.0-SNAPSHOT-runner
-rwxrwxr-x. 1 gsmet gsmet 34M Feb 22 15:27 target/rest-client-1.0-SNAPSHOT-runner
$ ls -lh target/rest-client-quickstart-1.0-SNAPSHOT-runner
-rwxrwxr-x. 1 gandrian gandrian 46M Jun 11 13:01 target/rest-client-quickstart-1.0-SNAPSHOT-runner
```

== Let's disable SSL and see how it goes
Expand Down Expand Up @@ -138,11 +138,11 @@ And we end up with:
You remember we checked the size of the native executable with SSL enabled?
Let's check again with SSL support entirely disabled:
```
$ ls -lh target/rest-client-1.0-SNAPSHOT-runner
-rwxrwxr-x. 1 gsmet gsmet 25M Feb 22 15:19 target/rest-client-1.0-SNAPSHOT-runner
$ ls -lh target/rest-client-quickstart-1.0-SNAPSHOT-runner
-rwxrwxr-x. 1 gandrian gandrian 35M Jun 11 13:06 target/rest-client-quickstart-1.0-SNAPSHOT-runner
```

Yes, it is now **25 MB** whereas it used to be **34 MB**. SSL comes with a 9 MB overhead in native executable size.
Yes, it is now **35 MB** whereas it used to be **46 MB**. SSL comes with a 11 MB overhead in native executable size.

And there's more to it.

Expand All @@ -161,71 +161,36 @@ And let's build the native executable again:
[#the-truststore-path]
== The TrustStore path

You haven't noticed anything but, while building the image,
Quarkus has automatically set `javax.net.ssl.trustStore` to point to the `cacerts` file bundled in the GraalVM distribution.
This file contains the root certificates.

This is useful when running tests but, obviously, it is not portable as this path is hardcoded.
[WARNING]
====
This behavior is new to GraalVM 19.3+.
====

You can check that pretty easily:
When creating a native binary, GraalVM embraces the principle of "immutable security" for the root certificates.
This essentially means that the root certificates are fixed at image build time, based on the certificate configuration used at that build time
(which for Quarkus means when you perform a build having `quarkus.package.type=native` set).
This avoids shipping a `cacerts` file or requiring a system property be set in order to set up root
certificates that are provided by the OS where the binary runs.

* move your GraalVM directory to another place (let's call it `<new-graalvm-home>`)
* run the native executable `./target/rest-client-1.0-SNAPSHOT-runner`
* in a browser, go to `http://localhost:8080/country/name/greece`
* you will have an Internal Server Error
* in your terminal, you should have an exception: `java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty`
* hit `Ctrl+C` to stop the application
As a consequence, system properties such as `javax.net.ssl.trustStore` do not have an effect at
run time, so when the defaults need to be changed, these system properties must be provided at image build time.
The easiest way to do so is by setting `quarkus.native.additional-build-args`. For example:

To make it work, you need to manually set `javax.net.ssl.trustStore` to point to the new GraalVM home:
```
./target/rest-client-1.0-SNAPSHOT-runner -Djavax.net.ssl.trustStore=<new-graalvm-home>/jre/lib/security/cacerts
quarkus.native.additional-build-args=-J-Djavax.net.ssl.trustStore=/tmp/mycerts,-J-Djavax.net.ssl.trustStorePassword=changeit
```

Now, the application should work as expected:
will ensure that the certificates of `/tmp/mycerts` are baked into the native binary and used *in addition* to the default cacerts.

* in a browser, go to `http://localhost:8080/country/name/greece`
* you should see a JSON output with some information about Greece
* hit `Ctrl+C` to stop the application

[TIP]
[IMPORTANT]
====
The root certificates file of GraalVM might not be totally up to date.
If you have issues with some certificates, your best bet is to include the `cacerts` file of a regular JDK instead.
====

[WARNING]
====
Don't forget to move your GraalVM directory back to where it was.
The file containing the custom TrustStore does *not* have to be present at runtime as its content has been baked into the native binary.
====

=== Working with containers

When working with containers, the idea is to bundle the certificates in the container and to point your binary to them using the system property mentioned above.

You can for example modify your `Dockerfile.native` as follows to copy the required files to your final image:

[source, subs=attributes+]
----
FROM quay.io/quarkus/ubi-quarkus-native-image:{graalvm-flavor} as nativebuilder
RUN mkdir -p /tmp/ssl \
&& cp /opt/graalvm/lib/security/cacerts /tmp/ssl/
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY --from=nativebuilder /tmp/ssl/ /work/
COPY target/*-runner /work/application
# set up permissions for user `1001`
RUN chmod 775 /work /work/application \
&& chown -R 1001 /work \
&& chmod -R "g+rwX" /work \
&& chown -R 1001:root /work
EXPOSE 8080
USER 1001
CMD ["./application", "-Dquarkus.http.host=0.0.0.0", "-Djavax.net.ssl.trustStore=/work/cacerts"]
----
No special action needs to be taken when running the native binary in a container. If the native binary was properly built with the custom TrustStore
as described in the previous section, it will work properly in container as well.

== Conclusion

Expand Down

0 comments on commit aa5820e

Please sign in to comment.