Home > Enterprise >  Check if lines matching one pattern also match another
Check if lines matching one pattern also match another

Time:03-23

I'm trying to check all files with specific extension on the current folder to see if those lines that contain key=value pairs where the key is username, password or key have the value in the form ENC(...).

If any username, password or key is not paired with an ENC(...) value, I need to detect this and fail with an error.

I currently have written code that searches for ENC(...), but that's all it does -- it isn't also looking for username, password or key.


Current Code

#!/bin/bash
pattern='username password key'
find='ENC('   
FILE=test.properties  #need to search for *.properties on that folder 

if test -f "$FILE"; then
    echo "$FILE exists."
#need to check on the line that has a word in pattern if has the value of $find
# for example on the *.properties on line starting with username if it has the value of $find
    while read -r line
    do
        case $line in 
            *${find}*) 
                echo $line " encrypted" 
                ;;
        esac
    done < $FILE
else 
    echo "$FILE does not exist."    
fi

Test Case

The following, when run, creates a directory where the script should emit output like that given below:

#!/bin/sh
testdir="$(mktemp -d "testdir.XXXXXX")" || exit
cd "$testdir" || exit

cat >a-good.properties <<EOF
# comments do not have any effect, neither do other keys
otherkey=also_ignored
# but other keys _can_ have encrypted values, it just doesn't matter
yet_another_key_but_encrypted=ENC(fffggghhh)

username=ENC(aaabbbccc)
password=ENC(bbbcccddd)
key=ENC(dddeeefff)
EOF

# a log with no key, value or password doesn't matter
cat >b-irrelevant.properties <<EOF
other_key=other_value
EOF

cat >c-bad.properties <<EOF
# this log has unencrypted data, we should fail when it exists
username=someone
password=ThisIsASecretDontTellAnyone
key=ThisIsAnotherSecret
EOF

echo "Test-suite files created in directory $testdir" >&2

Desired Output

a-good.properties exists.
username=ENC(aaabbbccc) is encrypted
password=ENC(bbbcccddd) is encrypted
key=ENC(dddeeefff) is encrypted
b-irrelevant.properties exists.
c-bad.properties exists.
ERROR: username should be encrypted but is not.
ERROR: password should be encrypted but is not.
ERROR: key should be encrypted but is not.

...and the exit status should be an error.

CodePudding user response:

Switching from glob-style expressions (as used with case) to ERE-syntax regular expressions will make your task easier.

Given the description of the problem you're trying to solve from the comments, implementing this in native bash (as opposed to using tools like grep) might look like:

#!/usr/bin/env bash
case $BASH_VERSION in '') echo "ERROR: must be run with bash" >&2; exit 1;; esac

faults_found=0
encryption_required_re='^[[:space:]]*(username|password|key)=(.*)$'
encryption_present_re='ENC[(][^)] [)]'

for file in *.properties; do
    if [[ -f $file ]]; then
        echo "$file exists" >&2
    else
        continue # no properties files found so the glob didn't expand
    fi
    while IFS= read -r line; do
        # ignore lines that do not match encryption_required_re
        [[ $line =~ $encryption_required_re ]] || continue
        key=${BASH_REMATCH[1]}; value=${BASH_REMATCH[2]}
        # ignore lines where value matches encryption_present_re
        [[ $value =~ $encryption_present_re ]] && {
          printf '%s\n' "$key=$value encrypted" >&2
          continue
        }
        # flag so the script fails on exit, and print an alert to stderr
        ((   faults_found ))
        printf '%s\n' "ERROR: $file: $key should be encrypted but is not" >&2
    done <"$file"
done

# exit with status 1 if faults_found is nonzero
exit $(( faults_found ? 1 : 0 ))

See a repl running this code (modified only for ease-of-testing) at https://replit.com/@CharlesDuffy2/NavyThirdVerification#example.bash


Otherwise, a quick-and-dirty approach with grep might look like:

#!/bin/sh
if grep -Ee '^(username|password|key)=' *.properties \
   | grep -Ev '=ENC[(].*[)]'; then
  echo "ERROR: Found unencrypted secrets" >&2
  exit 1
else
  echo "No unencrypted secrets found" >&2
  exit 0
fi

...note that this one writes those unencrypted secrets to your terminal, which may be undesired behavior.

  •  Tags:  
  • bash
  • Related