Skip to content

Commit d568fa4

Browse files
authored
ENH: encryption extension (#5581)
ADD: encryption extension Signed-off-by: George Chen <qchea@amazon.com>
1 parent 7d6ac6d commit d568fa4

70 files changed

Lines changed: 3760 additions & 8 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.dataprepper.model.encryption;
7+
8+
public interface EncryptionEngine {
9+
/**
10+
* Encrypts raw data into {@link EncryptionEnvelope}.
11+
*
12+
* @param data the raw data in bytes
13+
* @return returns the encryption envelope
14+
*/
15+
EncryptionEnvelope encrypt(byte[] data);
16+
17+
/**
18+
* Decrypts the encryption envelope into raw data.
19+
*
20+
* @param encryptionEnvelope the encryption envelope
21+
* @return returns the raw data in bytes
22+
*/
23+
byte[] decrypt(EncryptionEnvelope encryptionEnvelope);
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.dataprepper.model.encryption;
7+
8+
public interface EncryptionEnvelope {
9+
/**
10+
* The encrypted data.
11+
*/
12+
byte[] getEncryptedData();
13+
14+
/**
15+
* The encrypted data key.
16+
*/
17+
String getEncryptedDataKey();
18+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.dataprepper.model.encryption;
7+
8+
@FunctionalInterface
9+
public interface KeyProvider {
10+
byte[] decryptKey(byte[] encryptedKey);
11+
}

data-prepper-core/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dependencies {
2323
implementation project(':data-prepper-event')
2424
implementation project(':data-prepper-plugins:blocking-buffer')
2525
implementation project(':data-prepper-plugins:common')
26+
implementation project(':data-prepper-plugins:encryption-plugin')
2627
implementation project(':data-prepper-logstash-configuration')
2728
implementation project(':data-prepper-pipeline-parser')
2829
implementation project(':data-prepper-plugin-framework')

data-prepper-core/src/main/java/org/opensearch/dataprepper/core/pipeline/server/DataPrepperServer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.sun.net.httpserver.HttpHandler;
1111
import com.sun.net.httpserver.HttpServer;
1212
import io.micrometer.prometheus.PrometheusMeterRegistry;
13+
import org.opensearch.dataprepper.plugins.encryption.EncryptionHttpHandler;
1314
import org.slf4j.Logger;
1415
import org.slf4j.LoggerFactory;
1516
import org.springframework.beans.factory.annotation.Autowired;
@@ -32,6 +33,7 @@ public class DataPrepperServer {
3233
private final ListPipelinesHandler listPipelinesHandler;
3334
private final GetPipelinesHandler getPipelinesHandler;
3435
private final ShutdownHandler shutdownHandler;
36+
private final EncryptionHttpHandler encryptionHttpHandler;
3537
private final PrometheusMeterRegistry prometheusMeterRegistry;
3638
private final Authenticator authenticator;
3739
private final ExecutorService executorService;
@@ -43,13 +45,15 @@ public DataPrepperServer(
4345
final ListPipelinesHandler listPipelinesHandler,
4446
final ShutdownHandler shutdownHandler,
4547
final GetPipelinesHandler getPipelinesHandler,
48+
@Autowired(required = false) @Nullable final EncryptionHttpHandler encryptionHttpHandler,
4649
@Autowired(required = false) @Nullable final PrometheusMeterRegistry prometheusMeterRegistry,
4750
@Autowired(required = false) @Nullable final Authenticator authenticator
4851
) {
4952
this.serverProvider = serverProvider;
5053
this.listPipelinesHandler = listPipelinesHandler;
5154
this.shutdownHandler = shutdownHandler;
5255
this.getPipelinesHandler = getPipelinesHandler;
56+
this.encryptionHttpHandler = encryptionHttpHandler;
5357
this.prometheusMeterRegistry = prometheusMeterRegistry;
5458
this.authenticator = authenticator;
5559
executorService = Executors.newFixedThreadPool(3);
@@ -72,6 +76,10 @@ private HttpServer createServer() {
7276
createContext(server, shutdownHandler, authenticator, "/shutdown");
7377
createContext(server, getPipelinesHandler, authenticator, "/pipelines");
7478

79+
if (encryptionHttpHandler != null) {
80+
createContext(server, encryptionHttpHandler, authenticator, "/encryption/rotate");
81+
}
82+
7583
if (prometheusMeterRegistry != null) {
7684
final PrometheusMetricsHandler prometheusMetricsHandler = new PrometheusMetricsHandler(prometheusMeterRegistry);
7785
createContext(server, prometheusMetricsHandler, authenticator, "/metrics/prometheus", "/metrics/sys");

data-prepper-core/src/test/java/org/opensearch/dataprepper/core/pipeline/server/DataPrepperServerTest.java

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.mockito.ArgumentCaptor;
1717
import org.mockito.Mock;
1818
import org.mockito.junit.jupiter.MockitoExtension;
19+
import org.opensearch.dataprepper.plugins.encryption.EncryptionHttpHandler;
1920

2021
import java.net.InetSocketAddress;
2122
import java.util.concurrent.ExecutorService;
@@ -51,6 +52,9 @@ public class DataPrepperServerTest {
5152
@Mock
5253
private GetPipelinesHandler getPipelinesHandler;
5354

55+
@Mock
56+
private EncryptionHttpHandler encryptionHttpHandler;
57+
5458
@Mock
5559
private PrometheusMeterRegistry prometheusMeterRegistry;
5660

@@ -71,15 +75,15 @@ public void tearDown() {
7175

7276
@Test
7377
public void testDataPrepperServerConstructor() {
74-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, authenticator);
78+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, authenticator, null);
7579
assertThat(dataPrepperServer, is(notNullValue()));
7680
}
7781

7882
@Test
7983
public void testGivenValidServerWhenStartThenShouldCallServerStart() {
8084
mockServerStart();
8185

82-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, authenticator);
86+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, authenticator, null);
8387
dataPrepperServer.start();
8488

8589
verifyServerStart();
@@ -88,11 +92,25 @@ public void testGivenValidServerWhenStartThenShouldCallServerStart() {
8892
verify(context, times(5)).setAuthenticator(eq(authenticator));
8993
}
9094

95+
@Test
96+
public void testServerStartWithEncryptionHttpHandler() {
97+
mockServerStart();
98+
99+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, authenticator, encryptionHttpHandler);
100+
dataPrepperServer.start();
101+
102+
verifyServerStart();
103+
verify(server).createContext(eq("/metrics/prometheus"), any(PrometheusMetricsHandler.class));
104+
verify(server).createContext(eq("/metrics/sys"), any(PrometheusMetricsHandler.class));
105+
verify(server).createContext(eq("/encryption/rotate"), any(EncryptionHttpHandler.class));
106+
verify(context, times(6)).setAuthenticator(eq(authenticator));
107+
}
108+
91109
@Test
92110
public void testGivenValidServerWhenStartThenShouldCallServerStart_NullPrometheus() {
93111
mockServerStart();
94112

95-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, authenticator);
113+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, authenticator, null);
96114
dataPrepperServer.start();
97115

98116
verifyServerStart();
@@ -103,7 +121,7 @@ public void testGivenValidServerWhenStartThenShouldCallServerStart_NullPrometheu
103121
public void testGivenValidServerWhenStartThenShouldCallServerStart_NullAuthenticator() {
104122
mockServerStart();
105123

106-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, null);
124+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(prometheusMeterRegistry, null, null);
107125
dataPrepperServer.start();
108126

109127
verifyServerStart();
@@ -115,7 +133,7 @@ public void testGivenValidServerWhenStartThenShouldCallServerStart_NullAuthentic
115133
public void testGivenValidServerWhenStartThenShouldCallServerStart_NullPrometheusAndAuthenticator() {
116134
mockServerStart();
117135

118-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, null);
136+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, null, null);
119137
dataPrepperServer.start();
120138

121139
verifyServerStart();
@@ -126,7 +144,7 @@ public void testGivenValidServerWhenStartThenShouldCallServerStart_NullPrometheu
126144
public void testGivenValidServerWhenStopThenShouldCallServerStopWithNoDelay() {
127145
mockServerStart();
128146

129-
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, null);
147+
final DataPrepperServer dataPrepperServer = createObjectUnderTest(null, null, null);
130148
dataPrepperServer.start();
131149
dataPrepperServer.stop();
132150

@@ -161,7 +179,10 @@ private void verifyServerStart() {
161179
verify(socketAddress).getPort();
162180
}
163181

164-
private DataPrepperServer createObjectUnderTest(final PrometheusMeterRegistry prometheusMeterRegistry, final Authenticator authenticator) {
165-
return new DataPrepperServer(httpServerProvider, listPipelinesHandler, shutdownHandler, getPipelinesHandler, prometheusMeterRegistry, authenticator);
182+
private DataPrepperServer createObjectUnderTest(final PrometheusMeterRegistry prometheusMeterRegistry,
183+
final Authenticator authenticator,
184+
final EncryptionHttpHandler encryptionHttpHandler) {
185+
return new DataPrepperServer(
186+
httpServerProvider, listPipelinesHandler, shutdownHandler, getPipelinesHandler, encryptionHttpHandler, prometheusMeterRegistry, authenticator);
166187
}
167188
}

data-prepper-plugins/aws-plugin-api/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
dependencies {
33
implementation 'software.amazon.awssdk:auth'
44
implementation 'software.amazon.awssdk:apache-client'
5+
implementation 'software.amazon.awssdk:sts'
56
implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1'
67
implementation 'com.fasterxml.jackson.core:jackson-annotations'
78
testImplementation libs.commons.lang3
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.dataprepper.aws.api;
7+
8+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
9+
import software.amazon.awssdk.regions.Region;
10+
11+
/**
12+
* An interface available to plugins which provides the default AWS credentials and region.
13+
*/
14+
public interface AwsContext {
15+
AwsCredentialsProvider getOrDefault();
16+
17+
Region getRegionOrDefault();
18+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.dataprepper.aws.api;
7+
8+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
9+
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
10+
import software.amazon.awssdk.regions.Region;
11+
import software.amazon.awssdk.services.sts.StsClient;
12+
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider;
13+
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
14+
15+
import java.util.UUID;
16+
17+
// TODO: This class should be provided as Bean in aws-plugin once the issue is resolved:
18+
// https://github.com/opensearch-project/data-prepper/issues/2825
19+
public class AwsContextImpl implements AwsContext {
20+
private final AwsCredentialsConfig awsCredentialsConfig;
21+
22+
public AwsContextImpl(final AwsCredentialsConfig awsCredentialsConfig) {
23+
this.awsCredentialsConfig = awsCredentialsConfig;
24+
}
25+
26+
@Override
27+
public AwsCredentialsProvider getOrDefault() {
28+
if (awsCredentialsConfig == null || awsCredentialsConfig.getStsRoleArn() == null) {
29+
return getDefault();
30+
}
31+
32+
return getFromOptions(awsCredentialsConfig.toCredentialsOptions());
33+
}
34+
35+
@Override
36+
public Region getRegionOrDefault() {
37+
if (awsCredentialsConfig != null && awsCredentialsConfig.getRegion() != null) {
38+
return Region.of(awsCredentialsConfig.getRegion());
39+
}
40+
return null;
41+
}
42+
43+
private AwsCredentialsProvider getDefault() {
44+
final AwsCredentialsOptions credentialsOptions;
45+
if (awsCredentialsConfig != null) {
46+
credentialsOptions = awsCredentialsConfig.toCredentialsOptions();
47+
} else {
48+
credentialsOptions = AwsCredentialsOptions.defaultOptions();
49+
}
50+
51+
return getFromOptions(credentialsOptions);
52+
}
53+
54+
private AwsCredentialsProvider getFromOptions(AwsCredentialsOptions awsCredentialsOptions) {
55+
final AwsCredentialsProvider awsCredentialsProvider;
56+
final String awsStsRoleArn = awsCredentialsOptions.getStsRoleArn();
57+
if (awsStsRoleArn != null && !awsStsRoleArn.isEmpty()) {
58+
59+
final StsClient stsClient = StsClient.builder()
60+
.region(awsCredentialsOptions.getRegion())
61+
.build();
62+
63+
AssumeRoleRequest.Builder assumeRoleRequestBuilder = AssumeRoleRequest.builder()
64+
.roleSessionName("aws-iam-" + UUID.randomUUID())
65+
.roleArn(awsStsRoleArn);
66+
67+
awsCredentialsProvider = StsAssumeRoleCredentialsProvider.builder()
68+
.stsClient(stsClient)
69+
.refreshRequest(assumeRoleRequestBuilder.build())
70+
.build();
71+
72+
} else {
73+
// use default credential provider
74+
awsCredentialsProvider = DefaultCredentialsProvider.create();
75+
}
76+
77+
return awsCredentialsProvider;
78+
}
79+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
*
3+
* * Copyright OpenSearch Contributors
4+
* * SPDX-License-Identifier: Apache-2.0
5+
*
6+
*/
7+
8+
package org.opensearch.dataprepper.aws.api;
9+
10+
public interface AwsCredentialsConfig {
11+
String getRegion();
12+
String getStsRoleArn();
13+
14+
AwsCredentialsOptions toCredentialsOptions();
15+
}

0 commit comments

Comments
 (0)