Skip to content

Commit 16f176b

Browse files
authored
Remove nested secret (#8859)
1 parent 38ae962 commit 16f176b

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

airbyte-config/persistence/src/main/java/io/airbyte/config/persistence/split_secrets/JsonSecretsProcessor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,12 @@ public JsonNode maskSecrets(final JsonNode obj, final JsonNode schema) {
5858
if (copy.has(key)) {
5959
((ObjectNode) copy).put(key, SECRETS_MASK);
6060
}
61+
} else if (canBeProcessed(fieldSchema) && copy.has(key)) {
62+
((ObjectNode) copy).set(key, maskSecrets(copy.get(key), fieldSchema));
6163
}
6264

6365
final var combinationKey = findJsonCombinationNode(fieldSchema);
66+
6467
if (combinationKey.isPresent() && copy.has(key)) {
6568
var combinationCopy = copy.get(key);
6669
final var arrayNode = (ArrayNode) fieldSchema.get(combinationKey.get());
@@ -111,8 +114,9 @@ public JsonNode copySecrets(final JsonNode src, final JsonNode dst, final JsonNo
111114
// We only copy the original secret if the destination object isn't attempting to overwrite it
112115
// i.e: if the value of the secret isn't set to the mask
113116
if (isSecret(fieldSchema) && src.has(key)) {
114-
if (dst.has(key) && dst.get(key).asText().equals(SECRETS_MASK))
117+
if (dst.has(key) && dst.get(key).asText().equals(SECRETS_MASK)) {
115118
dstCopy.set(key, src.get(key));
119+
}
116120
}
117121

118122
final var combinationKey = findJsonCombinationNode(fieldSchema);

airbyte-config/persistence/src/test/java/io/airbyte/config/persistence/split_secrets/JsonSecretsProcessorTest.java

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
package io.airbyte.config.persistence.split_secrets;
66

7-
import static org.junit.jupiter.api.Assertions.*;
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
88

99
import com.fasterxml.jackson.databind.JsonNode;
1010
import com.google.common.collect.ImmutableMap;
@@ -153,8 +153,98 @@ public class JsonSecretsProcessorTest {
153153
+ " }\n"
154154
+ " }");
155155

156+
private final static String test = """
157+
{
158+
"provider": {
159+
"bucket": "bucket",
160+
"endpoint": "",
161+
"path_prefix": "",
162+
"aws_access_key_id": "nothingtosee",
163+
"aws_secret_access_key": "same"
164+
}
165+
}
166+
""";
167+
168+
private final static String testSpecs =
169+
"""
170+
{
171+
"type": "object",
172+
"title": "S3 Source Spec",
173+
"required": [
174+
"dataset",
175+
"path_pattern",
176+
"provider"
177+
],
178+
"properties": {
179+
"provider": {
180+
"type": "object",
181+
"title": "S3: Amazon Web Services",
182+
"required": [
183+
"bucket"
184+
],
185+
"properties": {
186+
"bucket": {
187+
"type": "string",
188+
"title": "Bucket",
189+
"description": "Name of the S3 bucket where the file(s) exist."
190+
},
191+
"use_ssl": {
192+
"type": "boolean",
193+
"title": "Use Ssl",
194+
"description": "Is remote server using secure SSL/TLS connection"
195+
},
196+
"endpoint": {
197+
"type": "string",
198+
"title": "Endpoint",
199+
"default": "",
200+
"description": "Endpoint to an S3 compatible service. Leave empty to use AWS."
201+
},
202+
"path_prefix": {
203+
"type": "string",
204+
"title": "Path Prefix",
205+
"default": "",
206+
"description": "By providing a path-like prefix (e.g. myFolder/thisTable/) under which all the relevant files sit, we can optimise finding these in S3. This is optional but recommended if your bucket contains many folders/files."
207+
},
208+
"verify_ssl_cert": {
209+
"type": "boolean",
210+
"title": "Verify Ssl Cert",
211+
"description": "Allow self signed certificates"
212+
},
213+
"aws_access_key_id": {
214+
"type": "string",
215+
"title": "Aws Access Key Id",
216+
"description": "In order to access private Buckets stored on AWS S3, this connector requires credentials with the proper permissions. If accessing publicly available data, this field is not necessary.",
217+
"airbyte_secret": true
218+
},
219+
"aws_secret_access_key": {
220+
"type": "string",
221+
"title": "Aws Secret Access Key",
222+
"description": "In order to access private Buckets stored on AWS S3, this connector requires credentials with the proper permissions. If accessing publicly available data, this field is not necessary.",
223+
"airbyte_secret": true
224+
}
225+
}
226+
}
227+
}
228+
}
229+
""";
230+
156231
JsonSecretsProcessor processor = new JsonSecretsProcessor();
157232

233+
@Test
234+
public void testNestedSecrets() {
235+
final JsonNode obj = Jsons.deserialize(test);
236+
final JsonNode specObj = Jsons.deserialize(testSpecs);
237+
final JsonNode sanitized = processor.maskSecrets(obj, specObj);
238+
239+
final JsonNode expected = Jsons.jsonNode(ImmutableMap.builder()
240+
.put("bucket", "bucket")
241+
.put("endpoint", "")
242+
.put("path_prefix", "")
243+
.put("aws_access_key_id", JsonSecretsProcessor.SECRETS_MASK)
244+
.put("aws_secret_access_key", JsonSecretsProcessor.SECRETS_MASK).build());
245+
assertEquals(expected, sanitized.get("provider"));
246+
}
247+
158248
@Test
159249
public void testMaskSecrets() {
160250
final JsonNode obj = Jsons.jsonNode(ImmutableMap.builder()

0 commit comments

Comments
 (0)