Как извлечь значение из файла JSON, содержащего закодированный объект JSON

У меня была эта проблема, и, прежде чем переходить к чему-либо еще, вы можете перезагрузить компьютер.

5
10.10.2020, 06:10
2 ответа

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

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

aws... |
jq -r '.Policy'

Чтобы получить значение ключа Effectиз бита, содержащего этот ключ aws:SecureTransport, нам нужно снова проанализировать документ:

aws... |
jq -r '.Policy' |
jq -r '.Statement[] | select(.Condition.Bool."aws:SecureTransport").Effect'

Последний вызов jqпроходит по всем элементам массива Statementв поисках того, у которого есть ключ с именем .Condition.Bool."aws:SecureTransport". Затем он получает значение ключа Effect, связанного с этим элементом Statement.

Выполнение этого для ваших данных выводит значение Deny.

Если вы хотите значение этого ключа .Condition.Bool."aws:SecureTransport"(falseв вашем документе ), используйте .Condition.Bool."aws:SecureTransport"вместо .Effectвыше.

В качестве альтернативы используйте инструкцию fromjsonв jqвместо второго вызова jq:

aws... |
jq -r '.Policy | fromjson |.Statement[] | select(.Condition.Bool."aws:SecureTransport").Effect'

Здесь fromjsonдекодирует закодированный документ JSON и передает его на более поздние этапы обработки.


Просто для справки: внутренний закодированный документ JSON выглядит следующим образом(aws... | jq -r '.Policy | fromjson'):

{
  "Version": "2012-10-17",
  "Id": "S3SecureTransportPolicy",
  "Statement": [
    {
      "Sid": "ForceSSLOnlyAccess",
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::amn/*",
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    },
    {
      "Sid": "AWSCloudTrailAclCheck20150319",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::amn"
    },
    {
      "Sid": "AWSCloudTrailWrite20150319",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::amn/AWSLogs/405042254276/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}
10
18.03.2021, 22:59

Во-первых, не делайте этого! Используйте jq, как описано в ответе Кусалананды . Это гораздо более надежное решение, чем возиться с регулярными выражениями. Тем не менее, вот один из способов сделать это сgrep:

aws... | grep -oP 'aws:SecureTransport.":."\K.+?(?=\\")'

То будет искать aws:SecureTransport, то любой символ(.; это просто проще, чем написать \\, чтобы избежать косой черты ), а затем ". \Kотбрасывает все, что совпало до этой точки (, поэтому часть, совпадающая с aws:SecureTransport.":."). Затем найдите самую короткую строку (.+?), за которой следует \"((?=\\")).

Выполнение этого в файле, содержащем вывод вашего примера, дает:

$ grep -oP 'aws:SecureTransport.":."\K.+?(?=\\")' file
false
3
18.03.2021, 22:59

Теги

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