Open CrispinStichart opened 2 years ago
I agree the out-of-the-box might not cover the docker image, unfortunately, due to the exposed IP.
Regarding adding you own certificate:
Relates to #284 .
For GreenMail 1.6.x, you need to actually add it to the JAR in the container image (so that it is found first in the class path, before the shipped default greenmail.p12). Not very user friendly.
Interesting. I don't know much about Java, but I was under the impression that you could override resources by putting their location in the classpath. In fact, this is what the comment in DummySSLServerSocketFactory.java
says:
GreenMail provides the keystore resource. For customization, place your greenmail.p12 before greenmail JAR in the classpath.
Perhaps I'm misreading that, and/or Java classpath/resource loading doesn't work like I think it does.
Looking at your journey, the provided/shipped greenmail.p12 should be provided by default parallel to the greenmail-standalone.jar and configured by default (easier to override via eg COPY or bind-mount).
Yeah, that'd be nice.
Anyway, I finally got it working, with the following steps, listed here for the benefit of anyone else struggling with a similar problem:
1: Create a certificate and key:
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
-keyout greenmail.key -out greenmail.crt -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
The subjectAltName
is the critical bit; a lot of places on the internet imply that it'll work as long as the CN is set to localhost
. However, support for that has been apparently deprecated for almost two decades. Had to learn that from a random post on the python bug tracker. 🙄
2: Generate the .p12
keystore:
openssl pkcs12 -export -out greenmail.p12 -inkey greenmail.key -in greenmail.crt
When it asks for a password, use changeit
.
3: Add certificate as a Trusted Root Certificate Authority
In Linux:
sudo cp greenmail.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
In Windows, use the graphical Certificate Manager (just search "certificate" and it should come up).
4: Add the keystore to the JAR
Get the greenmail-standalone.jar
file, either from the Docker image (not sure how, but I think it can be done) or just downloading it from maven.
Add the keystore: jar uvf greenmail-standalone.jar greenmail.p12
(or just open the jar in 7zip or whatever).
5: Bind mount the JAR when running docker:
docker run -v <full path to greenmail-standalone.jar>:/home/greenmail/greenmail-standalone.jar -t -i -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -D-Dgreenmail.verbose' -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 greenmail/standalone:1.6.7
Note that I had to use the full path, not relative, of the local JAR file to get it working.
After all that, I can successfully establish a secure connection with the greenmail server.
According to Greenmail's website's FAQ, Greenmail should work out-of-the box with SSL/TLS. However, since it makes mention of Java's keystore, I'm wondering if the same applies to the stand-alone docker image.
I'm trying to set up integration testing for a simple email client I'm writing in Rust (with rust-imap). Attempting to connect to greenmail gives me an error (on my client side) about an untrusted root certificate.
I don't know much about security stuff, so I've spent the last five-plus hours trying to figure out what's going on.
From what I've learned, it seems like it's not expected to work out-of-the-box when doing integration testing, since the connection has to go through the OS, and the OS will reject any untrusted certificates.
So next I attempted to create my own
greenmail.p12
, add it as a "Trusted Root Certificate Authority", and insert it into the java classpath when running the docker image. I must be doing something wrong, because it's not using mine. I'm running this command:docker run -v greenmail.p12:/jks/ -t -i -e JAVA_OPTS='-classpath /jks/' -e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' -p 3025:3025 -p 3110:3110 -p 3143:3143 -p 3465:3465 -p 3993:3993 -p 3995:3995 greenmail/standalone:1.6.7
Next I tried extracting the
greenmail.p12
keystore that ships with the 1.6.7 JAR and adding that as a Trusted Root Certificate Authority, and I got a bit further: now I'm getting an error about the CN not matching.Looking into this error, it seems like it's because the FQDM of the certificate needs to match the domain I'm connecting to, which in this case is localhost.
Before I spend more hours on this, I just want to ask: am I doing something dumb? Is this supposed to be easy? The fact that the
rust-imap
tests take the route of configuring a TLS connector to accept invalid certificates doesn't fill me with hope. And I mean yeah, I could do that in this case, but I'm also trying to learn something here, especially in case I ever want to use greenmail in a different context where I can't do that.At the very least, are there any good examples of setting up and using greenmail with integration tests outside of Java? Everything I can find on google is Java-related.