Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.1.x #9

Merged
merged 7 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -764,4 +764,76 @@ Soap Adapter Config
}
```

## Configuring SSL with PEM-encoded Certificates

To configure SSL in our integration adapters using PEM-encoded certificates, add the following properties to your
`settings.properties` file:

### Example Configuration

For embedding an SSL certificate in a keystore:

```properties
config.adapter.mirket.v1={\
...,\
"http": {\
...,\
"skipSsl": false,\
"ssl": {\
"pem": {\
"truststore": {\
"certificate": "file:/Users/johndoe/mirket-certs/*"\
},\
"keystore": {\
"certificate": "file:/Users/johndoe/mirket-certs/*",\
"privateKey": "file:/Users/johndoe/mirket-certs/private/application.key",\
"privateKeyPassword": "your_private_key_password_here"\
}\
}\
},\
...\
},\
...\
}
```

### Configuration Details

- `truststore.certificate`: This property accepts a glob pattern to match all certificate files. The certificates
matched by the pattern will be combined into the truststore.
- `keystore.certificate`: Path to the PEM-encoded certificate file.
- `keystore.privateKey`: Path to the PEM-encoded private key file.
- `keystore.privateKeyPassword`: Password used to decrypt the private key, if it is encrypted.
- `skipSsl`: Set to `false` to enable SSL.

### Using PEM Content Directly

PEM content can also be used directly for both the `certificate` and `privateKey` properties. If the property values contain `BEGIN` and `END` markers, they will be treated as PEM content rather than a resource location.

```properties
config.adapter.mirket.v1={\
...,\
"http": {\
...,\
"skipSsl": false,\
"ssl": {\
"pem": {\
"truststore": {\
"certificate": "-----BEGIN CERTIFICATE-----\nMIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL\nBQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI\n... (rest of certificate content) ...\n-----END CERTIFICATE-----"\
},\
"keystore": {\
"certificate": "-----BEGIN CERTIFICATE-----\nMIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL\nBQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI\n... (rest of certificate content) ...\n-----END CERTIFICATE-----",\
"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD... (rest of private key content) ...\n-----END PRIVATE KEY-----",\
"privateKeyPassword": "your_private_key_password_here"\
}\
}\
},\
...\
},\
...\
}
```

This configuration ensures that SSL is set up using PEM-encoded certificates and private keys, and the settings are read from a JSON value in the `settings.properties` file.


6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ subprojects {
ext {
versions = [
//main libs
integration : '1.1.0',
middleware : '1.1.0',
integration : '1.1.1',
middleware : '1.1.1',
//adapter ext
dac_bridge : '1.1.0',
dac_bridge : '1.1.1',
//ext libs
spring_boot_ws : '3.1.5',
spring_ws_core : '4.0.5',
Expand Down
2 changes: 1 addition & 1 deletion dynamic-adapter-config-bridge/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public AdapterConfig getConfigV1(String key) {

// Merge with common configuration
AdapterConfig adapterConfig = new AdapterConfig(key, adapterProperties);
AdapterConfig mergedAdapterConfig = mergeWithCommonConfigIfNotSetInAdapterConfig(adapterConfig);
AdapterConfig mergedAdapterConfig = mergeWithCommonConfigIfNotSetInAdapterConfig(
adapterConfig);

// Handle configuration reload logic
handleConfigReload(key, mergedAdapterConfig);
Expand Down Expand Up @@ -112,8 +113,9 @@ public <T> List<T> getConfigs(String key, Class<T> classToDeserialize, List<T> d

private Auth extractAuthCredentials(Map<String, Object> adapterPropertiesMap) {
Map<String, Object> authMap = (Map<String, Object>) adapterPropertiesMap.get("auth");
if (authMap == null) {
throw new AdapterConfigException("'auth' section is missing in adapter properties");
if (authMap == null || authMap.isEmpty()) {
LOG.info("'auth' section is missing in adapter properties so that return null for using common config value");
return null;
}
return getAuthCredentials(authMap);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import static org.mockito.Mockito.when;

import com.inomera.adapter.config.bridge.exception.AdapterConfigException;
import com.inomera.integration.auth.AuthType;
import com.inomera.integration.config.model.AdapterConfig;
import com.inomera.integration.config.model.AdapterProperties;
import com.inomera.integration.config.model.Auth;
import com.inomera.telco.commons.config.ConfigurationHolder;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -60,6 +62,52 @@ void testGetConfigV1_Success() {
verify(configurationHolder, times(1)).getJsonObjectProperty(eq(key), eq(Map.class));
}

@Test
void testGetConfigV1WithoutAdapterAuthConfig_Success() {
String key = "testKey";
AdapterProperties mockAdapterProperties = new AdapterProperties();
mockAdapterProperties.setUrl("https://api.mirket.com");
AdapterProperties mockCommonAdapterProperties = new AdapterProperties();
mockCommonAdapterProperties.setAuth(new Auth.NoneAuth());

Map<String, Object> mockAdapterPropertiesMap = Map.of("url", "https://api.mirket.com");

when(configurationHolder.getJsonObjectProperty(eq(key), eq(Map.class))).thenReturn(mockAdapterPropertiesMap);
when(configurationHolder.getJsonObjectProperty(eq(key), eq(AdapterProperties.class))).thenReturn(mockAdapterProperties);
when(configurationHolder.getJsonObjectProperty(eq("config.adapter.common.v1"), eq(AdapterProperties.class))).thenReturn(mockCommonAdapterProperties);

AdapterConfig result = handler.getConfigV1(key);

assertNotNull(result);
assertEquals(key, result.getKey());
assertEquals("https://api.mirket.com", result.getAdapterProperties().getUrl());
assertNotNull(result.getAdapterProperties());
verify(configurationHolder, times(1)).getJsonObjectProperty(eq(key), eq(Map.class));
}

@Test
void testGetConfigV1WithoutAdapterAuthConfigCommonAndAdapter_Success_Default() {
String key = "testKey";
AdapterProperties mockAdapterProperties = new AdapterProperties();
mockAdapterProperties.setUrl("https://api.mirket.com");
AdapterProperties mockCommonAdapterProperties = new AdapterProperties();

Map<String, Object> mockAdapterPropertiesMap = Map.of("url", "https://api.mirket.com");

when(configurationHolder.getJsonObjectProperty(eq(key), eq(Map.class))).thenReturn(mockAdapterPropertiesMap);
when(configurationHolder.getJsonObjectProperty(eq(key), eq(AdapterProperties.class))).thenReturn(mockAdapterProperties);
when(configurationHolder.getJsonObjectProperty(eq("config.adapter.common.v1"), eq(AdapterProperties.class))).thenReturn(mockCommonAdapterProperties);

AdapterConfig result = handler.getConfigV1(key);

assertNotNull(result);
assertEquals(key, result.getKey());
assertEquals("https://api.mirket.com", result.getAdapterProperties().getUrl());
assertEquals(AuthType.NONE, result.getAdapterProperties().getAuth().getType());
assertNotNull(result.getAdapterProperties());
verify(configurationHolder, times(1)).getJsonObjectProperty(eq(key), eq(Map.class));
}

@Test
void testGetConfigV1_KeyNotFound_ThrowsException() {
String key = "testKey";
Expand Down Expand Up @@ -116,17 +164,4 @@ void testGetConfigs_Success() {
verify(configurationHolder, times(1)).getJsonListProperty(eq(key), eq(AdapterProperties.class));
}

@Test
void testGetConfigV1_AuthExtraction_ThrowsException() {
String key = "testKey";
Map<String, Object> mockAdapterPropertiesMap = Map.of();

when(configurationHolder.getJsonObjectProperty(eq(key), eq(Map.class))).thenReturn(mockAdapterPropertiesMap);

AdapterConfigException exception = assertThrows(AdapterConfigException.class, () -> handler.getConfigV1(key));
assertEquals("'auth' section is missing in adapter properties", exception.getCause().getMessage());

verify(configurationHolder, times(1)).getJsonObjectProperty(eq(key), eq(Map.class));
}

}
11 changes: 11 additions & 0 deletions example/ms-example/src/main/resources/certs/smallstep.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBojCCAUmgAwIBAgIQMoaotBxdaZjJTXSWvU/gxzAKBggqhkjOPQQDAjAwMRIw
EAYDVQQKEwlTbWFsbHN0ZXAxGjAYBgNVBAMTEVNtYWxsc3RlcCBSb290IENBMB4X
DTI1MDEyMzA4MDIzMloXDTM1MDEyMTA4MDIzMlowMDESMBAGA1UEChMJU21hbGxz
dGVwMRowGAYDVQQDExFTbWFsbHN0ZXAgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABLhdxZL9pjSVyzn78VeSbdLWzQ1hH4VLMcQ561PrVIwVftQw6Z+F
8Sr9oHXNQYXFeP29/4JPN8y321sevJHq75ejRTBDMA4GA1UdDwEB/wQEAwIBBjAS
BgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBSlf+os8AlKA4crK00fqfsPWdIK
yTAKBggqhkjOPQQDAgNHADBEAiAQfhrkGqtBDpr4D5F63m0S6oERJ23qSl6LwpiI
8LE6SwIgXD96CgCYhotT8I1s88RnyXlNGlzwntFzaiiRKWrLXHY=
-----END CERTIFICATE-----
28 changes: 27 additions & 1 deletion example/ms-example/src/main/resources/settings.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
config.adapter.common.v1={"logging":{"strategy":"REQ_RES","sensitiveFields":[],"nonLoggingFields":[]},"headers":{},"http":{"requestTimeout":30000,"connectTimeout":10000,"idleConnectionsTimeout":180000,"maxConnections":10,"maxConnPerRoute":10,"poolConcurrencyPolicy":"LAX","timeToLive":60000,"skipSsl":true,"redirectsEnable":true},"auth":{"type":"NONE"}}
config.adapter.mirket.v1={"runtime": true,"auth":{"type":"NONE"},"headers":{"X-GW-TOKEN":""},"http":{"requestTimeout":30000,"connectTimeout":10000,"idleConnectionsTimeout":60000,"maxConnections":50,"maxConnPerRoute":50,"poolConcurrencyPolicy":"LAX","timeToLive":60000,"skipSsl":true,"redirectsEnable":true},"logging":{"strategy":"REQ_RES","sensitiveFields":["Authorization"],"nonLoggingFields":["file","content"]},"url":"https://api.mirket.inomera.com/"}
config.adapter.mirket.v1={\
"runtime": true,\
"auth": { "type": "NONE" },\
"headers": { "X-GW-TOKEN": "" },\
"http": {\
"requestTimeout": 30000,\
"connectTimeout": 10000,\
"idleConnectionsTimeout": 60000,\
"maxConnections": 50,\
"maxConnPerRoute": 50,\
"poolConcurrencyPolicy": "LAX",\
"timeToLive": 60000,\
"skipSsl": true,\
"ssl": {\
"pem": {\
"truststore": { "certificate": "classpath:certs/smallstep.pem" }\
}\
},\
"redirectsEnable": true\
},\
"logging": {\
"strategy": "REQ_RES",\
"sensitiveFields": ["Authorization"],\
"nonLoggingFields": ["file","content"]\
},\
"url": "https://api.mirket.inomera.com"\
}
config.adapter.country.v1={"runtime": true,"logging":{"strategy":"ALL","sensitiveFields":[],"nonLoggingFields":[]},"headers":{},"http":{"requestTimeout":30000,"connectTimeout":10000,"idleConnectionsTimeout":180000,"maxConnections":10,"maxConnPerRoute":10,"poolConcurrencyPolicy":"LAX","timeToLive":60000,"skipSsl":true,"redirectsEnable":true},"auth":{"type":"NONE"},"url": "http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso"}
2 changes: 1 addition & 1 deletion micro-integration/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ public class AdapterProperties implements Serializable {
private String url;
private Map<String, String> headers;
private HttpClientProperties http;
private Auth auth;
private Boolean runtime;
private Auth auth = new Auth.NoneAuth();
private Boolean runtime = false;

public AdapterProperties() {
}
Expand Down Expand Up @@ -91,20 +91,20 @@ public void patch(AdapterProperties commonConfigAdapterProperties) {
if (commonConfigAdapterProperties == null) {
return;
}
if (this.logging == null && commonConfigAdapterProperties.getLogging() == null) {
if (this.logging == null) {
this.logging = new AdapterLogging();
this.logging.patch(commonConfigAdapterProperties.getLogging());
}
this.logging.patch(commonConfigAdapterProperties.getLogging());

if (this.http == null && commonConfigAdapterProperties.getHttp() == null) {
if (this.http == null) {
this.http = new HttpClientProperties();
this.http.patch(commonConfigAdapterProperties.getHttp());
}
this.http.patch(commonConfigAdapterProperties.getHttp());

if (this.auth == null && commonConfigAdapterProperties.getAuth() == null) {
if (this.auth == null) {
this.auth = new Auth.NoneAuth();
this.auth.patch(commonConfigAdapterProperties.getAuth());
}
this.auth.patch(commonConfigAdapterProperties.getAuth());

if (this.getHeaders() == null) {
this.setHeaders(commonConfigAdapterProperties.getHeaders());
Expand All @@ -113,6 +113,7 @@ public void patch(AdapterProperties commonConfigAdapterProperties) {
this.getHeaders().putIfAbsent(key, value)
);
}

this.runtime = this.runtime != null ? this.runtime : commonConfigAdapterProperties.isRuntime();
}

Expand Down
2 changes: 1 addition & 1 deletion micro-middleware/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1