Я пытаюсь проверить все файлы с определенным расширением в текущей папке, чтобы увидеть, имеют ли те строки, которые содержат пары key=value
, где ключ username
, password
или key
, значение в форме ENC(...)
.
Если какое-либо username
, password
или key
не связано со значением ENC(...)
, мне нужно обнаружить это и выдать ошибку.
В настоящее время я написал код, который ищет ENC(...)
, но это все, что он делает — он не ищет username
, password
или key
.
#!/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
Следующее при запуске создает каталог, в котором скрипт должен выдавать вывод, подобный приведенному ниже:
#!/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
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.
... и статус выхода должен быть ошибкой.
К вашему сведению, echo $line " encrypted"
цитирует именно то, что неправильный. echo "$line" encrypted
было бы лучше, или echo "$line encrypted"
было бы еще лучше. printf '%s encrypted\n' "$line"
будет даже лучше, чем оба, по причинам, описанным в Почему printf лучше эха?.
... прямо сейчас, если ваша строка содержит ENC( * )
, ваша echo
напечатает список файлов в вашем текущем каталоге вместо *
. Рассмотрите возможность запуска вашего кода через shellcheck.net, чтобы обнаружить этот класс проблем.
Что касается вопроса, то он говорит, что вы пытаетесь сделать, он показывает ваш код, но не показывает, как этот код дает сбой. Убедитесь, что вы на самом деле задаю вопрос. «Почему этот код делает X вместо Y?» это пример вопроса, который должен быть добавлен редактировать в сам вопрос, а не добавлен в качестве комментария.
Кроме того, из-за exit 1
вы выходите, когда находите строку Любые без ENC(
в ней. Если вы хотите проверить только первую строку, зачем использовать цикл while read
, созданный для чтения нескольких строк?
Имейте в виду, что вы можете запустить read -r line <"$FILE"
без каких-либо while
, если все, что вы хотите сделать, это прочитать самую первую строку.
(Кроме того, sh или bash? Если вы действительно нацелены на bash, вам не нужно case
, потому что вы можете использовать [[ $line = *"$find"* ]]
, и вы должны удалить тег sh; тогда как, если вы нацеливаетесь на sh, вы должны удалить тег баш-тег).
Вы показываете нам результат, который у вас есть (хотя было бы лучше в виде текста, а не снимка экрана), но, пожалуйста, также явно показывайте точный образец вывода, который вы хотеть.
@CharlesDuffy это результат, который мне нужен ... мне нужно найти строки, которые начинаются с примера слова шаблона, если есть строка, начинающаяся с «пароля», если она имеет значение «ENC («» на данный момент она показывает только все строки со значением "ENC("
"например, если есть строка, начинающаяся с пароля, если она имеет значение ENC(" -- тогда какая? Это предложение описывает условие, но не описывает желаемый ответ, связанный с этим условием.
Одна вещь, которая добавляет путаницы, заключается в том, что вы показываете нам пример выход, но не показываете пример ввода, который соответствует этому выводу.
... если входной файл содержит ровно password=ENC(cEjemHosjc/hjA8sad)
, то разве выходной файл уже не такой, каким вы хотите его видеть?
Если вы хотите сопоставить именно password=ENC(*)
, измените *${find}*)
на password=ENC(*)
(я не вижу веских причин использовать здесь переменную find
)
(кстати, меня нет на вечер; любое будущее участие будет около 8 часов).
@CharlesDuffy спасибо за ваше время. входной файл будет состоять из всех файлов *.properties внутри папки scripts, например. если «шаблон» не зашифрован, это означает, что значение не будет начинаться с ENC (даст выход 1
Ах! Это, наконец, хорошее объяснение того, чего вы пытаетесь достичь; Спасибо тебе за это.
Кстати, в будущем вы должны искать дубликаты для как можно большего количества частей проблемы и сужать вопрос, чтобы задавать только конкретные проблемы, для которых у нас нет дубликатов. Например, у нас уже есть дубликат для Перебрать все файлы с определенным расширением для циклической части.
Более важно то, что вывод примера полезен только для людей когда он связан с примером ввода. Нам не нужно угадывать, каков ваш ожидаемый формат ввода - я собираюсь немного отредактировать вопрос, чтобы продемонстрировать, как выглядит вопрос с минимальный воспроизводимый пример, включая добавление моих собственных предположений в пример ввода; пожалуйста, подтвердите их.
Готово. Имеет ли это смысл с точки зрения того, что потребуется, чтобы написать лучший вопрос в следующий раз?
@CharlesDuffy ваше редактирование было точным. Спасибо за ваше время. Я проверил дубликаты, но не нашел нужных мне частей. Я буду иметь это в виду на будущее.
Переход от выражений в стиле glob (используемых с case
) к регулярным выражениям с синтаксисом ERE облегчит вашу задачу.
Учитывая описание проблемы, которую вы пытаетесь решить из комментариев, реализация этого в собственном bash (в отличие от использования таких инструментов, как grep
) может выглядеть так:
#!/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 ))
См. реплику, выполняющую этот код (измененный только для простоты тестирования) по адресу https://replit.com/@CharlesDuffy2/NavyThirdVerification#example.bash.
В противном случае быстрый и грязный подход с grep
может выглядеть так:
#!/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
... обратите внимание, что этот записывает эти незашифрованные секреты на ваш терминал, что может быть нежелательным поведением.
для одного файла проверит, существует ли значение, но не на основе шаблона