创建一个将 lambda 配置为触发器的 Cognito UserPool
Creating a Cognito UserPool with lambda's configured as triggers
我正在尝试使用 JavaScript SDK 从脚本以编程方式创建 Cognito 用户池。
我已经成功创建了用户池并通过在我的配置中指定相关 lambda 的 arn 定义了预注册和 post-确认触发器。 (根据 docs)
我的脚本如下所示:
const aws = require('aws-sdk');
const awsConfig = require('../config/config');
aws.config.update({ region: awsConfig.REGION });
const provider = new aws.CognitoIdentityServiceProvider();
// user provided args
const stage = process.argv[2];
if (!stage) {
process.stdout.write('Please provide stage as argument\n');
process.exit(1);
}
// generate arns for pre and post cognito triggers
const getArn = (lambdaName) => {
return `arn:aws:lambda:${awsConfig.REGION}:${awsConfig.AWS_ACCOUNT_ID}` +
`:function:my-project-name-${stage}-${lambdaName}`;
};
const preSignUp = getArn('preSignUp');
const postConfirmation = getArn('postConfirmation');
const userPoolConfig = {
PoolName: `mypool-${stage}`,
AutoVerifiedAttributes: ['email'],
Schema: [
{
"StringAttributeConstraints": {
"MaxLength": "2048",
"MinLength": "0"
},
"Mutable": true,
"Required": true,
"AttributeDataType": "String",
"Name": "email",
"DeveloperOnlyAttribute": false
}
],
LambdaConfig: {
PostConfirmation: postConfirmation,
PreSignUp: preSignUp
}
};
const callback = (err, resp) => {
if (err) {
process.stdout.write(`${err}\n`);
} else {
process.stdout.write(resp.UserPool.Id);
}
};
provider.createUserPool(userPoolConfig, callback);
当我 运行 此脚本成功创建用户池时,当我在控制台中检查它时,触发器设置正确。
当我尝试在我的用户池中注册用户时出现错误:
AccessDeniedException { code: 'UnexpectedLambdaException', ... }
如果我进入控制台并手动设置触发器,它就可以正常工作。
已报告此错误 - 但我没有看到确认信息,也没有看到解决方案:
https://github.com/aws/aws-cli/issues/2256
绝望地无法修复或找到解决方法。
我设法解决了这个问题。问题是 lambda 没有与 cognito 交互的正确权限。
我发现这段信息被隐藏了 here
因此,在创建用户池的回调函数中,我附加了正确的权限,如下所示:
const callback = (err, resp) => {
if (err) {
process.stdout.write(`${err}\n`);
} else {
const userPoolId = resp.UserPool.Id;
// the lambdas must have a permission attached that allows them to interact
// directly with cognito
const generateLambdaPersmission = (userPoolName, lambdaName) => {
return {
Action: 'lambda:InvokeFunction',
Principal: 'cognito-idp.amazonaws.com',
SourceArn: `arn:aws:cognito-idp:${awsConfig.REGION}:${awsConfig.AWS_ACCOUNT_ID}:userpool/${userPoolId}`,
FunctionName: getArn(lambdaName),
StatementId: `${stage}1`
};
};
lambda.addPermission(generateLambdaPersmission(userPoolId, 'preSignUp'), (err, resp) => {
if (err) {
process.stdout.write(`error attaching permission to lambda: ${err}`);
}
});
lambda.addPermission(generateLambdaPersmission(userPoolId, 'postConfirmation'), (err, resp) => {
if (err) {
process.stdout.write(`error attaching permission to lambda: ${err}`);
}
});
process.stdout.write(userPoolId);
}
};
请参阅有关通过 JavaScript SDK 添加权限的文档 here
如果您在云形成中设置了用户池和 lambda 触发器,则需要为用户池添加适当的权限以调用 lambda 函数。
您必须将类似的内容添加到您的云形成模板中。
"UserPoolPreSignupLambdaInvokePermission" : {
"Type" : "AWS::Lambda::Permission",
"Properties" : {
"Action" : "lambda:invokeFunction",
"Principal" : "cognito-idp.amazonaws.com",
"FunctionName" :{ "Ref" : "AutoVerifyEmailPreSignupLambdaFunction" },
"SourceArn" : {
"Fn::Sub" : "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${UserPool}"
}
}
}
如果您需要在 serverless.yml 文件中添加权限,那么这对我们有用。将其添加到您的资源部分:
UserPoolLambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:invokeFunction
Principal: cognito-idp.amazonaws.com
FunctionName: <function-name>
SourceArn: arn:aws:cognito-idp:<your region>:<your account>:userpool/*
这使所有用户池都能够调用您的特定功能。
您可以通过查看 .serverless/serverless-state.json 获取要使用的函数名称,然后在您的 lambda 中您会看到 FunctionName 属性.
我正在尝试使用 JavaScript SDK 从脚本以编程方式创建 Cognito 用户池。
我已经成功创建了用户池并通过在我的配置中指定相关 lambda 的 arn 定义了预注册和 post-确认触发器。 (根据 docs)
我的脚本如下所示:
const aws = require('aws-sdk');
const awsConfig = require('../config/config');
aws.config.update({ region: awsConfig.REGION });
const provider = new aws.CognitoIdentityServiceProvider();
// user provided args
const stage = process.argv[2];
if (!stage) {
process.stdout.write('Please provide stage as argument\n');
process.exit(1);
}
// generate arns for pre and post cognito triggers
const getArn = (lambdaName) => {
return `arn:aws:lambda:${awsConfig.REGION}:${awsConfig.AWS_ACCOUNT_ID}` +
`:function:my-project-name-${stage}-${lambdaName}`;
};
const preSignUp = getArn('preSignUp');
const postConfirmation = getArn('postConfirmation');
const userPoolConfig = {
PoolName: `mypool-${stage}`,
AutoVerifiedAttributes: ['email'],
Schema: [
{
"StringAttributeConstraints": {
"MaxLength": "2048",
"MinLength": "0"
},
"Mutable": true,
"Required": true,
"AttributeDataType": "String",
"Name": "email",
"DeveloperOnlyAttribute": false
}
],
LambdaConfig: {
PostConfirmation: postConfirmation,
PreSignUp: preSignUp
}
};
const callback = (err, resp) => {
if (err) {
process.stdout.write(`${err}\n`);
} else {
process.stdout.write(resp.UserPool.Id);
}
};
provider.createUserPool(userPoolConfig, callback);
当我 运行 此脚本成功创建用户池时,当我在控制台中检查它时,触发器设置正确。
当我尝试在我的用户池中注册用户时出现错误:
AccessDeniedException { code: 'UnexpectedLambdaException', ... }
如果我进入控制台并手动设置触发器,它就可以正常工作。
已报告此错误 - 但我没有看到确认信息,也没有看到解决方案:
https://github.com/aws/aws-cli/issues/2256
绝望地无法修复或找到解决方法。
我设法解决了这个问题。问题是 lambda 没有与 cognito 交互的正确权限。
我发现这段信息被隐藏了 here
因此,在创建用户池的回调函数中,我附加了正确的权限,如下所示:
const callback = (err, resp) => {
if (err) {
process.stdout.write(`${err}\n`);
} else {
const userPoolId = resp.UserPool.Id;
// the lambdas must have a permission attached that allows them to interact
// directly with cognito
const generateLambdaPersmission = (userPoolName, lambdaName) => {
return {
Action: 'lambda:InvokeFunction',
Principal: 'cognito-idp.amazonaws.com',
SourceArn: `arn:aws:cognito-idp:${awsConfig.REGION}:${awsConfig.AWS_ACCOUNT_ID}:userpool/${userPoolId}`,
FunctionName: getArn(lambdaName),
StatementId: `${stage}1`
};
};
lambda.addPermission(generateLambdaPersmission(userPoolId, 'preSignUp'), (err, resp) => {
if (err) {
process.stdout.write(`error attaching permission to lambda: ${err}`);
}
});
lambda.addPermission(generateLambdaPersmission(userPoolId, 'postConfirmation'), (err, resp) => {
if (err) {
process.stdout.write(`error attaching permission to lambda: ${err}`);
}
});
process.stdout.write(userPoolId);
}
};
请参阅有关通过 JavaScript SDK 添加权限的文档 here
如果您在云形成中设置了用户池和 lambda 触发器,则需要为用户池添加适当的权限以调用 lambda 函数。
您必须将类似的内容添加到您的云形成模板中。
"UserPoolPreSignupLambdaInvokePermission" : {
"Type" : "AWS::Lambda::Permission",
"Properties" : {
"Action" : "lambda:invokeFunction",
"Principal" : "cognito-idp.amazonaws.com",
"FunctionName" :{ "Ref" : "AutoVerifyEmailPreSignupLambdaFunction" },
"SourceArn" : {
"Fn::Sub" : "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${UserPool}"
}
}
}
如果您需要在 serverless.yml 文件中添加权限,那么这对我们有用。将其添加到您的资源部分:
UserPoolLambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:invokeFunction
Principal: cognito-idp.amazonaws.com
FunctionName: <function-name>
SourceArn: arn:aws:cognito-idp:<your region>:<your account>:userpool/*
这使所有用户池都能够调用您的特定功能。
您可以通过查看 .serverless/serverless-state.json 获取要使用的函数名称,然后在您的 lambda 中您会看到 FunctionName 属性.