iam-policy-validator 1.15.6__tar.gz → 1.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/ci.yml +4 -4
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/pre-release.yml +1 -1
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/release.yml +1 -1
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/CHANGELOG.md +19 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/PKG-INFO +1 -1
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/action.yaml +3 -3
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__version__.py +1 -1
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/__init__.py +2 -0
- iam_policy_validator-1.16.0/iam_validator/checks/condition_key_validation.py +125 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/condition_type_mismatch.py +20 -0
- iam_policy_validator-1.16.0/iam_validator/checks/ifexists_condition_check.py +210 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/set_operator_validation.py +20 -6
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/check_registry.py +1 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/condition_validators.py +77 -3
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_condition_key_validation_check.py +133 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_condition_type_mismatch.py +69 -0
- iam_policy_validator-1.16.0/tests/checks/test_ifexists_condition_check.py +342 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_set_operator_validation.py +77 -0
- iam_policy_validator-1.15.6/iam_validator/checks/condition_key_validation.py +0 -88
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/dependabot.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/cleanup-prereleases.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/codeql.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/docs.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/scorecard.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.gitignore +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/CONTRIBUTING.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/LICENSE +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/Makefile +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/README.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/SECURITY.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/checks.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/exceptions.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/models.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/api-reference/sdk.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/changelog.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/development-setup.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/releasing.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/contributing/testing.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/architecture.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/best-practices.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/examples.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/custom-checks/tutorial.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/advanced.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/policy-utilities.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/quickstart.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/developer-guide/sdk/validation.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/first-validation.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/installation.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/getting-started/quickstart.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/includes/abbreviations.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/github-actions.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/gitlab-ci.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/mcp-server.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/integrations/pre-commit.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/stylesheets/extra.css +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/advanced-checks.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/aws-validation.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/checks/security-checks.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/cli-reference.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/configuration.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/index.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/output-formats.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/docs/user-guide/troubleshooting.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/README.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/access-analyzer/example1.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/access-analyzer/example2.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/aws-service-definitions/iam.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/aws-service-definitions/s3.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/full-reference-config.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/github-labels-config.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/minimal-validation-config.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/offline-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/policy-level-condition-enforcement-config.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/configs/strict-security.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/custom_checks/cross_account_external_id_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/custom_checks/domain_restriction_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/access-analyzer-only.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/basic-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/custom-policy-checks.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/multi-region-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/resource-policy-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/sarif-code-scanning.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/sequential-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/two-step-validation.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/github-actions/validate-changed-files.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/allowed-wildcard-resource.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/api_gateway_management.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/athena_query_access.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/backup_vault_access.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cloudformation_deployer.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cloudwatch_monitoring.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/cognito_user_pool.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/dynamodb_table_access.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/ecs_task_execution.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/eventbridge_rules.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/glue_etl_jobs.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/insecure_policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/insecure_policy.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-resource-constraint.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-sid-special-chars.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid-sid-with-spaces.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/invalid_policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/kms_encryption_keys.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/lambda_developer.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/lambda_developer.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/maximum_size_policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_missing_required_tags.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_tag_enforcement_example.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/policy_with_wildcard_resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/privilege_escalation_scattered.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/rds_database_admin.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/s3_bucket_access.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sample_policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sample_policy.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/secrets_manager_access.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sensitive-action-wildcards.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/sns_sqs_messaging.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/step_functions_workflow.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/terraform-template-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/test_none_of_valid.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/test_none_of_violations.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/valid-sid-formats.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wildcard_examples.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wildcard_examples.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wrong-condition-key.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/identity-policies/wrong-s3-condition.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-allow-effect.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-not-action.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-specific-principal.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-unsupported-service.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-invalid-wildcard-action.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-control-policies/rcp-valid-enforce-encryption.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/backup-vault-policy-org-access.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/ecr-repository-policy-org-restricted.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/ecr-repository-policy-public.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/efs-filesystem-policy-vpc-only.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/glacier-vault-policy-cross-account.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-cross-account.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-insecure.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-org-restricted.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/kms-key-policy-service-specific.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-api-gateway.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-cross-account-invoke.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-eventbridge-multiple.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-public-url.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/lambda-permission-s3-trigger.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/opensearch-domain-policy-ip-restricted.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-cloudfront.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-cross-account-org.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-insecure-transport.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-ip-restriction.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-public-with-conditions.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-public.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-specific-account.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-vpc-endpoint.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/s3-bucket-policy-wildcard-actions.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/secrets-manager-policy-cross-account.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-cross-account-mfa.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-cross-account.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-eventbridge.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-org-wide.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sns-topic-policy-public-no-conditions.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-cross-account-role.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-iam-users-mfa.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-public.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/resource-policies/sqs-queue-policy-sns-subscription.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/deny-root-account-usage.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/require-mfa.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/service-control-policies/restrict-regions.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/correct-condition-wrong-key.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/dynamodb-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/ec2-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/iam-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/lambda-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/s3-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/sqs-sns-wrong-resources.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/iam-test-policies/wrong_actions_mismatch/typo-condition-field.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/README.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/SYSTEM_PROMPT.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/example_conversation.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/mcp-llm-instructions/organization_config.yaml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/lambda-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/s3-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/quick-start/user-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/INVALID-wrong-principal-type.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/cross-account-trust-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/github-actions-oidc-trust-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/lambda-service-role-trust-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/examples/trust-policies/saml-federated-trust-policy.json +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/__main__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_condition_enforcement.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_resource_matching.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/action_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/full_wildcard.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/mfa_condition_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/not_action_not_resource.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_size.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_structure.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/policy_type_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/principal_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/resource_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/sensitive_action.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/service_wildcard.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/sid_uniqueness.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/trust_policy_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/action_parser.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/policy_level_checks.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/sensitive_action_matcher.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/utils/wildcard_expansion.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/wildcard_action.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/wildcard_resource.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/analyze.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/base.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/cache.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/completion.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/download_services.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/mcp.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/post_to_pr.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/query.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/commands/validate.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/access_analyzer.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/access_analyzer_report.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_fetcher.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/cache.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/client.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/fetcher.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/parsers.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/patterns.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/storage.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/aws_service/validators.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/cli.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/codeowners.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/aws_api.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/aws_global_conditions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/category_suggestions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/check_documentation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/condition_requirements.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/config_loader.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/defaults.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/principal_requirements.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/sensitive_actions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/service_principals.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/config/wildcards.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/constants.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/diff_parser.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/finding_fingerprint.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/base.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/console.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/csv.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/enhanced.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/html.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/json.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/markdown.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/formatters/sarif.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignore_patterns.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignore_processor.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/ignored_findings.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/label_manager.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/models.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/policy_checks.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/policy_loader.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/pr_commenter.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/report.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/github_integration.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/integrations/ms_teams.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/models.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/server.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/session_config.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/templates/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/templates/builtin.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/generation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/org_config_tools.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/query.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/mcp/tools/validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/arn_matching.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/context.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/exceptions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/helpers.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/policy_utils.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/query_utils.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/sdk/shortcuts.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/cache.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/regex.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/utils/terminal.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/mkdocs.yml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/pyproject.toml +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/README.md +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_action_validation_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_aws_global_conditions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_custom_policy_checks.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_full_wildcard_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_mfa_condition_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_not_action_not_resource.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_policy_size_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_principal_validation_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_resource_validation_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_filtering.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_suggestions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sensitive_action_wildcard_expansion.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_service_principal_wildcard.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_service_wildcard_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_sid_uniqueness_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_wildcard_action_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/checks/test_wildcard_resource_check.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/test_completion_command.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/commands/test_query_command.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/config/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/config/test_config_loader.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_condition_enforcement.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_condition_enforcement_policy_level.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_action_resource_matching.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_aws_api_config.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_aws_fetcher_wildcards.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_id_in_comments.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_id_injection.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_check_registry.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_codeowners.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_comment_truncation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_diff_parser.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_finding_fingerprint.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_ignore_patterns.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_ignored_findings.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_models.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_multipart_comments.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_policy_loader.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_policy_type_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_pr_commenter_diff_filtering.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_regex_utils.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_detection.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_multiple_statements.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_oidc_aud_required.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/core/test_trust_policy_validation.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_comment_deduplication.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_github_pagination.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/integrations/test_label_manager.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/__init__.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/conftest.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_custom_instructions.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_generation_tools.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_org_config.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_query_tools.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_server_integration.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_templates.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/tests/mcp/test_validation_tools.py +0 -0
- {iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/uv.lock +0 -0
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
|
|
27
27
|
|
|
28
28
|
- name: Install uv
|
|
29
|
-
uses: astral-sh/setup-uv@
|
|
29
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
30
30
|
with:
|
|
31
31
|
enable-cache: true
|
|
32
32
|
|
|
@@ -56,7 +56,7 @@ jobs:
|
|
|
56
56
|
python-version: ${{ matrix.python-version }}
|
|
57
57
|
|
|
58
58
|
- name: Install uv
|
|
59
|
-
uses: astral-sh/setup-uv@
|
|
59
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
60
60
|
with:
|
|
61
61
|
enable-cache: true
|
|
62
62
|
|
|
@@ -80,7 +80,7 @@ jobs:
|
|
|
80
80
|
python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
|
|
81
81
|
|
|
82
82
|
- name: Install uv
|
|
83
|
-
uses: astral-sh/setup-uv@
|
|
83
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
84
84
|
with:
|
|
85
85
|
enable-cache: true
|
|
86
86
|
|
|
@@ -104,7 +104,7 @@ jobs:
|
|
|
104
104
|
python-version: "${{ env.DEFAULT_PYTHON_VERSION }}"
|
|
105
105
|
|
|
106
106
|
- name: Install uv
|
|
107
|
-
uses: astral-sh/setup-uv@
|
|
107
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
108
108
|
with:
|
|
109
109
|
enable-cache: true
|
|
110
110
|
|
{iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/.github/workflows/pre-release.yml
RENAMED
|
@@ -80,7 +80,7 @@ jobs:
|
|
|
80
80
|
python-version: ${{ inputs.python_version }}
|
|
81
81
|
|
|
82
82
|
- name: Install uv
|
|
83
|
-
uses: astral-sh/setup-uv@
|
|
83
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
84
84
|
with:
|
|
85
85
|
enable-cache: true
|
|
86
86
|
|
|
@@ -31,7 +31,7 @@ jobs:
|
|
|
31
31
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
32
32
|
|
|
33
33
|
- name: Install uv
|
|
34
|
-
uses: astral-sh/setup-uv@
|
|
34
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
35
35
|
with:
|
|
36
36
|
enable-cache: true
|
|
37
37
|
|
|
@@ -13,6 +13,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
## [1.16.0] - 2026-02-05
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- New `ifexists_condition_usage` check validating proper usage of the `IfExists` suffix on condition operators:
|
|
21
|
+
- Detects `IfExists` on security-sensitive keys in Allow statements (may bypass controls)
|
|
22
|
+
- Warns about non-negated `IfExists` weakening Deny statements
|
|
23
|
+
- Flags redundant `IfExists` on always-present keys (e.g., `aws:SecureTransport`)
|
|
24
|
+
- Optionally suggests `IfExists` for negated operators in Deny statements
|
|
25
|
+
- Security-sensitive and always-present condition key constants in `condition_validators` module
|
|
26
|
+
|
|
27
|
+
### Improved
|
|
28
|
+
|
|
29
|
+
- `condition_key_validation`: Suppress false positive errors when `IfExists` is used with keys valid for some but not all actions in the statement
|
|
30
|
+
- `condition_type_mismatch`: Detect `NullIfExists` as invalid syntax (the `Null` operator already checks for key existence)
|
|
31
|
+
- `set_operator_validation`: Compound warning when `ForAllValues` is combined with `IfExists` (doubly permissive pattern)
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
16
35
|
## [1.15.5] - 2025-01-28
|
|
17
36
|
|
|
18
37
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iam-policy-validator
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.16.0
|
|
4
4
|
Summary: Validate AWS IAM policies for correctness and security using AWS Service Reference API
|
|
5
5
|
Project-URL: Homepage, https://github.com/boogy/iam-policy-validator
|
|
6
6
|
Project-URL: Documentation, https://boogy.github.io/iam-policy-validator
|
|
@@ -183,7 +183,7 @@ runs:
|
|
|
183
183
|
python-version-file: "${{ github.action_path }}/.python-version"
|
|
184
184
|
|
|
185
185
|
- name: Install uv
|
|
186
|
-
uses: astral-sh/setup-uv@
|
|
186
|
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
|
187
187
|
with:
|
|
188
188
|
enable-cache: true
|
|
189
189
|
cache-suffix: ci # Prune cache in CI to reduce bloat
|
|
@@ -211,7 +211,7 @@ runs:
|
|
|
211
211
|
|
|
212
212
|
- name: Restore AWS service definitions cache
|
|
213
213
|
id: cache-aws-services
|
|
214
|
-
uses: actions/cache/restore@
|
|
214
|
+
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
|
215
215
|
with:
|
|
216
216
|
path: ~/.cache/iam-validator/aws_services
|
|
217
217
|
# Cache key refreshes weekly to get latest AWS service updates
|
|
@@ -553,7 +553,7 @@ runs:
|
|
|
553
553
|
# Attempting to save with an existing key will silently do nothing
|
|
554
554
|
# Use always() to ensure cache is saved even if validation fails
|
|
555
555
|
if: always() && steps.cache-aws-services.outputs.cache-hit != 'true'
|
|
556
|
-
uses: actions/cache/save@
|
|
556
|
+
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
|
557
557
|
with:
|
|
558
558
|
path: ~/.cache/iam-validator/aws_services
|
|
559
559
|
key: aws-services-${{ runner.os }}-${{ steps.week.outputs.week }}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This file is the single source of truth for the package version.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
__version__ = "1.
|
|
6
|
+
__version__ = "1.16.0"
|
|
7
7
|
# Parse version, handling pre-release suffixes like -rc, -alpha, -beta
|
|
8
8
|
_version_base = __version__.split("-", maxsplit=1)[0] # Remove pre-release suffix if present
|
|
9
9
|
__version_info__ = tuple(int(part) for part in _version_base.split("."))
|
{iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/checks/__init__.py
RENAMED
|
@@ -10,6 +10,7 @@ from iam_validator.checks.action_validation import ActionValidationCheck
|
|
|
10
10
|
from iam_validator.checks.condition_key_validation import ConditionKeyValidationCheck
|
|
11
11
|
from iam_validator.checks.condition_type_mismatch import ConditionTypeMismatchCheck
|
|
12
12
|
from iam_validator.checks.full_wildcard import FullWildcardCheck
|
|
13
|
+
from iam_validator.checks.ifexists_condition_check import IfExistsConditionCheck
|
|
13
14
|
from iam_validator.checks.mfa_condition_check import MFAConditionCheck
|
|
14
15
|
from iam_validator.checks.not_action_not_resource import NotActionNotResourceCheck
|
|
15
16
|
from iam_validator.checks.policy_size import PolicySizeCheck
|
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
|
31
32
|
"ConditionKeyValidationCheck",
|
|
32
33
|
"ConditionTypeMismatchCheck",
|
|
33
34
|
"FullWildcardCheck",
|
|
35
|
+
"IfExistsConditionCheck",
|
|
34
36
|
"MFAConditionCheck",
|
|
35
37
|
"NotActionNotResourceCheck",
|
|
36
38
|
"PolicySizeCheck",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Condition key validation check - validates condition keys against AWS definitions."""
|
|
2
|
+
|
|
3
|
+
from typing import ClassVar
|
|
4
|
+
|
|
5
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
6
|
+
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
7
|
+
from iam_validator.core.condition_validators import has_if_exists_suffix
|
|
8
|
+
from iam_validator.core.models import Statement, ValidationIssue
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ConditionKeyValidationCheck(PolicyCheck):
|
|
12
|
+
"""Validates condition keys against AWS service definitions and global keys."""
|
|
13
|
+
|
|
14
|
+
check_id: ClassVar[str] = "condition_key_validation"
|
|
15
|
+
description: ClassVar[str] = "Validates condition keys against AWS service definitions"
|
|
16
|
+
default_severity: ClassVar[str] = "error" # Invalid condition keys are IAM policy errors
|
|
17
|
+
|
|
18
|
+
async def execute(
|
|
19
|
+
self,
|
|
20
|
+
statement: Statement,
|
|
21
|
+
statement_idx: int,
|
|
22
|
+
fetcher: AWSServiceFetcher,
|
|
23
|
+
config: CheckConfig,
|
|
24
|
+
) -> list[ValidationIssue]:
|
|
25
|
+
"""Execute condition key validation on a statement."""
|
|
26
|
+
issues = []
|
|
27
|
+
|
|
28
|
+
# Get conditions from statement
|
|
29
|
+
if not statement.condition:
|
|
30
|
+
return issues
|
|
31
|
+
|
|
32
|
+
# Check if global condition key warnings are enabled (default: True)
|
|
33
|
+
warn_on_global_keys = config.config.get("warn_on_global_condition_keys", True)
|
|
34
|
+
|
|
35
|
+
statement_sid = statement.sid
|
|
36
|
+
line_number = statement.line_number
|
|
37
|
+
actions = statement.get_actions()
|
|
38
|
+
resources = statement.get_resources()
|
|
39
|
+
|
|
40
|
+
# Extract all condition keys from all condition operators
|
|
41
|
+
for operator, conditions in statement.condition.items():
|
|
42
|
+
operator_has_ifexists = has_if_exists_suffix(operator)
|
|
43
|
+
|
|
44
|
+
for condition_key in conditions.keys():
|
|
45
|
+
key_valid_for_any_action = False
|
|
46
|
+
key_invalid_actions: list[tuple] = []
|
|
47
|
+
first_warning_result = None
|
|
48
|
+
|
|
49
|
+
# Validate this condition key against each action in the statement
|
|
50
|
+
for action in actions:
|
|
51
|
+
# Skip wildcard actions
|
|
52
|
+
if action == "*":
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
# Validate against action and resource types
|
|
56
|
+
result = await fetcher.validate_condition_key(action, condition_key, resources)
|
|
57
|
+
|
|
58
|
+
if result.is_valid:
|
|
59
|
+
key_valid_for_any_action = True
|
|
60
|
+
if result.warning_message and first_warning_result is None:
|
|
61
|
+
first_warning_result = (action, result)
|
|
62
|
+
else:
|
|
63
|
+
key_invalid_actions.append((action, result))
|
|
64
|
+
|
|
65
|
+
# If IfExists is used and the key is valid for at least one action,
|
|
66
|
+
# suppress errors for actions that don't support it.
|
|
67
|
+
# Warnings (global key usage) are still reported.
|
|
68
|
+
if operator_has_ifexists and key_valid_for_any_action:
|
|
69
|
+
if first_warning_result and warn_on_global_keys:
|
|
70
|
+
action, result = first_warning_result
|
|
71
|
+
warning_msg = result.warning_message or ""
|
|
72
|
+
issues.append(
|
|
73
|
+
ValidationIssue(
|
|
74
|
+
severity="warning",
|
|
75
|
+
statement_sid=statement_sid,
|
|
76
|
+
statement_index=statement_idx,
|
|
77
|
+
issue_type="global_condition_key_with_action_specific",
|
|
78
|
+
message=warning_msg,
|
|
79
|
+
action=action,
|
|
80
|
+
condition_key=condition_key,
|
|
81
|
+
line_number=line_number,
|
|
82
|
+
field_name="condition",
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
continue # Skip error reporting
|
|
86
|
+
|
|
87
|
+
# Report errors (first invalid action)
|
|
88
|
+
if key_invalid_actions:
|
|
89
|
+
action, result = key_invalid_actions[0]
|
|
90
|
+
issues.append(
|
|
91
|
+
ValidationIssue(
|
|
92
|
+
severity=self.get_severity(config),
|
|
93
|
+
statement_sid=statement_sid,
|
|
94
|
+
statement_index=statement_idx,
|
|
95
|
+
issue_type="invalid_condition_key",
|
|
96
|
+
message=result.error_message
|
|
97
|
+
or f"Invalid condition key: `{condition_key}`",
|
|
98
|
+
action=action,
|
|
99
|
+
condition_key=condition_key,
|
|
100
|
+
line_number=line_number,
|
|
101
|
+
suggestion=result.suggestion,
|
|
102
|
+
field_name="condition",
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
# Report warnings for valid keys (no IfExists suppression path)
|
|
108
|
+
if first_warning_result and warn_on_global_keys:
|
|
109
|
+
action, result = first_warning_result
|
|
110
|
+
warning_msg = result.warning_message or ""
|
|
111
|
+
issues.append(
|
|
112
|
+
ValidationIssue(
|
|
113
|
+
severity="warning",
|
|
114
|
+
statement_sid=statement_sid,
|
|
115
|
+
statement_index=statement_idx,
|
|
116
|
+
issue_type="global_condition_key_with_action_specific",
|
|
117
|
+
message=warning_msg,
|
|
118
|
+
action=action,
|
|
119
|
+
condition_key=condition_key,
|
|
120
|
+
line_number=line_number,
|
|
121
|
+
field_name="condition",
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return issues
|
|
@@ -8,6 +8,7 @@ from typing import ClassVar
|
|
|
8
8
|
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
9
9
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
10
10
|
from iam_validator.core.condition_validators import (
|
|
11
|
+
has_if_exists_suffix,
|
|
11
12
|
normalize_operator,
|
|
12
13
|
translate_type,
|
|
13
14
|
validate_value_for_type,
|
|
@@ -71,6 +72,25 @@ class ConditionTypeMismatchCheck(PolicyCheck):
|
|
|
71
72
|
# Unknown operator - this will be caught by another check
|
|
72
73
|
continue
|
|
73
74
|
|
|
75
|
+
# Detect NullIfExists as invalid syntax (must be BEFORE skip_operators guard)
|
|
76
|
+
if base_operator == "Null" and has_if_exists_suffix(operator):
|
|
77
|
+
issues.append(
|
|
78
|
+
ValidationIssue(
|
|
79
|
+
severity=self.get_severity(config),
|
|
80
|
+
message=(
|
|
81
|
+
f"Invalid operator `{operator}`. The `Null` condition operator "
|
|
82
|
+
f"does not support the `IfExists` suffix. The `Null` operator "
|
|
83
|
+
f"already checks for key existence \u2014 use `Null` directly."
|
|
84
|
+
),
|
|
85
|
+
statement_sid=statement_sid,
|
|
86
|
+
statement_index=statement_idx,
|
|
87
|
+
issue_type="invalid_operator",
|
|
88
|
+
line_number=line_number,
|
|
89
|
+
field_name="condition",
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
continue
|
|
93
|
+
|
|
74
94
|
if base_operator in skip_operators:
|
|
75
95
|
continue
|
|
76
96
|
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""IfExists Condition Usage Check.
|
|
2
|
+
|
|
3
|
+
Validates proper usage of the IfExists suffix on IAM condition operators.
|
|
4
|
+
|
|
5
|
+
Detects:
|
|
6
|
+
- IfExists on security-sensitive keys in Allow statements (may bypass controls)
|
|
7
|
+
- Non-negated IfExists in Deny statements (weakens the Deny)
|
|
8
|
+
- IfExists on always-present keys (redundant)
|
|
9
|
+
- Suggests IfExists for negated operators in Deny without it
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
15
|
+
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
16
|
+
from iam_validator.core.condition_validators import (
|
|
17
|
+
ALWAYS_PRESENT_CONDITION_KEYS,
|
|
18
|
+
SECURITY_SENSITIVE_CONDITION_KEYS,
|
|
19
|
+
has_if_exists_suffix,
|
|
20
|
+
is_negated_operator,
|
|
21
|
+
normalize_operator,
|
|
22
|
+
)
|
|
23
|
+
from iam_validator.core.models import Statement, ValidationIssue
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class IfExistsConditionCheck(PolicyCheck):
|
|
27
|
+
"""Check for improper or risky usage of IfExists condition operators."""
|
|
28
|
+
|
|
29
|
+
check_id: ClassVar[str] = "ifexists_condition_usage"
|
|
30
|
+
description: ClassVar[str] = "Validates proper usage of IfExists suffix on condition operators"
|
|
31
|
+
default_severity: ClassVar[str] = "warning"
|
|
32
|
+
|
|
33
|
+
async def execute(
|
|
34
|
+
self,
|
|
35
|
+
statement: Statement,
|
|
36
|
+
statement_idx: int,
|
|
37
|
+
fetcher: AWSServiceFetcher,
|
|
38
|
+
config: CheckConfig,
|
|
39
|
+
) -> list[ValidationIssue]:
|
|
40
|
+
"""Execute IfExists condition usage checks."""
|
|
41
|
+
issues: list[ValidationIssue] = []
|
|
42
|
+
|
|
43
|
+
if not statement.condition:
|
|
44
|
+
return issues
|
|
45
|
+
|
|
46
|
+
statement_sid = statement.sid
|
|
47
|
+
line_number = statement.line_number
|
|
48
|
+
effect = statement.effect
|
|
49
|
+
|
|
50
|
+
# Config options
|
|
51
|
+
warn_security_sensitive_allow = config.config.get("warn_security_sensitive_allow", True)
|
|
52
|
+
suggest_deny_ifexists = config.config.get("suggest_deny_ifexists", False)
|
|
53
|
+
warn_always_present_keys = config.config.get("warn_always_present_keys", True)
|
|
54
|
+
additional_security_keys = config.config.get("additional_security_sensitive_keys", [])
|
|
55
|
+
|
|
56
|
+
# Build the full set of security-sensitive keys
|
|
57
|
+
security_keys = SECURITY_SENSITIVE_CONDITION_KEYS | frozenset(additional_security_keys)
|
|
58
|
+
|
|
59
|
+
# Collect Null-checked keys for suppression
|
|
60
|
+
null_checked_keys: set[str] = set()
|
|
61
|
+
for op, conds in statement.condition.items():
|
|
62
|
+
base_op, _, _ = normalize_operator(op)
|
|
63
|
+
if base_op == "Null":
|
|
64
|
+
for key, value in conds.items():
|
|
65
|
+
# Only suppress if Null checks for key presence (value = "false")
|
|
66
|
+
values = value if isinstance(value, list) else [value]
|
|
67
|
+
if any(str(v).lower() == "false" for v in values):
|
|
68
|
+
null_checked_keys.add(key)
|
|
69
|
+
|
|
70
|
+
for operator, conditions in statement.condition.items():
|
|
71
|
+
has_ifexists = has_if_exists_suffix(operator)
|
|
72
|
+
is_negated = is_negated_operator(operator)
|
|
73
|
+
base_op, _, _ = normalize_operator(operator)
|
|
74
|
+
|
|
75
|
+
for condition_key in conditions:
|
|
76
|
+
# Normalize condition key for case-insensitive comparison
|
|
77
|
+
key_lower = condition_key.lower()
|
|
78
|
+
|
|
79
|
+
# Skip MFA key - handled by mfa_condition_antipattern check
|
|
80
|
+
if key_lower == "aws:multifactorauthpresent":
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
if has_ifexists:
|
|
84
|
+
# IfExists on always-present keys is redundant
|
|
85
|
+
if warn_always_present_keys:
|
|
86
|
+
always_present_match = any(
|
|
87
|
+
k.lower() == key_lower for k in ALWAYS_PRESENT_CONDITION_KEYS
|
|
88
|
+
)
|
|
89
|
+
if always_present_match:
|
|
90
|
+
# Reconstruct the operator without IfExists for the message
|
|
91
|
+
raw_base = operator
|
|
92
|
+
if ":" in operator:
|
|
93
|
+
parts = operator.split(":", 1)
|
|
94
|
+
if parts[0] in ("ForAllValues", "ForAnyValue"):
|
|
95
|
+
raw_base = parts[1]
|
|
96
|
+
base_without_ifexists = (
|
|
97
|
+
raw_base[:-8] if raw_base.endswith("IfExists") else raw_base
|
|
98
|
+
)
|
|
99
|
+
if ":" in operator:
|
|
100
|
+
parts = operator.split(":", 1)
|
|
101
|
+
if parts[0] in ("ForAllValues", "ForAnyValue"):
|
|
102
|
+
base_without_ifexists = f"{parts[0]}:{base_without_ifexists}"
|
|
103
|
+
|
|
104
|
+
issues.append(
|
|
105
|
+
ValidationIssue(
|
|
106
|
+
severity="info",
|
|
107
|
+
message=(
|
|
108
|
+
f"Redundant `IfExists`: The condition key "
|
|
109
|
+
f"`{condition_key}` is always present in the "
|
|
110
|
+
f"request context. Using `{operator}` has the "
|
|
111
|
+
f"same effect as `{base_without_ifexists}` for "
|
|
112
|
+
f"this key."
|
|
113
|
+
),
|
|
114
|
+
statement_sid=statement_sid,
|
|
115
|
+
statement_index=statement_idx,
|
|
116
|
+
issue_type="ifexists_on_always_present_key",
|
|
117
|
+
condition_key=condition_key,
|
|
118
|
+
line_number=line_number,
|
|
119
|
+
field_name="condition",
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Check if key is security-sensitive (case-insensitive)
|
|
124
|
+
is_security_key = any(k.lower() == key_lower for k in security_keys)
|
|
125
|
+
|
|
126
|
+
if effect == "Allow" and warn_security_sensitive_allow:
|
|
127
|
+
# IfExists on security-sensitive keys in Allow may bypass controls
|
|
128
|
+
if is_security_key:
|
|
129
|
+
# Check for complementary Null check
|
|
130
|
+
if condition_key not in null_checked_keys:
|
|
131
|
+
issues.append(
|
|
132
|
+
ValidationIssue(
|
|
133
|
+
severity=self.get_severity(config),
|
|
134
|
+
message=(
|
|
135
|
+
f"Security control may be bypassed: "
|
|
136
|
+
f"`{operator}` with `{condition_key}` in "
|
|
137
|
+
f"an Allow statement means the restriction "
|
|
138
|
+
f"is not enforced when the key is missing "
|
|
139
|
+
f"from the request context. Not all API "
|
|
140
|
+
f"calls include `{condition_key}` (e.g., "
|
|
141
|
+
f"calls made by AWS services on your "
|
|
142
|
+
f"behalf). Consider using the operator "
|
|
143
|
+
f"without `IfExists` or adding a `Null` "
|
|
144
|
+
f"condition check."
|
|
145
|
+
),
|
|
146
|
+
statement_sid=statement_sid,
|
|
147
|
+
statement_index=statement_idx,
|
|
148
|
+
issue_type="ifexists_weakens_security_condition",
|
|
149
|
+
condition_key=condition_key,
|
|
150
|
+
line_number=line_number,
|
|
151
|
+
field_name="condition",
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
elif effect == "Deny":
|
|
156
|
+
# Non-negated IfExists in Deny weakens the restriction
|
|
157
|
+
if not is_negated and is_security_key:
|
|
158
|
+
if condition_key not in null_checked_keys:
|
|
159
|
+
issues.append(
|
|
160
|
+
ValidationIssue(
|
|
161
|
+
severity=self.get_severity(config),
|
|
162
|
+
message=(
|
|
163
|
+
f"Weakened Deny: `{operator}` with "
|
|
164
|
+
f"`{condition_key}` in a Deny statement "
|
|
165
|
+
f"means the Deny does not apply when "
|
|
166
|
+
f"`{condition_key}` is missing from the "
|
|
167
|
+
f"request context. Consider removing "
|
|
168
|
+
f"`IfExists` or adding a `Null` condition "
|
|
169
|
+
f"check."
|
|
170
|
+
),
|
|
171
|
+
statement_sid=statement_sid,
|
|
172
|
+
statement_index=statement_idx,
|
|
173
|
+
issue_type="ifexists_weakens_deny",
|
|
174
|
+
condition_key=condition_key,
|
|
175
|
+
line_number=line_number,
|
|
176
|
+
field_name="condition",
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
elif not has_ifexists and effect == "Deny" and suggest_deny_ifexists:
|
|
181
|
+
# Suggest IfExists for negated operator in Deny without it
|
|
182
|
+
if is_negated:
|
|
183
|
+
# Only suggest for keys that may be absent
|
|
184
|
+
is_always_present = any(
|
|
185
|
+
k.lower() == key_lower for k in ALWAYS_PRESENT_CONDITION_KEYS
|
|
186
|
+
)
|
|
187
|
+
is_security_key = any(k.lower() == key_lower for k in security_keys)
|
|
188
|
+
if not is_always_present and is_security_key:
|
|
189
|
+
issues.append(
|
|
190
|
+
ValidationIssue(
|
|
191
|
+
severity="info",
|
|
192
|
+
message=(
|
|
193
|
+
f"Consider using `{base_op}IfExists` instead "
|
|
194
|
+
f"of `{base_op}` in this Deny statement. "
|
|
195
|
+
f"Without `IfExists`, the Deny does not apply "
|
|
196
|
+
f"when `{condition_key}` is missing from the "
|
|
197
|
+
f"request context. With `{base_op}IfExists`, "
|
|
198
|
+
f"the Deny still applies even when the key is "
|
|
199
|
+
f"absent."
|
|
200
|
+
),
|
|
201
|
+
statement_sid=statement_sid,
|
|
202
|
+
statement_index=statement_idx,
|
|
203
|
+
issue_type="ifexists_deny_suggestion",
|
|
204
|
+
condition_key=condition_key,
|
|
205
|
+
line_number=line_number,
|
|
206
|
+
field_name="condition",
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return issues
|
|
@@ -11,6 +11,7 @@ from typing import ClassVar
|
|
|
11
11
|
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
12
12
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
13
13
|
from iam_validator.core.condition_validators import (
|
|
14
|
+
has_if_exists_suffix,
|
|
14
15
|
is_multivalued_context_key,
|
|
15
16
|
normalize_operator,
|
|
16
17
|
)
|
|
@@ -81,6 +82,7 @@ class SetOperatorValidationCheck(PolicyCheck):
|
|
|
81
82
|
# Second pass: Validate set operator usage
|
|
82
83
|
for operator, conditions in statement.condition.items():
|
|
83
84
|
base_operator, _operator_type, set_prefix = normalize_operator(operator)
|
|
85
|
+
has_ifexists = has_if_exists_suffix(operator)
|
|
84
86
|
|
|
85
87
|
if not set_prefix:
|
|
86
88
|
continue
|
|
@@ -110,15 +112,27 @@ class SetOperatorValidationCheck(PolicyCheck):
|
|
|
110
112
|
# Issue 2: ForAllValues with Allow effect without Null check (security risk)
|
|
111
113
|
if set_prefix == "ForAllValues" and effect == "Allow":
|
|
112
114
|
if condition_key not in null_checked_keys:
|
|
115
|
+
if has_ifexists:
|
|
116
|
+
message = (
|
|
117
|
+
f"Compounded security risk: `{operator}` with `Allow` effect "
|
|
118
|
+
f"on `{condition_key}` is doubly permissive. `ForAllValues` "
|
|
119
|
+
f"passes when the value set is empty, and `IfExists` passes "
|
|
120
|
+
f"when the key is missing entirely. Both mechanisms "
|
|
121
|
+
f"independently allow access without matching any values. "
|
|
122
|
+
f'Add: `"Null": {{"{condition_key}": "false"}}` and consider '
|
|
123
|
+
f"removing `IfExists`."
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
message = (
|
|
127
|
+
f"Security risk: `ForAllValues` with `Allow` effect on `{condition_key}` "
|
|
128
|
+
f"should include a `Null` condition check. Without it, requests with missing "
|
|
129
|
+
f'`{condition_key}` will be granted access. Add: `"Null": {{"{condition_key}": "false"}}`. '
|
|
130
|
+
f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
|
|
131
|
+
)
|
|
113
132
|
issues.append(
|
|
114
133
|
ValidationIssue(
|
|
115
134
|
severity="warning",
|
|
116
|
-
message=
|
|
117
|
-
f"Security risk: `ForAllValues` with `Allow` effect on `{condition_key}` "
|
|
118
|
-
f"should include a `Null` condition check. Without it, requests with missing "
|
|
119
|
-
f'`{condition_key}` will be granted access. Add: `"Null": {{"{condition_key}": "false"}}`. '
|
|
120
|
-
f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
|
|
121
|
-
),
|
|
135
|
+
message=message,
|
|
122
136
|
statement_sid=statement_sid,
|
|
123
137
|
statement_index=statement_idx,
|
|
124
138
|
issue_type="forallvalues_allow_without_null_check",
|
{iam_policy_validator-1.15.6 → iam_policy_validator-1.16.0}/iam_validator/core/check_registry.py
RENAMED
|
@@ -706,6 +706,7 @@ def create_default_registry(
|
|
|
706
706
|
# 3. TYPE VALIDATION (Condition operator type checking)
|
|
707
707
|
registry.register(checks.ConditionTypeMismatchCheck()) # Operator-value type compatibility
|
|
708
708
|
registry.register(checks.SetOperatorValidationCheck()) # ForAllValues/ForAnyValue usage
|
|
709
|
+
registry.register(checks.IfExistsConditionCheck()) # IfExists usage validation
|
|
709
710
|
|
|
710
711
|
# 4. RESOURCE MATCHING (Action-resource relationship validation)
|
|
711
712
|
registry.register(
|