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

Fix Blake2b hash #5089

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.opensearch.security.user.User;
import org.opensearch.test.framework.TestSecurityConfig;

import static org.opensearch.security.privileges.dlsfls.FieldMasking.Config.BLAKE2B_LEGACY_DEFAULT;
import static org.opensearch.security.util.MockIndexMetadataBuilder.indices;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
Expand Down Expand Up @@ -141,6 +142,18 @@ public void simple() throws Exception {
assertNull(expression.getRegexReplacements());

FieldMasking.FieldMaskingRule.Field field = new FieldMasking.FieldMaskingRule.Field(expression, FieldMasking.Config.DEFAULT);
assertEquals("c042e214a8b49561577445be44c188a8e6274006b36cd0c6fba5312253cf9293", field.apply("foobar"));
}

@Test
public void simple_legacyDefaultAlgorithm() throws Exception {
FieldMasking.FieldMaskingExpression expression = new FieldMasking.FieldMaskingExpression("field_*");
FieldMasking.FieldMaskingRule.Field field = new FieldMasking.FieldMaskingRule.Field(
expression,
FieldMasking.Config.fromSettings(
Settings.builder().put("plugins.security.masked_fields.algorithm.default", BLAKE2B_LEGACY_DEFAULT).build()
)
);
assertEquals("96c8d1da7eb153db858d4f0585120319e17ed1162db9e94bee19fb10b6d19727", field.apply("foobar"));
}

Expand Down Expand Up @@ -260,9 +273,9 @@ public void simple() throws Exception {
assertFalse("FieldMasking.FieldMaskingRule should return false for isAllowAll()", rule.isAllowAll());
assertTrue("Rule applies to field field_masked_1", rule.isMasked("field_masked_1"));
assertFalse("Rule does not apply to field field_other", rule.isMasked("field_other"));
assertEquals("96c8d1da7eb153db858d4f0585120319e17ed1162db9e94bee19fb10b6d19727", rule.get("field_masked_1").apply("foobar"));
assertEquals("c042e214a8b49561577445be44c188a8e6274006b36cd0c6fba5312253cf9293", rule.get("field_masked_1").apply("foobar"));
assertEquals(
new BytesRef("96c8d1da7eb153db858d4f0585120319e17ed1162db9e94bee19fb10b6d19727".getBytes(StandardCharsets.UTF_8)),
new BytesRef("c042e214a8b49561577445be44c188a8e6274006b36cd0c6fba5312253cf9293".getBytes(StandardCharsets.UTF_8)),
rule.get("field_masked_1").apply(new BytesRef("foobar".getBytes(StandardCharsets.UTF_8)))
);
assertEquals("FM:[field_masked_*]", rule.toString());
Expand All @@ -275,7 +288,7 @@ public void keyword() throws Exception {
assertTrue("Rule applies to field field_masked_1", rule.isMasked("field_masked"));
assertTrue("Rule applies to field field_masked_1.keyword", rule.isMasked("field_masked.keyword"));
assertEquals(
"96c8d1da7eb153db858d4f0585120319e17ed1162db9e94bee19fb10b6d19727",
"c042e214a8b49561577445be44c188a8e6274006b36cd0c6fba5312253cf9293",
rule.get("field_masked.keyword").apply("foobar")
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ public void maskSimpleAttribute() throws Exception {
String expectedDocument = """
{
"a": "x",
"b": "1147ddc9246d856b1ce322f1dc9eeda895b56d545c324510c2eca47a9dcc5d3f",
"b": "4b694e9cb9ce9e0983fbe4c5df2d464949610f074460adc76bda5a9d0bcc38a5",
"c": "z"
}
""";
Expand Down Expand Up @@ -351,7 +351,7 @@ public void maskObjectAttribute() throws Exception {
{
"a": "x",
"b": {
"b1": "19937da9d0b0fb38c3ce369bed130b647fa547914d675e09a62ba260a6d7811b",
"b1": "f16d01664d4270a4f39cdba8c89ac024380b5f249f0fbec1049497bc745cf30f",
"b2": "y2"
},
"c": "z"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@

import static org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.ENDPOINTS_WITH_PERMISSIONS;
import static org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.SECURITY_CONFIG_UPDATE;
import static org.opensearch.security.privileges.dlsfls.FieldMasking.Config.BLAKE2B_LEGACY_DEFAULT;
import static org.opensearch.security.setting.DeprecatedSettings.checkForDeprecatedSetting;
import static org.opensearch.security.support.ConfigConstants.OPENDISTRO_SECURITY_AUTHENTICATED_USER;
import static org.opensearch.security.support.ConfigConstants.SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX;
Expand Down Expand Up @@ -448,7 +449,7 @@ public List<Path> run() {

try {
String maskingAlgorithmDefault = settings.get(ConfigConstants.SECURITY_MASKED_FIELDS_ALGORITHM_DEFAULT);
if (StringUtils.isNotEmpty(maskingAlgorithmDefault)) {
if (StringUtils.isNotEmpty(maskingAlgorithmDefault) && !BLAKE2B_LEGACY_DEFAULT.equalsIgnoreCase(maskingAlgorithmDefault)) {
MessageDigest.getInstance(maskingAlgorithmDefault);
}
} catch (Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,14 @@ public static class Field {
private final String hashAlgorithm;
private final Salt salt;
private final byte[] saltBytes;
private final boolean useLegacyDefaultAlgorithm;

Field(FieldMaskingExpression expression, FieldMasking.Config fieldMaskingConfig) {
this.expression = expression;
this.hashAlgorithm = expression.getAlgoName() != null ? expression.getAlgoName()
: StringUtils.isNotEmpty(fieldMaskingConfig.getDefaultHashAlgorithm()) ? fieldMaskingConfig.getDefaultHashAlgorithm()
: null;
this.useLegacyDefaultAlgorithm = fieldMaskingConfig.useLegacyDefaultAlgorithm();
this.salt = fieldMaskingConfig.getSalt();
this.saltBytes = this.salt.getSalt16();
}
Expand All @@ -252,10 +254,12 @@ public WildcardMatcher getPattern() {
public byte[] apply(byte[] value) {
if (expression.getRegexReplacements() != null) {
return applyRegexReplacements(value, expression.getRegexReplacements());
} else if (this.useLegacyDefaultAlgorithm) {
return blake2bHash(value, true);
} else if (this.hashAlgorithm != null) {
return customHash(value, this.hashAlgorithm);
} else {
return blake2bHash(value);
return blake2bHash(value, false);
}
}

Expand Down Expand Up @@ -301,10 +305,13 @@ private byte[] applyRegexReplacements(byte[] value, List<FieldMaskingExpression.
return string.getBytes(StandardCharsets.UTF_8);
}

private byte[] blake2bHash(byte[] in) {
// Salt is passed incorrectly but order of parameters is retained at present to ensure full backwards compatibility
// Tracking with https://github.com/opensearch-project/security/issues/4274
final Blake2b hash = new Blake2b(null, 32, null, saltBytes);
private byte[] blake2bHash(byte[] in, boolean useLegacyDefaultAlgorithm) {
final Blake2b hash;
if (useLegacyDefaultAlgorithm) {
hash = new Blake2b(null, 32, null, saltBytes);
} else {
hash = new Blake2b(null, 32, saltBytes, null);
}
hash.update(in, 0, in.length);
final byte[] out = new byte[hash.getDigestSize()];
hash.digest(out, 0);
Expand Down Expand Up @@ -461,6 +468,8 @@ String getSource() {
}

public static class Config {
public static final String BLAKE2B_LEGACY_DEFAULT = "BLAKE2B_LEGACY_DEFAULT";

public static Config fromSettings(Settings settings) {
return new Config(settings.get(ConfigConstants.SECURITY_MASKED_FIELDS_ALGORITHM_DEFAULT), Salt.from(settings));
}
Expand All @@ -469,10 +478,12 @@ public static Config fromSettings(Settings settings) {

private final String defaultHashAlgorithm;
private final Salt salt;
private final boolean useLegacyDefaultAlgorithm;

Config(String defaultHashAlgorithm, Salt salt) {
this.defaultHashAlgorithm = defaultHashAlgorithm;
this.salt = salt;
this.useLegacyDefaultAlgorithm = BLAKE2B_LEGACY_DEFAULT.equalsIgnoreCase(defaultHashAlgorithm);
}

public String getDefaultHashAlgorithm() {
Expand All @@ -482,6 +493,10 @@ public String getDefaultHashAlgorithm() {
public Salt getSalt() {
return salt;
}

public boolean useLegacyDefaultAlgorithm() {
return useLegacyDefaultAlgorithm;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ public void testComplexMappingSearch() throws Exception {
"88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166"
)
);
Assert.assertFalse(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53"));
Assert.assertFalse(res.getBody().contains("9fe023e13d5179157b2023c21c60bc98340a12470538affd306281619d2477c3"));
Assert.assertFalse(res.getBody().contains("*.*.*.*"));
Assert.assertFalse(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38"));
Assert.assertFalse(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3"));
Assert.assertFalse(res.getBody().contains("5115e9707d1a18772af2a1274e2d3450284754a921692d6b1aef922c33cda8fa"));
Assert.assertFalse(res.getBody().contains("8915d31ba2e0ac9eea0c8af1beb058dfa3d01147c233ede320d441cc1b65fa33"));
Assert.assertFalse(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat"));
Assert.assertFalse(
res.getBody()
Expand Down Expand Up @@ -207,10 +207,10 @@ public void testComplexMappingSearch() throws Exception {
"88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166"
)
);
Assert.assertTrue(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53"));
Assert.assertTrue(res.getBody().contains("9fe023e13d5179157b2023c21c60bc98340a12470538affd306281619d2477c3"));
Assert.assertTrue(res.getBody().contains("*.*.*.*"));
Assert.assertTrue(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38"));
Assert.assertTrue(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3"));
Assert.assertTrue(res.getBody().contains("5115e9707d1a18772af2a1274e2d3450284754a921692d6b1aef922c33cda8fa"));
Assert.assertTrue(res.getBody().contains("8915d31ba2e0ac9eea0c8af1beb058dfa3d01147c233ede320d441cc1b65fa33"));
Assert.assertTrue(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat"));
Assert.assertTrue(
res.getBody()
Expand All @@ -236,9 +236,9 @@ public void testComplexMappingSearch() throws Exception {
"88783587fef740690c4fa39476fb86314d034fa3370e1a1fa186f6d9d4644a18ad85063c1e3161f8929f7ca019bb8740611eaf337709113901e7c3a6b59f4166"
)
);
Assert.assertFalse(res.getBody().contains("e90a2fdf7b1939ec06e294321fd7d23e1a70d8fc080a3f85d0f3bf08c205b53"));
Assert.assertFalse(res.getBody().contains("9fe023e13d5179157b2023c21c60bc98340a12470538affd306281619d2477c3"));
Assert.assertFalse(res.getBody().contains("*.*.*.*"));
Assert.assertFalse(res.getBody().contains("430a65d4b9c51de7192e048b2639db0de5c56f1901afccc2a01ef97f6a769a38"));
Assert.assertFalse(res.getBody().contains("8915d31ba2e0ac9eea0c8af1beb058dfa3d01147c233ede320d441cc1b65fa33"));
Assert.assertFalse(res.getBody().contains("7f48bb3636edf546a75968ca7cd0bdfe63e9ce7af04ef7cb642931fa15d2d7a3"));
Assert.assertFalse(res.getBody().contains("https://www.static.co/downloads/beats/metricbeat"));
Assert.assertFalse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ public void testDFMRestrictedUser() throws Exception {
Assert.assertFalse(response.getBody().contains("value-2-4"));

// field2 - check also some masked values
Assert.assertTrue(response.getBody().contains("514b27191e2322b0f7cd6afc3a5d657ff438fd0cc8dc229bd1a589804fdffd99"));
Assert.assertTrue(response.getBody().contains("3090f7e867f390fb96b20ba30ee518b09a927b857393ebd1262f31191a385efa"));
Assert.assertTrue(response.getBody().contains("b83363be1efc9a30269963686915db175630744f7b9b53eaf012275c10028ed8"));
Assert.assertTrue(response.getBody().contains("1036e0c7154ead29670a4d0a609727aeec7e6f39a97b72053d49255b5865e341"));
}

/**
Expand Down Expand Up @@ -271,7 +271,7 @@ public void testDFMRestrictedAndUnrestrictedOneIndex() throws Exception {
Assert.assertTrue(response.getBody().contains("value-2-4"));

// but we still have masked values for index1-2 and index1-3
Assert.assertTrue(response.getBody().contains("514b27191e2322b0f7cd6afc3a5d657ff438fd0cc8dc229bd1a589804fdffd99"));
Assert.assertTrue(response.getBody().contains("3090f7e867f390fb96b20ba30ee518b09a927b857393ebd1262f31191a385efa"));
Assert.assertTrue(response.getBody().contains("b83363be1efc9a30269963686915db175630744f7b9b53eaf012275c10028ed8"));
Assert.assertTrue(response.getBody().contains("1036e0c7154ead29670a4d0a609727aeec7e6f39a97b72053d49255b5865e341"));
}
}
Loading
Loading