forked from opensearch-project/data-prepper
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
4602 one way hash (opensearch-project#4750)
added capabilities for working with OneWay Hash Signed-off-by: mishavay-aws <140549901+mishavay-aws@users.noreply.github.com> Signed-off-by: Krishna Kondaka <krishkdk@dev-dsk-krishkdk-2c-bd29c437.us-west-2.amazon.com>
- Loading branch information
1 parent
18e6e07
commit 7353258
Showing
11 changed files
with
465 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
...ava/org/opensearch/dataprepper/plugins/processor/obfuscation/action/OneWayHashAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.processor.obfuscation.action; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.SecureRandom; | ||
import java.util.Arrays; | ||
import java.util.Base64; | ||
import java.util.List; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.opensearch.dataprepper.model.annotations.DataPrepperPlugin; | ||
import org.opensearch.dataprepper.model.annotations.DataPrepperPluginConstructor; | ||
import org.opensearch.dataprepper.model.event.Event; | ||
import org.opensearch.dataprepper.model.record.Record; | ||
import org.opensearch.dataprepper.plugins.processor.obfuscation.ObfuscationProcessor; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import org.opensearch.dataprepper.model.event.EventKey; | ||
|
||
@DataPrepperPlugin(name = "hash", pluginType = ObfuscationAction.class, pluginConfigurationType = OneWayHashActionConfig.class) | ||
public class OneWayHashAction implements ObfuscationAction { | ||
|
||
|
||
private final MessageDigest messageDigest; | ||
private final byte[] salt; | ||
private EventKey saltKey; | ||
private static final Logger LOG = LoggerFactory.getLogger(ObfuscationProcessor.class); | ||
|
||
@DataPrepperPluginConstructor | ||
public OneWayHashAction(final OneWayHashActionConfig config) { | ||
|
||
this.saltKey = config.getSaltKey(); | ||
|
||
if (config.getSalt() == null || config.getSalt().isEmpty() ) { | ||
this.salt = generateSalt(); | ||
} else { | ||
this.salt = config.getSalt().getBytes(StandardCharsets.UTF_8); | ||
} | ||
|
||
try { | ||
messageDigest = MessageDigest.getInstance(config.getFormat()); | ||
} catch (NoSuchAlgorithmException noSuchAlgorithmException){ | ||
LOG.error("The hash format provided ({}) is not a known algorithm [{}]", config.getFormat(), noSuchAlgorithmException); | ||
throw new RuntimeException(noSuchAlgorithmException); | ||
} | ||
} | ||
|
||
@Override | ||
public String obfuscate(String source, List<Pattern> patterns, Record<Event> record) { | ||
|
||
byte [] saltToApply = this.salt; | ||
|
||
// Resolve salt to compute based on a path provided in the configuration. | ||
// For records where path was not found, the salt value defined in the pipeline configuration will be used, if salt value was not configured, one will be generated. | ||
|
||
if(saltKey != null && saltKey.equals("") == false) { | ||
|
||
final Event recordEvent = record.getData(); | ||
|
||
if (recordEvent.containsKey(saltKey)) { | ||
|
||
saltToApply = computeSaltBasedOnKeyValue(recordEvent.get(saltKey, String.class)); | ||
} else { | ||
LOG.info("Unable to find a key '{}' for using as salt, using default salt pipeline configuration for the record instead", saltKey); | ||
} | ||
} | ||
|
||
if (patterns == null || patterns.size() == 0) { | ||
// no pattern to match, replace the whole string | ||
return oneWayHashString(source,saltToApply); | ||
} | ||
|
||
String replacementString = source; | ||
|
||
for (Pattern pattern : patterns) { | ||
|
||
Matcher matcher = Pattern.compile(pattern.pattern()).matcher(replacementString); | ||
StringBuffer stringBuffer = new StringBuffer(); | ||
|
||
while (matcher.find()) { | ||
|
||
String stringToHash = replacementString.substring(matcher.start(),matcher.end()); | ||
matcher.appendReplacement(stringBuffer, oneWayHashString(stringToHash,saltToApply)); | ||
} | ||
|
||
matcher.appendTail(stringBuffer); | ||
replacementString = stringBuffer.toString(); | ||
} | ||
return replacementString; | ||
|
||
|
||
} | ||
|
||
private String oneWayHashString(String source, byte[] salt) { | ||
|
||
String oneWayHashedSource = ""; | ||
|
||
try { | ||
MessageDigest messageDigestClone = (MessageDigest) messageDigest.clone(); | ||
|
||
messageDigestClone.update(salt); | ||
byte[] bytes = messageDigestClone.digest(source.getBytes(StandardCharsets.UTF_8)); | ||
|
||
oneWayHashedSource = Base64.getEncoder().encodeToString(bytes); | ||
|
||
} catch (CloneNotSupportedException cloneNotSupportedException) { | ||
LOG.error("There was an exception while processing Event [{}]", cloneNotSupportedException); | ||
throw new RuntimeException(cloneNotSupportedException); | ||
} | ||
|
||
return oneWayHashedSource; | ||
} | ||
|
||
private byte [] computeSaltBasedOnKeyValue(String saltValue) { | ||
|
||
byte [] value = saltValue.getBytes(StandardCharsets.UTF_8); | ||
byte [] result = new byte [64]; | ||
|
||
Arrays.fill(result, Byte.MIN_VALUE); | ||
|
||
System.arraycopy(value, 0, result, 0, | ||
(value.length >= result.length) ? result.length : value.length); | ||
|
||
return result; | ||
} | ||
|
||
private byte[] generateSalt() { | ||
|
||
byte [] saltBytes = new byte[64]; | ||
SecureRandom secureRandom = new SecureRandom(); | ||
secureRandom.nextBytes(saltBytes); | ||
return saltBytes; | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
...g/opensearch/dataprepper/plugins/processor/obfuscation/action/OneWayHashActionConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.processor.obfuscation.action; | ||
|
||
import org.opensearch.dataprepper.model.event.EventKeyConfiguration; | ||
import org.opensearch.dataprepper.model.event.EventKeyFactory; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.annotation.JsonPropertyDescription; | ||
|
||
import jakarta.validation.constraints.Pattern; | ||
import jakarta.validation.constraints.Size; | ||
|
||
import org.opensearch.dataprepper.model.event.EventKey; | ||
import org.opensearch.dataprepper.model.event.EventKeyConfiguration; | ||
import org.opensearch.dataprepper.model.event.EventKeyFactory; | ||
|
||
|
||
public class OneWayHashActionConfig { | ||
|
||
@JsonProperty("salt") | ||
@JsonPropertyDescription("Salt value to use when generating hash. If not specified, salt will be randomly generated by the processor.") | ||
@Size(min = 16, message = "Minimum size of salt string is 16.") | ||
@Size(max = 64, message = "Maximum size of salt string is 64") | ||
private String salt; | ||
|
||
@JsonProperty("format") | ||
@Pattern(regexp = "SHA-512", message = "Valid values: SHA-512") | ||
@JsonPropertyDescription("Format of one way hash to generate. Default to SHA-512.") | ||
private String format = "SHA-512"; | ||
|
||
@JsonProperty("salt_key") | ||
@JsonPropertyDescription("A key to compute salt based on a value provided as part of a record." + | ||
"If key or value was not found in the record(s), a salt defined in the pipeline configuration will be used instead.") | ||
@EventKeyConfiguration(EventKeyFactory.EventAction.GET) | ||
private EventKey saltKey; | ||
|
||
public OneWayHashActionConfig(){ | ||
|
||
} | ||
|
||
public String getSalt () { | ||
return salt; | ||
} | ||
|
||
public String getFormat() { | ||
return format; | ||
} | ||
|
||
public EventKey getSaltKey() { | ||
return saltKey; | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...rg/opensearch/dataprepper/plugins/processor/obfuscation/action/ObfuscationActionTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.dataprepper.plugins.processor.obfuscation.action; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.opensearch.dataprepper.event.TestEventFactory; | ||
import org.opensearch.dataprepper.model.event.EventBuilder; | ||
import org.opensearch.dataprepper.model.event.Event; | ||
import org.opensearch.dataprepper.model.record.Record; | ||
|
||
interface ObfuscationActionTest { | ||
|
||
default Record<Event> createRecord(String message) { | ||
final Map<String, Object> testData = new HashMap<>(); | ||
testData.put("message", message); | ||
|
||
return new Record<>(TestEventFactory.getTestEventFactory().eventBuilder(EventBuilder.class).withEventType("event").withData(testData).build()); | ||
} | ||
} |
Oops, something went wrong.