Skip to content

Commit 4943f06

Browse files
authored
Merge pull request #6 from artekorzel/feature/aws-parameter-store-integration
Add integration with AWS Parameter Store
2 parents 8fb4cb9 + 614e4af commit 4943f06

File tree

8 files changed

+181
-16
lines changed

8 files changed

+181
-16
lines changed

README.md

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,17 @@ app:
191191
index_pattern: "'data-exchange-client-' + T(java.time.LocalDate).now().format(T(java.time.format.DateTimeFormatter).ofPattern('YYYY-MM'))"
192192
```
193193
194-
#### Consul configuration section
194+
#### Remote configuration
195195
196-
Currently this library comes with support of consul config. By default consul is disabled but by writing your own bootstrap.yml file in your project,
197-
you can make use of it. It is mainly for storing connection credentials (i.e. hostname, port, username, password) in one common place.
196+
This library comes with a support for reading remote configuration from Consul or AWS Parameter Store. By default, this feature is disabled,
197+
but by writing your own bootstrap.yml file in your project, you can make use of it. It is mainly for storing connection credentials (i.e. hostname, port,
198+
username, password) in one common place.
198199
199-
Here is one example configuration of your bootstrap.yml file. Don't forget to specify -Dspring.profiles.active in order for the correct profile to be loaded.
200-
```
200+
##### Consul connection configuration
201+
202+
Here is one example configuration of your bootstrap.yml file, which enables Consul support.
203+
Don't forget to specify `-Dspring.profiles.active` in order for the correct profile to be loaded.
204+
```yaml
201205
spring:
202206
cloud:
203207
consul:
@@ -221,13 +225,48 @@ spring:
221225
222226
```
223227

224-
In order to let the pollers know that they will take the configuration from Consul, you need to do the following changes. Following is an example of a download poller
228+
##### AWS Parameter Store connection configuration
229+
230+
This library uses Spring Cloud AWS to integrate with AWS Parameter Store.
231+
It is configured using `aws.paramstore.*` properties described in Spring Cloud AWS documentation.
232+
Its functionality is extended by allowing you to configure `AWSStaticCredentialsProvider` or `STSAssumeRoleSessionCredentialsProvider`
233+
using `aws.credentials.*` properties described below.
234+
235+
Here is one example configuration of your bootstrap.yml file, which enables AWS Parameter Store support.
236+
```yaml
237+
spring:
238+
cloud:
239+
consul:
240+
enabled: false
241+
242+
aws:
243+
credentials:
244+
use-static-provider: true
245+
access-key: ...
246+
secret-key: ...
247+
region: ...
248+
# specify below properties if you need to assume STS role
249+
sts-role-arn: ...
250+
role-session-name: data-exchange-client
251+
paramstore:
252+
enabled: true
253+
prefix: /config
254+
name: data-exchange-client
255+
256+
```
257+
258+
Using the above configuration, a parameter stored in AWS Parameter Store under the key `/config/data-exchange-client/connections/test/password`
259+
will be available in Spring as `connections.test.password`.
260+
261+
##### Pollers configuration
262+
263+
In order to let the pollers know that they will take the configuration from remote store, you need to do the following changes. Following is an example of a download poller
225264
but same works for upload poller:
226265
```
227266
ftps:
228267
-
229268
name: localhostFTP # arbitrary name, should be unique
230-
remoteConfigName: <config_name_from_consul's_yaml>
269+
remoteConfigName: <config_name_from_remote_configuration_store>
231270
download-pollers:
232271
-
233272
name: testFtpDownloadPoller
@@ -240,7 +279,7 @@ ftps:
240279
poll-interval-milliseconds: 30000 # 30s, defaults to 10s
241280
```
242281

243-
So with consul the following have been replaced.
282+
So with Consul the following have been replaced.
244283
remote-config-name --> user, password, host, port
245284
file-type --> remote-input-folder or remote-output-folder
246285

pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>com.dataexchange</groupId>
77
<artifactId>data-exchange-client</artifactId>
8-
<version>1.4.0</version>
8+
<version>1.5.0</version>
99
<packaging>jar</packaging>
1010

1111
<name>data-exchange-client</name>
@@ -63,6 +63,10 @@
6363
<groupId>org.springframework.cloud</groupId>
6464
<artifactId>spring-cloud-starter-consul-config</artifactId>
6565
</dependency>
66+
<dependency>
67+
<groupId>org.springframework.cloud</groupId>
68+
<artifactId>spring-cloud-starter-aws-parameter-store-config</artifactId>
69+
</dependency>
6670

6771
<dependency>
6872
<groupId>org.springframework.cloud</groupId>

src/main/java/com/dataexchange/client/config/ConsulConfiguration.java renamed to src/main/java/com/dataexchange/client/config/RemoteConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
@Component
1212
@RefreshScope
1313
@ConfigurationProperties
14-
public class ConsulConfiguration {
14+
public class RemoteConfiguration {
1515

1616
private Map<String, RemoteConnectionConfiguration> connections;
1717

1818
public RemoteConnectionConfiguration getConnectionConfigByName(String configName) {
1919
return connections.get(configName);
2020
}
2121

22-
public Map<String, RemoteConnectionConfiguration> getAllConnections() {
22+
public Map<String, RemoteConnectionConfiguration> getConnections() {
2323
return connections;
2424
}
2525

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.dataexchange.client.config.aws;
2+
3+
import com.amazonaws.auth.AWSCredentialsProvider;
4+
import com.amazonaws.auth.AWSStaticCredentialsProvider;
5+
import com.amazonaws.auth.BasicAWSCredentials;
6+
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
7+
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
8+
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
9+
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagement;
10+
import com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClient;
11+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
12+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
13+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
14+
import org.springframework.cloud.aws.autoconfigure.paramstore.AwsParamStoreBootstrapConfiguration;
15+
import org.springframework.context.annotation.Bean;
16+
import org.springframework.context.annotation.Configuration;
17+
18+
import static com.amazonaws.util.StringUtils.isNullOrEmpty;
19+
20+
21+
@Configuration
22+
@EnableConfigurationProperties(AWSCredentials.class)
23+
@AutoConfigureBefore(value = AwsParamStoreBootstrapConfiguration.class)
24+
@ConditionalOnProperty(
25+
prefix = "aws.credentials",
26+
name = {"use-static-provider"}
27+
)
28+
public class AWSConfiguration {
29+
30+
@Bean
31+
public AWSSimpleSystemsManagement ssmClient(AWSCredentials credentials) {
32+
return AWSSimpleSystemsManagementClient.builder()
33+
.withCredentials(buildCredentialsProvider(credentials))
34+
.withRegion(credentials.getRegion())
35+
.build();
36+
}
37+
38+
private AWSCredentialsProvider buildCredentialsProvider(AWSCredentials credentials) {
39+
if (isNullOrEmpty(credentials.getStsRoleArn())) {
40+
return buildDefaultCredentialsProvider(credentials);
41+
} else {
42+
return new STSAssumeRoleSessionCredentialsProvider.Builder(credentials.getStsRoleArn(), credentials.getRoleSessionName())
43+
.withStsClient(buildSecurityTokenService(credentials))
44+
.build();
45+
}
46+
}
47+
48+
private AWSSecurityTokenService buildSecurityTokenService(AWSCredentials credentials) {
49+
return AWSSecurityTokenServiceClientBuilder.standard()
50+
.withCredentials(buildDefaultCredentialsProvider(credentials))
51+
.withRegion(credentials.getRegion())
52+
.build();
53+
}
54+
55+
private AWSCredentialsProvider buildDefaultCredentialsProvider(AWSCredentials credentials) {
56+
return new AWSStaticCredentialsProvider(new BasicAWSCredentials(credentials.getAccessKey(), credentials.getSecretKey()));
57+
}
58+
59+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.dataexchange.client.config.aws;
2+
3+
import com.amazonaws.regions.Regions;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
6+
7+
@ConfigurationProperties("aws.credentials")
8+
public class AWSCredentials {
9+
10+
private Regions region;
11+
private String accessKey;
12+
private String secretKey;
13+
private String stsRoleArn;
14+
private String roleSessionName;
15+
16+
public Regions getRegion() {
17+
return region;
18+
}
19+
20+
public void setRegion(Regions region) {
21+
this.region = region;
22+
}
23+
24+
public String getAccessKey() {
25+
return accessKey;
26+
}
27+
28+
public void setAccessKey(String accessKey) {
29+
this.accessKey = accessKey;
30+
}
31+
32+
public String getSecretKey() {
33+
return secretKey;
34+
}
35+
36+
public void setSecretKey(String secretKey) {
37+
this.secretKey = secretKey;
38+
}
39+
40+
public String getStsRoleArn() {
41+
return stsRoleArn;
42+
}
43+
44+
public void setStsRoleArn(String stsRoleArn) {
45+
this.stsRoleArn = stsRoleArn;
46+
}
47+
48+
public String getRoleSessionName() {
49+
return roleSessionName;
50+
}
51+
52+
public void setRoleSessionName(String roleSessionName) {
53+
this.roleSessionName = roleSessionName;
54+
}
55+
}

src/main/java/com/dataexchange/client/config/model/MainConfiguration.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.dataexchange.client.config.model;
22

3-
import com.dataexchange.client.config.ConsulConfiguration;
3+
import com.dataexchange.client.config.RemoteConfiguration;
44
import org.springframework.beans.factory.annotation.Autowired;
55
import org.springframework.boot.context.properties.ConfigurationProperties;
66
import org.springframework.core.io.ByteArrayResource;
@@ -18,7 +18,7 @@
1818
public class MainConfiguration {
1919

2020
@Autowired
21-
private ConsulConfiguration consulConfiguration;
21+
private RemoteConfiguration remoteConfiguration;
2222

2323
@Valid
2424
private List<SftpPollerConfiguration> sftps = new ArrayList<>();
@@ -31,7 +31,7 @@ public void setUpFromRemote() {
3131
.filter(SftpPollerConfiguration::hasRemoteConfig)
3232
.forEach(sftp -> {
3333
RemoteConnectionConfiguration remoteConfig =
34-
consulConfiguration.getConnectionConfigByName(sftp.getRemoteConfigName());
34+
remoteConfiguration.getConnectionConfigByName(sftp.getRemoteConfigName());
3535
setConnectionConfiguration(sftp, remoteConfig);
3636
setRemoteFolders(sftp, remoteConfig);
3737
sftp.setPrivateKey(new ByteArrayResource(remoteConfig.getPrivateKey().getBytes()));
@@ -41,7 +41,7 @@ public void setUpFromRemote() {
4141
.filter(FtpPollerConfiguration::hasRemoteConfig)
4242
.forEach(ftp -> {
4343
RemoteConnectionConfiguration remoteConfig =
44-
consulConfiguration.getConnectionConfigByName(ftp.getRemoteConfigName());
44+
remoteConfiguration.getConnectionConfigByName(ftp.getRemoteConfigName());
4545
setConnectionConfiguration(ftp, remoteConfig);
4646
setRemoteFolders(ftp, remoteConfig);
4747
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
2+
com.dataexchange.client.config.aws.AWSConfiguration

src/main/resources/bootstrap.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,10 @@ spring:
33
consul:
44
enabled: false
55
config:
6-
enabled: false
6+
enabled: false
7+
8+
aws:
9+
credentials:
10+
use-static-provider: false
11+
paramstore:
12+
enabled: false

0 commit comments

Comments
 (0)