Hi there
I’m trying to make a snap that can accept a custom CA in the java truststore. The JVM expects the truststore to be in the file
usr/lib/jvm/default-java/lib/security/cacerts
which is typically a symlink to
/etc/ssl/certs/java/cacerts
This can be installed into the snap using the ca-certs-java apt package. Great. However it’s installed onto a readonly filesystem. I need the cacerts file to be on the $SNAP_COMMON filesystem and then symlinked to the location that the JVM expects, noted above and on the readonly filesystem.
How to do this? I’ve tried using the install hook script, but obviously it’s too late in the lifecycle to create the symlink at that stage, since the $SNAP filesystem is already readonly. Within snapcraft.yaml I can’t reference $SNAP_COMMON, as I only get the directory of snapcraft itself.
You want to copy the content from $SNAP to $SNAP_DATA using the install hook and then use a layout to re-map the dir from $SNAP_DATA to the respective place in /etc…
error: cannot perform the following tasks:
- Run install hook of "mysnap" snap if present (run hook "install":
-----
cannot update snap namespace: cannot write to "/etc/ssl/certs/java/cacerts" because it would affect the host in "/etc/ssl"
snap-update-ns failed with code 1
-----)
checking on my local ubuntu install, cacerts is actually an empty symlink shipped inside the package, but only populated from the dpkg postinst script through a dpkg-trigger call:
(this is openjdk-8 but i doubt newer ones are different)
so what you likely need to do during your build is to add your jdk package as build-package and then pull in the actual /etc/ssl/certs/java from the host into your build … for stage-packages the postinst scripts are explicitly disabled, so you wouldn’t get the properly populated dir from that …
But for some reason the layout section doesn’t want to work, the symlink from $SNAP_COMMON/etc/ssl/certs/java/cacerts to $SNAP/usr/lib/jvm/java-11-openjdk-amd64/lib/security/cacerts just doesn’t seem to get made.
Thanks for your help thus far,
Err, why would you want that ? What you want is a symlink from /etc/ssl/certs/java pointing to $SNAP_COMMON/etc/ssl/certs/java and populate the latter from the install hook
well that would be great but then I’m back to this error
cannot update snap namespace: cannot write to "/etc/ssl/certs/java/cacerts" because it would affect the host in "/etc/ssl"
snap-update-ns failed with code 1
Hmm, i wonder if /etc/ssl as a whole is blocked then… i could understand why we would prevent the top level to be protected, but not a subdirectory like the java one… @zyga do you happen to know more?
I don’t remember off the top of my head. The problem with /etc is that it’s a literal bind-mount from real host /etc. Making things writable there is tricky, creating new entries is tricky. We do some “creative” things to work around this, but it’s not guaranteed.
Having said that, /etc/ssl/certs/java exists on my host so it should be fine to bind-mount to the directory. Does the reporter @grob also have that directory around?
One more note on the error message, it’s not from apparmor, it’s actually from our own system that is designed to not mutate the host unless we really explicitly want to, and the part about “because it would affect the host” is precisely from that piece.
Having said that, /etc/ssl/certs/java exists on my host so it should be fine to bind-mount to the directory. Does the reporter @grob also have that directory around?
I’ll need to check as I was using a VM to build on, which I’ve since misplaced - let me dig about a bit and see if I can find it. But honestly I’m having trouble understanding why this is an issue - I thought the whole point of an overlay is that it offers an isolated view of the filesystem that only affects the snap and not the host?