GithubHelp home page GithubHelp logo

Comments (9)

misraved avatar misraved commented on May 31, 2024

Thanks for raising the question @rbracewell 👍 .

Adding the relevant slack thread for additional details - https://steampipe.slack.com/archives/C01UECB59A7/p1673974501135479

from steampipe-mod-aws-perimeter.

misraved avatar misraved commented on May 31, 2024

Going through the documentation provided by AWS, I think we should add a condition to check for kms:CallerAccount since setting this parameter to * can result in the key becoming public.

@khushboo9024 @rajlearner17 could you please provide some more insight on this issue?

from steampipe-mod-aws-perimeter.

github-actions avatar github-actions commented on May 31, 2024

'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.'

from steampipe-mod-aws-perimeter.

github-actions avatar github-actions commented on May 31, 2024

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.

from steampipe-mod-aws-perimeter.

bigdatasourav avatar bigdatasourav commented on May 31, 2024

Hey @rbracewell, sorry for the delayed response.

The kms:CallerAccount condition is often used to enforce access control and limit the usage of KMS keys to specific AWS accounts. By including this condition in a key policy, we can ensure that only authorized AWS accounts can perform operations on the KMS key, such as encrypting or decrypting data. I have created a KMS key in CloudTrail, and the below policies are created by default. I have updated the kms:CallerAccount value to '*' in one of the below policies.

-- alias/test-key

select jsonb_pretty(policy) from aws_kms_key where id = '01d1934c-af89-4cf9-8ed7-b6b49c0a85e3'
+---------------------------------------------------------------------------------------------------------------+
| jsonb_pretty                                                                                                  |
+---------------------------------------------------------------------------------------------------------------+
| {                                                                                                             |
|     "Id": "Key policy created by CloudTrail",                                                                 |
|     "Version": "2012-10-17",                                                                                  |
|     "Statement": [                                                                                            |
|         {                                                                                                     |
|             "Sid": "Enable IAM User Permissions",                                                             |
|             "Action": "kms:*",                                                                                |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Principal": {                                                                                    |
|                 "AWS": [                                                                                      |
|                     "arn:aws:sts::123456789:assumed-role/superuser/[email protected]", |
|                     "arn:aws:iam::123456789:root"                                                          |
|                 ]                                                                                             |
|             }                                                                                                 |
|         },                                                                                                    |
|         {                                                                                                     |
|             "Sid": "Allow CloudTrail to encrypt logs",                                                        |
|             "Action": "kms:GenerateDataKey*",                                                                 |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Condition": {                                                                                    |
|                 "StringLike": {                                                                               |
|                     "kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:123456789:trail/*"   |
|                 },                                                                                            |
|                 "StringEquals": {                                                                             |
|                     "AWS:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789:trail/test-trail"             |
|                 }                                                                                             |
|             },                                                                                                |
|             "Principal": {                                                                                    |
|                 "Service": "cloudtrail.amazonaws.com"                                                         |
|             }                                                                                                 |
|         },                                                                                                    |
|         {                                                                                                     |
|             "Sid": "Allow CloudTrail to describe key",                                                        |
|             "Action": "kms:DescribeKey",                                                                      |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Principal": {                                                                                    |
|                 "Service": "cloudtrail.amazonaws.com"                                                         |
|             }                                                                                                 |
|         },                                                                                                    |
|         {                                                                                                     |
|             "Sid": "Allow principals in the account to decrypt log files",                                    |
|             "Action": [                                                                                       |
|                 "kms:Decrypt",                                                                                |
|                 "kms:ReEncryptFrom"                                                                           |
|             ],                                                                                                |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Condition": {                                                                                    |
|                 "StringLike": {                                                                               |
|                     "kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:123456789:trail/*"
                      "kms:CallerAccount": "*"  // I have edited the policy here |
|                 },                                                                                            |                                                                                          |
|             },                                                                                                |
|             "Principal": {                                                                                    |
|                 "AWS": "*"                                                                                    |
|             }                                                                                                 |
|         },                                                                                                    |
|         {                                                                                                     |
|             "Sid": "Allow alias creation during setup",                                                       |
|             "Action": "kms:CreateAlias",                                                                      |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Condition": {                                                                                    |
|                 "StringEquals": {                                                                             |
|                     "kms:ViaService": "ec2.us-east-1.amazonaws.com",                                          |
|                     "kms:CallerAccount": "123456789"                                                       |
|                 }                                                                                             |
|             },                                                                                                |
|             "Principal": {                                                                                    |
|                 "AWS": "*"                                                                                    |
|             }                                                                                                 |
|         },                                                                                                    |
|         {                                                                                                     |
|             "Sid": "Enable cross account log decryption",                                                     |
|             "Action": [                                                                                       |
|                 "kms:Decrypt",                                                                                |
|                 "kms:ReEncryptFrom"                                                                           |
|             ],                                                                                                |
|             "Effect": "Allow",                                                                                |
|             "Resource": "*",                                                                                  |
|             "Condition": {                                                                                    |
|                 "StringLike": {                                                                               |
|                     "kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:123456789:trail/*"   |
|                 },                                                                                            |
|                 "StringEquals": {                                                                             |
|                     "kms:CallerAccount": "123456789"                                                       |
|                 }                                                                                             |
|             },                                                                                                |
|             "Principal": {                                                                                    |
|                 "AWS": "*"                                                                                    |
|             }                                                                                                 |
|         }                                                                                                     |
|     ]                                                                                                         |
| }                                                                                                             |
+---------------------------------------------------------------------------------------------------------------+

Here is the updated the mod control query - (got the expected output)

 with wildcard_action_policies as (
      select
        arn,
        count(*) as statements_num
      from
        aws_kms_key,
        jsonb_array_elements(policy_std -> 'Statement') as s
      where
        s ->> 'Effect' = 'Allow'
        -- kms:CallerAccount.   // check for  CallerAccount
        and s -> 'Condition' -> 'StringLike' -> 'kms:calleraccount' ? '*'
        -- aws:SourceOwner
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceowner' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceowner' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' ? '*'
        )
        -- aws:SourceAccount
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceaccount' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceaccount' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' ? '*'
        )
        -- aws:PrincipalOrgID
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalorgid' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalorgid' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' ? '*'
        )
        -- aws:PrincipalAccount
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalaccount' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalaccount' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' ? '*'
        )
        -- aws:PrincipalArn
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalarn' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalarn' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' ? '*'
        )
        -- aws:SourceArn
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourcearn' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourcearn' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Principal' -> 'AWS' = '["*"]'
          or s ->> 'Principal' = '*'
        )
      group by
        arn
    )
    select
      r.arn as resource,
      case
        when p.arn is null then 'ok'
        else 'alarm'
      end as status,
      case
        when p.arn is null then title || ' policy does not allow public access.'
        else title || ' policy contains ' || coalesce(p.statements_num, 0) ||
        ' statement(s) that allow public access.'
      end as reason
    from
      aws_kms_key as r
      left join wildcard_action_policies as p on p.arn = r.arn
    where
      key_manager = 'CUSTOMER';
+------------------------------------------------------------------------------+--------+---------------------------------------------------------------------------+
| resource                                                                     | status | reason                                                                    |
+------------------------------------------------------------------------------+--------+---------------------------------------------------------------------------+
| arn:aws:kms:ap-south-1:123456789:key/e6ce31c8-5f6f-45ce-bec4-ee7354a4757d | ok     | alias/intg-test policy does not allow public access.                      |
| arn:aws:kms:us-east-1:123456789:key/01d1934c-af89-4cf9-8ed7-b6b49c0a85e3  | alarm  | alias/test-key policy contains 1 statement(s) that allow public access.   |
| arn:aws:kms:ap-south-1:123456789:key/a1dbc718-e60a-416e-8ab5-3a935043eeae | ok     | alias/test2 policy does not allow public access.                          |
+------------------------------------------------------------------------------+--------+---------------------------------------------------------------------------+

Could you please check the above query and let us know if it solves the problem?

@misraved @rajlearner17 Please share your views regarding the updated query.

from steampipe-mod-aws-perimeter.

rbracewell avatar rbracewell commented on May 31, 2024

When running the existing query from the documentation I get the following results
ok: 192
alarm: 8

Running the revised query from above I get the following results
ok: 200
alarm: 0

This is not what I expected. Of those 8 in alarm only one of them uses CallerAccount so I would still have expected the alarm count to be 7 with the new query.

from steampipe-mod-aws-perimeter.

bigdatasourav avatar bigdatasourav commented on May 31, 2024

Hey @rbracewell, thanks for the quick check. Could you please try the below one? I hope this will work as it was expected. If it does not work, please share one policy structure(without sensitive info) where CallerAccount is not used.

 with wildcard_action_policies as (
      select
        arn,
        count(*) as statements_num
      from
        aws_kms_key,
        jsonb_array_elements(policy_std -> 'Statement') as s
      where
        s ->> 'Effect' = 'Allow'
        -- kms:CallerAccount.   // check for  CallerAccount
       and s -> 'Condition' -> 'StringEquals' -> 'kms:calleraccount' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'kms:calleraccount' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'kms:calleraccount' is null
          or s -> 'Condition' -> 'StringLike' -> 'kms:calleraccount' ? '*'
        )
        -- aws:SourceOwner
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceowner' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceowner' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourceowner' ? '*'
        )
        -- aws:SourceAccount
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourceaccount' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourceaccount' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourceaccount' ? '*'
        )
        -- aws:PrincipalOrgID
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalorgid' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalorgid' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalorgid' ? '*'
        )
        -- aws:PrincipalAccount
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalaccount' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalaccount' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalaccount' ? '*'
        )
        -- aws:PrincipalArn
        and s -> 'Condition' -> 'StringEquals' -> 'aws:principalarn' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:principalarn' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:principalarn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'ArnEquals' -> 'aws:principalarn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' is null
          or s -> 'Condition' -> 'ArnLike' -> 'aws:principalarn' ? '*'
        )
        -- aws:SourceArn
        and s -> 'Condition' -> 'StringEquals' -> 'aws:sourcearn' is null
        and s -> 'Condition' -> 'StringEqualsIgnoreCase' -> 'aws:sourcearn' is null
        and (
          s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'StringLike' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'ArnEquals' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' is null
          or s -> 'Condition' -> 'ArnLike' -> 'aws:sourcearn' ? '*'
        )
        and (
          s -> 'Principal' -> 'AWS' = '["*"]'
          or s ->> 'Principal' = '*'
        )
      group by
        arn
    )
    select
      r.arn as resource,
      case
        when p.arn is null then 'ok'
        else 'alarm'
      end as status,
      case
        when p.arn is null then title || ' policy does not allow public access.'
        else title || ' policy contains ' || coalesce(p.statements_num, 0) ||
        ' statement(s) that allow public access.'
      end as reason
    from
      aws_kms_key as r
      left join wildcard_action_policies as p on p.arn = r.arn
    where
      key_manager = 'CUSTOMER';

from steampipe-mod-aws-perimeter.

rbracewell avatar rbracewell commented on May 31, 2024

The revised query returned the expected results this time.
The policy correctly detected kms:CallerAccount and marked as ok rather than alarm

from steampipe-mod-aws-perimeter.

misraved avatar misraved commented on May 31, 2024

Thanks @rbracewell for testing the updated query suggested by @bigdatasourav 👍.

The feedback has been extremely helpful in nailing down the query output 🎉 .

from steampipe-mod-aws-perimeter.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.