Skip to content

Commit

Permalink
chore: migrate sms only MFA infra to Gen 2 (#5291)
Browse files Browse the repository at this point in the history
* chore: add new auth backend

* chore: add auth extension

* chore: add license headers

* chore: add mfa to env

* chore: add trigger to enable MFA

* chore: add infra for sms required

* chore: refactor tests for gen 2 backends

* chore: add backends to deploy script

* chore: package-lock for mfa-required-sms

* chore: remove bundling of @aws-crypto/client-node

* chore: fix formatting
  • Loading branch information
Jordan-Nelson authored Aug 14, 2024
1 parent c51445e commit 04406a5
Show file tree
Hide file tree
Showing 28 changed files with 423 additions and 150 deletions.
5 changes: 5 additions & 0 deletions infra-gen2/backends/auth/mfa-optional-sms/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# amplify
node_modules
.amplify
amplify_outputs*
amplifyconfiguration*
14 changes: 14 additions & 0 deletions infra-gen2/backends/auth/mfa-optional-sms/amplify/auth/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineAuth } from "@aws-amplify/backend";

export const auth = defineAuth({
loginWith: {
email: true,
},
multifactor: {
mode: "OPTIONAL",
sms: true,
},
});
25 changes: 25 additions & 0 deletions infra-gen2/backends/auth/mfa-optional-sms/amplify/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineBackend } from "@aws-amplify/backend";
import { addAuthUserExtensions } from "infra-common";
import { auth } from "./auth/resource";

const backend = defineBackend({
auth,
});

const resources = backend.auth.resources;
const { userPool, cfnResources } = resources;
const { stack } = userPool;
const { cfnUserPool } = cfnResources;

// Adds infra for creating/deleting users via App Sync and fetching confirmation
// and MFA codes from App Sync.
const customOutputs = addAuthUserExtensions({
name: "mfa-optional-sms",
stack,
userPool,
cfnUserPool,
});
backend.addOutput(customOutputs);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
17 changes: 17 additions & 0 deletions infra-gen2/backends/auth/mfa-optional-sms/amplify/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2022",
"module": "es2022",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"$amplify/*": [
"../.amplify/generated/*"
]
}
}
}
5 changes: 5 additions & 0 deletions infra-gen2/backends/auth/mfa-optional-sms/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "mfa-optional-sms",
"version": "1.0.0",
"main": "index.js"
}
5 changes: 5 additions & 0 deletions infra-gen2/backends/auth/mfa-required-sms/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# amplify
node_modules
.amplify
amplify_outputs*
amplifyconfiguration*
14 changes: 14 additions & 0 deletions infra-gen2/backends/auth/mfa-required-sms/amplify/auth/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineAuth } from "@aws-amplify/backend";

export const auth = defineAuth({
loginWith: {
email: true,
},
multifactor: {
mode: "REQUIRED",
sms: true,
},
});
25 changes: 25 additions & 0 deletions infra-gen2/backends/auth/mfa-required-sms/amplify/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineBackend } from "@aws-amplify/backend";
import { addAuthUserExtensions } from "infra-common";
import { auth } from "./auth/resource";

const backend = defineBackend({
auth,
});

const resources = backend.auth.resources;
const { userPool, cfnResources } = resources;
const { stack } = userPool;
const { cfnUserPool } = cfnResources;

// Adds infra for creating/deleting users via App Sync and fetching confirmation
// and MFA codes from App Sync.
const customOutputs = addAuthUserExtensions({
name: "mfa-required-sms",
stack,
userPool,
cfnUserPool,
});
backend.addOutput(customOutputs);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
17 changes: 17 additions & 0 deletions infra-gen2/backends/auth/mfa-required-sms/amplify/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2022",
"module": "es2022",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"$amplify/*": [
"../.amplify/generated/*"
]
}
}
}
5 changes: 5 additions & 0 deletions infra-gen2/backends/auth/mfa-required-sms/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "mfa-required-sms",
"version": "1.0.0",
"main": "index.js"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CfnUserPool, IUserPool } from "aws-cdk-lib/aws-cognito";
import { addCreateUserLambda } from "./create-user-lambda";
import { addCustomSenderLambda } from "./custom-sender-lambda";
import { addDeleteUserLambda } from "./delete-user-lambda";
import { addEnableSmsMfaLambda } from "./enable-sms-mfa-lambda";
import { addUserGraphql } from "./user-graphql";

type AmplifyOutputs = Parameters<BackendBase["addOutput"]>[0];
Expand All @@ -23,6 +24,7 @@ export const addAuthUserExtensions = ({
addCustomSenderLambda({ name, stack, cfnUserPool, graphQL });
addCreateUserLambda({ name, stack, userPool, graphQL });
addDeleteUserLambda({ name, stack, userPool, graphQL });
addEnableSmsMfaLambda({ name, stack, userPool, graphQL });
return {
data: {
aws_region: stack.region,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ export function addCustomSenderLambda({
"custom-email-sender.js"
),
runtime: Runtime.NODEJS_18_X,
bundling: {
nodeModules: ["@aws-crypto/client-node"],
},
environment: {
GRAPHQL_API_ENDPOINT: graphQL.graphqlUrl,
GRAPHQL_API_KEY: graphQL.apiKey!,
Expand All @@ -68,9 +65,6 @@ export function addCustomSenderLambda({
"custom-sms-sender.js"
),
runtime: Runtime.NODEJS_18_X,
bundling: {
nodeModules: ["@aws-crypto/client-node"],
},
environment: {
GRAPHQL_API_ENDPOINT: graphQL.graphqlUrl,
GRAPHQL_API_KEY: graphQL.apiKey!,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { Stack } from "aws-cdk-lib";
import { GraphqlApi, MappingTemplate } from "aws-cdk-lib/aws-appsync";
import { IUserPool } from "aws-cdk-lib/aws-cognito";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import path from "path";

export function addEnableSmsMfaLambda({
name,
stack,
graphQL,
userPool,
}: {
name: string;
stack: Stack;
graphQL: GraphqlApi;
userPool: IUserPool;
}) {
const enableSmsMfaLambda = new NodejsFunction(stack, `${name}-enableSmsMfa`, {
runtime: Runtime.NODEJS_18_X,
entry: path.resolve(
__dirname,
"..",
"lambda-triggers",
"enable-sms-mfa.js"
),
environment: {
USER_POOL_ID: userPool.userPoolId,
},
});

userPool.grant(enableSmsMfaLambda, "cognito-idp:AdminSetUserMFAPreference");

// Mutation.enableSmsMfa
const enableSmsMfaSource = graphQL.addLambdaDataSource(
"GraphQLApiEnableSmsMfaLambda",
enableSmsMfaLambda
);

enableSmsMfaSource.createResolver("MutationEnableSmsMfaResolver", {
typeName: "Mutation",
fieldName: "enableSmsMfa",
requestMappingTemplate: MappingTemplate.lambdaRequest(),
responseMappingTemplate: MappingTemplate.lambdaResult(),
});
}
54 changes: 54 additions & 0 deletions infra-gen2/infra-common/src/lambda-triggers/enable-sms-mfa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import * as cognito from "@aws-sdk/client-cognito-identity-provider";
import type * as lambda from "aws-lambda";

interface EnableSmsMfaRequest {
username: string;
}

interface EnableSmsMfaResponse {
success: boolean;
error?: string;
}

const USER_POOL_ID = process.env.USER_POOL_ID;
const CLIENT = new cognito.CognitoIdentityProviderClient({
region: process.env.REGION,
});

export const handler: lambda.AppSyncResolverHandler<
EnableSmsMfaRequest,
EnableSmsMfaResponse
> = async (
event: lambda.AppSyncResolverEvent<EnableSmsMfaRequest>
): Promise<EnableSmsMfaResponse> => {
console.log(`Got event: ${JSON.stringify(event, null, 2)}`);

const { username } = event.arguments;
console.log(`Enabling SMS MFA for user ${username}...`);
try {
const mfaParams: cognito.AdminSetUserMFAPreferenceCommandInput = {
UserPoolId: USER_POOL_ID,
Username: username,
SMSMfaSettings: {
Enabled: true,
PreferredMfa: true,
},
};
const resp = await CLIENT.send(
new cognito.AdminSetUserMFAPreferenceCommand(mfaParams),
);
console.log(`Successfully enabled MFA for ${username}`, resp);
return {
success: true,
};
} catch (err: any) {
console.log(`Could not enable MFA for ${username}`, err);
return {
success: false,
error: err.toString(),
};
}
};
14 changes: 14 additions & 0 deletions infra-gen2/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions infra-gen2/tool/deploy_gen2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ const List<AmplifyBackendGroup> infraConfig = [
identifier: 'phone-sign-in',
pathToSource: 'infra-gen2/backends/auth/phone-sign-in',
),
AmplifyBackend(
name: 'mfa-optional-sms',
identifier: 'mfa-opt-sms',
pathToSource: 'infra-gen2/backends/auth/mfa-optional-sms',
),
AmplifyBackend(
name: 'mfa-required-sms',
identifier: 'mfa-req-sms',
pathToSource: 'infra-gen2/backends/auth/mfa-required-sms',
),
],
),
AmplifyBackendGroup(
Expand Down
Loading

0 comments on commit 04406a5

Please sign in to comment.