简体   繁体   中英

How to use jq on an AWS IAM policy?

The Question - Why does jq generate lines with values, instead of generating the built-in json array? (I've tried using [.[]] with no success)

The code snippet @ jqplay.org - https://jqplay.org/s/IDhVa5KID8

The Challenge - Generate an array of allowed Action s ( Effect == Allow ).

IAM Policy (input)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "cloudformation:UpdateStack",
            "Resource": "arn:aws:cloudformation:eu-west-1:123456789012:stack/sokker-stack-dev/*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "lambda:UpdateFunctionConfiguration",
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:eu-west-1:123456789012:function:sokker-api-dev-GetApiKeyValueFunction-MYDISTRIBID",
            "Effect": "Allow"
        },
        {
            "Action": [
                "cloudfront:GetDistribution",
                "cloudfront:UpdateDistribution"
            ],
            "Resource": "arn:aws:cloudfront::*:distribution/MYDISTRIBID",
            "Effect": "Allow"
        },
        {
            "Action": [
                "apigateway:GET",
                "apigateway:HEAD",
                "apigateway:OPTIONS",
                "apigateway:PUT",
                "iam:GetRole",
                "iam:PassRole",
                "lambda:GetFunctionConfiguration"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

My Solution (not good enough):

jq '.Statement | map(select(.Effect == "Allow"))[].Action | if type == "string" then . else .[] end' iampolicy.json

My Solution's Output:

# Why is it a list of values? Why isn't it a json array?
"cloudformation:UpdateStack"
"lambda:UpdateFunctionConfiguration"
"lambda:InvokeFunction"
"cloudfront:GetDistribution"
"cloudfront:UpdateDistribution"
"apigateway:GET"
"apigateway:HEAD"
"apigateway:OPTIONS"
"apigateway:PUT"
"iam:GetRole"
"iam:PassRole"
"lambda:GetFunctionConfiguration"

Desired output:

[
  "cloudformation:UpdateStack",
  "lambda:UpdateFunctionConfiguration",
  "lambda:InvokeFunction",
  "cloudfront:GetDistribution",
  "cloudfront:UpdateDistribution",
  "apigateway:GET",
  "apigateway:HEAD",
  "apigateway:OPTIONS",
  "apigateway:PUT",
  "iam:GetRole",
  "iam:PassRole",
  "lambda:GetFunctionConfiguration"
]

The last part of your jq pipeline is:

| .[]

This results in the stream that you don't want. One solution therefore would be to enclose your entire expression in square brackets; one of several better alternatives would be:

.Statement
| [.[]
   | select(.Effect == "Allow")
   | .Action
   | if type == "string" then . else .[] end ]

Ok that was silly, surrounding my final output with [] did the trick

.Statement | [map(select(.Effect == "Allow"))[].Action | if type == "string" then . else .[] end]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM