Skip to main content

Amazon Verified Permissions L2 CDK Construct

This repo contains the implementation of an L2 CDK Construct for Amazon Verified Permissions

Project Stability

This construct is still versioned with alpha/v0 major version and we could introduce breaking changes even without a major version bump. Our goal is to keep the API stable & backwards compatible as much as possible but we currently cannot guarantee that. Once we'll publish v1.0.0 the breaking changes will be introduced via major version bumps.

Getting Started

Policy Store

Define a Policy Store with defaults (No description, No schema & Validation Settings Mode set to OFF):

test = PolicyStore(scope, "PolicyStore")

Define a Policy Store without Schema definition (Validation Settings Mode must be set to OFF):

validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
test = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off
)

Define a Policy Store with Description and Schema definition (a STRICT Validation Settings Mode is strongly suggested for Policy Stores with schemas):

validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = {
    "PhotoApp": {
        "entity_types": {
            "User": {},
            "Photo": {}
        },
        "actions": {
            "view_photo": {
                "applies_to": {
                    "principal_types": ["User"],
                    "resource_types": ["Photo"]
                }
            }
        }
    }
}
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict,
    description="PolicyStore description"
)

Define a Policy Store with Validation Settings to OFF and Deletion Protection enabled:

validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
test = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off,
    deletion_protection=DeletionProtectionMode.ENABLED
)

Define a Policy Store with AWS owned key encryption (default behavior):

from cdklabs.cdk_verified_permissions import ValidationSettings, EncryptionSettings
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=ValidationSettings(
        mode=ValidationSettingsMode.OFF
    ),
    encryption_settings=EncryptionSettings(
        aws_owned_key=True
    )
)

Define a Policy Store with a customer-managed KMS key for encryption:

from cdklabs.cdk_verified_permissions import ValidationSettings, EncryptionSettings, KmsEncryptionSettings
key = kms.Key(scope, "PolicyStoreKey",
    description="Key for Verified Permissions Policy Store encryption"
)

policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=ValidationSettings(
        mode=ValidationSettingsMode.OFF
    ),
    encryption_settings=EncryptionSettings(
        customer_managed_key=KmsEncryptionSettings(
            key=key
        )
    )
)

Define a Policy Store with a customer-managed KMS key and encryption context:

from cdklabs.cdk_verified_permissions import ValidationSettings, EncryptionSettings, KmsEncryptionSettings
key = kms.Key(scope, "PolicyStoreKey",
    description="Key for Verified Permissions Policy Store encryption"
)

policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=ValidationSettings(
        mode=ValidationSettingsMode.OFF
    ),
    encryption_settings=EncryptionSettings(
        customer_managed_key=KmsEncryptionSettings(
            key=key,
            encryption_context={
                "department": "security",
                "project": "verified-permissions"
            }
        )
    )
)

Schemas

If you want to have type safety when defining a schema, you can accomplish this only in typescript. Simply use the Schema type exported by the @cedar-policy/cedar-wasm.

You can also generate simple schemas using the static functions schemaFromOpenApiSpec or schemaFromRestApi in the PolicyStore construct. This functionality replicates what you can find in the AWS Verified Permissions console.

Generate a schema from an OpenAPI spec:

validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = PolicyStore.schema_from_open_api_spec("path/to/swaggerfile.json", "UserGroup")
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict,
    description="Policy store with schema generated from API Gateway"
)

Generate a schema from a RestApi construct:

validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = PolicyStore.schema_from_rest_api(
    RestApi(scope, "RestApi"), "UserGroup")
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict,
    description="Policy store with schema generated from RestApi construct"
)

Identity Source

Define Identity Source with Cognito Configuration and required properties:

from cdklabs.cdk_verified_permissions import IdentitySourceConfiguration, CognitoUserPoolConfiguration
user_pool = UserPool(scope, "UserPool") # Creating a new Cognito UserPool
validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = {
    "PhotoApp": {
        "entity_types": {
            "User": {},
            "Photo": {}
        },
        "actions": {
            "view_photo": {
                "applies_to": {
                    "principal_types": ["User"],
                    "resource_types": ["Photo"]
                }
            }
        }
    }
}
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict
)
IdentitySource(scope, "IdentitySource",
    configuration=IdentitySourceConfiguration(
        cognito_user_pool_configuration=CognitoUserPoolConfiguration(
            user_pool=user_pool
        )
    ),
    policy_store=policy_store
)

Define Identity Source with Cognito Configuration and all properties:

from cdklabs.cdk_verified_permissions import IdentitySourceConfiguration, CognitoUserPoolConfiguration, CognitoGroupConfiguration
validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = {
    "PhotoApp": {
        "entity_types": {
            "User": {},
            "Photo": {}
        },
        "actions": {
            "view_photo": {
                "applies_to": {
                    "principal_types": ["User"],
                    "resource_types": ["Photo"]
                }
            }
        }
    }
}
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict
)
cognito_group_entity_type = "test"
user_pool = UserPool(scope, "UserPool") # Creating a new Cognito UserPool
IdentitySource(scope, "IdentitySource",
    configuration=IdentitySourceConfiguration(
        cognito_user_pool_configuration=CognitoUserPoolConfiguration(
            client_ids=["&ExampleCogClientId;"],
            user_pool=user_pool,
            group_configuration=CognitoGroupConfiguration(
                group_entity_type=cognito_group_entity_type
            )
        )
    ),
    policy_store=policy_store,
    principal_entity_type="PETEXAMPLEabcdefg111111"
)

Define Identity Source with OIDC Configuration and Access Token selection config:

from cdklabs.cdk_verified_permissions import IdentitySourceConfiguration, OpenIdConnectConfiguration, OpenIdConnectGroupConfiguration, OpenIdConnectAccessTokenConfiguration
validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = {
    "PhotoApp": {
        "entity_types": {
            "User": {},
            "Photo": {}
        },
        "actions": {
            "view_photo": {
                "applies_to": {
                    "principal_types": ["User"],
                    "resource_types": ["Photo"]
                }
            }
        }
    }
}
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict
)
issuer = "https://iamanidp.com"
principal_id_claim = "sub"
entity_id_prefix = "prefix"
group_claim = "group"
group_entity_type = "GroupType"
IdentitySource(scope, "IdentitySource",
    configuration=IdentitySourceConfiguration(
        open_id_connect_configuration=OpenIdConnectConfiguration(
            issuer=issuer,
            entity_id_prefix=entity_id_prefix,
            group_configuration=OpenIdConnectGroupConfiguration(
                group_claim=group_claim,
                group_entity_type=group_entity_type
            ),
            access_token_only=OpenIdConnectAccessTokenConfiguration(
                audiences=["testAudience"],
                principal_id_claim=principal_id_claim
            )
        )
    ),
    policy_store=policy_store,
    principal_entity_type="TestType"
)

Define Identity Source with OIDC Configuration and Identity Token selection config:

from cdklabs.cdk_verified_permissions import IdentitySourceConfiguration, OpenIdConnectConfiguration, OpenIdConnectGroupConfiguration, OpenIdConnectIdentityTokenConfiguration
validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
cedar_json_schema = {
    "PhotoApp": {
        "entity_types": {
            "User": {},
            "Photo": {}
        },
        "actions": {
            "view_photo": {
                "applies_to": {
                    "principal_types": ["User"],
                    "resource_types": ["Photo"]
                }
            }
        }
    }
}
cedar_schema = {
    "cedar_json": JSON.stringify(cedar_json_schema)
}
policy_store = PolicyStore(scope, "PolicyStore",
    schema=cedar_schema,
    validation_settings=validation_settings_strict
)
issuer = "https://iamanidp.com"
entity_id_prefix = "prefix"
group_claim = "group"
group_entity_type = "UserGroup"
principal_id_claim = "sub"
IdentitySource(scope, "IdentitySource",
    configuration=IdentitySourceConfiguration(
        open_id_connect_configuration=OpenIdConnectConfiguration(
            issuer=issuer,
            entity_id_prefix=entity_id_prefix,
            group_configuration=OpenIdConnectGroupConfiguration(
                group_claim=group_claim,
                group_entity_type=group_entity_type
            ),
            identity_token_only=OpenIdConnectIdentityTokenConfiguration(
                client_ids=[],
                principal_id_claim=principal_id_claim
            )
        )
    ),
    policy_store=policy_store
)

Policy

Load all the .cedar files in a given folder and define Policy objects for each of them. All policies will be associated with the same policy store. PLEASE NOTE: this method internally uses the Policy.fromFile so the same rules applies.

validation_settings_strict = {
    "mode": ValidationSettingsMode.STRICT
}
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_strict
)
policy_store.add_policies_from_path("/path/to/my-policies")

Define a Policy and add it to a specific Policy Store:

from cdklabs.cdk_verified_permissions import PolicyDefinitionProperty, StaticPolicyDefinitionProperty
statement = """permit(
    principal,
    action in [MyFirstApp::Action::"Read"],
    resource
) when {
    true
};"""

description = "Test policy assigned to the test store"
validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off
)

# Create a policy and add it to the policy store
policy = Policy(scope, "MyTestPolicy",
    definition=PolicyDefinitionProperty(
        static=StaticPolicyDefinitionProperty(
            statement=statement,
            description=description
        )
    ),
    policy_store=policy_store
)

Define a policy with a template linked definition:

from cdklabs.cdk_verified_permissions import PolicyDefinitionProperty, TemplateLinkedPolicyDefinitionProperty, EntityIdentifierProperty, EntityIdentifierProperty
validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off
)
policy_template_statement = """
permit (
  principal == ?principal,
  action in [TinyTodo::Action::"ReadList", TinyTodo::Action::"ListTasks"],
  resource == ?resource
);"""
template = PolicyTemplate(scope, "PolicyTemplate",
    statement=policy_template_statement,
    policy_store=policy_store
)

policy = Policy(scope, "MyTestPolicy",
    definition=PolicyDefinitionProperty(
        template_linked=TemplateLinkedPolicyDefinitionProperty(
            policy_template=template,
            principal=EntityIdentifierProperty(
                entity_id="exampleId",
                entity_type="exampleType"
            ),
            resource=EntityIdentifierProperty(
                entity_id="exampleId",
                entity_type="exampleType"
            )
        )
    ),
    policy_store=policy_store
)

Define a Policy with a statement from file: PLEASE NOTE:

  • The Policy.fromFile static method supports multiple Cedar policies per file. Every Policy must follow the standard Cedar rules. This means that every Policy must be terminated with a ; char.
  • You can specify the id of the Policy directly inside the Policy file through Cedar Annotations, using the annotation @cdkId. The id defined in the annotation will have priority with respect to the one passed in the Policy.fromFile method. In case no annotation is defined, the id passed in the Policy.fromFile method will be used. Since the Policy.fromFile method supports multiple Cedar policies per file, it is strongly suggested to define policy ids through the annotation, in order to avoid having many Policy Constructs with the same id (which will result in a CDK runtime error).
  • You can specify the description of the policy directly inside the Policy file, using the annotation @cdkDescription. The description defined in the annotation will have priority with respect to the one passed in the properties object of the Policy.fromFile method.
description = "Test policy assigned to the test store"
validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off
)

# Create a policy and add it to the policy store
policy_from_file_props = {
    "policy_store": policy_store,
    "path": "/path/to/policy-statement.cedar",
    "description": "the policy description"
}
policy = Policy.from_file(scope, "MyTestPolicy", policy_from_file_props)

Policy Store Alias

A Policy Store Alias provides an alternative identifier that you can use to reference a policy store in API operations. This operation is idempotent — if multiple requests are made with the same aliasName and policyStoreId, subsequent requests will be ignored.

Define a Policy Store Alias for an existing policy store:

from cdklabs.cdk_verified_permissions import ValidationSettings
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=ValidationSettings(
        mode=ValidationSettingsMode.OFF
    )
)

PolicyStoreAlias(scope, "PolicyStoreAlias",
    alias_name="my-app-production",
    policy_store=policy_store
)

Reference an existing Policy Store Alias:

alias = PolicyStoreAlias.from_alias_name(scope, "ImportedAlias", "my-app-production")

Policy Template

Define a Policy Template referring to a Cedar Statement in local file:

validation_settings_off = {
    "mode": ValidationSettingsMode.OFF
}
policy_store = PolicyStore(scope, "PolicyStore",
    validation_settings=validation_settings_off
)
template_from_file_props = {
    "policy_store": policy_store,
    "path": "/path/to/template-statement.cedar",
    "description": "Allows sharing photos in full access mode"
}
template = PolicyTemplate.from_file(scope, "PolicyTemplate", template_from_file_props)

Notes

Metadata

Release files for cdklabs.cdk-verified-permissions 0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cdklabs.cdk-verified-permissions 0.3.5
File Size Uploaded
cdklabs_cdk_verified_permissions-0.3.5.tar.gz 4.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for cdklabs.cdk-verified-permissions 0.3.5
File Interpreter ABI Platform
cdklabs_cdk_verified_permissions-0.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 9.1 MB

Release files / cdklabs_cdk_verified_permissions-0.3.5.tar.gz

Download URL cdklabs_cdk_verified_permissions-0.3.5.tar.gz
Size 4.5 MB
Tags Source
SHA-256 checksum
How to use checksums
63e4dfebabca1b0e248e38e941a9403771d06779882c63cb31e8971b2af9d6e5
BLAKE2b-256 checksum
How to use checksums
ae7cf8c91ba851a524f6865c39e24a6acbd528ad032c4ff7202d204848c63af4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.14.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 19, 2026.

Transparency log

Release files / cdklabs_cdk_verified_permissions-0.3.5-py3-none-any.whl

Download URL cdklabs_cdk_verified_permissions-0.3.5-py3-none-any.whl
Size 4.5 MB
Tags Python 3
SHA-256 checksum
How to use checksums
0d058d9df35b8574c823986a2e32712133870f485faa873f49aed8c6b890ca14
BLAKE2b-256 checksum
How to use checksums
7c43a668cfdb627414ab8c8f133f3628c98498be55af8947993947091000b6b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.14.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 19, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page