diff --git a/src/pages/gen2/build-a-backend/add-aws-services/overriding-resources/index.mdx b/src/pages/gen2/build-a-backend/add-aws-services/overriding-resources/index.mdx index 681493776b2..3069f8c5c6c 100644 --- a/src/pages/gen2/build-a-backend/add-aws-services/overriding-resources/index.mdx +++ b/src/pages/gen2/build-a-backend/add-aws-services/overriding-resources/index.mdx @@ -1,7 +1,6 @@ export const meta = { title: 'Overriding resources', - description: - 'Learn how to override resources.' + description: 'Learn how to override resources.' }; export function getStaticProps(context) { @@ -13,40 +12,103 @@ export function getStaticProps(context) { } -When defining resources you can access some underlying AWS CDK construct props to modify resource configurations. + -## Customize Cognito UserPool email verification settings +Using overrides may cause you to create a backend that the Amplify libraries or client config is unable to interpret properly. Always test changes in a staging environment. -```ts title="amplify/auth/resource.ts" -import { defineAuth } from "@aws-amplify/backend"; + -export const auth = defineAuth({ - loginWith: { - email: { - verificationEmailStyle: "CODE", - verificationEmailBody: (code: string) => - `Welcome! Your verification code is ${code}.`, - verificationEmailSubject: "Welcome! Here is your verification code", - }, - }, +When defining resources you can access some underlying [AWS Cloud Development Kit (CDK)](https://docs.aws.amazon.com/cdk/latest/guide/home.html) construct properties to modify resource configurations. This allows you to customize backend resources beyond what is offered via the `define*` functions. + +Overrides are defined in the `amplify/backend.ts` file after the `defineBackend` call has been made. + +```ts title="amplify/backend.ts" +// amplify/backend.ts +import { defineBackend } from '@aws-amplify/backend'; +import { auth } from './auth/resource'; +import { data } from './data/resource'; + +const backend = defineBackend({ + auth, + data +}); + +// overrides go here +``` + +The `backend` object exposes a `resources` property with objects for each of the components passed into the `defineBackend` function. Each of these resource objects exposes underlying L1 and L2 CDK Constructs that you can modify. + +For example, here is how you can access the Cognito UserPool that is created by `defineAuth` and set a custom removal policy on the resource. + +```ts title="amplify/backend.ts" +// amplify/backend.ts +import { defineBackend } from '@aws-amplify/backend'; +import { auth } from './auth/resource'; +import { UserPool } from 'aws-cdk-lib/aws-cognito'; +import { RemovalPolicy } from 'aws-cdk-lib'; + +const backend = defineBackend({ + auth }); + +const userPool = backend.resources.auth.resources.userPool as UserPool; +userPool.applyRemovalPolicy(RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE); ``` -Alternatively you can mutate the synthesized CDK constructs directly after setting them on your `backend`: +Most L1 and L2 CDK Constructs that are used by the `define*` functions are accessible in this way. + +## Example - Grant access permissions between resources + + + +**Under active development**: We are actively working to improve the experience of granting one resource access to another. For the time being, overrides can be used to achieve this. -## Override Cognito UserPool password policies + + +Consider the case that we want to grant a function created by `defineFunction` access to call the Cognito UserPool created by `defineAuth`. This can be accomplished with the following overrides. ```ts title="amplify/backend.ts" -import { Backend } from '@aws-amplify/backend'; +// amplify/backend.ts +import { defineBackend } from '@aws-amplify/backend'; import { auth } from './auth/resource'; +import { data } from './data/resource'; +import { demoFunction } from './functions/demo-function/resource'; +import { UserPool } from 'aws-cdk-lib/aws-cognito'; +import { Function } from 'aws-cdk-lib/aws-lambda'; -const backend = new Backend({ +const backend = defineBackend({ auth, + data, + demoFunction +}); + +const userPool = backend.resources.auth.resources.userPool as UserPool; +const lambdaFunction = backend.resources.demoFunction.resources + .lambda as Function; + +// grant the lambdaFunction read access to users +userPool.grant(lambdaFunction, 'cognito:GetUser', 'cognito:ListUsers'); + +// pass the Lambda the UserPool ID so that the Lambda can use it to make SDK calls +lambdaFunction.addEnvironment('USER_POOL_ID', userPool.userPoolId); +``` + +## Example - Mutate synthesized CloudFormation + +It's possible to reach all the way down to the raw CloudFormation to mutate properties using `addPropertyOverride` on a CDK Construct. To edit the password policies of the Cognito UserPool in `defineAuth`, you can use the following code. + +```ts +// amplify/backend.ts +import { defineBackend } from '@aws-amplify/backend'; +import { auth } from './auth/resource'; + +const backend = defineBackend({ + auth }); // override userpool password policies backend.resources.auth.resources.cfnResources.cfnUserPool.addPropertyOverride( - "Policies", + 'Policies', { PasswordPolicy: { MinimumLength: 10, @@ -54,41 +116,44 @@ backend.resources.auth.resources.cfnResources.cfnUserPool.addPropertyOverride( RequireNumbers: true, RequireSymbols: true, RequireUppercase: true, - TemporaryPasswordValidityDays: 20, - }, + TemporaryPasswordValidityDays: 20 + } } ); ``` +Note the usage of `auth.resources.cfnResources`. This property exposes [L1 CDK Constructs](https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_l1_using). These are constructs that map 1:1 with the underlying CloudFormation properties. -Below are additional example scenarios where you may want to override resources. - +The `auth.resources.cfnResources.cfnUserPool` property in the above example directly maps to the [AWS::Cognito::UserPool CloudFormation resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html). -## Add tags to resources +This is different than `auth.resources.userPool` in the first example which is an [L2 CDK Construct](https://docs.aws.amazon.com/cdk/v2/guide/constructs.html#constructs_using). These are constructs that provide a convenient interface around several related L1 constructs. -### Amplify Data's underlying GraphQL API +## Example - Add tags to resources ```ts title="amplify/backend.ts" -import { defineBackend } from "@aws-amplify/backend"; -import { auth } from "./auth/resource.js"; -import { data } from "./data/resource.js"; +// amplify/backend.ts +import { defineBackend } from '@aws-amplify/backend'; +import { auth } from './auth/resource'; +import { data } from './data/resource'; const backend = defineBackend({ auth, - data, + data }); backend.resources.data.resources.cfnResources.cfnGraphqlApi.addPropertyOverride( - "Tags", + 'Tags', [ { - Key: "graphqlapi-tag-1", - Value: "graphql-tag-value-1", + Key: 'graphqlapi-tag-1', + Value: 'graphql-tag-value-1' }, { - Key: "graphqlapi-tag-2", - Value: "graphql-tag-value-2", - }, + Key: 'graphqlapi-tag-2', + Value: 'graphql-tag-value-2' + } ] ); ``` + +For even more customization of your backend, see [custom resources](/gen2/build-a-backend/add-aws-services/custom-resources)