1
0
mirror of synced 2026-01-08 21:05:13 -05:00

🐛 Correctly populate secrets inside nested non-combination objects (#10926)

This commit is contained in:
Edward Gao
2022-03-09 17:01:05 -08:00
committed by GitHub
parent d9ccc626f2
commit e4be0df9a1
2 changed files with 121 additions and 10 deletions

View File

@@ -163,19 +163,25 @@ public class JsonSecretsProcessor {
final ObjectNode properties = (ObjectNode) schema.get(PROPERTIES_FIELD);
for (final String key : Jsons.keys(properties)) {
// If the source object doesn't have this key then we have nothing to copy, so we should skip to the
// next key.
if (!src.has(key)) {
continue;
}
final JsonNode fieldSchema = properties.get(key);
// We only copy the original secret if the destination object isn't attempting to overwrite it
// i.e: if the value of the secret isn't set to the mask
if (isSecret(fieldSchema) && src.has(key)) {
if (dst.has(key) && dst.get(key).asText().equals(SECRETS_MASK)) {
dstCopy.set(key, src.get(key));
}
}
if (isSecret(fieldSchema) && dst.has(key) && dst.get(key).asText().equals(SECRETS_MASK)) {
dstCopy.set(key, src.get(key));
} else if (dstCopy.has(key)) {
// If the destination has this key, then we should consider copying it
final var combinationKey = findJsonCombinationNode(fieldSchema);
if (combinationKey.isPresent() && dstCopy.has(key)) {
var combinationCopy = dstCopy.get(key);
if (src.has(key)) {
// Check if this schema is a combination node; if it is, find a matching sub-schema and copy based
// on that sub-schema
final var combinationKey = findJsonCombinationNode(fieldSchema);
if (combinationKey.isPresent()) {
var combinationCopy = dstCopy.get(key);
final var arrayNode = (ArrayNode) fieldSchema.get(combinationKey.get());
for (int i = 0; i < arrayNode.size(); i++) {
final JsonNode childSchema = arrayNode.get(i);
@@ -189,8 +195,12 @@ public class JsonSecretsProcessor {
combinationCopy = copySecrets(src.get(key), combinationCopy, childSchema);
}
}
dstCopy.set(key, combinationCopy);
} else {
// Otherwise, this is just a plain old json object; recurse into it.
final JsonNode copiedField = copySecrets(src.get(key), dstCopy.get(key), fieldSchema);
dstCopy.set(key, copiedField);
}
dstCopy.set(key, combinationCopy);
}
}

View File

@@ -6,6 +6,7 @@ package io.airbyte.config.persistence.split_secrets;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
@@ -324,4 +325,104 @@ public class JsonSecretsProcessorTest {
assertEquals(expected, actual);
}
@Test
public void copiesSecrets_inNestedNonCombinationNode() throws JsonProcessingException {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode source = objectMapper.readTree(
"""
{
"top_level": {
"a_secret": "hunter2"
}
}
""");
final JsonNode dest = objectMapper.readTree(
"""
{
"top_level": {
"a_secret": "**********"
}
}
""");
final JsonNode schema = objectMapper.readTree(
"""
{
"type": "object",
"properties": {
"top_level": {
"type": "object",
"properties": {
"a_secret": {
"type": "string",
"airbyte_secret": true
}
}
}
}
}
""");
final JsonNode copied = processor.copySecrets(source, dest, schema);
final JsonNode expected = objectMapper.readTree(
"""
{
"top_level": {
"a_secret": "hunter2"
}
}
""");
assertEquals(expected, copied);
}
@Test
public void doesNotCopySecrets_inNestedNonCombinationNodeWhenDestinationMissing() throws JsonProcessingException {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode source = objectMapper.readTree(
"""
{
"top_level": {
"a_secret": "hunter2"
}
}
""");
final JsonNode dest = objectMapper.readTree(
"""
{
"top_level": {
}
}
""");
final JsonNode schema = objectMapper.readTree(
"""
{
"type": "object",
"properties": {
"top_level": {
"type": "object",
"properties": {
"a_secret": {
"type": "string",
"airbyte_secret": true
}
}
}
}
}
""");
final JsonNode copied = processor.copySecrets(source, dest, schema);
final JsonNode expected = objectMapper.readTree(
"""
{
"top_level": {
}
}
""");
assertEquals(expected, copied);
}
}