AWS IAM SDK รับเอกสารนโยบายทั้งหมดสำหรับบทบาทเฉพาะเมื่อใช้บทบาทกลุ่ม Cognito
ฉันใช้กลุ่ม AWS Cognito User Pool เพื่อจัดการสิทธิ์สำหรับ API เกตเวย์ API ฉันเชื่อว่านี่เป็นการใช้งานที่ถูกต้องสำหรับ Groups ตามที่เอกสารระบุไว้ที่นี่:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html#using-groups-to-control-permission-with-amazon-api-gateway.
น่าเสียดายที่โดยพื้นฐานแล้วเอกสารนั้นไม่มีอยู่สำหรับกรณีการใช้งานนี้เท่าที่ฉันสามารถบอกได้ (นอกเหนือจากย่อหน้าเล็ก ๆ นั้น) ฉันกำลังพยายามหาวิธีการทำงานกับฟังก์ชัน Lambda ผู้เขียนเกตเวย์ API ที่กำหนดเอง ฉันได้สร้างบทบาทการทดสอบและกำหนดสิ่งนี้ให้กับกลุ่มทดสอบใน Cognito บทบาทนี้มีนโยบายเดียวที่แนบมา แต่ในอนาคตบทบาทจะมีหลายนโยบาย
ตอนนี้ในผู้สร้างที่กำหนดเองของฉันฉันกำลังตรวจสอบโทเค็นการเข้าถึงและอื่น ๆ อยู่แล้วและทุกอย่างก็ใช้ได้ดี ตอนนี้ฉันกำลังพยายามเพิ่มการควบคุมการเข้าถึงแบบละเอียดนี้โดยใช้กลุ่ม / บทบาท / นโยบาย ฉันได้ติดตั้ง IAM SDK แล้วและกำลังค้นหาว่าต้องโทรไปทางไหน ดูเหมือนว่าไม่มีวิธีง่ายๆในการเข้ามามีบทบาทและเป็นนโยบายทั้งหมด สิ่งที่ดีที่สุดที่ฉันได้มีดังต่อไปนี้:
public async Task<IEnumerable<string>> GetGroupPermissionsForUserAsync(Models.User user)
{
if (!user.UserAttributes.TryGetValue(UserAttributeName.UserPoolId, out var userPoolId))
{
return null;
}
var groups = await GetUserGroups(user.Username, userPoolId);
var groupRoleArn = groups.FirstOrDefault()?.RoleArn;
var policies = new List<string>();
if (!string.IsNullOrWhiteSpace(groupRoleArn))
{
var roleName = groupRoleArn.Substring(groupRoleArn.IndexOf('/') + 1);
var rolePoliciesResponse = await _iamClient.ListAttachedRolePoliciesAsync(new ListAttachedRolePoliciesRequest { RoleName = roleName });
foreach (var rolePolicy in rolePoliciesResponse.AttachedPolicies)
{
var policyVersionsResponse = await _iamClient.ListPolicyVersionsAsync(new ListPolicyVersionsRequest
{
PolicyArn = rolePolicy.PolicyArn
});
var latestPolicyVerson = policyVersionsResponse.Versions.OrderByDescending(x => x.CreateDate).LastOrDefault();
var policyVersionResponse = await _iamClient.GetPolicyVersionAsync(new GetPolicyVersionRequest
{
PolicyArn = rolePolicy.PolicyArn,
VersionId = latestPolicyVerson.VersionId
});
if (!string.IsNullOrWhiteSpace(policyVersionResponse?.PolicyVersion.Document))
{
policies.Add(HttpUtility.UrlDecode(policyVersionResponse.PolicyVersion.Document));
}
}
}
return policies;
}
private async Task<IEnumerable<GroupType>> GetUserGroups(string username, string userPoolId)
{
string nextToken = null;
var groups = new List<GroupType>();
do
{
var response = await _cognitoClient.AdminListGroupsForUserAsync(new AdminListGroupsForUserRequest
{
Username = username,
UserPoolId = userPoolId
});
groups.AddRange(response.Groups);
nextToken = response.NextToken;
} while (!string.IsNullOrWhiteSpace(nextToken));
return groups.OrderBy(x => x.Precedence);
}
อย่างที่คุณเห็นฉันต้องโทรหลายครั้งเพื่อรับนโยบายสำหรับบทบาท
_cognitoClient.AdminListGroupsForUserAsync
เพื่อรับกลุ่มของผู้ใช้จาก Cognito_iamClient.ListAttachedRolePoliciesAsync
เพื่อรับนโยบายที่เกี่ยวข้องกับบทบาท_iamClient.ListPolicyVersionsAsync
เพื่อรับเวอร์ชันสำหรับแต่ละนโยบาย_iamClient.GetPolicyVersionAsync
เพื่อรับเวอร์ชันนโยบายส่วนบุคคลซึ่งในที่สุดก็มีเอกสารนโยบาย
ListPolicyVersionsAsync
ส่งคืนการตอบกลับพร้อมคุณสมบัติเอกสาร แต่มักจะเป็นโมฆะด้วยเหตุผลบางประการดังนั้นจึงจำเป็นต้องมีการGetPolicyVersionAsync
โทรพิเศษ
สิ่งนี้ไม่เพียง แต่เพิ่มเวลาในการตอบสนอง (ซึ่งเป็นปัญหาในฟังก์ชั่นผู้เขียนที่ทุกการเรียก API จะทำงานผ่านรหัสนี้) แต่มันทำให้ฉันมีเพียงนโยบายส่วนบุคคลจำนวนมากซึ่งฉันจำเป็นต้องหลอกลวง ก่อนที่จะกลับไปที่ API Gateway
ไม่มีวิธีที่ง่ายกว่า / เร็วกว่านี้จริง ๆ หรือ มีวิธีรับข้อมูลทั้งหมดนี้ด้วยการโทรน้อยลงหรือไม่และมีวิธีทำให้นโยบายแบนราบในกรณีที่กฎทับซ้อนกันหรือไม่
คำตอบ
มีหลายวิธีในการตั้งค่าการอนุญาตด้วย Cognito และ API Gateway ซึ่งเป็นการยากที่จะบอกว่าอะไรจะดีที่สุดสำหรับคุณโดยไม่ทราบว่าทรัพยากร AWS ใดที่คุณพยายามเข้าถึงผ่านเมธอด API Gateway ของคุณ ตัวอย่างเช่นเมธอด API Gateway ของคุณผสานรวมกับเมธอดแลมบ์ดาที่เข้าถึงข้อมูลฐานข้อมูลหรือเรียกใช้บริการโดยตรงหรือไม่
ถ้าฉันเข้าใจถูกต้องคุณต้องการรวมสิทธิ์สำหรับ (ที่อาจเป็นไปได้) หลายกลุ่มที่ผู้ใช้อาจเป็นสมาชิกเพื่อที่จะได้รับสิทธิ์ชุดเดียวที่จะใช้สำหรับคำขอนั้น ๆ ดังนั้นuser
บทบาทอาจอนุญาตให้เข้าถึงข้อมูลผู้ใช้และadmin
บทบาทนี้อาจขยายการเข้าถึงไปยังปลายทางของผู้ดูแลระบบอื่น ๆ ต่อไป?
สมมติว่าคุณมีสถานการณ์ที่ค่อนข้างเป็นมาตรฐานที่เมธอด API Gateway ของคุณผสานรวมกับเมธอดแลมบ์ดาซึ่งกำลังเข้าถึงทรัพยากร AWS พื้นฐานเช่นฐานข้อมูลจากนั้นคุณสามารถใช้ Custom Authorizers ได้ดังนี้:
ช่วยลดความซับซ้อนของสิ่งต่างๆได้มากหาก Custom Authorizers เพียงแค่คืนสิทธิ์ที่จำเป็นในการเรียกใช้เมธอด API ที่ร้องขอ:
{
"principalId": "sub-from-ID-token",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": [
"arn:aws:execute-api:eu-west-1:1234567890:qwerty:prod:GET/user/address"
]
}
]
}
}
ในสถานการณ์จำลองมาตรฐานคำขอที่ได้รับอนุญาตที่ประสบความสำเร็จจะดำเนินการแลมบ์ดาที่มีตรรกะของ API แลมด้าสำรองนี้จะมีบทบาทในการดำเนินการซึ่งกำหนดสิทธิ์ทั้งหมดในการเข้าถึงทรัพยากรที่มีการป้องกันเช่นข้อมูลในตาราง DynamoDB เป็นต้นดังนั้นเมื่อใดก็ตามที่แลมบ์ดาสำรองของคุณเข้าถึงทรัพยากร AWS อื่นคุณไม่จำเป็นต้องอัปเดตสิทธิ์สำหรับ บทบาทของกลุ่มจำนวนหนึ่ง แต่คุณจะจัดการสิทธิ์เหล่านั้นที่ตำแหน่งเดียวในระบบของคุณแทน
ด้วยการตั้งค่านี้คุณสามารถมี Custom Authorizer ที่ค่อนข้างง่ายสำหรับแต่ละพื้นที่ของ API ของคุณที่ต้องการการปกป้อง
ตัวอย่างเช่นเพื่อป้องกัน/user/*
ปลายทางของคุณคุณสามารถมีผู้ให้สิทธิ์แบบกำหนดเองหนึ่งรายการที่ตรวจสอบเพื่อดูว่าโทเค็น ID ที่ส่งไปยัง Authorizer มีuser
กลุ่มในการcognito:groups
อ้างสิทธิ์หรือไม่ หากเป็นเช่นนั้นคุณจะคืนสิทธิ์ที่จำเป็นในการเรียกใช้เมธอด api ที่ร้องขอ ( execute-api:Invoke
) จากนั้นคุณอาจมีผู้กำหนดเองอื่นที่ปกป้อง/admin/*
เส้นทางของคุณโดยตรวจสอบว่าadmin
กลุ่มนั้นอยู่ในการcognito:groups
อ้างสิทธิ์ของโทเค็น ID หรือไม่เป็นต้น
การแคชการตอบสนองของ Authorizer ที่กำหนดเอง
ผู้ให้สิทธิ์ที่กำหนดเองแต่ละตัวมีการตั้งค่า TTL ที่เป็นทางเลือกซึ่งกำหนดระยะเวลาที่จะแคชการตอบกลับ (สำหรับโทเค็น JWT เฉพาะ) ซึ่งจะช่วยลดเวลาในการอุ่นเครื่องแลมบ์ดาหรือเวลาที่ใช้โดยข้อความเสริมเพิ่มเติมในเครื่องมือสร้าง
หาก Authorizer นำเสนอวิธีการต่างๆเช่น:
- รับ / ผู้ใช้ / ที่อยู่
- POST / ผู้ใช้ / ที่อยู่
- รับ / ผู้ใช้ / มือถือ
สิ่งสำคัญคือต้องทราบว่าการตอบกลับที่ได้รับอนุญาตที่ประสบความสำเร็จจะถูกแคชสำหรับวิธีการเหล่านี้ทั้งหมดจนกว่าการแคชจะหมดเวลา ดังนั้นนโยบายที่ส่งคืนโดยผู้ให้สิทธิ์ที่กำหนดเองจะต้องส่งคืนรายการทรัพยากรที่กำหนดวิธีการทั้งหมดที่ผู้ใช้สามารถดำเนินการได้หรือใช้สัญลักษณ์แทน
ตัวอย่างการตอบกลับสำหรับ Authorizer ที่ครอบคลุม/user/*
เส้นทางทั้งหมด
{
"principalId": "sub-from-ID-token",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": [
"arn:aws:execute-api:eu-west-1:1234567890:qwerty:prod:GET/user/address",
"arn:aws:execute-api:eu-west-1:1234567890:qwerty:prod:POST/user/address",
"arn:aws:execute-api:eu-west-1:1234567890:qwerty:prod:GET/user/mobile"
]
}
]
}
}
ตัวอย่างการตอบกลับ (โดยใช้สัญลักษณ์แทน) สำหรับ Authorizer ที่ครอบคลุม/user/*
เส้นทางทั้งหมด
{
"principalId": "sub-from-ID-token",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": [
"arn:aws:execute-api:eu-west-1:1234567890:qwerty:prod:*/user/*"
]
}
]
}
}