20.2
Condition, Resource Policy, Boundary আর পুরো Evaluation Logic
condition key, S3 bucket ARN বনাম object ARN, role বনাম resource policy, permission boundary, আর AWS শুরু থেকে শেষ পর্যন্ত কীভাবে সিদ্ধান্ত নেয়।
28 মিনিট পড়া + Animation
টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।
এই লেসন শেষে তুমি পারবে
- যেকোনো
Conditionblock পড়তে আর লিখতে: operator, key, value, একাধিক key আর একাধিক value কীভাবে মেলে, আর key না থাকলে কী হয়। - পরীক্ষায় যে global condition key-গুলো আসে (
aws:SourceIp,aws:RequestedRegion,aws:MultiFactorAuthPresent,aws:PrincipalOrgID, tag-এর key,aws:SecureTransport) আর service-এর নিজস্ব keyec2:ResourceTag,s3:prefix,iam:PermissionsBoundaryব্যবহার করতে, আর কোনটা কোথায় ভেঙে পড়ে তা জানতে। - Tag দিয়ে attribute-based access control (ABAC) বানাতে, আর tag-গুলোকেই পাহারা দিতে।
- এমন S3 policy লিখতে যেখানে bucket-level আর object-level action ঠিক ঠিক ARN-এর সঙ্গে জোড়া পায়।
- Cross-account access-এর জন্য IAM role আর resource-based policy-র মধ্যে বাছতে, আর বোঝাতে কেন role নিলে নিজের permission ছেড়ে দিতে হয়।
- Permissions boundary দিয়ে developer-দের নিরাপদে role বানাতে দিতে, আর boundary কীভাবে SCP, session policy আর resource-based policy-র সঙ্গে মেশে তা জানতে।
- যেকোনো request হাতে-কলমে যাচাই করতে, এক account-এ বা দুই account জুড়ে, RCP, SCP, boundary আর session policy সহ, আর production-এ যাওয়ার আগে policy পরীক্ষা করতে।
#লেসন ২.২ যেখানে থেমেছিল
লেসন ২.২-এ শিখেছ সেই তিন নিয়ম যা প্রতিটা request মানে: শুরুতে সবকিছু deny, একটা explicit Allow সেই default তুলে দেয়, আর একটা explicit Deny সব Allow-কে হারিয়ে দেয়। Owner-এর নোট শুরুই হয় এর প্রমাণ দিয়ে: এক user আছে Group A-তে (S3 পড়া-লেখার Allow) আর Group B-তে (S3-এ Deny), ফল deny, কারণ group-এর কোনো অগ্রাধিকার নেই আর একটা মিলে যাওয়া Deny-ই জেতে; Group B যদি S3 নিয়ে চুপ থাকে, তবে Group A-র Allow কাজ করে। লেসন ২.২ ছয় ধরনের policy-র তালিকা দিয়েছে, এক account-এর পুরো flow দেখিয়েছে, আর SCP আর boundary-র একটা ঝলক দিয়েছে।
এই লেসন চারটা জিনিসে আরও গভীরে যায়, যেগুলো ওই সহজ ছবিটাকে আসল পরীক্ষার প্রশ্নে বদলে দেয়:
- Condition: policy-র সেই অংশ যা ঠিক করে একটা statement কখন আর কীভাবে খাটবে।
- Resource: S3-এর bucket বনাম object-এর ফাঁদ, আর
aws:PrincipalOrgIDসহ resource-based policy। - Role বনাম resource-based policy: account-এর সীমানা পেরোনোর দুটো পথ, যাদের আচরণ একেবারে আলাদা।
- সীমা: permissions boundary, session policy, আর SCP ও RCP (এদের organization কাঠামো লেসন ২০.১-এ) কীভাবে পুরো evaluation flow-তে বসে, এক account-এ আর দুই account জুড়ে।
#Condition: গভীরে
নোটে বলা আছে Condition block হলো policy-র সবচেয়ে শক্তিশালী অংশ, আর কথাটা ঠিক। User আর resource বলে কে কী করতে পারবে; condition বলে কখন আর কীভাবে: শুধু অফিসের network থেকে, শুধু MFA থাকলে, শুধু একটা Region-এ, শুধু তোমার team-এর tag লাগানো resource-এ।
#গঠন: operator, key, value
প্রতিটা condition-এর তিনটা অংশ (লেসন ২.১-এ পরিচয় হয়েছে):
"Condition": {
"StringEquals": { "aws:RequestedRegion": ["eu-west-1", "ap-south-1"] },
"Bool": { "aws:SecureTransport": "true" }
}
- Operator (
StringEquals,Bool) বলে কীভাবে তুলনা হবে। - Key (
aws:RequestedRegion) হলো request context-এর একটা তথ্য: প্রতিটা call নিয়ে AWS যে তথ্যের পোঁটলা জড়ো করে (কে, কোথা থেকে, কখন, কোন credential দিয়ে, কোন resource-এ, কোন tag সহ)। - Value হলো যার সঙ্গে ওই তথ্য মেলানো হবে।
মেলানোর নিয়ম এক টেবিলেই ধরে যায়:
Condition block-এর ভেতরে | যুক্তি | উদাহরণ |
|---|---|---|
| একাধিক operator | AND | Region মেলে এবং TLS ব্যবহার হয়েছে |
| এক operator-এর নিচে একাধিক key | AND | "StringEquals": {"aws:RequestedRegion": "eu-west-1", "aws:PrincipalTag/team": "data"} |
| এক key-র একাধিক value | OR | Region eu-west-1 অথবা ap-south-1 |
| একাধিক statement | প্রত্যেকটা আলাদা করে যাচাই হয় | অফিসের জন্য একটা Allow statement, VPN-এর জন্য আরেকটা |
দুই আলাদা key-র মধ্যে “A অথবা B” লাগলে (অফিস থেকে অথবা MFA দিয়ে), এক condition block-এ লেখা যায় না: দুটো statement লেখো।
#Operator-গুলো
| পরিবার | Operator | সাধারণ key | সাবধান |
|---|---|---|---|
| String | StringEquals, StringNotEquals, StringEqualsIgnoreCase, StringLike (*, ?), StringNotLike | aws:RequestedRegion, aws:PrincipalTag/team, s3:prefix | IgnoreCase না দিলে বড়-ছোট হাতের অক্ষর আলাদা; wildcard শুধু Like-এ |
| Numeric | NumericEquals, NumericLessThan, NumericGreaterThanEquals… | aws:MultiFactorAuthAge, s3:max-keys | মান লেখা হয় string হিসেবে: "3600" |
| Date | DateLessThan, DateGreaterThan… | aws:CurrentTime, aws:TokenIssueTime | ISO 8601 বা epoch সময় |
| Boolean | Bool | aws:SecureTransport, aws:MultiFactorAuthPresent, aws:ViaAWSService | key না থাকা মানে false না |
| IP address | IpAddress, NotIpAddress | aws:SourceIp | শুধু public address; VPC endpoint দিয়ে এলে থাকে না |
| ARN | ArnEquals, ArnLike, ArnNotLike | aws:SourceArn, aws:PrincipalArn | ARN-এর প্রতিটা অংশ আলাদা করে মেলে |
| আছে কি নেই | Null | যেকোনো key | "Null": {"aws:TokenIssueTime": "true"} মানে “key-টা নেই” |
| Modifier | Null বাদে যেকোনো operator-এর শেষে …IfExists | যে key কখনো থাকে, কখনো থাকে না | key না থাকলে মিল ধরা হয় |
| Set operator | operator-এর আগে ForAnyValue:, ForAllValues: | বহু-মানের key: aws:TagKeys, aws:CalledVia, aws:PrincipalOrgPaths | বহু-মানের key-তে লাগবেই; এক-মানের key-তে কখনো না |
#Key না থাকলে কী হয়
অবাক করা condition-ফলের বেশিরভাগ এই এক নিয়মেই ব্যাখ্যা হয়, তাই হুবহু মনে রাখো। IAM User Guide অনুযায়ী:
- স্বাভাবিক operator-এ key না থাকলে ফল false।
aws:SourceIpছাড়া request-এIpAddressমেলে না। - উল্টো (negated) operator-এ (
NotIpAddress,StringNotEquals,ArnNotLike…) key না থাকলে ফল true। address-ই যখন নেই, তখন “address অফিসের না” কথাটাকে সত্যি ধরা হয়। …IfExistsoperator-এ key না থাকলে ফল true: “থাকলে যাচাই করো, না থাকলে মাথা ঘামিও না”।Nullখোদ উপস্থিতিটাই যাচাই করে:true= নেই,false= আছে।
এর সঙ্গে statement-এর effect মেলালে চারটা আচরণ মনে রাখার মতো:
| Statement | Key নেই | Request-এর ওপর প্রভাব |
|---|---|---|
| Allow + স্বাভাবিক operator | condition false | Allow খাটে না: প্রায়ই implicit deny |
Allow + …IfExists | condition true | Allow খাটে |
| Deny + উল্টো operator | condition true | deny, প্রায়ই অবাক করে |
Deny + স্বাভাবিক operator (Bool false) | condition false | Deny খাটে না: পাহারা ফাঁকি দিয়ে পার |
#নোটের তিনটা পরীক্ষার scenario
নোটে তিনটা কথা আছে যা শুনলেই মাথায় আসা উচিত “Condition element”, আর slide-ও একই key দেখায়:
| পরীক্ষার কথা | Key | উত্তরের ধরন |
|---|---|---|
| “Restrict API calls to the corporate IP range” | aws:SourceIp | NotIpAddress সহ Deny, অথবা IpAddress সহ Allow |
| “Force MFA for deleting an S3 bucket” | aws:MultiFactorAuthPresent | BoolIfExists false সহ s3:DeleteBucket-এ Deny (অথবা Bool true সহ Allow) |
| “Allow EC2 creation only in eu-west-1” | aws:RequestedRegion | অনুমোদিত Region-এর সঙ্গে StringNotEquals সহ Deny, global service বাদ দিয়ে (লেসন ২.২-এর Region পাহারা) |
#aws:SourceIp, VPC endpoint আর AWS service
aws:SourceIp-এ থাকে request যে public address থেকে এসেছে সেটা। দুটো খুব সাধারণ পথে তোমার নিয়ন্ত্রণের এমন কোনো address থাকে না:
- VPC endpoint দিয়ে (লেসন ২২.২): key-টা request context-এ থাকেই না। Deny +
NotIpAddressপাহারা থাকলে, উল্টো operator-এ key না থাকায় ফল true, তাই তোমার নিজের private server-ই deny খায়। এদের মেলাওaws:SourceVpce(endpoint ID),aws:SourceVpc(VPC ID) বাaws:VpcSourceIp(private address, সবসময় বাকি দুটোর একটার সঙ্গে) দিয়ে। - তোমার হয়ে কোনো AWS service (CloudFormation resource বানাচ্ছে, Athena তোমার identity দিয়ে S3 পড়ছে): লক্ষ্য service দেখে ডাকা service-এর address। IAM docs সোজাসুজি বলে: এমন call-এ
aws:SourceIpব্যবহার কোরো না। এভাবে করা request-এ (forward access session)aws:ViaAWSService=trueথাকে আরaws:CalledVia-তে service-গুলোর নাম থাকে, তাই Deny-তে"Bool": {"aws:ViaAWSService": "false"}যোগ করলে এরা ছাড় পায়। আর service যখন নিজেই principal (যেমন CloudTrail log লিখছে), তখন মেলানোর key হলোaws:PrincipalIsAWSService।
তাই অফিস পাহারার ঠিক করা রূপ এরকম। তিনটা condition AND হিসেবে পড়ো: deny শুধু তখন, যখন call অফিস থেকে না, এবং আমাদের endpoint দিয়ে না, এবং আমাদের হয়ে কোনো service-ও করছে না।
{
"Sid": "DenyOutsideOfficeAndEndpoint",
"Effect": "Deny",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::payroll-example", "arn:aws:s3:::payroll-example/*"],
"Condition": {
"NotIpAddress": { "aws:SourceIp": "203.0.113.0/24" },
"StringNotEquals": { "aws:SourceVpce": "vpce-0a1b2c3d" },
"Bool": { "aws:ViaAWSService": "false" }
}
}
একটা IP নিয়ম, S3 call করার পাঁচটা পথ
Payroll bucket-এ একটা পাহারা বসানো: যে request-এর aws:SourceIp মতিঝিল head office-এর 203.0.113.0/24 range-এর না, সেটা deny। দেখো কোন call পার পায়, আর কোনগুলো অবাক করে আটকে যায়।
পরিস্থিতি
স্বাভাবিক ঘটনা: অফিসের range থেকে সরাসরি call।
Request context
aws:SourceIp
203.0.113.25
aws:SourceVpce
(নেই)
aws:ViaAWSService
false
Head office-এর একজন accountant একটা payslip file নামাচ্ছেন। request বের হয় অফিসের public address 203.0.113.25 দিয়ে, তাই AWS request context-এ aws:SourceIp হিসেবে ওই address-টাই বসায়।
#Bool বনাম BoolIfExists: না থাকা মানে false না
লেসন ২.৩-এ MFA-র টেবিল দেখেছ; এবার দেখো কেন সেটা ওভাবে কাজ করে। aws:MultiFactorAuthPresent থাকে শুধু temporary credential-এ: console (যেটা ভেতরে ভেতরে temporary credential চালায়), STS session, আর কোনো service তোমার identity আবার ব্যবহার করলে যে temporary credential বানায়। Long-term access key-তে এটা একেবারেই থাকে না।
Deny+"Bool": {"aws:MultiFactorAuthPresent": "false"}: স্বাভাবিক operator-এ key না থাকলে false, তাই access key চালানো প্রতিটা script পাহারার পাশ দিয়ে হেঁটে চলে যায়। এটাই ফাঁদ।Deny+"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}: না থাকাটাও মিল ধরা হয়, তাই access key-ও deny খায়। “MFA ছাড়া কিছুই না” নিয়মের জন্য AWS এটাই সুপারিশ করে।Allow+"Bool": {"aws:MultiFactorAuthPresent": "true"}: শুধু যে session সত্যিই MFA করেছে।- “সম্প্রতি” মানে
aws:MultiFactorAuthAge-এNumericLessThan, যেমন"3600"সেকেন্ড।
নিচের tester-এ সব রকম মিলিয়ে দেখো: request কোথা থেকে আসছে বেছে নাও, তারপর দেখো কোন key আছে আর ছয়টা চেনা statement কী করে।
Condition tester: key-টা আদৌ আছে তো?
request কোথা থেকে আসছে বেছে নাও। lab দেখাবে AWS request context-এ কোন কোন condition key বসায়, তারপর ছয়টা চেনা statement সেটার ওপর যাচাই করবে। যে key নেই, সেগুলোর দিকে চোখ রাখো।
Request context
Allow: শুধু অফিস থেকে Allow
- IpAddress aws:SourceIp 203.0.113.0/24
203.0.113.25 → true
খাটে
স্বাভাবিক operator-এ key না থাকলে false, তাই Allow-টা খাটেই না।
Deny: অফিসের বাইরে Deny (সাদামাটা)
- NotIpAddress aws:SourceIp 203.0.113.0/24
203.0.113.25 → false
খাটে না
উল্টো (negated) operator-এ key না থাকলে true, তাই এই Deny VPC endpoint-এর traffic আর তোমার হয়ে কাজ করা service-কেও মারে।
Deny: অফিসের বাইরে Deny (ঠিক করা)
- NotIpAddress aws:SourceIp 203.0.113.0/24
203.0.113.25 → false - StringNotEquals aws:SourceVpce vpce-0a1b2c3d
key নেই → উল্টো operator true - Bool aws:ViaAWSService false
false → true
খাটে না
এক statement-এ তিনটা condition AND হয়: Deny খাটবে “অফিস না” এবং “আমাদের endpoint না” এবং “তোমার হয়ে কোনো service না” হলে।
Deny: MFA ছাড়া Deny, Bool (ফাঁদ)
- Bool aws:MultiFactorAuthPresent false
true → false
খাটে না
long-term access key-তে MFA key-ই নেই, তাই Bool false কখনো মেলে না, আর এরা সোজা পার হয়ে যায়।
Deny: MFA ছাড়া Deny, BoolIfExists
- BoolIfExists aws:MultiFactorAuthPresent false
true → false
খাটে না
IfExists থাকলে key না থাকাটাও মিল ধরা হয়, তাই access key-ও deny খায়। AWS এই পাহারাটাই সুপারিশ করে।
Allow: শুধু MFA থাকলে Allow, Bool
- Bool aws:MultiFactorAuthPresent true
true → true
খাটে
এই Allow পায় শুধু যে session সত্যিই MFA করেছে; access key বা MFA ছাড়া role পায় না।
Head office থেকে passkey দিয়ে console-এ ঢোকা। console ভেতরে ভেতরে temporary credential ব্যবহার করে, তাই MFA key আছে, মান true।
#বহু-মানের key: ForAnyValue আর ForAllValues
বেশিরভাগ key-তে এক request-এ একটাই মান থাকে (একটা source IP, একটা Region)। কয়েকটায় থাকে একটা set: aws:TagKeys (tag দেওয়ার request-এর সব tag key), aws:CalledVia, aws:PrincipalOrgPaths। এদের জন্য set operator লাগবেই:
ForAnyValue:StringEquals: request-এর অন্তত একটা মান তোমার তালিকায় থাকলে true। key না থাকলে false।ForAllValues:StringEquals: request-এর প্রতিটা মান তোমার তালিকায় থাকলে true, আর key না থাকলে বা খালি হলেও true।
শেষ কথাটা একটা সত্যিকারের নিরাপত্তা-ফাঁদ: Allow + ForAllValues:StringEquals aws:TagKeys ["team", "env"] লিখে বোঝাতে চেয়েছিলে “শুধু এই tag key-গুলো ব্যবহার করা যাবে”, কিন্তু কোনো tag ছাড়া request-ও মিলে যায়। AWS-এর সমাধান হলো "Null": {"aws:TagKeys": "false"} যোগ করা (key থাকতেই হবে)। উল্টো ভুলটাও হয়: aws:ResourceTag/team-এর মতো এক-মানের key-তে set operator বসালে policy উদ্দেশ্যের চেয়ে বেশি ঢিলে হয়ে যেতে পারে।
#Service-এর নিজস্ব key
প্রতিটা service নিজের key প্রকাশ করে, সামনে service-এর নাম। পরীক্ষায় আর বাস্তব design-এ আসে এমন চারটা:
| Key | কী থাকে | সাধারণ ব্যবহার |
|---|---|---|
ec2:ResourceTag/<key> | যে EC2 resource-এ কাজ হচ্ছে তার একটা tag | “শুধু env=dev tag-ওয়ালা instance চালু-বন্ধ” (slide-এর উদাহরণ) |
s3:prefix | ListBucket request-এর folder prefix | “শুধু home/<তোমার নাম>/ দেখো” |
iam:PermissionsBoundary | user বা role বানানো বা বদলানোর request-এ boundary-র ARN | প্রতিটা নতুন role-এ অনুমোদিত boundary বাধ্যতামূলক (নিচে) |
iam:PassedToService | role-টা কোন service-কে দেওয়া হচ্ছে | iam:PassRole শুধু lambda.amazonaws.com-কে |
শেষটা লেসন ২.৪-এর iam:PassRole-এর গল্প শেষ করে: iam:PassRole সীমিত রাখো নির্দিষ্ট role ARN-এ, আর iam:PassedToService দিয়ে শুধু সেই service-এ যার পাওয়ার কথা, যাতে কেউ নিজের নিয়ন্ত্রণের function-কে administrator role ধরিয়ে দিতে না পারে।
#Policy variable
value-এর ভেতরে একটা variable থাকতে পারে, যেটা AWS request context থেকে ভরে দেয়: ${aws:username}, ${aws:PrincipalTag/team}, ${aws:PrincipalAccount}। তখন একটাই policy প্রত্যেক caller-এর জন্য আলাদা আচরণ করে। S3-এর home folder নকশায় আর নিচের ABAC-এ variable দেখবে। Variable কাজ করে 2012-10-17 policy version-এ (পুরোনো 2008-10-17 ${…}-কে সাধারণ লেখা ধরে)।
#ABAC: tag থেকে permission
Attribute-based access control resource-এর তালিকা না লিখে tag মিলিয়ে access দেয়। চারটা key দিয়ে এটা চলে:
| Key | কী থাকে | ABAC-এ কাজ |
|---|---|---|
aws:PrincipalTag/<key> | ডাকছে যে user বা role তার একটা tag (বা identity provider থেকে আসা session tag) | caller কে: team, project, cost centre |
aws:ResourceTag/<key> (বা ec2:ResourceTag/<key>) | আগে থেকে থাকা resource-এর একটা tag | resource-টা কার |
aws:RequestTag/<key> | এই request-এ যে tag বসানো হচ্ছে | নতুন resource ঠিক tag নিয়ে বানাতে বাধ্য করা |
aws:TagKeys | এই request-এর সব tag key (বহু-মানের) | কোন tag key যোগ বা মুছতে দেওয়া হবে |
একটা statement-ই সব team সামলায়:
{
"Effect": "Allow",
"Action": ["ec2:StartInstances", "ec2:StopInstances"],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringEquals": { "aws:ResourceTag/team": "${aws:PrincipalTag/team}" }
}
}
RBAC (role-based access control)-এর বদলে ABAC কেন: RBAC-এ প্রতিটা team-এর নিজের policy লাগে যেখানে তার resource-এর তালিকা, আর প্রতিটা নতুন project মানে policy বদলানো। ABAC-এ payments team-এর নতুন instance যেই team=payments tag পায়, সেই মুহূর্তেই ঢেকে যায়, আর নতুন team-এর জন্য নতুন policy-ই লাগে না। দামটা হলো: tag-ই permission হয়ে যায়, তাই tag বদলানোকে policy বদলানোর মতোই কড়া হাতে আটকাতে হয় (platform team ছাড়া সবার জন্য team key-তে CreateTags/DeleteTags deny), আর aws:RequestTag দিয়ে নতুন resource-কে tag নিতে বাধ্য করতে হয়। লেসন ২০.৩-এ দেখবে IAM Identity Center কীভাবে তোমার identity provider থেকে attribute-গুলো session tag হিসেবে পাঠায়, ফলে কোম্পানির directory-তে একজনের department-ই হয়ে যায় তার aws:PrincipalTag।
ABAC: কে কোনটা ছোঁবে, ঠিক করে tag
একটা telecom-এর সব developer-এর জন্য একটাই policy: instance-এর team tag আর তোমার নিজের team tag মিললে তবেই সেটা চালু-বন্ধ করতে পারবে। কোথাও instance ID-র কোনো তালিকা নেই।
পরিস্থিতি
aws:PrincipalTag/team আর ec2:ResourceTag/team সমান।
খরচ বাঁচাতে Rafi রাতে payments-এর একটা instance বন্ধ করছে। তার IAM role-এ tag আছে team=payments।
#S3-এর জন্য IAM: bucket ARN বনাম object ARN
S3-এর permission চলে দুই ধরনের resource-এর ওপর, আর slide একটা bucket দিয়েই কথাটা বোঝায়:
| স্তর | Action | Resource ARN |
|---|---|---|
| Bucket | s3:ListBucket, s3:GetBucketLocation, s3:GetBucketPolicy, s3:PutBucketVersioning… | arn:aws:s3:::reports-example |
| Object | s3:GetObject, s3:PutObject, s3:DeleteObject, s3:GetObjectTagging… | arn:aws:s3:::reports-example/* |
শুধু reports-example/* থাকলে যে file-এর নাম আগে থেকে জানো সেটা পড়া যায়, কিন্তু ListBucket AccessDenied দেয়, কারণ bucket/* pattern কখনো bucket নিজের সঙ্গে মেলে না। s3:* দিলেও লাভ নেই; bucket ARN যোগ করলেই হয়:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListTheBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::reports-example"
},
{
"Sid": "ReadAndWriteObjects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::reports-example/*"
}
]
}
share করা bucket-এ প্রত্যেক user-কে নিজের folder দিতে s3:prefix-এর condition সহ একটা ListBucket statement, আর home/${aws:username}/*-এ object-এর statement মেলাও। s3:prefix key থাকে শুধু list request-এ, ঠিক এজন্যই এটা bucket-level statement-এ বসে।
Bucket ARN নাকি object ARN?
S3-এর action দুই আলাদা resource-এর ওপর চলে: bucket নিজে, আর তার ভেতরের object। দেখো policy-তে এর একটার নাম লিখলে কী হয়।
পরিস্থিতি
policy শুধু arn:aws:s3:::reports-example/*-এ s3:* allow করে, আর কিছু না।
চেনা একটা file পড়া। GetObject চলে object ARN arn:aws:s3:::reports-example/q3.csv-এর ওপর, যেটা bucket/* pattern-এর সঙ্গে মেলে।
#Resource-based policy আর aws:PrincipalOrgID
Resource-based policy থাকে resource-এর গায়ে আর তাতে একটা Principal লেখা থাকে (লেসন ২.১)। bucket policy-তে partner account একটা একটা করে লিখলে, যেদিন নতুন account যোগ হয় সেদিনই ভাঙে। Slide-এর উত্তর, আর পরীক্ষারও, হলো aws:PrincipalOrgID: তোমার AWS Organization-এর সবাইকে allow, আর কাউকে না।
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "OrgMembersRead",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::finance-data-example", "arn:aws:s3:::finance-data-example/*"],
"Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-a1b2c3d4e5" } }
}]
}
"Principal": "*" দেখে ভয় লাগে, কিন্তু condition-টা একে সরু করে শুধু সেই principal-এ নামায় যাদের account o-a1b2c3d4e5-এর ভেতরে; organization-এর বাইরের user-এর এই key-ই নেই, তাই allow পায় না। নতুন member account নিজে থেকেই ঢুকে যায়, বেরিয়ে যাওয়া account নিজে থেকেই access হারায় (লেসন ১০.২-এ bucket policy-তে এই key-ই দেখেছ)। তবে যেকোনো cross-account request-এর মতো caller-এর নিজের identity policy-কেও call-টা allow করতে হবে।
কাছাকাছি key-গুলো, প্রত্যেকটা আলাদা প্রশ্নের জন্য:
| Key | প্রশ্ন | সাধারণ ব্যবহার |
|---|---|---|
aws:PrincipalOrgID | Caller কি এই organization-এর? | পুরো organization-এর জন্য খোলা bucket, queue বা key policy |
aws:PrincipalOrgPaths | Caller কি এই OU path-এর নিচে? (বহু-মানের) | bucket শুধু Prod OU-র জন্য: ForAnyValue:StringLike o-a1b2c3d4e5/r-ab12/ou-ab12-cdef3456/* |
aws:ResourceOrgID | Resource কি এই organization-এর? | SCP বা identity policy: “আমাদের লোক শুধু আমাদের organization-এর bucket-এ লিখবে” (ব্যক্তিগত bucket-এ data পাচার আটকায়) |
aws:SourceArn, aws:SourceAccount | কোন resource বা account একটা AWS service-কে দিয়ে কাজ করাল? | service principal তোমার resource-এ লিখলে confused deputy আটকানো |
শেষ লাইনটা লেসন ২.৪-এর external ID-র service principal সংস্করণ। একটা queue policy যখন sns.amazonaws.com-কে message পাঠাতে দেয়, তখন যেকোনো account-এর যেকোনো SNS topic ওই অনুমতি কাজে লাগাতে পারে। "ArnEquals": {"aws:SourceArn": "arn:aws:sns:ap-south-1:111122223333:orders-topic"} (বা aws:SourceAccount) যোগ করো, তখন শুধু তোমার topic পারবে।
#IAM role বনাম resource-based policy
দুটোই একজন principal-কে account-এর সীমানা পার করায়, slide যেমন দেখায়: account A-র user হয় account B-তে একটা role assume করে (role তখন মাধ্যম), নয়তো B এমন একটা resource-based policy বসায় যাতে user-এর নাম সরাসরি লেখা। আসল তফাতটা নোটেই আছে।
#Role নিলে identity বদলে যায়
কোনো user, application বা service একটা role assume করলে, ওই session-এর জন্য নিজের আসল permission ছেড়ে দেয়, আর হাতে থাকে শুধু role-এর permission। call যায় assumed-role/<role>/<session> নামে, আসল user-এর নামে না।
#Resource-based policy-তে identity অটুট থাকে
resource-based policy-তে caller নিজেই থাকে, নিজের সব permission সহ, আর শুধু ওই একটা resource-এ access পায়।
Slide-এর উদাহরণে তফাতটা স্পষ্ট: account A-র এক user-কে A-র একটা DynamoDB table scan করে dump লিখতে হবে B-র একটা S3 bucket-এ।
- B-তে role নিয়ে: session B-র bucket-এ লিখতে পারে, কিন্তু A-র table আর পড়তে পারে না: B-র role-এর সেখানে কোনো permission নেই, আর user-এর নিজের permission তখন পাশে সরানো। কাজটায় লাগে দুই identity, দুই ধাপ।
- B-তে bucket policy দিয়ে, যাতে user-এর নাম: user নিজে হিসেবেই এক session-এ A-র table scan করে, B-র bucket-এ লেখে।
Role নেবে, নাকি guest list-এ নাম থাকবে?
Account A-র Nadia-কে account A-র একটা DynamoDB table scan করে, তার dump account B-র একটা bucket-এ লিখতে হবে। cross-account access দেওয়ার দুটো উপায় একেবারে আলাদা আচরণ করে।
পরিস্থিতি
role হলো একটা মাধ্যম: যতক্ষণ Nadia role পরে থাকে, ততক্ষণ নিজের permission ছেড়ে দেয়।
B-র export role account A-কে trust করে, আর Nadia-র policy তাকে ওই role-এ sts:AssumeRole করতে দেয়। সে role-এর temporary credential পায় (লেসন ২.৪)।
উল্টো দিকের ঘটনাও খুব হয়: Nadia account B-র একটা bucket পড়তে সেখানে role নিল, তারপর file-গুলো A-তে নিজের bucket-এ কপি করতে গেল। কপি fail করে, কারণ role-এ থাকার সময় সে আর Nadia না; কাজ করবে শুধু যদি A-র bucket policy B-র role-কে trust করে। ২০২৪ থেকে DynamoDB-ও resource-based policy সমর্থন করে, তাই slide-এর scan-ও একইভাবে ঠিক করা যায়, table-এর policy-তে B-র role-কে allow দিয়ে।
#কোন service-এ resource-based policy আছে
সব service-এ নেই, তাই সবসময় পছন্দটা তোমার হাতে থাকে না:
| Resource-based policy আছে | কখন এটাই স্বাভাবিক বাছাই |
|---|---|
| S3 bucket (bucket policy), S3 access point | account-এর বাইরে বা পুরো organization-এর সঙ্গে data share |
| SQS queue, SNS topic, EventBridge event bus | অন্য account বা কোনো service-কে message বা event পাঠাতে দেওয়া |
| Lambda function (function policy) | S3, SNS, API Gateway বা অন্য account-কে function চালাতে দেওয়া |
| KMS key (key policy) | প্রতিটা key-র একটা থাকে; সেটাকে access allow করতেই হবে (লেসন ২১.২) |
| Secrets Manager secret, ECR repository, Backup vault, DynamoDB table আর stream, API Gateway REST API, OpenSearch domain, Glacier vault | ওই একটা resource-এ cross-account access |
| IAM role (trust policy) | কে role-টা assume করতে পারবে |
যেগুলোর নেই (বেশিরভাগ EC2 resource, RDS instance, EBS volume), সেগুলো অন্য account-এর সঙ্গে ভাগ হয় role দিয়ে, আর networking resource হলে AWS Resource Access Manager দিয়ে (লেসন ২০.১)। EventBridge কোনো rule-এর target-এ পৌঁছানোর অনুমতি কীভাবে পায়, সেটাও এই ভাগেই ঠিক হয়: Lambda, SNS, SQS আর এরকম service-এ তাদের resource-based policy দিয়ে, বাকিগুলোয় একটা IAM role দিয়ে, যেমন লেসন ১৯.৫-এ আছে।
#কোনটা বাছবে
| পরিস্থিতি | বাছাই | কেন |
|---|---|---|
| “অন্য account-এর bucket access, নিজের এখনকার permission না হারিয়ে” (নোটের পরীক্ষার কথা) | Resource-based policy | caller নিজের identity আর permission রেখে দেয় |
| “EC2 instance-কে dynamically credential দাও” (নোটের আরেকটা কথা) | IAM role (instance profile) | service temporary credential পায় শুধু role দিয়ে |
| বাইরের কোনো vendor তোমার account-এ কাজ করবে | external ID সহ IAM role | অল্প সময়ের credential, audit trail, সহজে বাতিল |
| অন্য account-এর অনেক resource বা service-এ access | IAM role | এক trust, এক permission set; ডজনখানেক resource policy-তে user-এর নাম লেখা টেকে না |
| resource-টার কোনো resource-based policy নেই | IAM role | আর কোনো উপায় নেই |
| পুরো organization একটা bucket পড়বে | aws:PrincipalOrgID সহ resource-based policy | একটা statement, account-প্রতি role লাগে না |
#দুই account মানে দুই দিকেই allow
এক account-এর ভেতরে identity-based অথবা resource-based policy-র একটা Allow-ই যথেষ্ট (union)। দুই account হলে AWS দুটো যাচাই চালায়, প্রতি account-এ একটা, আর request allowed হয় শুধু যদি দুটোই Allow দেয়:
- Caller-এর account (trusted account) যাচাই করে তার identity-based policy আর যা যা সেটাকে সীমিত করে: SCP, permissions boundary, session policy।
- Resource-এর account (trusting account) যাচাই করে resource-based policy আর যা সেটাকে সীমিত করে: RCP।
তাই B-র bucket policy-তে Nadia-র নাম থেকেও লাভ নেই, যদি A-তে Nadia-র নিজের policy ওই bucket ARN-এ s3:PutObject allow না করে; আর A-তে উদার identity policy থেকেও লাভ নেই, যদি B-র bucket policy-তে A-র নাম না থাকে। দুটো resource-based policy-কে এক account-এর ভেতরেও allow করতেই হয়, কারণ resource-টা আদৌ কে ব্যবহার করবে তা এরাই ঠিক করে: role trust policy আর KMS key policy।
#Permissions boundary: গভীরে
Permissions boundary হলো একটা managed policy (AWS managed বা customer managed), যেটা একটা IAM user বা role-এ লাগানো হয় তার সর্বোচ্চ permission হিসেবে। এটা নিজে কিছুই দেয় না; slide একে আঁকে “boundary + IAM policy” হিসেবে, যেখানে কাজে লাগে শুধু দুটোর মিলটুকু, আর permission policy একেবারে না থাকলে ফল কোনো permission-ই না।
- Boundary বসে শুধু user আর role-এ, group-এ না (নোট ইঙ্গিত দেয়; slide সরাসরি বলে)।
- আসল permission = identity-based policy ∩ boundary (আর থাকলে ∩ SCP, ∩ RCP, ∩ session policy)।
- Boundary-তে explicit Deny থাকলে deny, অন্য যেকোনো Deny-এর মতোই।
নোটের উদাহরণ: এক user-এর boundary শুধু S3 read আর EC2 read allow করে, অথচ তার identity policy AdministratorAccess। User পারবে শুধু S3 read আর EC2 read: AdministratorAccess সব দিতে চায়, boundary রাখে শুধু ওই দুটো।
#দায়িত্ব ভাগ করে দেওয়ার নকশা
নোটে পরীক্ষার সবচেয়ে প্রিয় scenario: “Developer-রা নতুন IAM role বানাতে পারবে, কিন্তু ওই role দিয়ে নিজেদের administrator বানাতে পারবে না।” উত্তর হলো তারা যা বানায় তার সবকিছুতে boundary বাধ্যতামূলক করা। Slide-ও একই ব্যবহারগুলো বলে: non-administrator-দের তাদের boundary-র ভেতরে কাজ ভাগ করে দেওয়া, developer-দের নিজের permission নিজে সামলাতে দেওয়া কিন্তু escalate করতে না দেওয়া, আর পুরো account-এ SCP না বসিয়ে একজন নির্দিষ্ট user-কে সীমিত করা।
Developer-দের নিজের policy-র চারটা অংশ:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateRolesOnlyWithTheBoundary",
"Effect": "Allow",
"Action": ["iam:CreateRole", "iam:PutRolePermissionsBoundary",
"iam:AttachRolePolicy", "iam:DetachRolePolicy", "iam:PutRolePolicy"],
"Resource": "arn:aws:iam::111122223333:role/app/*",
"Condition": {
"StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/DevBoundary" }
}
},
{
"Sid": "PassOnlyTheirRolesToLambda",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::111122223333:role/app/*",
"Condition": { "StringEquals": { "iam:PassedToService": "lambda.amazonaws.com" } }
},
{
"Sid": "NeverRemoveABoundary",
"Effect": "Deny",
"Action": ["iam:DeleteRolePermissionsBoundary", "iam:DeleteUserPermissionsBoundary"],
"Resource": "*"
},
{
"Sid": "NeverEditTheBoundaryPolicy",
"Effect": "Deny",
"Action": ["iam:CreatePolicyVersion", "iam:SetDefaultPolicyVersion", "iam:DeletePolicy"],
"Resource": "arn:aws:iam::111122223333:policy/DevBoundary"
}
]
}
app/path-এর নিচে role বানাতে আর বদলাতে পারবে শুধু যদি request-এ boundary হিসেবে DevBoundary-র নাম থাকে। এটা ছাড়াCreateRoleকরলেiam:PermissionsBoundarykey-ই থাকে না, condition false, request implicitly deny।- ওই role-গুলো শুধু Lambda-কে দিতে পারবে।
- কোনো boundary কখনো খুলতে পারবে না।
- Boundary policy নিজেই বদলাতে পারবে না, নইলে সেটাকে চওড়া করে নিলেই হতো।
সাধারণত developer-দের নিজেদের গায়েও একই boundary থাকে, যাতে তারা নিজেদের IAM ক্ষমতা দিয়ে তাদের বানানো role-এর চেয়ে বেশি কিছু করতে না পারে।
Developer role বানায়, তবে বেড়ার ভেতরেই
Tanvir security team-এর অপেক্ষা না করেই নিজের Lambda function-এর জন্য IAM role বানাতে পারে, কিন্তু প্রতিটা role-এ অনুমোদিত boundary DevBoundary বসাতেই হবে, যেটা শুধু S3, DynamoDB আর CloudWatch Logs allow করে।
পরিস্থিতি
যে পথ খোলা।
Tanvir চালাল aws iam create-role, সঙ্গে --permissions-boundary দিয়ে DevBoundary-কে দেখিয়ে দিল।
#Boundary, SCP নাকি session policy?
তিনটাই শুধু সীমা টানে। তফাত হলো কীসের গায়ে বসে আর কে বসায়:
| Permissions boundary | SCP | Session policy | |
|---|---|---|---|
| কীসের গায়ে | একটা IAM user বা role | Organization-এর root, OU বা account | একটা session, AssumeRole/federation-এর সময় দেওয়া |
| কে বসায় | যে ওই user বা role বানায় বা সামলায় | Organization-এর administrator (লেসন ২০.১) | যে session বানায় |
| পরিধি | ওই একটা identity, সবসময় | account-এর প্রতিটা principal (management account বাদে) | শুধু ওই session, মেয়াদ শেষ হওয়া পর্যন্ত |
| সাধারণ ব্যবহার | দায়িত্ব ভাগ; একজন developer-কে সীমিত করা | পুরো account-এর পাহারা | একটা broker প্রতিটা job-কে সরু credential দেয় |
Slide-এর কথা “boundary SCP-র সঙ্গে মিলিয়ে ব্যবহার করা যায়” আসলে শুধু intersection: একটা action-কে identity policy আর boundary আর SCP, তিনটাকেই allow করতে হবে।
#Boundary আর resource-based policy: সূক্ষ্ম নিয়ম
IAM User Guide এমন একটা খুঁটিনাটি যোগ করে যা অনেক কোর্সই ভুল শেখায়। একই account-এর ভেতরে:
- যে resource-based policy একটা IAM user ARN-কে access দেয়, সেটা ওই user-এর identity policy বা boundary-র implicit deny-তে সীমিত হয় না। Bucket-এর Allow একাই দাঁড়ায়।
- যে resource-based policy একটা IAM role ARN-কে access দেয়, সেটা role-এর boundary আর session policy-র implicit deny-তে সীমিত হয়।
- যে resource-based policy সরাসরি একটা role session ARN-এর নাম লেখে, সেটা ওই session-কেই দেয়, ওগুলোয় সীমিত হয় না।
- Boundary-তে explicit Deny থাকলে সেটা সবসময় জেতে।
দুই account জুড়ে এই সূক্ষ্মতা আর থাকে না: caller-এর account-কে identity ∩ boundary ∩ session দিয়ে request allow করতেই হবে, resource policy যা-ই বলুক।
#Session policy
Session policy হলো এমন একটা policy যা session বানানোর সময় দেওয়া হয়: aws sts assume-role --policy (inline JSON) বা --policy-arns (সর্বোচ্চ ১০টা managed policy), আর AssumeRoleWithSAML, AssumeRoleWithWebIdentity, GetFederationToken-এও একই parameter। Session পায় role-এর (বা user-এর) policy আর session policy-র intersection। এটা কখনো কিছু যোগ করতে পারে না।
কেন ব্যবহার করবে: একটাই চওড়া role অনেক job চালায়, আর প্রতিটা job পায় তার যতটুকু দরকার ততটুকুতে ছাঁটা credential। একটা data-export service ExportRole নেয় (সব bucket পড়ার অনুমতি), কিন্তু সঙ্গে এমন session policy দেয় যা শুধু একজন customer-এর prefix-এ s3:GetObject allow করে, ফলে এক job-এর bug অন্য customer-এর file পড়তে পারে না।
#পুরো evaluation flow
#এক account-এ
লেসন ২.২-এ documented ক্রম ধাপে ধাপে দেখেছ; সংক্ষেপে (IAM User Guide, নভেম্বর ২০২৬-এ মিলিয়ে দেখা):
- কোনো ধরনের policy-তে কোনো explicit Deny → Deny।
- RCP-কে allow করতে হবে (বাস্তবে
RCPFullAWSAccessসবসময় লাগানো থাকে, তাই RCP request থামায় শুধু Deny দিয়ে)। - SCP-কে allow করতে হবে (management account-এ না)।
- Resource-based policy allow করে? IAM user ARN হলে এটাই যথেষ্ট → Allow। role ARN হলে এগিয়ে যাও, কিন্তু Allow-টা মনে রাখো।
- Identity-based policy-কে allow করতে হবে (৪ নম্বর ধাপ allow না করে থাকলে)।
- Permissions boundary থাকলে সেটাকেও allow করতে হবে।
- Session policy সহ session হলে session policy-কেও allow করতে হবে → Allow।
#দুই account জুড়ে
Cross-account request-এ AWS flow-টা দুবার চালায়:
| যাচাই | যে policy দেখা হয় | সাধারণত কোথায় থামে |
|---|---|---|
| Caller-এর account (A) | A-র policy-তে explicit Deny, A-র SCP, caller-এর identity-based policy, boundary, session policy | “no identity-based policy allows”; A-র এমন SCP যা data A-র organization-এর ভেতরে রাখে (aws:ResourceOrgID) |
| Resource-এর account (B) | B-র policy-তে explicit Deny, B-র RCP, resource-based policy | “no resource-based policy allows”; B-র এমন RCP যা B-র organization-এর বাইরের principal ফিরিয়ে দেয় |
Request allowed শুধু যদি দুটোই Allow বলে। B-র SCP-র এখানে কোনো ভূমিকা নেই (ওটা B-র principal সীমিত করে, A-র না), আর A-র RCP-রও নেই (ওটা A-র resource সীমিত করে)।
দুই account-এ: দুটো যাচাই, দুটোতেই পাস লাগবে
একটা partner কোম্পানির analytics role (account 444455556666) তোমার account 111122223333-এর একটা share করা bucket পড়ে। AWS request-টা caller-এর দিকেও যাচাই করে, resource-এর দিকেও।
পরিস্থিতি
যে setup কাজ করে।
প্রথম যাচাই, caller-এর account-এ: কোথাও Deny? তার SCP কি S3 allow করে? role-এর identity policy কি bucket ARN-এ GetObject allow করে? boundary বা session policy থাকলে সেগুলো কি allow করে?
#Evaluation lab
প্রতিটা স্তর নিজে সেট করো। Bucket-টা একই account-এ রাখো বা অন্য account-এ, user বা role session বাছো, identity policy-তে MFA চাও, আর SCP, RCP, bucket policy, boundary আর session policy-কে Allow, চুপ আর Deny-এর মধ্যে বদলাও। Lab প্রতিটা যাচাইয়ের gate দেখায়, আর request কোথায় থামে তাও।
Evaluation lab: এক account নাকি দুই
একটা principal একটা bucket-এ s3:GetObject চাইছে। bucket-টা একই account-এ রাখো বা অন্য account-এ, প্রতিটা policy স্তর সেট করো, আর দেখো request কোথায় থামে। দুই account হলে lab দুটো যাচাই চালায়, প্রতি account-এ একটা।
Account A: caller-এর দিক
1. কোথাও Deny?
Deny নেই
2. SCP
allow করে
3. Identity-based
একটা Allow মিলেছে
4. Boundary
নেই
5. Session
Allow
Account B: bucket-এর দিক
1. কোথাও Deny?
Deny নেই
2. RCP
full access
3. Bucket policy
caller-এর নাম: Allow
সিদ্ধান্ত: Allowed
একটা partner-এর analytics role তোমার bucket পড়ছে। তার নিজের policy bucket ARN allow করে, তোমার bucket policy-তে role-এর নাম আছে: দুই যাচাই-ই allow করে। দুই যাচাই-ই Allow দিয়েছে, তাই request allowed। যেকোনো একটা fail করলেই request deny হতো।
#হাতে-কলমে উদাহরণ: slide-এর policy
শেষ slide একটা policy নিয়ে তিনটা প্রশ্ন করে। একই ধরনের একটা policy:
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Deny", "Action": "sqs:*", "Resource": "*" },
{ "Effect": "Allow", "Action": "sqs:DeleteQueue",
"Resource": "arn:aws:sqs:ap-south-1:111122223333:orders-queue" }
]
}
sqs:CreateQueue?sqs:*-এর Deny মিলে যায়: explicit deny।orders-queue-এsqs:DeleteQueue? Allow মেলে, কিন্তু Deny-ও মেলে। কম নির্দিষ্ট বলে Deny হারে না: explicit deny।ec2:DescribeInstances? Deny শুধু SQS নিয়ে, আর EC2 কেউ allow করে না: implicit deny।
নিজেকে যাচাই করোপ্রশ্ন
এক IAM user-এর শুধু এই policy আছে: * -এ sqs:* Deny, আর একটা queue ARN-এ sqs:DeleteQueue Allow। User ওই queue-তে sqs:DeleteQueue call করলে কী হবে?
#ক্ষতি হওয়ার আগেই policy পরীক্ষা
Condition আর boundary সূক্ষ্মভাবে ভুল করা খুব সহজ। লাগানোর আগে পরীক্ষা করো:
- IAM policy simulator (খসড়ার জন্য
aws iam simulate-custom-policy, আগে থেকে থাকা user বা role-এর জন্যsimulate-principal-policy)।--context-entriesদিয়ে condition key পাঠাও: অফিসের IP, বাসার IP, বা MFA true/false। এটা--permissions-boundary-policy-input-listআর--resource-policy-ও নেয়। Organization-এর policy (SCP, RCP) পরীক্ষা করা ভালো একটা sandbox account-এ। - IAM Access Analyzer policy validation (
aws accessanalyzer validate-policy): লিখতে লিখতেই ১০০-রও বেশি যাচাই, ভুল ধরে (arn:awn-এর মতো invalid ARN), নিরাপত্তার সতর্কতা দেয় (*সহiam:PassRole,NotActionসহAllow), আর পরামর্শও দেয়। - Access Analyzer custom policy check:
check-no-new-access(নতুন version কি এমন কিছু দেয় যা reference policy দেয় না?),check-access-not-granted(এটা কিiam:CreateUserবাs3:DeleteBucketallow করে?),check-no-public-access(bucket বা key policy কি resource-টাকে public করে দেয়?)। এগুলো CI pipeline-এ বসাও, যাতে ঝুঁকির বদল এলে build fail করে। Access Analyzer-এর বাকি feature (external আর unused access) লেসন ২.৪-এ।
#কোথায় গোলমাল হয়
| লক্ষণ | কারণ | সমাধান |
|---|---|---|
| অফিস-IP পাহারায় EC2-র app deny খায় | Request এসেছে VPC endpoint দিয়ে; aws:SourceIp নেই, NotIpAddress true | Deny-তে aws:SourceVpce / aws:SourceVpc যোগ করো |
| IP পাহারার নিচে CloudFormation বা Athena fail করে | Service নিজের address দিয়ে call করে | "Bool": {"aws:ViaAWSService": "false"} যোগ করো |
| CLI user-রা MFA নিয়ম মানে না | Deny + Bool false; access key-তে key নেই | BoolIfExists ব্যবহার করো |
| Tag-এর বাধা tag-ছাড়া request ছেড়ে দেয় | key না থাকলে ForAllValues true | "Null": {"aws:TagKeys": "false"} যোগ করো |
s3:* থাকতেও ListBucket → AccessDenied | Resource শুধু bucket/* | Bucket ARN যোগ করো |
| Bucket policy allow করলেও cross-account call deny | Caller-এর identity policy চুপ | Caller-এর account-এও bucket ARN allow করো |
| Assume করা role নিজের account-এ ফেরত লিখতে পারে না | Role session-এর হাতে শুধু role-এর permission | নিজের bucket-এর policy-তে role-কে trust করো, বা resource-based policy নাও |
| Developer role বানাতে পারে না | --permissions-boundary নেই বা ভুল | অনুমোদিত boundary ARN দাও |
| Administrator-ও কিছু একটা পারে না | Boundary, SCP বা session policy | শুধু identity policy না, প্রতিটা সীমা দেখো |
| অচেনা কারো SNS topic থেকে queue-তে message আসে | aws:SourceArn ছাড়া service principal allow | aws:SourceArn / aws:SourceAccount যোগ করো |
#System design আর পরীক্ষায় কীভাবে আসে
- Network perimeter: সংবেদনশীল bucket-এ IP আর VPC endpoint-এর condition, এমন Deny পাহারা হিসেবে লেখা যা VPC endpoint আর service-এর call বোঝে।
- Identity perimeter: resource policy-তে
aws:PrincipalOrgIDআর বাইরের লোক ফিরিয়ে দেওয়া একটা RCP; resource perimeter: SCP-তেaws:ResourceOrgID, যাতে ভেতরের লোক বাইরের bucket-এ data কপি করতে না পারে। একসঙ্গে এরাই AWS-এর “data perimeter” নকশা। - ABAC দিয়ে বড় পরিসর: অনেক team আর project-এর জন্য tag-ভিত্তিক policy, tag বদলানো তালাবদ্ধ।
- নিরাপদে দায়িত্ব ভাগ: boundary, সঙ্গে
iam:PermissionsBoundaryআর সরুiam:PassRole, যাতে team-গুলো ticket-এর লাইনে না দাঁড়িয়ে দ্রুত চলে। - প্রতিটা job-এ least privilege: share করা role-এ session policy।
#নিজে করে দেখো
CLI সেট করা থাকলে (লেসন ১.৩) একটা test account-এ এগুলো চালাও। Simulator-এর command কিছুই বদলায় না।
# 1. Test the office guard with different source addresses (nothing is attached)
aws iam simulate-custom-policy \
--policy-input-list file://office-guard.json \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::payroll-example/jan.csv \
--context-entries ContextKeyName=aws:SourceIp,ContextKeyValues=198.51.100.7,ContextKeyType=ip \
ContextKeyName=aws:ViaAWSService,ContextKeyValues=false,ContextKeyType=boolean \
--query 'EvaluationResults[].[EvalActionName,EvalDecision]' --output text
# s3:GetObject explicitDeny
# Repeat with 203.0.113.25: allowed (if the file also contains an Allow statement)
# 2. Bool vs BoolIfExists: leave the MFA key out to imitate a long-term access key
aws iam simulate-custom-policy \
--policy-input-list file://mfa-guard.json \
--action-names s3:DeleteBucket --resource-arns arn:aws:s3:::reports-example \
--context-entries ContextKeyName=aws:MultiFactorAuthPresent,ContextKeyValues=false,ContextKeyType=boolean \
--query 'EvaluationResults[0].EvalDecision' --output text
# explicitDeny (now delete the --context-entries line: Bool lets it through, BoolIfExists does not)
# 3. What can an existing role really do, boundary included?
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:role/app/orders-fn-role \
--action-names s3:GetObject iam:CreateUser \
--query 'EvaluationResults[].[EvalActionName,EvalDecision]' --output text
# s3:GetObject allowed
# iam:CreateUser implicitDeny
# 4. Create a role with the approved boundary, then put a boundary on an existing user
aws iam create-role --role-name app/orders-fn-role \
--assume-role-policy-document file://lambda-trust.json \
--permissions-boundary arn:aws:iam::111122223333:policy/DevBoundary
aws iam put-user-permissions-boundary --user-name tanvir \
--permissions-boundary arn:aws:iam::111122223333:policy/DevBoundary
aws iam put-role-permissions-boundary --role-name legacy-etl \
--permissions-boundary arn:aws:iam::111122223333:policy/DevBoundary
# 5. Validate a draft policy (finds the arn:awn typo and risky patterns)
aws accessanalyzer validate-policy --policy-type IDENTITY_POLICY \
--policy-document file://s3-policy.json \
--query 'findings[].[findingType,issueCode]' --output text
# one ERROR line for the invalid arn:awn prefix, then any SECURITY_WARNING,
# WARNING and SUGGESTION findings (for example a PassRole with a wildcard)
# 6. A session policy: assume a broad role, receive narrow credentials
aws sts assume-role \
--role-arn arn:aws:iam::111122223333:role/ExportRole \
--role-session-name job-4711 \
--policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"s3:GetObject","Resource":"arn:aws:s3:::exports-example/customer-42/*"}]}'
# 7. Open a bucket to the whole organization
aws s3api put-bucket-policy --bucket finance-data-example --policy file://org-read.json
তারপর একটা sandbox account-এ দায়িত্ব ভাগের নকশাটা বানাও: DevBoundary তৈরি করো, একজন test user-কে ওপরের developer policy দাও, আর aws iam create-role চালাও --permissions-boundary সহ আর ছাড়া, শেষে aws iam delete-role-permissions-boundary।
#সারসংক্ষেপ
মূল কথা
- Condition মানে operator → key → value। Operator আর key-রা AND, এক key-র value-রা OR; দুই key-র মধ্যে “A অথবা B” লাগলে দুটো statement।
- Key না থাকলে স্বাভাবিক operator false, উল্টো operator true, আর
…IfExiststrue। এই এক নিয়মেইaws:SourceIp-এর চমক (VPC endpoint, তোমার হয়ে service) আর MFA-রBoolবনামBoolIfExistsফাঁদ বোঝা যায়। aws:SourceIppublic address থেকে আসা API request যাচাই করে; endpoint-এর traffic-এর জন্যaws:SourceVpce/aws:SourceVpc, service-এর call-এর জন্যaws:ViaAWSService। Console-এ ঢোকা এটা আটকায় না।- বহু-মানের key (
aws:TagKeys,aws:CalledVia,aws:PrincipalOrgPaths)-এForAnyValue/ForAllValuesলাগে; key না থাকলেForAllValuestrue, তাইNullযাচাই যোগ করো। - ABAC
aws:PrincipalTagমেলায়aws:ResourceTag-এর সঙ্গে,aws:RequestTagদিয়ে tag বাধ্যতামূলক করে, আর tag বদলানো পাহারা দিতে হয়। - S3:
ListBucketbucket ARN-এ, object-এর actionbucket/*-এ। Slide-এরarn:awnআসলেarn:aws-এর টাইপো। aws:PrincipalOrgIDএকটা resource পুরো organization-এর জন্য খোলে;aws:SourceArn/aws:SourceAccountservice principal-এর confused deputy আটকায়।- Role assume করলে নিজের permission ছাড়তে হয়; resource-based policy-তে থেকে যায়। দুই account হলে caller-এর identity policy আর resource policy দুটোকেই allow করতে হয়।
- Permissions boundary (user আর role-এ, group-এ কখনো না) হলো ছাদ। দায়িত্ব ভাগ =
CreateRoleallow শুধুiam:PermissionsBoundary= অনুমোদিত boundary হলে, boundary খোলা বা বদলানো deny,iam:PassRoleসরু। - পুরো ক্রম: Deny → RCP → SCP → resource-based → identity-based → boundary → session। দুই account হলে flow প্রতি account-এ একবার চলে, আর দুটোকেই allow করতে হয়।
#নিজেকে যাচাই
আগে নিজে উত্তর দাও, তারপর ব্যাখ্যাটা পড়ো। ঠিক হলেও পড়ো, কারণ ভুল Option-গুলো কেন ভুল, সেটাও ওখানে আছে।
নিজেকে যাচাই করোপ্রশ্ন
একটা policy-র condition block-এ StringEquals-এর নিচে দুটো key, আর প্রথম key-তে দুটো value। AWS এদের কীভাবে মেলায়?
নিজেকে যাচাই করোপ্রশ্ন
একটা bucket policy s3:* deny করে যখন NotIpAddress aws:SourceIp 203.0.113.0/24। অফিসের user-রা ঠিকঠাক কাজ করে, কিন্তু private subnet-এর একটা EC2-র application, যেটা gateway VPC endpoint দিয়ে S3-এ যায়, AccessDenied পায়। কেন?
নিজেকে যাচাই করোপ্রশ্ন
আগের প্রশ্নের একই অবস্থা। সবচেয়ে ছোট কোন বদলে application-টা endpoint দিয়ে ঢুকতে পারবে, অথচ বাসার user-রা আটকেই থাকবে?
নিজেকে যাচাই করোপ্রশ্ন
MFA বাধ্যতামূলক করতে একজন administrator সংবেদনশীল action-এ Bool aws:MultiFactorAuthPresent false সহ একটা Deny বসিয়েছে। MFA ছাড়া console user-রা আটকে যায়, কিন্তু long-term access key দিয়ে চলা script এখনো ওই action চালাতে পারে। কোন বদলে ফাঁকটা বন্ধ হবে?
নিজেকে যাচাই করোপ্রশ্ন
aws:MultiFactorAuthPresent নিয়ে কোন দুটো কথা ঠিক? (দুটো বাছো।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা Allow statement user-দের tag দিতে দেয় শুধু যখন ForAllValues:StringEquals aws:TagKeys হলো [team, env]। এক user একেবারে কোনো tag key ছাড়া (খালি set) ec2:CreateTags call করল। Condition কী করে?
নিজেকে যাচাই করোপ্রশ্ন
তুমি এমন একটা Deny চাও যা team tag key সহ যেকোনো tag request আটকাবে, একই request-এ অন্য tag key থাকলেও। aws:TagKeys-এর সঙ্গে কোন operator?
নিজেকে যাচাই করোপ্রশ্ন
একটা role-এর আছে শুধু arn:aws:s3:::reports-example/*-এ s3:*। চেনা object পড়া যায়, কিন্তু bucket-এর তালিকা দেখতে গেলে AccessDenied। সমাধান কী?
নিজেকে যাচাই করোপ্রশ্ন
নিচের কোনটা resource-based policy না?
নিজেকে যাচাই করোপ্রশ্ন
Account A-র এক user-কে account B-র একটা bucket-এ লিখতে হবে, A-তে তার এখনকার কোনো permission না হারিয়ে। কী কী থাকতে হবে? (দুটো বাছো।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
Nadia account B-তে একটা role নিল, B-র একটা bucket থেকে file নামাল, আর একই session-এ সেগুলো account A-তে নিজের bucket-এ upload করতে গেল। Upload deny হলো, যদিও Nadia নিজে ওই bucket-এ লিখতে পারে। কারণ কী?
নিজেকে যাচাই করোপ্রশ্ন
একই account-এ একটা bucket policy alice নামের IAM user-কে তার user ARN দিয়ে s3:GetObject allow করে। Alice-এর নিজের identity-based S3 permission নেই, আর তার permissions boundary শুধু EC2 allow করে। কোনো policy কিছু deny করে না। Alice কি object পড়তে পারবে?
নিজেকে যাচাই করোপ্রশ্ন
একই account। একটা bucket policy role arn:aws:iam::111122223333:role/report-কে s3:GetObject allow করে। Role-এর নিজের কোনো S3 policy নেই, আর তার permissions boundary শুধু EC2 allow করে। ওই role-এর একটা session object পড়ল। কী হবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা কোম্পানি চায় developer-রা ticket ছাড়াই নিজেদের Lambda function-এর জন্য IAM role বানাক, কিন্তু অনুমোদিত কয়েকটা service-এর চেয়ে বেশি ক্ষমতার role কখনো বানাতে না পারুক। সবচেয়ে ভালো নকশা কোনটা?
নিজেকে যাচাই করোপ্রশ্ন
Permissions boundary নিয়ে কোন দুটো কথা ঠিক? (দুটো বাছো।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
এক user-এর identity policy হলো AdministratorAccess। তার permissions boundary allow করে s3:* আর ec2:Describe*। কোনো SCP বা session policy নেই। সে কী কী পারবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা member account-এ একজন নির্দিষ্ট contractor-কে শুধু S3 read-এ সীমিত করতে হবে, বাকি সবাই এখনকার permission রাখবে। কোন নিয়ন্ত্রণ সবচেয়ে মানানসই?
নিজেকে যাচাই করোপ্রশ্ন
Account A-র একটা role account B-র একটা bucket-এ s3:GetObject call করল। B-র bucket policy role-কে allow করে। A-তে role-এর identity policy S3 নিয়ে কিছু বলে না, আর কেউ deny করে না। ফল কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা security team চায় কোম্পানির organization-এর বাইরের কোনো principal কোনো member account-এর S3 bucket থেকে কখনো data পড়তে না পারুক, পরে কোনো developer অতিরিক্ত উদার bucket policy লিখলেও। কী ব্যবহার করবে?
নিজেকে যাচাই করোপ্রশ্ন
কোন দুটো condition key একটা bucket policy-কে তোমার organization-এর, বা তার একটা OU-র principal-দের মধ্যে সীমিত করতে পারে? (দুটো বাছো।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা SQS queue policy sns.amazonaws.com-কে sqs:SendMessage allow করে। এক review সতর্ক করল যে অন্য customer-দের account-এর SNS topic-ও queue-তে message দিতে পারে। Statement-এ কী যোগ করা উচিত?
নিজেকে যাচাই করোপ্রশ্ন
একটা IP পাহারা (অফিস range-এর জন্য NotIpAddress সহ Deny) অফিস থেকে engineer-দের চালানো CloudFormation stack ভেঙে দেয়, কারণ অন্য service-এ CloudFormation-এর নিজের call deny খায়। Documented সমাধান কী?
নিজেকে যাচাই করোপ্রশ্ন
একটা batch job এমন একটা role নেয় যার permission policy শুধু dynamodb:* allow করে। Job সঙ্গে এমন session policy দেয় যা s3:* allow করে। Session কী করতে পারবে?
নিজেকে যাচাই করোপ্রশ্ন
একটা কোম্পানি চায় developer-রা EC2 instance চালু করুক শুধু eu-west-1-এ। কোন উপায় পরীক্ষার প্রত্যাশার সঙ্গে মেলে?
নিজেকে যাচাই করোপ্রশ্ন
কোন দুটো AWS resource-এ resource-based policy আছে? (দুটো বাছো।)
বেছে নাও ২
নিজেকে যাচাই করোপ্রশ্ন
একটা IAM policy-তে দুটো statement: * -এ sqs:* Deny আর একটা queue ARN-এ sqs:DeleteQueue Allow। কোন call সফল হবে?
নিজেকে যাচাই করোপ্রশ্ন
নোটে বলা আছে aws:SourceIp দিয়ে user-দের “শুধু কোম্পানির IP থেকে login” করানো যায়। সঠিক কথা কোনটা?
নিজেকে যাচাই করোপ্রশ্ন
একটা কোম্পানি ৪০টা team-এর জন্য একটাই policy চায়: প্রত্যেক engineer শুধু নিজের team-এর tag লাগানো resource সামলাবে, আর নতুন project-এ policy বদলাতে হবে না। Policy-র মূলে কোন key?
নিজেকে যাচাই করোপ্রশ্ন
একটা team চায় কোনো pull request IAM policy এমনভাবে বদলালে যে আগের version-এর চেয়ে নতুন permission দেয়, তখনই তাদের CI pipeline fail করুক। কোন tool মানানসই?
নিজেকে যাচাই করোপ্রশ্ন
Developer-রা Lambda function বানাতে পারে। এক security review-তে ধরা পড়ল একজন আগে থেকে থাকা একটা administrator role function-এ লাগিয়ে তা দিয়ে IAM বদলেছে। সবচেয়ে নির্দিষ্ট প্রতিরোধ কোনটা?