I'm trying to mask sensitive values like keys, token, etc... in a command line before writing it into a log file.
For example:
MY_TOKEN='MaskThisPlease'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | gawk -v k="${MY_TOKEN}" -v m="XXXXXX" '{gsub(k,m);print}'
The result is:
my_command XXXXXX SomeOtherString
Now when MY_TOKEN contains specific characters, the masking will not work and/or will produce an error. Some of the special characters are: $ ^ * ( ) + [ ] | \ ?
The below works fine
MY_TOKEN='MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | awk -v k="${MY_TOKEN}" -v m="XXXXXX" '{gsub(k,m);print}'
I tried sed but there's the delimiter limitation, i.e. when the '+' is in MY_TOKEN
MY_TOKEN='MaskThisPlease_SomeABCs_Some123s_SomeOther+PlusSign+here'
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
echo "${MY_CMD}" | sed "s+${MY_TOKEN}+XXXXXX+g"
sed: -e expression #1, char 55: unknown option to `s'
So, my question is
Is there another way to perform a masking without hitting the above and without size limitations (MY_TOKEN maybe 700 characters)?
The below was added later in response of your comments and Answer 1:
I just join Stack Overflow and it's my first posting. I was unable to attach my test data as r.dat. Each line in r.dat is the value of my token (see answer 1 below for more details).
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz
AlphaNumericCharacters1234567890
''MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..zzzzzzzzzzzzzzzzzzzzzzzzz''
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^(zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?**zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*)zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*.zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?.*zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?*(zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\\zzzzzzzzzzzzzzzzzzzzzzzzz
MaskThisPlease_SomeABCs_Some123s_SomeOther//!!@@##%%_--==``~~{{}}::;;""<<>>,,..$^()+[]|?\zzzzzzzzzzzzzzzzzzzzzzzzz
Here's the 1st code snippet which shows some limitations in the r.awk and in bash build-in replace functions
clear
# Read one by one my test cases
I=0
cat ./r.dat | while IFS= read -r MY_TOKEN
do
I=$((I+1))
echo
echo "#########################################################"
echo "${I}) MyToken is ${MY_TOKEN}"
echo "#########################################################"
# Build my command including the value of my token
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
printf "Mask with gawk function: "
echo "${MY_CMD}" | gawk -F'\n' -v k="${MY_TOKEN}" -v m="XXXXXX" -f ./r.awk 2>/dev/null
printf "Mask with bash built-in: "
echo "${MY_CMD/${MY_TOKEN}/XXXXXX}"
done
The test case 19 show that the r.awk does better than the bash build-in replace function
The test case 20 show that both fail
The test case 21 show that both fail
Here's the 2nd code snippet which shows how to fix the issues in both r.awk and bash build-in replace functions
clear
# Read one by one my test cases
I=0
cat ./r.dat | while IFS= read -r MY_TOKEN
do
I=$((I+1))
# Escape RegEx characters
MY_TOKEN_ESCAPED=$(echo ${MY_TOKEN} | sed 's:[][\/.^$*]:\\&:g')
echo
echo "#########################################################"
echo "${I}) MyToken is ${MY_TOKEN}"
echo "${I}) Escaped is ${MY_TOKEN_ESCAPED}"
echo "#########################################################"
# Build my command including the value of my token
MY_CMD="my_command ${MY_TOKEN} SomeOtherString"
printf "Mask with gawk function: "
echo "${MY_CMD}" | gawk -F'\n' -v k="${MY_TOKEN_ESCAPED}" -v m="XXXXXX" -f ./r.awk 2>/dev/null
printf "Mask with bash built-in: "
echo "${MY_CMD/${MY_TOKEN_ESCAPED}/XXXXXX}"
done
May be there's a better & simple way to handle it and that's 100% POSIX....