Заменить JSON объекты в неизвестных местах внутри дерева JSON - PullRequest
1 голос
/ 25 января 2020

В файле JSON мне нужно заменить зашифрованные значения их значениями открытого текста в качестве процесса инициализации с использованием инструмента командной строки jq. Затем приложение повторно зашифрует значения своими собственными ключами, перезаписав значения открытого текста. Зашифрованные значения представляются в виде объектов «$ crypto», содержащих информацию о методе шифрования и используемых ключах, в следующем виде:

{
    "$crypto" : {
        "type" : "x-simple-encryption",
        "value" : {
            "cipher" : "AES/CBC/PKCS5Padding",
            "stableId" : "someId",
            "salt" : "4J5ckE6+JaS8TLqAN4073g==",
            "data" : "vBeHAPJXLl+X/8Enp9vxMA==",
            "keySize" : 16,
            "purpose" : "someDescription",
            "iv" : "N2xCe5RiJibHv9hLY+OduA==",
            "mac" : "VoOo1BKptwfqIJeSOb/qGA=="
        }
    }
}

Эти объекты «$ crypto» могут находиться в любом месте JSON структура. Пример входного документа выглядит следующим образом:

{
    "unknownKey1" : {
        "unknownKey2" : {
            "name" : "JWT_SESSION",
            "properties" : {
                "maxTokenLifeMinutes" : 120,
                "tokenIdleTimeMinutes" : 30
            }
        },
        "unknownKey3" : [
            {
                "unknownKey4" : "STATIC_USER",
                "unknownKey5" : {
                    "unknownKey6" : "internal/user",
                    "unknownKey7" : "anonymous",
                    "unknownKey8" : {
                        "$crypto" : {
                            "type" : "x-simple-encryption",
                            "value" : {
                                "cipher" : "AES/CBC/PKCS5Padding",
                                "stableId" : "someId",
                                "salt" : "4J5ckE6+JaS8TLqAN4073g==",
                                "data" : "vBeHAPJXLl+X/8Enp9vxMA==",
                                "keySize" : 16,
                                "purpose" : "someDescription",
                                "iv" : "N2xCe5RiJibHv9hLY+OduA==",
                                "mac" : "VoOo1BKptwfqIJeSOb/qGA=="
                            }
                        }
                    }
                },
                "enabled" : true
            }
        ]
    }
}

Итак, значение «unknownKey8» было зашифровано. Мне нужно, чтобы этот документ выглядел следующим образом:

{
    "unknownKey1" : {
        "unknownKey2" : {
            "name" : "JWT_SESSION",
            "properties" : {
                "maxTokenLifeMinutes" : 120,
                "tokenIdleTimeMinutes" : 30
            }
        },
        "unknownKey3" : [
            {
                "unknownKey4" : "STATIC_USER",
                "unknownKey5" : {
                    "unknownKey6" : "internal/user",
                    "unknownKey7" : "anonymous",
                    "unknownKey8" : "clearTextValue"
                },
                "enabled" : true
            }
        ]
    }
}

Мне удалось найти криптообъекты во входном файле с помощью следующей команды:

cat input.json | jq 'paths | select(.[-1] == "$crypto")'
[
  "unknownKey1",
  "unknownKey3",
  0,
  "unknownKey5",
  "unknownKey8",
  "$crypto"
]

Но я не смог добиться значительного прогресса в выполнении замены.

Ответы [ 2 ]

0 голосов
/ 26 января 2020

В качестве дополнения к принятому ответу и при использовании jq v1.5 используйте это как decrypt.jq

# input is assumed to be an object
def decrypt($value):
  with_entries(if .value|type == "object"
    then with_entries(if .value | (type == "object" and has("$crypto"))
      then .value = $value else . end)
    else . end) ;

# walk was added after the release of jq@1.5
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;

walk(if type == "object" then decrypt($cleartext) else . end)
0 голосов
/ 26 января 2020

Следующая выполняет замену, описанную в тексте. Предполагается вызов по линии

jq --arg cleartext "clearTextValue" -f decrypt.jq sample.json

. Если ваш jq не имеет walk/1, то либо обновите его до jq 1.6, либо включите его def перед вызовом (условия поиска Google: jq def walk builtin.jq).

# input is assumed to be an object
def decrypt($value):
  with_entries(if .value|type == "object"
    then with_entries(if .value | (type == "object" and has("$crypto"))
      then .value = $value else . end)
    else . end) ;

walk(if type == "object" then decrypt($cleartext) else . end)
...