salesforce / policy_sentry

IAM Least Privilege Policy Generator
https://policy-sentry.readthedocs.io/
MIT License
1.99k stars 142 forks source link

Dependent actions allow broader permissions with wildcard #382

Open knastase opened 2 years ago

knastase commented 2 years ago

I am not sure if this was a conscious design decision or not. Dependent actions are always added with wildcards (*) and may not be the expected behavior.

Example

When generating a policy document for write actions on a KMS key ARN, the dependent actions are added as wildcards which could lead to granting more permissions than anticipated.

kms:ReplicateKey is a write action that is added when I specify a key ARN (as designed) Two dependent actions of it are kms:CreateKey and kms:PutKeyPolicy

I understand kms:CreateKey has no resource requirements and is added as a wildcard. kms:PutKeyPolicy on the other hand CAN take a key ARN as a resource constraint but is indiscriminately added as a wildcard action as well. This leads to the generated policy being able to put a key policy on any KMS key (if a key has the default key policy or an overly permissive one)

Observed behavior

- Sid: MultMultNone
  Effect: Allow
  Action:
  - kms:CreateKey
  - kms:PutKeyPolicy <--
  - kms:TagResource
  Resource:
  - '*' <--

Expected behavior

- Sid: KmsWriteKey
  Effect: Allow
  Action:
  ...
  - kms:Verify
  - kms:PutKeyPolicy <--
  - kms:TagResource
  Resource:
  - arn:aws:kms:us-east-1:123456789012:key/shaq <--
- Sid: MultMultNone
  Effect: Allow
  Action:
  - kms:CreateKey
  Resource:
  - '*'

Possible remediation

I attempted to add a bit of code to writing/sid_group.py to add the dependent action to the same SID as the other actions if they share the same resource constraint (but part of a different access_level).

if len(dependent_actions) > 0:
  for dep_action in dependent_actions:
      # If a dependent action has the same resource constraint, add it to actions 
      # instead of * which could grant more access than anticipated.
      for level in ["Read", "Write", "List", "Tagging", "Permissions management"]:
          if dep_action in get_actions_with_arn_type_and_access_level(
              service_prefix, resource_type_name, level):
                if not dep_action in actions:
                  actions.append(dep_action)
      if not dep_action in actions:
          self.add_action_without_resource_constraint(dep_action)
kmcquade commented 2 years ago

@knasty51 - right on! Would you mind sending that remediation in as a PR?

thanks so much for all of your contributions recently - you rock!

knastase commented 2 years ago

1st attempt - https://github.com/salesforce/policy_sentry/pull/395