我想要实现的是:
我有一个Cognito用户池,我有一些用户和一些组。我希望某些用户可以访问API网关功能,一些用户可以访问某些功能,而其他用户则无法访问。
我做了什么:
我创建了三个组,并将用户分配给每个组。我给每个小组一个IAM角色,并给每个角色一个特殊的政策。所有用户的组权限如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "execute-api:*",
"Resource": "*"
}
]
}
我通过Serverless框架创建了Lambda函数和API网关资源。我将authorizer设置为Cognito用户池authorizer。
(我尝试了几种不同的方法,比如使用联合身份,但似乎效果不佳(
我的结果是什么:
所有用户都可以完全访问API网关。给定的权限似乎对每个用户的访问没有任何影响。
帮助:我做错了什么?我该如何实现我的目标?
只有当您使用Cognito Federated Identity
为用户生成凭据时,附加到user pool group
的角色才会出现。将组添加到用户池
IAM角色及其权限与临时AWS绑定Amazon Cognito身份池提供的凭据经过身份验证的用户。组中的用户将自动分配当AWS凭据由亚马逊提供时,组的IAM角色使用Choose role from token选项识别联合身份。
所以基本上
- 创建一个连接到用户池的
identity pool
- 将API网关的授权更改为
IAM
- 登录用户池后,用户
id_token
生成federated identity
- 使用此标识(
secret key + access key + token
(对API网关进行授权
现在您的角色应该受到尊重。但请注意,您将被要求自行生成AWS SigV4凭据,因为出于某种原因,这不是现成的。我最终在浏览器中使用了aws签名网络。
PS:您的角色似乎提供了对API网关的全面访问。你也需要解决这个问题。例如,我用来限制访问一个API端点的示例角色
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Resource": [
"arn:aws:execute-api:us-east-2:<aws account id>:<API id>/*/*/acc/*"
],
"Effect": "Allow"
}
]
}
生成federated identity
的示例代码
function getAccessToken(idToken, idenPoolId, userPool) {
let region = idenPoolId.split(":")[0];
let provider = "cognito-idp." + region + ".amazonaws.com/" + userPool;
let login = {};
login[provider] = idToken;
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
Logins: login
});
//call refresh method in order to authenticate user and get new temp credentials
credentials.get((error) => {
if (error) {
console.error(error);
//let response = {
// statusCode: 500,
// body: JSON.stringify(error)
//};
return null;
} else {
console.log('Successfully logged!');
console.log('AKI:'+ credentials.accessKeyId);
console.log('AKS:'+ credentials.secretAccessKey);
console.log('token:' + credentials.sessionToken);
let response = JSON.stringify({
'AKI': credentials.accessKeyId,
'AKS': credentials.secretAccessKey,
'token': credentials.sessionToken
});
return response;
}
});
}
我有一个更好的解决方案,您不需要IAM。
只需将一对{username, serviceName}
保存在S3或DB中即可。所以每次,你都会收到一个服务请求:
- 检查用户是否获得授权(来自Cognito(
- 检查用户是否获得服务授权(S3、MySQL、RDS等(
为什么我认为它更好
因为从服务中添加/删除用户,所以您不需要以管理员身份登录IAM。希望以后,您可以创建一个用于管理的仪表板。
工作流程
UserA
向您的securityApi
发送请求-
SecurityApi
检查令牌是否被授权(用户是否有效(。 -
如果
UserA
有效,则securityApi
将用户的username
(可以从令牌的有效载荷中获得(和service name
发送到DB,以查看用户是否可以访问该用户。例如Mysql(使用RDS(:SELECT username from ServiceX LIMIT 1 WHERE username = "xyz";
-
如果通过了第二步或第三步,则用户为1。有效用户和2。有权使用该服务。如果用户在步骤2或3中失败,则用户无权使用该服务。