Dataset Permissions
Cognito based Dataset Permissions
It is possible to restrict access to Datasets for CRUD operations using configuration direct on a depot-cdk Dataset resource. The following operations can be configured with your desired access levels:
createreadupdatedelete
Access level configurations:
-
anonymous -
authenticated -
callerWithClaim -
withExpression -
callerWithCognitoGroup -
none -
Dataset access that does not meet the configured permission requirements via any of the Depot APIs will receive a
PermissionDeniedexception with HTTP status code 403. -
Dataset permissions are used as a fallback if specific Schema(s) do not have explicit permissions defined.
-
When no explicit permissions have been defined (at any object level), the default access allows authenticated users to access resources. i.e.
allowed = !anonymous. Taking this further, anonymous users are also able to view schemas (e.g. via GraphQL) but will not be able to execute those GQL queries.
The permissions across multiple resource levels are not merged: i.e. each Schema / Dataset / Environment permission set must be fully self-contained.
Requirements
The requirements to use Dataset Permissions that integrate with Cognito are:
- A Depot
CognitoLocation exists in the target environment. - A User schema named
Userexists for the target Dataset. - Auth is linked from the Cognito Location to the Dataset using the
auth.cognitoproperty.
Here is a sample in CDK for the Cognito Location and Dataset:
const cognitoRole = new Role(this, 'CognitoRole', {
assumedBy: new AccountPrincipal(depotEnvironment.accountId),
inlinePolicies: {
cognito: new PolicyDocument({
statements: [
new PolicyStatement({
effect: Effect.ALLOW,
actions: ['cognito-idp:*'],
resources: ["arn:aws:cognito-idp:eu-west-1:1234566789012:userpool/eu-west-1_ZzzzzZZ"]
})
]
})
}
});
const cognito = new Location.Cognito(this, "CognitoLocation", {
environment: depotEnvironment,
name: "cognito",
roleArn: cognitoRole.roleArn,
userPoolId: "eu-west-1_ZzzzzZZ",
clientId: "abc123456"
});
new Dataset(this, "Dataset", {
// etc...
auth: {
cognito: cognito.cognitoAuth
},
permissions: {
create: Permissions.authenticated(),
read: Permission.anonymous(),
// etc...
}
});
How to use Dataset Permissions
Use the depot-cdk Permission resource to access the functions to set access levels for each CRUD operation on your target Dataset.
For example, to allow anonymous access for read operations on a target dataset, you would set the following configuration:
new Dataset(stack, "DatasetWithAnonymousReadPermission", {
permissions: {
read: Permission.anonymous()
}
});
To only allow authenticated access, you would use the Permission.authenticated() function for the desired CRUD operation(s).
Cognito groups
The Permission.callerWithCognitoGroup() function is used to configure target CRUD operation access for a specific Cognito User Group. For example:
new Dataset(stack, "DatasetWithCongitoGroups", {
permissions: {
read: Permission.callerWithCognitoGroup("kennel_auditor"),
create: Permission.callerWithCognitoGroup("kennel_admin")
}
});
Custom permissions with expressions
You can fully customise permission configurations for CRUD operations on a target dataset by using the Permission.withExpression() function.
For example:
new Dataset(stack, "DatasetWithPermissionExpression", {
permissions: {
read: Permission.withExpression("'kennel_auditor' in caller.claims['cognito:group']"),
delete: Permission.withExpression("'kennel_admin' in caller.claims['cognito:group']"),
create: Permission.withExpression("'kennel_custodian' in caller.claims['cognito:group']")
}
});
No user access permissions
To prevent user access (anonymous or authenticated) - i.e. no user access at all, use the Permission.none() function.
No access will be allowed via any of the Depot APIs for the operations specified, aside from access via the Depot Lambda Gateway (which acts as a kind of superuser internally only).
For example:
new Dataset(stack, "DatasetWithNoUserAccess", {
permissions: {
read: Permission.none(),
delete: Permission.none(),
create: Permission.none(),
update: Permission.none()
}
});
Environment permissions
It is possible to configure default permissions on a Depot environment in the same style as on Datasets:
this.depotEnvironment = new depot.Environment(this, "DepotEnvironment", {
// etc...
permissions: {
create: Permissions.authenticated(),
read: Permission.anonymous(),
update: Permission.none(),
// etc...
}
});
Environment permissions are used only if Schema and Dataset have no permissions defined. The permissions are not merged: i.e. each Schema/Dataset/Environment permissions must be fully self-contained.
IAM Dataset Permissions
The DatasetPrincipalPermission depot-cdk resource provides:
- A custom resource that adds or removes AWS IAM principal permission grants to facilitate access to a dataset configured with IAM authentication (via the
Datasetresource propertyauth.iam).
IAM principals can be added directly on Dataset definitions in CDK (on the Dataset auth.iam.principals), however in cases where you might want to add principals to a 'remote' stack Dataset, you can use this resource, using the environment ID and dataset ID.
Example usage
Example:
new DatasetPrincipalPermission(stack, "MyDatasetPermission", {
environmentId: "environment123",
datasetId: "dataset123",
principal: "arn:aws:iam::123456789012:role/MyRoleName"
});
The IAM principal for a Dataset Principal Permission construct will be added and merged together with the target dataset's existing IAM principals.