Skip to content

Commit a74b20d

Browse files
authored
NIAD-3208: CustomTrustStore refactoring to exclude weird dependencies (#1054)
* changing from autowired field to constructor initizalization * checkstyle * suppress false positive alarms sent by spotbugs * refactoring to relax dependency injection rules * increasing test coverage * remove test which is inconsistent between localhost and GitHub Actions * checkstyle * addressing PR comments * throws an exception if s3Client can't be initialized * removal of an unnecessary bean tagging * checkstyle * making log entry more descriptive
1 parent e45d766 commit a74b20d

File tree

5 files changed

+74
-32
lines changed

5 files changed

+74
-32
lines changed

service/src/main/java/uk/nhs/adaptors/gp2gp/common/configuration/AppInitializer.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,39 @@
77

88
import lombok.RequiredArgsConstructor;
99
import lombok.extern.slf4j.Slf4j;
10+
import software.amazon.awssdk.services.s3.S3Client;
1011
import uk.nhs.adaptors.gp2gp.common.storage.StorageConnectorConfiguration;
1112

13+
import javax.naming.ConfigurationException;
14+
1215
@Component(value = "appInitializer")
1316
@Slf4j
1417
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
1518
public class AppInitializer implements InitializingBean {
19+
20+
private static final String S3_PREFIX = "s3";
1621
private final StorageConnectorConfiguration storageConnectorConfiguration;
17-
private final CustomTrustStore customTrustStore;
1822

1923
@Override
20-
public void afterPropertiesSet() {
24+
public void afterPropertiesSet() throws ConfigurationException {
2125
LOGGER.info("Running app initializer");
2226
if (StringUtils.isNotBlank(storageConnectorConfiguration.getTrustStoreUrl())) {
2327
LOGGER.info("Adding custom TrustStore to default one");
28+
final CustomTrustStore customTrustStore = new CustomTrustStore(getS3Client());
2429
customTrustStore.addToDefault(storageConnectorConfiguration.getTrustStoreUrl(),
2530
storageConnectorConfiguration.getTrustStorePassword());
2631
} else {
2732
LOGGER.warn("Trust store URL is not set. Running service without the trust store.");
2833
}
2934
}
35+
36+
public S3Client getS3Client() throws ConfigurationException {
37+
if (StringUtils.isNotBlank(storageConnectorConfiguration.getTrustStoreUrl())
38+
&& storageConnectorConfiguration.getTrustStoreUrl().startsWith(S3_PREFIX)) {
39+
return S3Client.builder().build();
40+
}
41+
42+
throw new ConfigurationException("S3Client cannot be instantiated: "
43+
+ "Trust store URL is either not set or does not start with the 's3://' prefix.");
44+
}
3045
}

service/src/main/java/uk/nhs/adaptors/gp2gp/common/configuration/CustomTrustStore.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,26 @@
99
import javax.net.ssl.TrustManager;
1010
import javax.net.ssl.TrustManagerFactory;
1111
import javax.net.ssl.X509TrustManager;
12-
13-
import org.springframework.beans.factory.annotation.Autowired;
14-
import org.springframework.stereotype.Component;
1512
import software.amazon.awssdk.core.ResponseInputStream;
1613
import software.amazon.awssdk.services.s3.S3Uri;
1714
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
1815
import software.amazon.awssdk.services.s3.S3Client;
1916
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
2017

2118
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
22-
import lombok.NoArgsConstructor;
2319
import lombok.RequiredArgsConstructor;
2420
import lombok.SneakyThrows;
2521
import lombok.extern.slf4j.Slf4j;
2622

27-
@Component
2823
@Slf4j
29-
@NoArgsConstructor
24+
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "S3Client is immutable and thread-safe.")
3025
public class CustomTrustStore {
31-
@Autowired(required = false)
32-
private S3Client s3Client;
26+
27+
private final S3Client s3Client;
28+
29+
public CustomTrustStore(S3Client s3Client) {
30+
this.s3Client = s3Client;
31+
}
3332

3433
@SneakyThrows
3534
public void addToDefault(String trustStorePath, String trustStorePassword) {
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
package uk.nhs.adaptors.gp2gp.common.storage;
22

3-
import org.apache.commons.lang3.StringUtils;
43
import org.springframework.boot.context.properties.ConfigurationProperties;
5-
import org.springframework.context.annotation.Bean;
64
import org.springframework.context.annotation.Configuration;
7-
8-
import software.amazon.awssdk.services.s3.S3Client;
9-
105
import lombok.Getter;
116
import lombok.Setter;
127

@@ -16,20 +11,10 @@
1611
@ConfigurationProperties(prefix = "gp2gp.storage")
1712
public class StorageConnectorConfiguration {
1813

19-
private static final String S3_PREFIX = "s3";
20-
2114
private String type;
2215
private String containerName;
2316
private String azureConnectionString;
2417
private String trustStoreUrl;
2518
private String trustStorePassword;
2619

27-
@Bean
28-
public S3Client getS3Client() {
29-
if (StringUtils.isNotBlank(trustStoreUrl) && trustStoreUrl.startsWith(S3_PREFIX)) {
30-
return S3Client.builder().build();
31-
}
32-
33-
return null;
34-
}
3520
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package uk.nhs.adaptors.gp2gp.common.configuration;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.Test;
5+
import uk.nhs.adaptors.gp2gp.common.storage.StorageConnectorConfiguration;
6+
import javax.naming.ConfigurationException;
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
import static org.junit.jupiter.api.Assertions.assertThrows;
9+
10+
class AppInitializerTest {
11+
12+
public static final String EXPECTED_ERROR_MESSAGE = "S3Client cannot be instantiated: "
13+
+ "Trust store URL is either not set or does not start with the 's3://' prefix.";
14+
private AppInitializer appInitializer;
15+
private StorageConnectorConfiguration storageConnectorConfiguration;
16+
17+
@BeforeEach
18+
void setUp() {
19+
storageConnectorConfiguration = new StorageConnectorConfiguration();
20+
}
21+
22+
@Test
23+
void getNullWhenTrustStoreUrlDoesNotExists() {
24+
25+
storageConnectorConfiguration.setTrustStoreUrl(null);
26+
appInitializer = new AppInitializer(storageConnectorConfiguration);
27+
28+
Exception exception = assertThrows(ConfigurationException.class, () -> appInitializer.getS3Client());
29+
30+
assertEquals(EXPECTED_ERROR_MESSAGE, exception.getMessage());
31+
}
32+
33+
@Test
34+
void getNullWhenTrustStoreUrlDoesNotStartWithS3Prefix() {
35+
36+
storageConnectorConfiguration.setTrustStoreUrl("http://localhost");
37+
appInitializer = new AppInitializer(storageConnectorConfiguration);
38+
39+
Exception exception = assertThrows(ConfigurationException.class, () -> appInitializer.getS3Client());
40+
41+
assertEquals(EXPECTED_ERROR_MESSAGE, exception.getMessage());
42+
}
43+
}

service/src/test/java/uk/nhs/adaptors/gp2gp/common/configuration/CustomTrustStoreTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
1313
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
1414
import java.io.File;
15-
import java.lang.reflect.Field;
1615
import java.net.URI;
1716
import static org.junit.jupiter.api.Assertions.assertNotNull;
1817

@@ -24,8 +23,7 @@ class CustomTrustStoreTest {
2423
private static final String BUCKET_NAME = "test-bucket";
2524
private static final String TRUSTSTORE_PATH = "test.jks";
2625
private static final String TRUSTSTORE_PASSWORD = "password";
27-
28-
private final CustomTrustStore customTrustStore = new CustomTrustStore();
26+
private static CustomTrustStore customTrustStore;
2927

3028
@BeforeAll
3129
static void setUp() {
@@ -48,18 +46,20 @@ static void setUp() {
4846
software.amazon.awssdk.core.sync.RequestBody.fromFile(trustStoreFile));
4947
}
5048

49+
@BeforeAll
50+
static void setup() {
51+
customTrustStore = new CustomTrustStore(s3Client);
52+
}
53+
5154
@AfterAll
5255
static void tearDown() {
5356
s3Mock.shutdown();
57+
customTrustStore = null;
5458
}
5559

5660
@Test
5761
void trustManagerLoadsSuccessfullyTest() throws NoSuchFieldException, IllegalAccessException {
5862

59-
Field s3ClientField = CustomTrustStore.class.getDeclaredField("s3Client");
60-
s3ClientField.setAccessible(true);
61-
s3ClientField.set(customTrustStore, s3Client);
62-
6363
String s3Uri = "s3://" + BUCKET_NAME + "/" + TRUSTSTORE_PATH;
6464

6565
var trustManager = customTrustStore.getCustomDbTrustManager(s3Client.utilities().parseUri(URI.create(s3Uri)), TRUSTSTORE_PASSWORD);

0 commit comments

Comments
 (0)