Amazon web services 无法将lambda策略中的${cognito identity.amazonaws.com:sub}用于无服务器和DynamoDB/cognito/API网关
目标:Amazon web services 无法将lambda策略中的${cognito identity.amazonaws.com:sub}用于无服务器和DynamoDB/cognito/API网关,amazon-web-services,amazon-dynamodb,aws-api-gateway,amazon-cognito,serverless-framework,Amazon Web Services,Amazon Dynamodb,Aws Api Gateway,Amazon Cognito,Serverless Framework,目标: { "Version": "2012-10-17", "Statement": [ { "Action": [ "logs:CreateLogStream", "logs:CreateLogGroup" ],
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Resource": [
"arn:aws:logs:us-east-1:xxx:log-group:/aws/lambda/exeampleservice*:*"
],
"Effect": "Allow"
},
{
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-1:xxxx:log-group:/aws/lambda/exampleservice*:*:*"
],
"Effect": "Allow"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:<identity pool id>"
}
}
}
]
}
cognito identity.amazonaws.com:sub
查询的DynamoDB表的访问${cognito identity.amazonaws.com:sub}
。如果我用一个值手动指定dynamodb:LeadingKeys
,它可以正常工作。看来我只需要Cognito来正确地填充子值,我到处都找过了,找不到解决方案
我的lambda角色/策略(修改了从serverless生成的版本,使其具有带有Cognito和DynamoDB规则的信任策略):
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Resource": [
"arn:aws:logs:us-east-1:xxx:log-group:/aws/lambda/exeampleservice*:*"
],
"Effect": "Allow"
},
{
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-1:xxxx:log-group:/aws/lambda/exampleservice*:*:*"
],
"Effect": "Allow"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:<identity pool id>"
}
}
}
]
}
具有信任关系:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Resource": [
"arn:aws:logs:us-east-1:xxx:log-group:/aws/lambda/exeampleservice*:*"
],
"Effect": "Allow"
},
{
"Action": [
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-1:xxxx:log-group:/aws/lambda/exampleservice*:*:*"
],
"Effect": "Allow"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:<identity pool id>"
}
}
}
]
}
我已经尽了一切努力在策略中获取变量${cognito identity.amazonaws.com:sub}
,但似乎没有任何效果
有人知道如何解决这个问题吗?或者我可能会错过什么。(如果我遗漏了任何关键信息,我将更新更多信息)
谢谢
编辑:(其他信息)
我的登录函数(lambda+httpapi)如下所示,我通过用户/密码授权用户,然后调用CognitoIdentityCredentials“注册”我的身份并从池中获取我的身份ID。(我验证了我是在身份池向用户显示时注册的)
然后,我的登录调用以accessToken、idToken、identityId响应
我的所有其他API调用都在授权我的承载授权调用中使用idToken,但是似乎没有假定我的身份池的授权角色,而是使用我的lambda角色执行
我错过了什么?我原以为Cognito会处理身份验证池的假定角色,但似乎整个身份验证池?感谢您的帮助
我的请求上下文(从我的登录函数中,请注意标识对象中充满了空值):
我的登录功能
const AWS = require('aws-sdk');
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
global.fetch = require('node-fetch').default; // .default for webpack.
const USER_POOL_ID = process.env.USER_POOL_ID;
const USER_POOL_CLIENT_ID = process.env.USER_POOL_CLIENT_ID;
const USER_POOL_IDENTITY_ID = process.env.USER_POOL_IDENTITY_ID;
console.log('USER_POOL_ID', USER_POOL_ID);
console.log('USER_POOL_CLIENT_ID', USER_POOL_CLIENT_ID);
console.log('USER_POOL_CLIENT_ID', USER_POOL_IDENTITY_ID);
const poolData = {
UserPoolId: USER_POOL_ID,
ClientId: USER_POOL_CLIENT_ID,
};
const poolRegion = 'us-east-1';
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
function login(Username, Password) {
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({
Username,
Password,
});
var userData = {
Username,
Pool: userPool,
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
return new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: USER_POOL_IDENTITY_ID, // your identity pool id here
Logins: {
// Change the key below according to the specific region your user pool is in.
[`cognito-idp.${poolRegion}.amazonaws.com/${USER_POOL_ID}`]: result
.getIdToken()
.getJwtToken(),
},
});
//refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
AWS.config.credentials.refresh((error) => {
if (error) {
console.error(error);
} else {
// Instantiate aws sdk service objects now that the credentials have been updated.
// example: var s3 = new AWS.S3();
console.log('Successfully Refreshed!');
AWS.config.credentials.get(() => {
// return back all tokens and identityId in login call response body.
const identityId = AWS.config.credentials.identityId;
const tokens = {
accessToken: result.getAccessToken().getJwtToken(),
idToken: result.getIdToken().getJwtToken(),
refreshToken: result.getRefreshToken().getToken(),
identityId,
};
resolve(tokens);
});
}
});
},
onFailure: (err) => {
console.log(err);
reject(err);
},
});
});
}
module.exports = {
login,
};
我不太清楚您是否使用了身份(将您的ID令牌从用户池交换为STS令牌) 令人困惑的是,cognito identity.amazonaws.com:sub解析为ID池标识ID,而不是来自用户池的ID令牌中的主题ID。请参阅本页的“注释”部分:
要获取身份凭证,请查看,如果您将AWS网关与Lambda一起使用,则无法使用这些变量 您必须直接从使用IAM auth(使用类似aws amplify的东西)注册身份的客户端应用程序访问DynamoDB
我最终使用STS在lambda函数中扮演Cognito的组身份验证角色,并完全绕过身份池。@JDClark感谢您的响应。为了澄清,我正在获取标识的凭据,并在登录lambda函数中获取identityId。但我不确定下一步是什么。看起来我的IdToken和access token即使在之后仍然保持不变,而且最重要的是,cognito似乎没有承担由我的identity auth提供的角色,因为它似乎仍在使用我的lambda执行策略的假定角色。这里是我的登录功能,如果你有时间来看看。在上面的登录函数中,我登录并获得证书,但由于我是在邮递员中完成这项工作的,所以我只是在所有呼叫中使用承载人。如果我只是通过用户池传递从我的授权中提供的承载者,它会保持注册的身份吗?在将JWTs交换为凭据(作为GetCredentialsForIdentity API的一部分)时,您将收到回凭据(本质上是一个STS令牌,与您直接承担角色相同)。这些将与ID池确定的角色相关联(该角色的确定方式是可配置的)。然后,您可以使用此令牌使用sigv4对HTTP请求进行签名,并通过IAM授权人访问lambda,或创建AWS会话,以将服务用作令牌相关的角色等。如果您只使用默认会话,则它将与lambda的角色一起使用。