Как исключить все ключи с определенным значением внутри JSON с помощью jq?

Здесь есть ряд понятий, которые распространены в мире безопасности.

Во-первых, мы всегда хотим, чтобы пользователи работали с «наименее необходимыми привилегиями». Идея, особенно в корпоративной среде (, я вернусь к этому чуть позже ), заключается в том, что мы хотим, чтобы люди имели разрешения, необходимые им для использования компьютера, но не более того. «Бизнес как обычно» (BAU )не требует изменения файлов в /etc; это исключительный случай.

Это ведет к следующей части; «повышение привилегий». Как только определено что-то за пределами BAU, мы хотим, чтобы пользователь знал, что он делает что-то более привилегированное. Поэтому используйте команду sudoи по поводу -введите свой пароль, чтобы подтвердить, что вы знаете, что делаете. Этот повторный -ввод пароля важен, поскольку он означает, что пользователь сознательно одобряет это действие. Это не обязательно должен быть пароль; есть версии, которые могут потребовать двухфакторную аутентификацию, которая будет регистрировать нажатие клавиши и записывать сеанс для последующего воспроизведения...

Итак, теперь мы подошли к «предприятию» и рассмотрели уроки Windows XP Home Edition. При этом пользователь, которого вы создали при установке (или первой -загрузке для OEM ), автоматически имел права администратора. Ты всегда работал как админ. Это означало, что любая ваша ошибка может привести к удалению важных файлов. Или любая из ошибок (, например, в электронной почте, или рендеринге изображений, или... ), которые позволяли злоумышленнику выполнять действия автоматически, имели права администратора. Это одна из причин, почему в старых версиях Windows свирепствовали вирусы и вредоносное ПО.

Таким образом, разделение «BAU» и «привилегированных» действий распространяется за пределы предприятия и на дом, а также на единую -пользовательскую среду. Стоит отметить, что, начиная с Vista, даже в Windows есть концепция «вы пытаетесь сделать что-то привилегированное; повторно -введите свой пароль».

Резюме:sudo— это просто способ переключения контекстов безопасности;от деятельности, которую вы могли бы разумно выполнять каждый день («прочитать электронную почту», «создать документ», «просматривать веб-страницы» )и прочее, что считается привилегированным («создать нового пользователя», «изменить конфигурация системы», «удалить файлы, принадлежащие другому пользователю»… ).

Для большинства домашних пользователей достаточно просто «повторно -введите свой пароль». Для предприятия все может стать намного сложнее; см.https://www.sweharris.org/post/2018-08-26-minimal-sudo/для примера некоторых проблем.

ИЗМЕНИТЬ ДЛЯ ДОБАВЛЕНИЯ:

Я также должен отметить, что в Unix также есть понятие «пользователь-администратор»; это «корневая» учетная запись. В корпоративной среде нам не нравятся люди, использующие это, потому что мы не знаем, использовали ли Том, Дик или Гарри учетную запись root для внесения изменений. sudo— это способ, позволяющий людям повышать свои привилегии проверяемым наименее привилегированным способом. Том может запустить sudo catи прочитать любой файл, но не может перезагрузить машину; Дик и Гарри могут sudo rebootперезагрузить машину, но не могут читать защищенные файлы.

Таким образом sudoпозволяет назначать минимальные привилегии, необходимые для выполнения роли . Что является ключевым требованием безопасности.

4
18.06.2021, 20:04
2 ответа
del(..|select(. == "null"))

При этом используется рекурсивный -оператор спуска..иselectфункция для поиска всех местоположений в любом месте объекта со значениями, равными "null", и присваивается им del. selectоценивает логическое выражение, чтобы решить, следует ли включать определенное значение или нет, в то время как ..передает ему каждое отдельное значение в дереве, а delпринимает любое выражение, которое создает местоположения, что и делает это.(демо)

Вы можете использовать функцию path, чтобы проверить, что она находит:

path(..|select(. == "null"))

и отладьте то, что, по его мнению, вы пытаетесь удалить в первую очередь. Выход представляет собой массив ключей, которым нужно рекурсивно следовать для достижения значения, поэтому последний элемент массива — это ключ, который фактически будет удален.

Вы также можете использовать назначение обновления -с |= emptyв jq 1.6 и выше (в более ранних версиях происходит сбой ). Вам может показаться, а может и нет, что эта:(..|select(. == "null")) |= empty(демонстрация)удаляет те же ключи.


Если ваши значения верны nulls, а не строки "null", вы можете использовать встроенную функцию nullsвместо всегоselect:del(..|nulls).

Если ваши значения являются истинными нулями и вы используете jq 1.5(текущую версию во многих дистрибутивах ), вам нужно будет использовать recurse(.[]?; true)вместо ... Это связано с тем, что нулевые значения специально исключены из ..(, поскольку определяется как recurse, определяется как recurse(.[]?), который определяется какrecurse(.[]?;. != null)). Это поведение изменилось на (более полезное )описанное выше в 1.6, хотя документация не изменилась, что похоже на ошибку документации .

10
28.07.2021, 11:23

Предполагая, что вы знаете, что хотите проверить значения на 2-м уровне:

jq 'del(.[][] | select(. == "null"))' file

Это удаляет каждую пару значений ключа -на 2-м уровне сверху, где значением является литеральная строка null.

Учитывая документ в вопросе, это дает ожидаемый результат.

Используя версию jqболее новую, чем 1.5, вы также можете просто обновить данные до битов, которые не имеют значения null:

jq '.[][] |= select(. != "null")' file
3
28.07.2021, 11:23

Теги

Похожие вопросы