Как расширить значение переменной, чтобы построить - PullRequest
0 голосов
/ 07 марта 2019

Извините, если это где-то включено, потратил 30-60 минут на что-то подобное. Я уверен, что я что-то пропустил! Всего JQ NUB!

В основном я пытаюсь выполнить динамическую операцию pick. Мой мыслительный процесс должен был сделать что-то вроде этого:

pickJSON() {
  getSomeJSON | jq -r --arg PICK "$1" '{ $PICK }'
}

pickJSON "foo, bar"

но это производит

{ "PICK": "foo, bar" }

Есть ли способ по существу попросить его расширить стиль оболочки?


Желаемый результат:

pickJSON() {
  getSomeJSON | jq -r --arg PICK "$1" '{ $PICK }'
  # perhaps something like...
  # getSomeJSON | jq -r --arg PICK "$1" '{ ...$PICK }'
}

pickJSON "foo, bar"
{ "foo": "foovalue", "bar": "barvalue" }

Обратите внимание, что я новичок в jq, и я просто упростил то, что я делаю - если синтаксис нарушен, вот почему: - В моей фактической реализации есть несколько каналов, и это работает, если я не пытаюсь выберите из него значения.

1 Ответ

0 голосов
/ 07 марта 2019

После довольно длительного экспериментального этапа, пытаясь сделать эту работу, я наконец-то нашел то, что кажется возможным и надежным решением без чрезвычайно тревожных недостатков, которые могут возникнуть при использовании eval.

Чтобы лучше выделить общее окончательное решение, я предлагаю немного больше обработки, с которой я сейчас работаю:

Цель

  1. Получите секрет из AWS Secrets Manager

  2. Синтаксически проанализируйте возвращенный JSON, который выглядит следующим образом:

{
  "ARN": "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3",
  "Name": "MyTestDatabaseSecret",
  "VersionId": "EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE",
  "SecretString": "{\n  \"username\":\"david\",\n  \"password\":\"BnQw&XDWgaEeT9XGTT29\"\n}\n",
  "VersionStages": [
    "AWSPREVIOUS"
  ],
  "CreatedDate": 1523477145.713
}

Выполнить некоторые изменения в полученной строке JSON и выбрать только статически запрашиваемые ключи из секрета

Установить и экспортировать эти значения в качестве переменных среды

Script

# Capture a AWS Secret from secretsmanager, parse the JSON and expand the given
# variables within it to pick them from the secret and return given portion of 
# the secret requested.
# @note similar to _.pick(obj, ["foo", "bar"])
getKeysFromSecret() {
  aws secretsmanager get-secret-value --secret-id "$1" \
    | jq -r '.SecretString | fromjson' \
    | jq -r "{ $2 }"
}

# Uses `getKeysFromSecret` to capture the requested keys from the secret
# then transforms the JSON into a string that we can read and loop through
# to set each resulting value as an exported environment variable.
#
## Transformation Flow:
#   { "foo": "bar", "baz": "qux" } 
# --> 
#   foo=bar
#   baz=qux 
# --> 
#   export foo=bar
#   export baz=qux
exportVariablesInSecret() {
  while IFS== read -r key value; do
    if [ -n "$value" ]; then 
      export "${key}"="${value}";
    fi
  done < <(getKeysFromSecret "$1" "$2" | jq -r 'to_entries | .[] | .key + "=" + .value')
}


Пример JSON

{
  ...othervalues
  "SecretString": "{\"foo\": \"bar\", \"baz\": \"qux\"}"
}

Пример использования

exportVariablesInSecret MY_SECRET "foo, bar"
echo $foo
# bar

Некоторые заметки / контекст

  1. Это предназначено для установки заданного набора значений в качестве переменных, чтобы мы не просто устанавливали весь произвольный объект JSON в качестве переменных, которые могут вызвать проблемы / затенение, если кто-то добавит значение типа «путь» к секрету

  2. Важнейшей задачей было абсолютно никогда не использовать eval для предотвращения возможных ситуаций инъекции.Слишком легко вводить вещи иначе.

  3. Рад видеть, есть ли у кого-нибудь более хороший способ сделать это.Я видел много людей, которые рекомендовали использовать declare, но это устанавливает переменную в область видимости локальной функции, поэтому она по сути бесполезна.


Благодаря @cas https://unix.stackexchange.com/a/413917/308550 за то, что я на правильном пути!

...