Skip to content

Commit d1dceb7

Browse files
committed
test: Cover weak RSA path and split resolvePort helper
Adds a 1024-bit RSA fixture and PemSslContextTest case that exercises the minimum-strength guard, lifting new-code coverage on PR 91 above the 80% Sonar gate. Splits the nested ternary in OpenApiServer.Builder into a resolvePort() helper to clear the matching SonarLint finding.
1 parent 6b0c59b commit d1dceb7

4 files changed

Lines changed: 48 additions & 2 deletions

File tree

src/main/java/com/retailsvc/http/OpenApiServer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,7 @@ public OpenApiServer build() throws IOException {
390390
Map.copyOf(securityValidators),
391391
externalAuth,
392392
List.copyOf(afterHooks));
393-
int resolvedPort =
394-
port != null ? port : (httpsCertChain != null ? DEFAULT_HTTPS_PORT : DEFAULT_PORT);
393+
int resolvedPort = resolvePort();
395394
SSLContext sslContext =
396395
httpsCertChain != null ? PemSslContext.load(httpsCertChain, httpsPrivateKey) : null;
397396
return new OpenApiServer(
@@ -404,6 +403,13 @@ public OpenApiServer build() throws IOException {
404403
sslContext);
405404
}
406405

406+
private int resolvePort() {
407+
if (port != null) {
408+
return port;
409+
}
410+
return httpsCertChain != null ? DEFAULT_HTTPS_PORT : DEFAULT_PORT;
411+
}
412+
407413
private static void validateHandlerWiring(Spec spec, Map<String, RequestHandler> handlers) {
408414
Set<String> specOps = new TreeSet<>();
409415
for (Operation op : spec.operations()) {

src/test/java/com/retailsvc/http/internal/PemSslContextTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class PemSslContextTest {
1717
private static final Path MISMATCHED_KEY = Path.of("src/test/resources/tls/mismatched-key.pem");
1818
private static final Path GARBAGE = Path.of("src/test/resources/tls/garbage.pem");
1919
private static final Path MISSING = Path.of("src/test/resources/tls/does-not-exist.pem");
20+
private static final Path WEAK_RSA_CERT = Path.of("src/test/resources/tls/weak-rsa-cert.pem");
21+
private static final Path WEAK_RSA_KEY = Path.of("src/test/resources/tls/weak-rsa-key.pem");
2022

2123
@Test
2224
void loadsRsaPemPair() throws Exception {
@@ -91,4 +93,12 @@ void acceptsEcKeyAtMinimumStrength() throws Exception {
9193
SSLContext ctx = PemSslContext.load(EC_CERT, EC_KEY);
9294
assertThat(ctx).isNotNull();
9395
}
96+
97+
@Test
98+
void rejectsWeakRsaKey() {
99+
assertThatThrownBy(() -> PemSslContext.load(WEAK_RSA_CERT, WEAK_RSA_KEY))
100+
.isInstanceOf(IllegalStateException.class)
101+
.hasMessageContaining("TLS RSA key below minimum strength")
102+
.hasMessageContaining("1024 bits");
103+
}
94104
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICGDCCAYGgAwIBAgIUROGXccQOoJe1ANi92SDG+ghoRe4wDQYJKoZIhvcNAQEL
3+
BQAwHTEbMBkGA1UEAwwSd2Vhay1yc2EtbG9jYWxob3N0MCAXDTI2MDUyMTA4NTUw
4+
MVoYDzIxMjYwNDI3MDg1NTAxWjAdMRswGQYDVQQDDBJ3ZWFrLXJzYS1sb2NhbGhv
5+
c3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK50Oy2AQ9HLGNRf8ncZ11Y1
6+
H9hewBbSqPW5vw0To//KxdzpSAprW1C37ZXBHTT1eiDqgr247GxTWBo6axCtLHq3
7+
uh5ODdqcXSdGxu2KbMu2Pa+0IYJvmgrwN8uBT+j0FtjCQxokni3l7Qhs7amNnTag
8+
ToSlGUzQE2nhAeV+IyohAgMBAAGjUzBRMB0GA1UdDgQWBBTV4Fiz8I5WXeQxzPU3
9+
pJLLVLhKaTAfBgNVHSMEGDAWgBTV4Fiz8I5WXeQxzPU3pJLLVLhKaTAPBgNVHRMB
10+
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAD4K1YYaJ00lKiQKHF/gKpoRzgzl
11+
8P5qbChHEtv46Nj4govB2QuoW0d1SHVSS15bnQ90doeEDF/MExossoC8W4b4i+7I
12+
LeyMMOB5wCFQntIslci+Ec/5z9mrWqf8EK4V6j2DIXKaEpQszApU0NnASwgmvyfP
13+
6r6aiu7Z4Izibc6P
14+
-----END CERTIFICATE-----
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK50Oy2AQ9HLGNRf
3+
8ncZ11Y1H9hewBbSqPW5vw0To//KxdzpSAprW1C37ZXBHTT1eiDqgr247GxTWBo6
4+
axCtLHq3uh5ODdqcXSdGxu2KbMu2Pa+0IYJvmgrwN8uBT+j0FtjCQxokni3l7Qhs
5+
7amNnTagToSlGUzQE2nhAeV+IyohAgMBAAECgYAakY8VrewmPlUouvgVVXUrJuoT
6+
rNJ6Z1jeG4zSNASNB1e8/jY/h/wfPfPME94b26re6nhA5rHzCXpofC8kGguk4Gwz
7+
FFSC+x21L37xFIGvSwv89DvL9cRA7RXZmhNWzsf5M730EOx5F2ffwyczsp0U0KXU
8+
0nh6Qx5BHDNSMZVHNQJBAOBT4YDibOINikJx7ciKje9MgQTcUztXhOWcN6jmn4Km
9+
AIo5yiLYgryW0gILpcnhQNMQfXDRc6Cbb7CI0KmNq78CQQDHFbaX/BK1wOVkddCN
10+
XHZxKmEHBV2JdZ+udSNaF8CnxTq3ooRvozJBpxQmbWTMaL6jZIPMSwKRM+ZTWBzV
11+
1CIfAkApXo65rAgUcBbNRiFp2FNwjBVHBjK7QNqbVYHWPiGwgFidJScn4fHKQa4c
12+
/nTmlAnWYrYfdiDyv3eLgM+qVRwVAkEAn6n6VsoC92FMl9Uk/To6g2fJiSf0bFm5
13+
RuELCSYjjGnRPZVJQX9QvvaQYoE5ZfZbbg8e5KkD1hAZmJ4CAjuvYQJBALI5HaIn
14+
ujOcOSVEK2NOIOH4JdtmoTx2O0IImYX3svje3h41Uj0+zh8bWRvejpdwU4Z7p/YL
15+
rh/zmtMxXQZadgM=
16+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)