prosgarz35 opened a new pull request, #3240:
URL: https://github.com/apache/james-project/pull/3240
## Summary
This pull request introduces support for configuring TLS on the JMAP server
directly using `.pem` certificates and private keys, as well as Java Keystores
(JKS / PKCS12), matching the existing PEM TLS support found in IMAP, POP3, and
SMTP protocols.
Prior to this change, JMAP relied on plain HTTP, requiring an external
reverse proxy (such as Nginx or Traefik) to terminate TLS. With this
enhancement, administrators can terminate TLS natively within Apache James JMAP
using standard PEM certificates (e.g. Let's Encrypt certificates) or existing
keystores.
## Key Changes
1. **`server/protocols/jmap` (`pom.xml`):**
- Added `ayza-for-pem` (`io.github.hakky54:ayza-for-pem`) dependency to
parse PEM-encoded certificates and private keys (PKCS#1, PKCS#8, EC, RSA) via
`PemUtils`, consistent with the rest of James.
- Added `james-server-filesystem-api` dependency to resolve
certificate/keystore resource locations (`file://`, `classpath://`, etc.).
2. **`JMAPConfiguration.java`:**
- Added TLS configuration options:
- `tls.keystoreURL` / `keystore`
- `tls.keystoreType` / `keystoreType` (optional, default: JKS)
- `tls.privateKey` / `privateKey`
- `tls.certificates` / `certificates`
- `tls.secret` / `secret` (optional password for keystore or encrypted
private key)
- Added `isTlsEnabled()` helper method checking if keystore or PEM
certificate/key pair is supplied.
- Preserved backward compatibility for testing constructors
(`@VisibleForTesting`).
3. **`JMAPServer.java`:**
- Injected `FileSystem` into the Guice constructor.
- Configured Reactor Netty `HttpServer` with `.secure(...)` when TLS is
enabled.
- Built Netty `SslContext`:
- **PEM Mode:** Parsed certificate chain via
`PemUtils.loadCertificate(...)` and private key via
`PemUtils.loadPrivateKey(...)`, configured via
`SslContextBuilder.forServer(privateKey, certificates)`.
- **Keystore Mode:** Loaded keystore via
`KeyStoreUtils.loadKeyStore(...)`, configured via
`SslContextBuilder.forServer(KeyManagerUtils.createKeyManager(keyStore,
password))`.
- **RFC Compliance:** Explicitly enforced TLS 1.2 and TLS 1.3 protocols
(`RFC 5246` and `RFC 8446`), avoiding insecure older versions (SSLv3, TLS 1.0,
TLS 1.1).
4. **`JMAPModule.java`:**
- Added parsing of TLS parameters from `jmap.properties`.
5. **Tests:**
- Added unit tests in `JMAPConfigurationTest` for verifying TLS
properties and builder options.
- Added integration test cases in `JMAPServerTest` verifying successful
HTTPS startup and request handling with both PEM certificates/keys and Keystore
configurations.
## Configuration Example (`jmap.properties`)
### Option A: PEM Certificates (e.g., Let's Encrypt)
```properties
# Enable JMAP
enabled=true
port=8443
# TLS with PEM files
tls.certificates=file://conf/cert.pem
tls.privateKey=file://conf/privkey.pem
# tls.secret=optional_key_password
```
### Option B: Keystore
```properties
# Enable JMAP
enabled=true
port=8443
# TLS with Keystore
tls.keystoreURL=file://conf/keystore
tls.keystoreType=PKCS12
tls.secret=mysecretpassword
```
## Adherence to Principles
- **KISS:** Directly leverages Netty's
`SslContextBuilder.forServer(PrivateKey, X509Certificate[])` without
superfluous wrapper layers.
- **DRY:** Reuses `ayza-for-pem` and `FileSystem` mechanisms already adopted
across James protocols.
- **YAGNI:** Only includes server-side TLS termination required for
HTTPS/JMAP, omitting unnecessary client-certificate authentication or dynamic
hot-swapping complexes.
- **RFC:** Strictly restricts protocol negotiation to TLSv1.2 and TLSv1.3.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]