9

I've a string like this: docker login -u username -p password docker-registry-url.

I execute the command in a Groovy script with execute. For debugging purposes, I print the command before execution, but since it contains sensitive data, I obfuscate the username and password.

def printableCmd = cmd.toString()

def m = printableCmd =~ /(?:.+) -u (.+) -p (.+) (?:.+)/

if (m.matches() && m[0].size() >= 3) {
  printableCmd = m[0][-1..-2].inject(m[0][0]) { acc, val -> acc.replaceAll(val, "***") }
}

The above works as expected and prints docker login -u *** -p *** docker-registry-url, but I'm wondering if there is a more idiomatic way to do this. Note that I don't want to delete the captured groups, just replace them with asterisks, thus making it very clear that the command is not wrong, but obfuscated for security purposes.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219

2 Answers2

13
def cmd='docker login -u username -p password docker-registry-url'
println cmd.replaceAll(/(\s-[up]\s+)(\S+)/,'$1***')

Output:

docker login -u *** -p *** docker-registry-url
daggett
  • 26,404
  • 3
  • 40
  • 56
1

I found the following solution myself using positive look-behind:

​def cmd = "docker login -u username -p password docker-registry-url"
println cmd.replaceAll(/(?<=-[up]\s)(\S+)/,"***")
Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • 1
    If there are 2 or more spaces between `-u` and 1+ non-whitespace chars, your lookbehind approach will fail. Capturing group approach is the correct one. You might use `/(?<=-[up]\s{1,100})(\S+)/`, but it is rather a hacky feature in a Java regex. – Wiktor Stribiżew Aug 03 '17 at 07:10
  • 1
    @WiktorStribiżew perhaps you are referring to the fact that look-behind in java has to be of known length, so \s+ wouldn't work. I used \s{1,10} instead. The reason I prefer this over daggett's answer is because, IMO, it expresses the requirement clearer. – Abhijit Sarkar Aug 03 '17 at 16:39