Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for custom Lambda function email senders in Auth construct #2087

Merged
merged 124 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 107 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
743354e
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
ab7f76f
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
7c55adc
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
36727ba
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
aa2f7d9
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
0302517
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
0adf873
chore: add changeset
vigy02 Sep 19, 2024
a5b5d3c
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
753701a
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
955cecc
fix: clearing the .amplify/generated/env/ before synthesis
vigy02 Sep 19, 2024
2a2b188
Merge branch 'main' of https://github.com/vigy02/amplify-backend
vigy02 Sep 19, 2024
fc0be7e
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
6c916e0
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
cab3f1a
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
954e1c0
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
d9212d8
chore: add changeset
vigy02 Sep 20, 2024
c09e1ee
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
05e1fd5
fix: Clear generated env directory before shim generation
vigy02 Sep 20, 2024
7714224
Merge branch 'issue-dir-clean'
vigy02 Sep 20, 2024
91faece
Merge branch 'aws-amplify:main' into main
vigy02 Sep 20, 2024
5977d8f
Merge branch 'aws-amplify:main' into main
vigy02 Sep 23, 2024
4c6616b
Merge branch 'main' of github.com:vigy02/amplify-backend
vigy02 Sep 25, 2024
cb908ed
feat: adding custom lambda function trigger for email
vigy02 Oct 2, 2024
dbbb9b8
feat: adding custom lambda function trigger for email
vigy02 Oct 2, 2024
2f7e6e8
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
f981039
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
e5ada8b
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
2cc04a9
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
1794ad0
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
e6c6730
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
4471aec
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
2b17234
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
61e10d8
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
fdbc617
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
5806d7f
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
e1ca822
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
f012a51
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
cb8f50d
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
6e7ab39
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
8fdd181
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
2187829
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
c86be92
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
c5f6ad4
feat: adding custom lambda function trigger for email
vigy02 Oct 4, 2024
f8f1c6a
Merge branch 'main' of github.com:vigy02/amplify-backend
vigy02 Oct 7, 2024
b8bb5a2
Merge branch 'aws-amplify:main' into main
vigy02 Oct 7, 2024
8e3f47d
cleanup
vigy02 Oct 7, 2024
b291851
chore: removed unwanted changesets
vigy02 Oct 7, 2024
206ec4e
chore: preparing for merge
vigy02 Oct 7, 2024
ad776e7
chore: preparing for merge
vigy02 Oct 7, 2024
eb24c3e
chore: preparing for merge
vigy02 Oct 7, 2024
3283dfd
feat: added a functionality to translate auth-props for custom fucnti…
vigy02 Oct 9, 2024
eac8809
chore: added changeset
vigy02 Oct 9, 2024
d9d7cae
chore: added new API
vigy02 Oct 9, 2024
872f88b
feat: added a functionality to translate auth-props for custom fucnti…
vigy02 Oct 9, 2024
afe3d89
feat: added a test case to cover custom function in backend-auth
vigy02 Oct 9, 2024
c829edf
Merge branch 'aws-amplify:main' into main
vigy02 Oct 9, 2024
fbfc8fe
feat: added a test case to cover custom function in backend-auth
vigy02 Oct 9, 2024
a4d17e8
feat: added a test case to cover custom function in backend-auth
vigy02 Oct 9, 2024
699986b
feat: added a test case to cover custom function in backend-auth
vigy02 Oct 9, 2024
b22de18
feat: added a test case to cover custom function in backend-auth
vigy02 Oct 9, 2024
f43703d
feat: narrowed down the permission by updating the conditions
vigy02 Oct 9, 2024
d1ff4aa
Refactored the code
vigy02 Oct 10, 2024
3262d3f
Merge branch 'aws-amplify:main' into main
vigy02 Oct 10, 2024
15b2fbf
Refactored the code
vigy02 Oct 10, 2024
5e02689
added a test case for checking lambdaTrigger={} empty condition
vigy02 Oct 10, 2024
606570a
added a test case for checking lambdaTrigger={} empty condition
vigy02 Oct 10, 2024
1cce05c
Merge branch 'main' into e2e/vigy/feature/custom-email-function
vigy02 Oct 10, 2024
7a5629b
Merge Branch
vigy02 Oct 10, 2024
16e07ed
Merge branch 'main' into e2e/vigy/feature/custom-email-function
vigy02 Oct 10, 2024
029b4d0
Merge Branch
vigy02 Oct 11, 2024
57daf18
Merge Branch
vigy02 Oct 11, 2024
04bca21
Merge Branch
vigy02 Oct 11, 2024
7d48cbe
Merge Branch
vigy02 Oct 11, 2024
7847881
Merge Branch
vigy02 Oct 11, 2024
43b7da0
Merge Branch
vigy02 Oct 11, 2024
e0532f3
Merge Branch
vigy02 Oct 11, 2024
7c007da
Merge Branch
vigy02 Oct 11, 2024
9178e8b
Merge Branch
vigy02 Oct 11, 2024
570de9e
fixed the code to use addTrigger instead of manually setting up permi…
vigy02 Oct 14, 2024
8a272d1
added KMS Key for customEmailSender
vigy02 Oct 14, 2024
c558111
changed KMS key to not read-only
vigy02 Oct 14, 2024
37b6d5d
changed the test case to include lambdaArn
vigy02 Oct 14, 2024
324afb6
add a test case validation for KMS key
vigy02 Oct 14, 2024
10444c7
Merge branch 'main' of github.com:vigy02/amplify-backend
vigy02 Oct 14, 2024
0c04155
Merge branch 'main' into feature/custom-email-function
vigy02 Oct 14, 2024
36160e5
fixed the code to use addTrigger instead of manually setting up permi…
vigy02 Oct 14, 2024
fff5cde
added KMS Key for customEmailSender
vigy02 Oct 14, 2024
22b8840
changed KMS key to not read-only
vigy02 Oct 14, 2024
a1b4056
changed the test case to include lambdaArn
vigy02 Oct 14, 2024
1b1a263
add a test case validation for KMS key
vigy02 Oct 14, 2024
7e688f6
detect transform errors with multiple errors (#2102)
rtpascual Oct 11, 2024
4772b2e
Add minify option to defineFunction (#2093)
fossamagna Oct 11, 2024
1d64301
upgrade constructs (#2103)
sobolk Oct 11, 2024
49b46d6
Remove deprecated messages field from event (#2106)
sobolk Oct 11, 2024
7119b35
detect generic CFN stack creation errors (#2108)
rtpascual Oct 11, 2024
0480694
Fix cdk tests when new dependencies are shipped to npm. (#2107)
sobolk Oct 14, 2024
793927a
Merge branch 'main' into feature/custom-email-function
vigy02 Oct 15, 2024
7665597
Merge branch 'feature/custom-email-function' of github.com:vigy02/amp…
vigy02 Oct 15, 2024
487f586
API changes
vigy02 Oct 15, 2024
2267f2a
Merge branch 'main' into feature/custom-email-function
vigy02 Oct 23, 2024
38c05f5
Update API changes
vigy02 Oct 23, 2024
be0d21e
Merge branch 'aws-amplify:main' into feature/custom-email-function
vigy02 Oct 23, 2024
50f7e94
Added kmsKeyArn for custom user KMS keys
vigy02 Oct 24, 2024
984bd69
chore: added changesets and updated API's
vigy02 Oct 24, 2024
70ae8a1
chore: added changesets
vigy02 Oct 24, 2024
fe1aaf1
Added integration tests for customEmailSender
vigy02 Oct 25, 2024
e06162b
updated the API files to reflect master
vigy02 Oct 25, 2024
b8d54a6
feat: added customSenderEmail with types and added exceptions to esli…
vigy02 Oct 29, 2024
3b03d3c
Merge branch 'main' into feature/custom-email-function
vigy02 Oct 29, 2024
3df2842
chore: Updated API
vigy02 Oct 29, 2024
4f21f21
chore: Updated API
vigy02 Oct 29, 2024
c7e53cc
chore: updated API
vigy02 Oct 29, 2024
e7d335c
Delete packages/ai-constructs/API.md
vigy02 Oct 29, 2024
30ffca8
chore: Updated API
vigy02 Oct 29, 2024
7411f34
chore: delete unused file
vigy02 Oct 29, 2024
1c6bef9
chore: update changeset
vigy02 Oct 29, 2024
65cbf67
chore: update changeset
vigy02 Oct 29, 2024
3e898fc
chore: Updated API and changeSets
vigy02 Oct 30, 2024
445e0a3
chore: Updated the API from main
vigy02 Oct 30, 2024
e4f879b
API updates to resolve conflicting naming
vigy02 Oct 30, 2024
a26da97
Updated the types in backend-auth
vigy02 Oct 31, 2024
3e49d70
chore: Updated changesets
vigy02 Oct 31, 2024
f5da56c
Added custom Email handler function and refactored the types of auth-…
vigy02 Oct 31, 2024
223181c
chore: updated API
vigy02 Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/curvy-pans-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@aws-amplify/auth-construct': minor
'@aws-amplify/backend-auth': minor
---

Added custom user KMS key for customEmailSender
6 changes: 6 additions & 0 deletions .changeset/unlucky-chairs-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@aws-amplify/auth-construct': minor
'@aws-amplify/backend-auth': minor
---

feat: Add support for custom Lambda function email senders in Auth construct
4 changes: 3 additions & 1 deletion .eslint_dictionary.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,7 @@
"xlarge",
"yaml",
"yargs",
"zoneinfo"
"zoneinfo",
"SKey",
"decrypt"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please insert those in alphabetical order.

]
1 change: 1 addition & 0 deletions packages/ai-constructs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type ConversationHandlerFunctionProps = {
modelId: string;
region?: string;
}>;
memoryMB?: number;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might need to merge latest main. this change shouldn't be on the diff.

outputStorageStrategy?: BackendOutputStorageStrategy<AIConversationOutput>;
};

Expand Down
4 changes: 3 additions & 1 deletion packages/auth-construct/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AuthResources } from '@aws-amplify/plugin-types';
import { aws_cognito } from 'aws-cdk-lib';
import { BackendOutputStorageStrategy } from '@aws-amplify/plugin-types';
import { Construct } from 'constructs';
import { IFunction } from 'aws-cdk-lib/aws-lambda';
import { NumberAttributeConstraints } from 'aws-cdk-lib/aws-cognito';
import { ResourceProvider } from '@aws-amplify/plugin-types';
import { SecretValue } from 'aws-cdk-lib';
Expand Down Expand Up @@ -47,7 +48,8 @@ export type AuthProps = {
externalProviders?: ExternalProviderOptions;
};
senders?: {
email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'>;
email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | IFunction;
kmsKeyArn?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is kmsKeyArn applicable to any of Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> ?

If not then we should introduce type for custom sender.
Something like:
type CustomEmailSender = { handler: IFunction, kmsKeyArn?: string } and then use that instead of IFunction in the union.

Or perhaps have email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | IFunction | CustomEmailSender so that passing function without kmskey is still easy.

The bottom line is that we should find typing that doesn't let you specify kmsKeyArn if IFunction is not used.

@josefaidt wdyt ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good point, i think this would be enough:
email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | CustomEmailSender

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feedback makes sense. I like this take

email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | IFunction | CustomEmailSender

this is also simple, and easier to understand that you only have two valid configuration options (ses or a sender function with/without a custom kms key)

email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | CustomEmailSender

};
userAttributes?: UserAttributes;
multifactor?: MFA;
Expand Down
64 changes: 51 additions & 13 deletions packages/auth-construct/src/construct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
UserPoolIdentityProviderOidc,
UserPoolIdentityProviderSaml,
UserPoolIdentityProviderSamlMetadataType,
UserPoolOperation,
UserPoolProps,
} from 'aws-cdk-lib/aws-cognito';
import { FederatedPrincipal, Role } from 'aws-cdk-lib/aws-iam';
Expand All @@ -51,6 +52,8 @@ import {
StackMetadataBackendOutputStorageStrategy,
} from '@aws-amplify/backend-output-storage';
import * as path from 'path';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { IKey, Key } from 'aws-cdk-lib/aws-kms';

type DefaultRoles = { auth: Role; unAuth: Role };
type IdentityProviderSetupResult = {
Expand Down Expand Up @@ -131,6 +134,8 @@ export class AmplifyAuth
};
} = {};

private customEmailSenderKMSkey: IKey | undefined;

/**
* Create a new Auth construct with AuthProps.
* If no props are provided, email login and defaults will be used.
Expand All @@ -141,24 +146,39 @@ export class AmplifyAuth
props: AuthProps = DEFAULTS.IF_NO_PROPS_PROVIDED
) {
super(scope, id);

this.name = props.name ?? '';
this.domainPrefix = props.loginWith.externalProviders?.domainPrefix;

// UserPool
this.computedUserPoolProps = this.getUserPoolProps(props);

this.userPool = new cognito.UserPool(
this,
`${this.name}UserPool`,
this.computedUserPoolProps
);
/**
* Configure custom email sender for Cognito User Pool
* Grant necessary permissions for Lambda function to decrypt emails
* and allow Cognito to invoke the Lambda function
*/
if (
props.senders?.email &&
props.senders.email instanceof lambda.Function &&
this.customEmailSenderKMSkey
) {
this.customEmailSenderKMSkey.grantDecrypt(props.senders.email);
this.customEmailSenderKMSkey.grantEncrypt(props.senders.email);
this.userPool.addTrigger(
UserPoolOperation.of('customEmailSender'),
props.senders.email
);
}

// UserPool - External Providers (Oauth, SAML, OIDC) and User Pool Domain
this.providerSetupResult = this.setupExternalProviders(
this.userPool,
props.loginWith
);

// UserPool Client
const userPoolClient = new cognito.UserPoolClient(
this,
Expand Down Expand Up @@ -478,7 +498,24 @@ export class AmplifyAuth
},
{ standardAttributes: {}, customAttributes: {} }
);

if (props.senders?.kmsKeyArn) {
this.customEmailSenderKMSkey = Key.fromKeyArn(
this,
`${this.name}CustomSenderKey`,
props.senders.kmsKeyArn
);
} else if (
props.senders?.email &&
props.senders.email instanceof lambda.Function
) {
this.customEmailSenderKMSkey = new Key(
props.senders.email.stack,
`${this.name}CustomSenderKey`,
{
enableKeyRotation: true,
}
);
}
const userPoolProps: UserPoolProps = {
signInCaseSensitive: DEFAULTS.SIGN_IN_CASE_SENSITIVE,
signInAliases: {
Expand All @@ -503,15 +540,15 @@ export class AmplifyAuth
customAttributes: {
...customAttributes,
},
email: props.senders
? cognito.UserPoolEmail.withSES({
fromEmail: props.senders.email.fromEmail,
fromName: props.senders.email.fromName,
replyTo: props.senders.email.replyTo,
sesRegion: Stack.of(this).region,
})
: undefined,

email:
props.senders && 'fromEmail' in props.senders.email
? cognito.UserPoolEmail.withSES({
fromEmail: props.senders.email.fromEmail,
fromName: props.senders.email.fromName,
replyTo: props.senders.email.replyTo,
sesRegion: Stack.of(this).region,
})
: undefined,
selfSignUpEnabled: DEFAULTS.ALLOW_SELF_SIGN_UP,
mfa: mfaMode,
mfaMessage: this.getMFAMessage(props.multifactor),
Expand All @@ -528,6 +565,7 @@ export class AmplifyAuth
props.loginWith.email?.userInvitation
)
: undefined,
customSenderKmsKey: this.customEmailSenderKMSkey,
};
return userPoolProps;
};
Expand Down
10 changes: 8 additions & 2 deletions packages/auth-construct/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
UserPoolIdentityProviderSamlMetadata,
UserPoolSESOptions,
} from 'aws-cdk-lib/aws-cognito';
import { IFunction } from 'aws-cdk-lib/aws-lambda';
export type VerificationEmailWithLink = {
/**
* The type of verification. Must be one of "CODE" or "LINK".
Expand Down Expand Up @@ -417,11 +418,16 @@ export type AuthProps = {
*/
senders?: {
/**
* Configure Cognito to send emails from SES
* Configure Cognito to send emails from SES or a custom message trigger
* SES configurations enable the use of customized email sender addresses and names
* Custom message triggers enable the use of third-party email providers when sending email notifications to users
* @see https://docs.amplify.aws/react/build-a-backend/auth/moving-to-production/#email
* @see https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-email-sender.html
*/
email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'>;
email:
| Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'>
| IFunction;
kmsKeyArn?: string;
};
/**
* The set of attributes that are required for every user in the user pool. Read more on attributes here - https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html
Expand Down
1 change: 1 addition & 0 deletions packages/backend-ai/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type DefineConversationHandlerFunctionProps = {
modelId: string | AiModel;
region?: string;
}>;
memoryMB?: number;
};

// @public (undocumented)
Expand Down
8 changes: 7 additions & 1 deletion packages/backend-auth/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { AmazonProviderProps } from '@aws-amplify/auth-construct';
import { AmplifyFunction } from '@aws-amplify/plugin-types';
import { AppleProviderProps } from '@aws-amplify/auth-construct';
import { AuthProps } from '@aws-amplify/auth-construct';
import { AuthResources } from '@aws-amplify/plugin-types';
Expand All @@ -22,6 +23,7 @@ import { ResourceAccessAcceptorFactory } from '@aws-amplify/plugin-types';
import { ResourceProvider } from '@aws-amplify/plugin-types';
import { StackProvider } from '@aws-amplify/plugin-types';
import { TriggerEvent } from '@aws-amplify/auth-construct';
import { UserPoolSESOptions } from 'aws-cdk-lib/aws-cognito';

// @public
export type ActionIam = 'addUserToGroup' | 'createGroup' | 'createUser' | 'deleteGroup' | 'deleteUser' | 'deleteUserAttributes' | 'disableUser' | 'enableUser' | 'forgetDevice' | 'getDevice' | 'getGroup' | 'getUser' | 'listUsers' | 'listUsersInGroup' | 'listGroups' | 'listDevices' | 'listGroupsForUser' | 'removeUserFromGroup' | 'resetUserPassword' | 'setUserMfaPreference' | 'setUserPassword' | 'setUserSettings' | 'updateDeviceStatus' | 'updateGroup' | 'updateUserAttributes';
Expand All @@ -36,10 +38,14 @@ export type AmazonProviderFactoryProps = Omit<AmazonProviderProps, 'clientId' |
};

// @public (undocumented)
export type AmplifyAuthProps = Expand<Omit<AuthProps, 'outputStorageStrategy' | 'loginWith'> & {
export type AmplifyAuthProps = Expand<Omit<AuthProps, 'outputStorageStrategy' | 'loginWith' | 'senders'> & {
loginWith: Expand<AuthLoginWithFactoryProps>;
triggers?: Partial<Record<TriggerEvent, ConstructFactory<ResourceProvider<FunctionResources>>>>;
access?: AuthAccessGenerator;
senders?: {
email: Pick<UserPoolSESOptions, 'fromEmail' | 'fromName' | 'replyTo'> | ConstructFactory<AmplifyFunction>;
kmsKeyArn?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar feedback here. We should find better typing.

};
}>;

// @public
Expand Down
133 changes: 133 additions & 0 deletions packages/backend-auth/src/factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { Policy, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { AmplifyUserError } from '@aws-amplify/platform-core';
import { CfnFunction } from 'aws-cdk-lib/aws-lambda';
import { Key } from 'aws-cdk-lib/aws-kms';

const createStackAndSetContext = (): Stack => {
const app = new App();
Expand Down Expand Up @@ -355,6 +356,138 @@ void describe('AmplifyAuthFactory', () => {
});
});
});

void it('sets customEmailSender when function is provided as email sender', () => {
const testFunc = new aws_lambda.Function(stack, 'testFunc', {
code: aws_lambda.Code.fromInline('test placeholder'),
runtime: aws_lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
});
const funcStub: ConstructFactory<ResourceProvider<FunctionResources>> = {
getInstance: () => {
return {
resources: {
lambda: testFunc,
cfnResources: {
cfnFunction: testFunc.node.findChild('Resource') as CfnFunction,
},
},
};
},
};

resetFactoryCount();

const authWithTriggerFactory = defineAuth({
loginWith: { email: true },
senders: { email: funcStub },
});

const backendAuth = authWithTriggerFactory.getInstance(getInstanceProps);

const template = Template.fromStack(backendAuth.stack);

template.hasResourceProperties('AWS::Cognito::UserPool', {
LambdaConfig: {
CustomEmailSender: {
LambdaArn: {
Ref: Match.stringLikeRegexp('testFunc'),
},
},
KMSKeyID: {
'Fn::GetAtt': [Match.anyValue(), 'Arn'],
},
},
});
});
void it('ensures empty lambdaTriggers do not remove triggers added elsewhere', () => {
const testFunc = new aws_lambda.Function(stack, 'testFunc', {
code: aws_lambda.Code.fromInline('test placeholder'),
runtime: aws_lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
});
const funcStub: ConstructFactory<ResourceProvider<FunctionResources>> = {
getInstance: () => {
return {
resources: {
lambda: testFunc,
cfnResources: {
cfnFunction: testFunc.node.findChild('Resource') as CfnFunction,
},
},
};
},
};

resetFactoryCount();

const authWithTriggerFactory = defineAuth({
loginWith: { email: true },
senders: { email: funcStub },
triggers: { preSignUp: funcStub },
});

const backendAuth = authWithTriggerFactory.getInstance(getInstanceProps);

const template = Template.fromStack(backendAuth.stack);
template.hasResourceProperties('AWS::Cognito::UserPool', {
LambdaConfig: {
PreSignUp: {
Ref: Match.stringLikeRegexp('testFunc'),
},
CustomEmailSender: {
LambdaArn: {
Ref: Match.stringLikeRegexp('testFunc'),
},
},
KMSKeyID: {
'Fn::GetAtt': [Match.anyValue(), 'Arn'],
},
},
});
});
void it('uses provided KMS key ARN and sets up custom email sender', () => {
const customKmsKeyArn = new Key(stack, `CustomSenderKey`, {
enableKeyRotation: true,
});
const testFunc = new aws_lambda.Function(stack, 'testFunc', {
code: aws_lambda.Code.fromInline('test placeholder'),
runtime: aws_lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
});
const funcStub: ConstructFactory<ResourceProvider<FunctionResources>> = {
getInstance: () => ({
resources: {
lambda: testFunc,
cfnResources: {
cfnFunction: testFunc.node.findChild('Resource') as CfnFunction,
},
},
}),
};

resetFactoryCount();

const authWithTriggerFactory = defineAuth({
loginWith: { email: true },
senders: {
email: funcStub,
kmsKeyArn: customKmsKeyArn.keyArn,
},
triggers: { preSignUp: funcStub },
});

const backendAuth = authWithTriggerFactory.getInstance(getInstanceProps);
const template = Template.fromStack(backendAuth.stack);

template.hasResourceProperties('AWS::Cognito::UserPool', {
LambdaConfig: {
KMSKeyID: {
Ref: Match.stringLikeRegexp('CustomSenderKey'),
},
},
});
});
});

const upperCaseFirstChar = (str: string) => {
Expand Down
Loading
Loading