Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(extra771): jq fail when policy action is an array #1031

Merged
merged 6 commits into from
Mar 2, 2022

Conversation

lazize
Copy link
Contributor

@lazize lazize commented Feb 4, 2022

Context

jq filter was failing when policy Action was an array.

Description

Fix jq select condition to handle Action as string or as array.
Add error handling.
When fail, print policies as just one line.

Fix issue #1026

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Fix jq select condition to handle Action as string or as array.
Add error handling.
When fail, print policies as just one line.
@lazize lazize requested review from a team, toniblyx and jfagoagas February 4, 2022 20:34
@lazize
Copy link
Contributor Author

lazize commented Feb 4, 2022

It will also fix partial issues from #1019

It will not expose policy in multiple lines anymore.

But it still needs to fix comma issue inside policy.

@lazize
Copy link
Contributor Author

lazize commented Feb 4, 2022

$ echo '
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "rule0",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::xxxx",
                "arn:aws:s3:::xxxx/*"
            ],
            "Condition": {
                "StringEquals": {
                "aws:PrincipalOrgID": "o-abc123"
                }
            }
        },
        {
            "Sid": "rule1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::xxxx",
                "arn:aws:s3:::xxxx/*"
            ],
            "Condition": {
                "StringEquals": {
                "aws:PrincipalOrgID": "o-abc123"
                }
            }
        },
        {
            "Sid": "rule2",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::xxxx",
                "arn:aws:s3:::xxxx/*"
            ]
        },
        {
            "Sid": "rule3",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::xxxx",
                "arn:aws:s3:::xxxx/*"
            ]
        }
    ]
}' | jq --compact-output '.Statement[]|select(
.Effect=="Allow" and
(
    ( (.Principal|type == "object") and (.Principal.AWS == "*") ) or
    ( (.Principal|type == "string") and (.Principal == "*") )
) and
(
    ( (.Action|type == "string") and (.Action|startswith("s3:Put")) ) or
    ( (.Action|type == "string") and (.Action|startswith("s3:*")) ) or
    ( (.Action|type == "array") and (.Action[]|startswith("s3:Put")) ) or
    ( (.Action|type == "array") and (.Action[]|startswith("s3:*")) )
) and
.Condition == null)' | tr '\n' ' '
{"Sid":"rule2","Effect":"Allow","Principal":"*","Action":"s3:PutObject","Resource":["arn:aws:s3:::xxxx","arn:aws:s3:::xxxx/*"]} {"Sid":"rule3","Effect":"Allow","Principal":"*","Action":["s3:GetObject","s3:PutObject","s3:ListBucket"],"Resource":["arn:aws:s3:::xxxx","arn:aws:s3:::xxxx/*"]}

@jfagoagas jfagoagas added the status/waiting-for-revision Waiting for maintainer's revision label Feb 8, 2022
@jfagoagas jfagoagas added severity/high Bug capable of collapsing large parts of the execution. severity/medium Results in some unexpected or undesired behavior. and removed severity/high Bug capable of collapsing large parts of the execution. labels Feb 15, 2022
toniblyx
toniblyx previously approved these changes Feb 17, 2022
@toniblyx toniblyx requested review from toniblyx and removed request for jfagoagas March 2, 2022 12:21
@toniblyx
Copy link
Member

toniblyx commented Mar 2, 2022

@lazize when I test it with the suggested policy I get this error:
jq: error (at <stdin>:1): startswith() requires string inputs.
Also, can you clarify the comment about the comma?

@lazize
Copy link
Contributor Author

lazize commented Mar 2, 2022

@toniblyx Did you test the echo | jq | tr command above? Did it fail? I tested it right now and it works fine for me.
If you give me more details I can try to reproduce and fix any issue. But unfortunately I can't test it on my own bucket, I can't make it public (read or write).

This is the output it returns me, one long string with violating policy.
But note the policy contains comma, because it is a json.
{"Sid":"rule2","Effect":"Allow","Principal":"*","Action":"s3:PutObject","Resource":["arn:aws:s3:::xxxx","arn:aws:s3:::xxxx/*"]} {"Sid":"rule3","Effect":"Allow","Principal":"*","Action":["s3:GetObject","s3:PutObject","s3:ListBucket"],"Resource":["arn:aws:s3:::xxxx","arn:aws:s3:::xxxx/*"]}

When we run prowler and ask it to generate CSV output, this json string with comma will break CSV result file.

@toniblyx
Copy link
Member

toniblyx commented Mar 2, 2022

yeah, the command works fine for me, the check itself doesn't. This is part of the debug output

+ for bucket in $LIST_OF_BUCKETS
++ /usr/local/bin/aws s3api --profile dev get-bucket-policy --region us-west-2 --bucket issue1031 --output json --query Policy
+ BUCKET_POLICY_STATEMENTS='"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"rule0\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule1\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule2\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:PutObject\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]},{\"Sid\":\"rule3\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]}]}"'
+ [[ "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"rule0\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule1\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule2\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:PutObject\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]},{\"Sid\":\"rule3\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]}]}" == *GetBucketPolicy* ]]
++ jq --arg arn arn:aws:s3:::issue1031 'fromjson | .Statement[]|select(.Effect=="Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and (.Action|startswith("s3:Put") or startswith("s3:*")) and .Condition == null)'
++ echo '"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"rule0\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule1\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"],\"Condition\":{\"StringEquals\":{\"aws:PrincipalOrgID\":\"o-abc123\"}}},{\"Sid\":\"rule2\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:PutObject\",\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]},{\"Sid\":\"rule3\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":[\"s3:GetObject\",\"s3:PutObject\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::issue1031\",\"arn:aws:s3:::issue1031/*\"]}]}"'
jq: error (at <stdin>:1): startswith() requires string inputs
+ BUCKET_POLICY_BAD_STATEMENTS=
+ [[ '' != '' ]]
+ textPass 'Bucket issue1031 has S3 bucket policy which does not allow public write access' us-east-1 issue1031
+ CHECK_RESULT=PASS
+ CHECK_RESULT_EXTENDED='Bucket issue1031 has S3 bucket policy which does not allow public write access'
+ CHECK_RESOURCE_ID=issue1031

See the jq error there.

@lazize
Copy link
Contributor Author

lazize commented Mar 2, 2022

Strange, the jq command you are running is the original one, not the one I changed. See it below.

This is from your output above:

++ jq --arg arn arn:aws:s3:::issue1031 'fromjson | .Statement[]|select(
    .Effect=="Allow" and 
    (
        ((.Principal|type == "object") and .Principal.AWS == "*") or 
        ((.Principal|type == "string") and .Principal == "*")
    ) and
    (
        .Action|startswith("s3:Put") or startswith("s3:*")
    ) and
    .Condition == null
)'

This is the command I pushed on this PR:

jq --compact-output --arg arn "arn:${AWS_PARTITION}:s3:::$bucket" 'fromjson | .Statement[]|select(
    .Effect=="Allow" and
    (
        ( (.Principal|type == "object") and (.Principal.AWS == "*") ) or
        ( (.Principal|type == "string") and (.Principal == "*") )
    ) and
    (
        ( (.Action|type == "string") and (.Action|startswith("s3:Put")) ) or
        ( (.Action|type == "string") and (.Action|startswith("s3:*")) ) or
        ( (.Action|type == "array") and (.Action[]|startswith("s3:Put")) ) or
        ( (.Action|type == "array") and (.Action[]|startswith("s3:*")) )
    ) and
    .Condition == null
  )'

Note the difference between several OR conditions.

@toniblyx
Copy link
Member

toniblyx commented Mar 2, 2022

OK, I get it now. I don't see the need to include the policy output to the check output. That could be removed or redacted as you suggest in line 57.

@toniblyx
Copy link
Member

toniblyx commented Mar 2, 2022

Can you update this PR with the line BUCKET_POLICY_BAD_STATEMENTS=$(echo ${BUCKET_POLICY_BAD_STATEMENTS}" | sed 's|,|[comma]|g') enabled? That makes more sense. Thanks!

Copy link
Member

@toniblyx toniblyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@toniblyx toniblyx merged commit 248cc9d into prowler-cloud:master Mar 2, 2022
@toniblyx
Copy link
Member

toniblyx commented Mar 2, 2022

Thanks @lazize, great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
severity/medium Results in some unexpected or undesired behavior. status/waiting-for-revision Waiting for maintainer's revision
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants