Reputation: 324
There is a list of sensitive data which I am trying to mask in an xml file. It is able to mask these list data, but on creating new xml (Masked XML) "Pack" xml tag content from Actual xml is not written back as expected in (Masked XML), only the values are written back and all tags inside "Pack" xml tag is ommitted.
Please help on what is going wrong here, even the ipAddres at one place is not getting masked.
I am attaching my code below which is working partially and provided both xml contents.
import groovy.xml.XmlUtil
import java.util.regex.Pattern;
public class SensitiveDatamasking {
private static String masked = "####"
def attributeList = ["username", "password","ipAddress"]
private static final String IPADDRESS_PATTERN = "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
String removeSensetiveData(File file){
removeSensetiveData(file.text)
}
String removeSensetiveData(String xmlText){
def root = new XmlParser().parseText(xmlText);
nameValuePair(root)
attributeValue(root)
nodeValue(root)
XmlUtil.serialize(root)
}
private void nodeValue(def root) {
def elements = root."**".findAll{
it.text().size() > 0 && it.children().size() == 1
}
Pattern pattern = Pattern.compile(IPADDRESS_PATTERN);
elements.each {
it.value = it.text().replaceAll(pattern, masked)
}
}
private void nameValuePair(def root) {
def nodes = root."**".findAll{
it?.@name?.toString()?.toLowerCase()?.contains("username" ) ||
it?.@name?.toString()?.toLowerCase()?.contains( "password") ||
it?.@name?.toString()?.toLowerCase()?.contains( "ipAddress") }
maskValue(nodes)
}
private void attributeValue(def root) {
attributeList.each {
maskAttribute( root, it)
}
}
private def maskAttribute(def root, String attribute) {
def nodes = root."**".findAll{ it."""@$attribute"""}
maskAttributes( nodes, attribute)
}
private void maskValue(def nodes) {
nodes.each { if (it.@value?.size() > 0) {
it.@value = masked }
}
}
private void maskAttributes(def nodes, String keyName) {
nodes.each { it."""@$keyName""" = masked }
}
static main(args) {
File file = new File("C:\\shared\\test\\zenderJan2019.xml")
SensitiveDatamasking xml = new SensitiveDatamasking()
String maskedXml = xml.removeSensetiveData(file)
File output = new File("C:\\shared\\test\\zenderJan2019_masked.xml")
output.write(maskedXml)
}
}
Actual xml (Expected output should match this xml content, with only masked changes in values for username, password & ipAddress)
<?xml version="1.0" encoding="UTF-8"?>
<org_dump date="1/25/19 8:17 AM" version="1.1">
<DETAIL>
<osname>Linux</osname>
<hostname>zion.zender.com</hostname>
<release>3.10.0-693.el7.x86_64</release>
</DETAIL>
<INFO>
<version>1.10.5 beta</version>
<Pack>
<INFO>
<NUM>1.1</NUM>
<PREVIOUS_PACK_APPLIED/>
<RELEASEDATETIME>Jan 17, 2019</RELEASEDATETIME>
<APPLIEDDATETIME>Thu Jan 24 14:28:52 IST 2019</APPLIEDDATETIME>
<PRODUCT>zender</PRODUCT>
<VERSION>1.10.5 beta</VERSION>
<SYMPTOMS>1.10.5 beta jag</SYMPTOMS>
</INFO>
</Pack>
<MetaData>
<Gateways>
<Node port="14528" httpPort="14527" host="zion.zender.com" name="node01" ipAddress="127.0.1.1"/>
</Gateways>
<TeamGroup name="DomainTeams">
<Team name="username" value="andysimmons"/>
<Team name="password" value="123456"/>
<Team name="ipAddress" value="127.0.1.1"/>
</TeamGroup>
<Service name="Jag_Service" version="">
<ServiceProcess>
<Node name="node01"/>
<PreStartCommand/>
<PostStartCommand/>
<JvmTeams/>
<TeamGroup name="CUSTOM_PROPERTIES"/>
<TeamGroup name="REPOSITORY">
<Team name="LoggingDirectory" value=""/>
<Team name="LogLevel" value="INFO"/>
<Team name="ActivateDumpPersistenceConfigurationToFile" value="false"/>
<Team name="ActivateLogPersistenceSQLToFile" value="false"/>
</TeamGroup>
</ServiceProcess>
<TeamGroup name="CACHE">
<Team name="EnableCache" value="false"/>
<Team name="CacheJVMTeams" value="-Xmx128m"/>
</TeamGroup>
</Service>
</MetaData>
</INFO>
</org_dump>
Masked XML
<?xml version="1.0" encoding="UTF-8"?>
<org_dump date="1/25/19 8:17 AM" version="1.1">
<DETAIL>
<osname>Linux</osname>
<hostname>zion.zender.com</hostname>
<release>3.10.0-693.el7.x86_64</release>
</DETAIL>
<INFO>
<version>1.10.5 beta</version>
<Pack>1.1Jan 17, 2019Thu Jan 24 14:28:52 IST 2019zender1.10.5 beta1.10.5 beta jag</Pack>
<MetaData>
<Gateways>
<Node port="14528" httpPort="14527" host="zion.zender.com" name="node01" ipAddress="####"/>
</Gateways>
<TeamGroup name="DomainTeams">
<Team name="username" value="####"/>
<Team name="password" value="####"/>
<Team name="ipAddress" value="127.1.1.1"/>
</TeamGroup>
<Service name="Jag_Service" version="">
<ServiceProcess>
<Node name="node01"/>
<PreStartCommand/>
<PostStartCommand/>
<JvmTeams/>
<TeamGroup name="CUSTOM_PROPERTIES"/>
<TeamGroup name="REPOSITORY">
<Team name="LoggingDirectory" value=""/>
<Team name="LogLevel" value="INFO"/>
<Team name="ActivateDumpPersistenceConfigurationToFile" value="false"/>
<Team name="ActivateLogPersistenceSQLToFile" value="false"/>
</TeamGroup>
</ServiceProcess>
<TeamGroup name="CACHE">
<Team name="EnableCache" value="false"/>
<Team name="CacheJVMTeams" value="-Xmx128m"/>
</TeamGroup>
</Service>
</MetaData>
</INFO>
</org_dump>
Upvotes: 3
Views: 8364
Reputation: 171114
You should be able to just do:
File file = new File("C:\\shared\\test\\zenderJan2019.xml")
def xml = new XmlParser().parse(file)
xml.'**'.findAll { it.@name in ['username', 'password', 'ipAddress'] }*.@value = '####'
println XmlUtil.serialize(xml)
Hope this helps 😀
def masked = ['username', 'password', 'ipAddress']
File file = new File("C:\\shared\\test\\zenderJan2019.xml")
def xml = new XmlParser().parse(file)
xml.'**'.each { node ->
if (node.@name in masked) {
node.@value = '####'
}
masked.each { m -> if (node.@"$m") node.@"$m" = '####' }
}
println XmlUtil.serialize(xml)
If you change: println XmlUtil.serialize(xml)
to:
StringWriter writer = new StringWriter()
new XmlNodePrinter(new IndentPrinter(new PrintWriter(writer), '', false)).print(xml)
println writer.toString()
It will output the XML in a "non-pretty" (minified) way
Upvotes: 3