-
Notifications
You must be signed in to change notification settings - Fork 259
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
chore: migrate sms only MFA infra to Gen 2 #5291
Changes from all commits
67a72b9
1a029eb
325cacc
7cb880a
797ffd1
b5831c4
63c15a5
f689c6b
e7f3aac
f1151aa
ab80d47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# amplify | ||
node_modules | ||
.amplify | ||
amplify_outputs* | ||
amplifyconfiguration* |
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, | ||
}, | ||
}); |
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" | ||
} |
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/*" | ||
] | ||
} | ||
} | ||
} |
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" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# amplify | ||
node_modules | ||
.amplify | ||
amplify_outputs* | ||
amplifyconfiguration* |
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, | ||
}, | ||
}); |
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" | ||
} |
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/*" | ||
] | ||
} | ||
} | ||
} |
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 |
---|---|---|
|
@@ -44,9 +44,6 @@ export function addCustomSenderLambda({ | |
"custom-email-sender.js" | ||
), | ||
runtime: Runtime.NODEJS_18_X, | ||
bundling: { | ||
nodeModules: ["@aws-crypto/client-node"], | ||
}, | ||
Comment on lines
-47
to
-49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: This was causing an issue deploying the infra, and is not needed. It am not sure why it was not causing an issue previously. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the clean up. |
||
environment: { | ||
GRAPHQL_API_ENDPOINT: graphQL.graphqlUrl, | ||
GRAPHQL_API_KEY: graphQL.apiKey!, | ||
|
@@ -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!, | ||
|
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(), | ||
}); | ||
} |
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(), | ||
}; | ||
} | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Will this add the lambda to every backend that calls this method? Can this be optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it will add it to each env. It could be optional. So could the other lambdas. I think it is simpler to add all the lambdas to each env rather than try to remember which envs have which lambda. It doesn't really cost anything if it doesn't get invoked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't need to come from this PR, but it would be a nice optimization to have these be pulled in as needed. Besides reducing the amount of resources added to the AWS account, it may speed up deployment of the entire infra stack. May also prevent maintenance confusion by having the bare minimum for each env.