Skip to content

Commit 0a09dc2

Browse files
Remove ACME / TLS certification related code
Have decided to just handle TLS / HTTPS configuration external to this server. Fix #289
1 parent d2ddd28 commit 0a09dc2

File tree

15 files changed

+17
-834
lines changed

15 files changed

+17
-834
lines changed

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM maven:3.8-eclipse-temurin-21 AS build
22
ARG CI_COMMIT_SHA
33
LABEL git-commit=$CI_COMMIT_SHA
44
# The `[]` is an optional COPY: doesn't copy if those files aren't there (https://stackoverflow.com/a/46801962/11416267)
5-
# They are needed for Tyler API usage, and serving the REST API as HTTPS
5+
# They are needed for Tyler API usage
66
COPY pom.xml /app/
77
COPY TylerEcf4 /app/TylerEcf4/
88
COPY TylerEcf5 /app/TylerEcf5/
@@ -13,7 +13,7 @@ RUN mvn -f /app/pom.xml -DskipTests clean dependency:resolve dependency:go-offli
1313

1414
COPY proxyserver /app/proxyserver
1515
RUN mvn -f /app/pom.xml -DskipTests package -PnoDockerTests -Dbuild.revision=$CI_COMMIT_SHA && cp /app/proxyserver/target/efspserver-with-deps.jar /app/
16-
COPY LICENSE client_sign.propertie[s] quartz.properties Suffolk.pf[x] acme_user.ke[y] acme_domain.ke[y] acme_domain-chain.cr[t] extract-tls-secrets-4.0.0.ja[r] jacocoagent.ja[r] /app/
16+
COPY LICENSE client_sign.propertie[s] quartz.properties Suffolk.pf[x] extract-tls-secrets-4.0.0.ja[r] jacocoagent.ja[r] /app/
1717
COPY docker_run_dev.sh /app/
1818

1919
EXPOSE 9000
@@ -25,8 +25,8 @@ LABEL git-commit=$CI_COMMIT_SHA
2525
COPY --from=build /app/proxyserver/target/efspserver-with-deps.jar /app/
2626
COPY --from=build /app/proxyserver/src/main/config /app/src/main/config/
2727
# The `[]` is an optional COPY: doesn't copy if those files aren't there (https://stackoverflow.com/a/46801962/11416267)
28-
# They are needed for Tyler API usage, and serving the REST API as HTTPS
29-
COPY LICENSE client_sign.propertie[s] quartz.properties Suffolk.pf[x] acme_user.ke[y] acme_domain.ke[y] acme_domain-chain.cr[t] /app/
28+
# They are needed for Tyler API usage
29+
COPY LICENSE client_sign.propertie[s] quartz.properties Suffolk.pf[x] /app/
3030
COPY docker_run_script.sh fly_startup_script.sh /app/
3131

3232
EXPOSE 9000

dev-compose.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,11 @@ services:
1111
ports: !override
1212
- target: 9009
1313
published: 9100
14-
- target: 9000
15-
published: 9101
1614
extra_hosts:
1715
- "host.docker.internal:host-gateway"
1816
depends_on:
1917
- "db"
2018
volumes:
21-
- type: bind
22-
source: ./proxyserver/src/main/config
23-
target: /tmp/tls_certs
2419
# Gets exact SOAP envelopes sent when running locally with wireshark
2520
- type: bind
2621
source: .

docker-compose.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,9 @@ services:
99
ports:
1010
- target: 9009
1111
published: 80
12-
- target: 9000
13-
published: 443
1412
env_file: .env
1513
depends_on:
1614
- "db"
17-
volumes:
18-
- type: bind
19-
source: ./proxyserver/src/main/config
20-
target: /tmp/tls_certs
2115
deploy:
2216
resources:
2317
limits:
@@ -28,7 +22,7 @@ services:
2822
env_file: .env
2923
volumes:
3024
- data-volume:/var/lib/postgresql/data
31-
- ./postgres-config:/etc/postgresql
25+
- ./config/postgres-config:/etc/postgresql
3226

3327
volumes:
3428
data-volume:

docs/README.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -70,28 +70,8 @@ docker compose -f dev-compose.yml down
7070

7171
### Docassemble
7272

73-
If you are running the docker container on the same machine as docassemble, you will likely need to add the following changes to your EfileProxyServer repo:
74-
75-
```diff
76-
diff --git a/docker-compose.yml b/docker-compose.yml
77-
index 1617ba05..776776b6 100644
78-
--- a/docker-compose.yml
79-
+++ b/docker-compose.yml
80-
@@ -6,9 +6,9 @@ services:
81-
# Necessary b/c docassemble is external to the docker network
82-
ports:
83-
- target: 9009
84-
- published: 80
85-
+ published: 9000
86-
- target: 9000
87-
- published: 443
88-
+ published: 9001
89-
env_file: .env
90-
depends_on:
91-
- "db"
92-
```
93-
94-
This allows both docassemble and the proxy server to run on the same machine (by default both use the default HTTP and HTTPS ports, 80 and 443).
73+
If you are running the docker container on the same machine as docassemble, use the `-f dev-compose.yml` command
74+
above to allow this server and docassemble to use different HTTP ports.
9575

9676
To communicate with the Efile Proxy Server from docassemble using the [EFSPIntegration package](https://github.com/SuffolkLITLab/docassemble-EFSPIntegration), you will need to add some config values in docassemble's config:
9777

docs/https.md

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,76 +5,6 @@ can read the sensitive information passed to the proxy server in plaintext.
55

66
For a simple explainer, see [Julia Evan's Twitter comic about it](https://twitter.com/b0rk/status/809594614147645440/photo/1).
77

8-
## Getting a Certificate
9-
10-
The first of two steps to using HTTPS is actually getting a signed TLS certificate from a certificate signer.
11-
12-
### Using Let's Encrypt and ACME
13-
14-
We've integrated [Let's Encrypt](https://letsencrypt.org/) support into our server with the [ACME protocol](https://letsencrypt.org/how-it-works/), using [acme4j](https://github.com/shred/acme4j).
15-
16-
We are still working to improve the steps, but current the process is:
17-
18-
1. In your `.env` file, set `USE_LETSENCRYPT=True`, and `CERT_PASSWORD` to a securely generated password, at least 16 characters.
19-
Something like `openssl rand -base64 12` will generate 16 characters securely.
20-
* You can also set a `MONITORING_EMAIL` which will be used for email renewal reminders from Lets Encrypt.
21-
2. Start up the docker containers (see [setup.md](setup.md)).
22-
3. Start a shell inside the running container: `docker exec -it efileproxyserver-efspjava-1 /bin/sh`
23-
4. Change directories to the app: `cd /app`.
24-
5. Run the ACME renewal process: `java -cp efspserver-with-deps.jar edu.suffolk.litlab.efsp.server.services.acme.AcmeRenewal renew`.
25-
If the renewal process succeeded, `acme-domain-chain.crt` and `tls_server_cert.jks`
26-
should both be present in `/tmp/tls_certs` inside the container and in `src/main/config` outside the container.
27-
6. Exit the shell you started, and rebuild and restart the java docker container.
28-
29-
The newly started container should be able to serve HTTPS correctly!
30-
31-
### (Not preferred) From a Certificate Authority
32-
33-
This was the original way we did things, but Let's Encrypt is currently simpler and more secure than
34-
sending around important certificates files. If Let's Encrypt doesn't work for your organization,
35-
you can follow the below steps that we took when we set up HTTPS using a purchased signed certificate.
36-
37-
You can purchase TLS Certificates from providers directly, (for example, [from namecheap](https://www.namecheap.com/security/ssl-certificates/)). You should receive the following files:
38-
* a bundle of certificate authorities who make up the chain of CAs who signed your certificate. In our case, this had a `*.ca-bundle` extension.
39-
* The signed certificate for your website. In our case, this had a `*.crt` extension.
40-
* The private key for your website, sometimes called the domain key. In our case, this had a `*.key` extension.
41-
42-
Once you have those three things, you need to turn convert them into the Java Key Store (JKS) format, which the server can read. You can follow the below steps in a shell with `openssl` and `keytool` installed:
43-
44-
```bash
45-
# Add the full list of CA signers to the cert. Going to the root signer means it's more likely
46-
# for the server to be trusted. Not always necessary, but was in our case.
47-
cat my_domain.ca-bundle my_domain.crt > my_domain.crt
48-
openssl pkcs12 -export -in my_domain.crt -inkey my_domain.key -out my_domain.p12
49-
keytool -importkeystore -srckeystore my_domain.p12 -srcstoretype PKCS12 -destkeystore my_domain.jks -deststoretype JKS
50-
```
51-
52-
Refer to the sources below if you need more details:
53-
* ["Java TLS with Keystores" cheat-sheet](https://stackoverflow.com/a/41469242/11416267)
54-
* [Install a Tomcat cert](https://www.tbs-certificates.co.uk/FAQ/en/ajouter-certificat-intermediaire-keystore-java.html)
55-
* [How to convert \*.crt and \*.key to \*.jks](https://community.datarobot.com/t5/data-prep/how-to-convert-crt-and-key-to-jks-file/td-p/6342)
56-
57-
58-
## Developer Notes: Using the cert in the CXF Server
59-
60-
Once you have the cert, you need to set up the CXF server properly to use it. To do so,
61-
[ServerConfig.xml](https://github.com/SuffolkLITLab/EfileProxyServer/blob/4a25a9f30d7d74d9e0828d142f6b908e1a3532ec/src/main/config/ServerConfig.xml#L33)
62-
needs to point to the `*.jks` file.
63-
64-
See the following files and their code comments for the current setup.
65-
66-
* [EfspServer.java](https://github.com/SuffolkLITLab/EfileProxyServer/blob/main/src/main/java/edu/suffolk/litlab/efsp/server/EfspServer.java)
67-
* [ServerConfig.xml](https://github.com/SuffolkLITLab/EfileProxyServer/blob/main/src/main/config/ServerConfig.xml)
68-
* The ServerConfig.xml shouldn't use the `clientAuthentication` elem, as it expects our connecting clients to also have a TLS cert, which isn't how HTTPS traffic usually works.
69-
* [HttpsCallbackHandler.java](https://github.com/SuffolkLITLab/EfileProxyServer/blob/main/src/main/java/edu/suffolk/litlab/efsp/server/utils/HttpsCallbackHandler.java)
70-
* [ServiceHelpers.java](https://github.com/SuffolkLITLab/EfileProxyServer/blob/main/src/main/java/edu/suffolk/litlab/efsp/server/utils/ServiceHelpers.java#L74)
71-
* The external address (i.e `ServerFactoryBean.setAddress`) needs to be `https://`, not `http://`. We use `CERT_PASSWORD` to determine if someone is trying to run with TLS, and if no `CERT_PASSWORD` is present, we use `http://`.
72-
73-
74-
The following CXF documentation pages have more information, but are kinda sparse:
75-
76-
* [https://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAXRSServices-Configuringendpoints]
77-
* [https://cwiki.apache.org/confluence/display/CXF20DOC/TLS+Configuration]
78-
* [https://cxf.apache.org/docs/standalone-http-transport.html]
79-
* [http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/jax_rs/basic_https/]
80-
8+
We previously had [custom code to retrieve certs](https://github.com/SuffolkLITLab/EfileProxyServer/blob/b287ed3fe42e71458b8a594d0287d542b6f6035e/docs/https.md#getting-a-certificate), but now use our hosting provider, fly, to [generate certs for us](https://fly.io/docs/flyctl/certs/). We recommend something similar for folks looking to run
9+
their own version of this server. If your hosting provider doesn't provide certs, you can
10+
look into using [nginx and letsencrypt together](esc.sh/blog/lets-encrypt-and-nginx-definitive-guide/) as a reverse proxy for this server.

env.example

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# An example .env file, which is used by the docker compose container.
22
# Copy this file, rename it to `.env`, and edit your copy to use it.
33

4-
# Password for the HTTPS certificate. NOT the same as Tyler's X509_PASSWORD
5-
CERT_PASSWORD=
6-
# If true, will try to use lets encrypt to get a certificate
7-
USE_LETSENCRYPT=True
84
# The URL that the external clients see when talking to the proxy server
95
EXTERNAL_DOMAIN=efile.example.com
106
TZ=America/New_York

proxyserver/pom.xml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
<slf4j.version>2.0.7</slf4j.version>
2424
<jackson.version>2.14.2</jackson.version>
2525
<bouncycastle.version>1.81</bouncycastle.version>
26-
<acme4j.version>2.16</acme4j.version>
2726
<testcontainers.version>1.18.0</testcontainers.version>
2827
<jacoco.skip>false</jacoco.skip>
2928
<skipTestsOnBuild>true</skipTestsOnBuild>
@@ -215,16 +214,6 @@
215214
<artifactId>postgresql</artifactId>
216215
<version>42.5.4</version>
217216
</dependency>
218-
<dependency>
219-
<groupId>org.shredzone.acme4j</groupId>
220-
<artifactId>acme4j-client</artifactId>
221-
<version>${acme4j.version}</version>
222-
</dependency>
223-
<dependency>
224-
<groupId>org.shredzone.acme4j</groupId>
225-
<artifactId>acme4j-utils</artifactId>
226-
<version>${acme4j.version}</version>
227-
</dependency>
228217
<dependency>
229218
<groupId>com.hubspot</groupId>
230219
<artifactId>algebra</artifactId>

proxyserver/src/main/config/ServerConfig.xml

Lines changed: 0 additions & 42 deletions
This file was deleted.

proxyserver/src/main/java/edu/suffolk/litlab/efsp/server/EfspServer.java

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import edu.suffolk.litlab.efsp.docassemble.DocassembleToFilingInformationConverter;
1212
import edu.suffolk.litlab.efsp.ecfcodes.tyler.CodeDatabase;
1313
import edu.suffolk.litlab.efsp.server.auth.SecurityHub;
14-
import edu.suffolk.litlab.efsp.server.services.AcmeChallengeService;
1514
import edu.suffolk.litlab.efsp.server.services.ApiUserSettingsService;
1615
import edu.suffolk.litlab.efsp.server.services.AuthenticationService;
1716
import edu.suffolk.litlab.efsp.server.services.JurisdictionServiceHandle;
@@ -22,7 +21,6 @@
2221
import edu.suffolk.litlab.efsp.server.setup.EfmRestCallbackInterface;
2322
import edu.suffolk.litlab.efsp.server.setup.jeffnet.JeffNetModuleSetup;
2423
import edu.suffolk.litlab.efsp.server.setup.tyler.TylerModuleSetup;
25-
import edu.suffolk.litlab.efsp.server.utils.HttpsCallbackHandler;
2624
import edu.suffolk.litlab.efsp.server.utils.JsonExceptionMapper;
2725
import edu.suffolk.litlab.efsp.server.utils.ObservabilityHeadersInterceptor;
2826
import edu.suffolk.litlab.efsp.server.utils.ObservabilityResetInterceptor;
@@ -32,7 +30,6 @@
3230
import edu.suffolk.litlab.efsp.server.utils.SoapExceptionMapper;
3331
import edu.suffolk.litlab.efsp.utils.InterviewToFilingInformationConverter;
3432
import jakarta.ws.rs.core.MediaType;
35-
import java.io.File;
3633
import java.security.NoSuchAlgorithmException;
3734
import java.sql.Connection;
3835
import java.sql.SQLException;
@@ -42,11 +39,7 @@
4239
import java.util.Map;
4340
import java.util.Optional;
4441
import java.util.function.Supplier;
45-
import javax.annotation.Nullable;
4642
import javax.sql.DataSource;
47-
import org.apache.cxf.Bus;
48-
import org.apache.cxf.BusFactory;
49-
import org.apache.cxf.bus.spring.SpringBusFactory;
5043
import org.apache.cxf.endpoint.Server;
5144
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
5245
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
@@ -59,43 +52,15 @@ public class EfspServer {
5952
private static Logger log = LoggerFactory.getLogger(EfspServer.class);
6053

6154
private JAXRSServerFactoryBean sf;
62-
private JAXRSServerFactoryBean acmeSf;
6355
private Server server;
64-
private Server acmeServer;
65-
66-
private static final File CERT_KEY_STORE = new File("src/main/config/tls_server_cert.jks");
67-
68-
// BusFactory.setDefaultBus needs to happen before other CXF code, so use a static block
69-
static {
70-
// Creating the Bus will immediately unlock the JKS file in `ServerConfig.xml`, so we set
71-
// CallbackHandler's CertPassword before we create the factory.
72-
Optional<String> certPassword = GetEnv("CERT_PASSWORD");
73-
if (certPassword.isPresent() && CERT_KEY_STORE.isFile()) {
74-
HttpsCallbackHandler.setCertPassword(certPassword.get());
75-
SpringBusFactory factory = new SpringBusFactory();
76-
Bus bus = factory.createBus("src/main/config/ServerConfig.xml");
77-
// bus.setProperty(HttpServerEngineSupport.ENABLE_HTTP2, true);
78-
BusFactory.setDefaultBus(bus);
79-
} else {
80-
if (certPassword.isEmpty()) {
81-
log.warn("Didn't enter a CERT_PASSWORD. Falling back to HTTP. Did you pass an .env file?");
82-
}
83-
if (!CERT_KEY_STORE.isFile()) {
84-
log.warn(
85-
CERT_KEY_STORE.getAbsolutePath()
86-
+ " doesn't exist, needed to run HTTPS. Falling back to HTTP.");
87-
}
88-
}
89-
}
9056

9157
protected EfspServer(
9258
DataSource codeDs,
9359
DataSource userDs,
9460
OrgMessageSender sender,
9561
List<EfmModuleSetup> modules,
9662
SecurityHub security,
97-
Map<String, InterviewToFilingInformationConverter> converterMap,
98-
@Nullable AcmeChallengeService challengeService)
63+
Map<String, InterviewToFilingInformationConverter> converterMap)
9964
throws SQLException, NoSuchAlgorithmException {
10065

10166
var jurisdictionMap = new HashMap<String, JurisdictionServiceHandle>();
@@ -127,15 +92,6 @@ protected EfspServer(
12792
services.put(
12893
JurisdictionSwitch.class,
12994
new SingletonResourceProvider(new JurisdictionSwitch(jurisdictionMap)));
130-
if (challengeService != null && !ServiceHelpers.BASE_ACME_URL.isBlank()) {
131-
services.put(AcmeChallengeService.class, new SingletonResourceProvider(challengeService));
132-
acmeSf = new JAXRSServerFactoryBean();
133-
acmeSf.setResourceClasses(AcmeChallengeService.class);
134-
acmeSf.setResourceProvider(
135-
AcmeChallengeService.class, new SingletonResourceProvider(challengeService));
136-
acmeSf.setAddress(ServiceHelpers.BASE_ACME_URL);
137-
acmeServer = acmeSf.create();
138-
}
13995

14096
sf = new JAXRSServerFactoryBean();
14197
sf.setResourceClasses(new ArrayList<Class<?>>(services.keySet()));
@@ -157,10 +113,6 @@ protected void stopServers() {
157113
server.stop();
158114
server.destroy();
159115
}
160-
if (acmeServer != null) {
161-
acmeServer.stop();
162-
acmeServer.destroy();
163-
}
164116
}
165117

166118
/**
@@ -286,15 +238,7 @@ public static void main(String[] args) throws Exception {
286238
log.info("Starting Server with the following Filers: {}", modules);
287239

288240
SecurityHub security = new SecurityHub(userDs, tylerEnv, jurisdictions);
289-
AcmeChallengeService challengeService = null;
290-
boolean useLetsEncrypt =
291-
GetEnv("USE_LETSENCRYPT").map(str -> Boolean.parseBoolean(str)).orElse(false);
292-
if (useLetsEncrypt) {
293-
log.info("Using lets encrypt!");
294-
challengeService = new AcmeChallengeService();
295-
}
296-
EfspServer server =
297-
new EfspServer(codeDs, userDs, sender, modules, security, converterMap, challengeService);
241+
EfspServer server = new EfspServer(codeDs, userDs, sender, modules, security, converterMap);
298242

299243
Runtime.getRuntime()
300244
.addShutdownHook(

0 commit comments

Comments
 (0)