Course-এর সূচি

20.2

Condition, Resource Policy, Boundary আর পুরো Evaluation Logic

condition key, S3 bucket ARN বনাম object ARN, role বনাম resource policy, permission boundary, আর AWS শুরু থেকে শেষ পর্যন্ত কীভাবে সিদ্ধান্ত নেয়।

28 মিনিট পড়া + Animation

টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।

এই লেসন শেষে তুমি পারবে

  • যেকোনো Condition block পড়তে আর লিখতে: operator, key, value, একাধিক key আর একাধিক value কীভাবে মেলে, আর key না থাকলে কী হয়।
  • পরীক্ষায় যে global condition key-গুলো আসে (aws:SourceIp, aws:RequestedRegion, aws:MultiFactorAuthPresent, aws:PrincipalOrgID, tag-এর key, aws:SecureTransport) আর service-এর নিজস্ব key ec2: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-র একটা ঝলক দিয়েছে।

এই লেসন চারটা জিনিসে আরও গভীরে যায়, যেগুলো ওই সহজ ছবিটাকে আসল পরীক্ষার প্রশ্নে বদলে দেয়:

  1. Condition: policy-র সেই অংশ যা ঠিক করে একটা statement কখন আর কীভাবে খাটবে।
  2. Resource: S3-এর bucket বনাম object-এর ফাঁদ, আর aws:PrincipalOrgID সহ resource-based policy।
  3. Role বনাম resource-based policy: account-এর সীমানা পেরোনোর দুটো পথ, যাদের আচরণ একেবারে আলাদা।
  4. সীমা: 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-এর ভেতরেযুক্তিউদাহরণ
একাধিক operatorANDRegion মেলে এবং TLS ব্যবহার হয়েছে
এক operator-এর নিচে একাধিক keyAND"StringEquals": {"aws:RequestedRegion": "eu-west-1", "aws:PrincipalTag/team": "data"}
এক key-র একাধিক valueORRegion eu-west-1 অথবা ap-south-1
একাধিক statementপ্রত্যেকটা আলাদা করে যাচাই হয়অফিসের জন্য একটা Allow statement, VPN-এর জন্য আরেকটা

দুই আলাদা key-র মধ্যে “A অথবা B” লাগলে (অফিস থেকে অথবা MFA দিয়ে), এক condition block-এ লেখা যায় না: দুটো statement লেখো।

#Operator-গুলো

পরিবারOperatorসাধারণ keyসাবধান
StringStringEquals, StringNotEquals, StringEqualsIgnoreCase, StringLike (*, ?), StringNotLikeaws:RequestedRegion, aws:PrincipalTag/team, s3:prefixIgnoreCase না দিলে বড়-ছোট হাতের অক্ষর আলাদা; wildcard শুধু Like-এ
NumericNumericEquals, NumericLessThan, NumericGreaterThanEquals…aws:MultiFactorAuthAge, s3:max-keysমান লেখা হয় string হিসেবে: "3600"
DateDateLessThan, DateGreaterThan…aws:CurrentTime, aws:TokenIssueTimeISO 8601 বা epoch সময়
BooleanBoolaws:SecureTransport, aws:MultiFactorAuthPresent, aws:ViaAWSServicekey না থাকা মানে false না
IP addressIpAddress, NotIpAddressaws:SourceIpশুধু public address; VPC endpoint দিয়ে এলে থাকে না
ARNArnEquals, ArnLike, ArnNotLikeaws:SourceArn, aws:PrincipalArnARN-এর প্রতিটা অংশ আলাদা করে মেলে
আছে কি নেইNullযেকোনো key"Null": {"aws:TokenIssueTime": "true"} মানে “key-টা নেই”
ModifierNull বাদে যেকোনো operator-এর শেষে …IfExistsযে key কখনো থাকে, কখনো থাকে নাkey না থাকলে মিল ধরা হয়
Set operatoroperator-এর আগে 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 অফিসের না” কথাটাকে সত্যি ধরা হয়।
  • …IfExists operator-এ key না থাকলে ফল true: “থাকলে যাচাই করো, না থাকলে মাথা ঘামিও না”।
  • Null খোদ উপস্থিতিটাই যাচাই করে: true = নেই, false = আছে।

এর সঙ্গে statement-এর effect মেলালে চারটা আচরণ মনে রাখার মতো:

StatementKey নেইRequest-এর ওপর প্রভাব
Allow + স্বাভাবিক operatorcondition falseAllow খাটে না: প্রায়ই implicit deny
Allow + …IfExistscondition trueAllow খাটে
Deny + উল্টো operatorcondition truedeny, প্রায়ই অবাক করে
Deny + স্বাভাবিক operator (Bool false)condition falseDeny খাটে না: পাহারা ফাঁকি দিয়ে পার

#নোটের তিনটা পরীক্ষার scenario

নোটে তিনটা কথা আছে যা শুনলেই মাথায় আসা উচিত “Condition element”, আর slide-ও একই key দেখায়:

পরীক্ষার কথাKeyউত্তরের ধরন
“Restrict API calls to the corporate IP range”aws:SourceIpNotIpAddress সহ Deny, অথবা IpAddress সহ Allow
“Force MFA for deleting an S3 bucket”aws:MultiFactorAuthPresentBoolIfExists 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।

Head office203.0.113.0/24
বাসার Wi-Fi198.51.100.7
CloudFormation
EC2 appprivate 10.0.1.25
VPC endpoint
S3 bucketpayroll-example
GetObject

Request context

aws:SourceIp

203.0.113.25

aws:SourceVpce

(নেই)

aws:ViaAWSService

false

ধাপ 1 / 2
1

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 আসছে

Request context

aws:SourceIp 203.0.113.25aws:SourceVpce (নেই)aws:ViaAWSService falseaws:MultiFactorAuthPresent true

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 পায় না।

i

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:prefixListBucket request-এর folder prefix“শুধু home/<তোমার নাম>/ দেখো”
iam:PermissionsBoundaryuser বা role বানানো বা বদলানোর request-এ boundary-র ARNপ্রতিটা নতুন role-এ অনুমোদিত boundary বাধ্যতামূলক (নিচে)
iam:PassedToServicerole-টা কোন 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-এর একটা tagresource-টা কার
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 সমান।

Rafiteam=payments
Policy engine
Instance Ateam=payments
Instance Bteam=lending
StopInstances
ধাপ 1 / 3
1

খরচ বাঁচাতে Rafi রাতে payments-এর একটা instance বন্ধ করছে। তার IAM role-এ tag আছে team=payments।

#S3-এর জন্য IAM: bucket ARN বনাম object ARN

S3-এর permission চলে দুই ধরনের resource-এর ওপর, আর slide একটা bucket দিয়েই কথাটা বোঝায়:

স্তরActionResource ARN
Buckets3:ListBucket, s3:GetBucketLocation, s3:GetBucketPolicy, s3:PutBucketVersioning…arn:aws:s3:::reports-example
Objects3: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 করে, আর কিছু না।

Report appIAM role
Policy engine
S3 bucketreports-example
GetObject q3.csv
ধাপ 1 / 5
1

চেনা একটা 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:PrincipalOrgIDCaller কি এই organization-এর?পুরো organization-এর জন্য খোলা bucket, queue বা key policy
aws:PrincipalOrgPathsCaller কি এই OU path-এর নিচে? (বহু-মানের)bucket শুধু Prod OU-র জন্য: ForAnyValue:StringLike o-a1b2c3d4e5/r-ab12/ou-ab12-cdef3456/*
aws:ResourceOrgIDResource কি এই 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 ছেড়ে দেয়।

Account A
Account B
NadiaIAM user
Orders table
Export roleভেতরে Nadia
Dump bucketbucket policy
AssumeRole
ধাপ 1 / 4
1

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 pointaccount-এর বাইরে বা পুরো 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 policycaller নিজের 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-এ accessIAM 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"
    }
  ]
}
  1. app/ path-এর নিচে role বানাতে আর বদলাতে পারবে শুধু যদি request-এ boundary হিসেবে DevBoundary-র নাম থাকে। এটা ছাড়া CreateRole করলে iam:PermissionsBoundary key-ই থাকে না, condition false, request implicitly deny।
  2. ওই role-গুলো শুধু Lambda-কে দিতে পারবে।
  3. কোনো boundary কখনো খুলতে পারবে না।
  4. Boundary policy নিজেই বদলাতে পারবে না, নইলে সেটাকে চওড়া করে নিলেই হতো।

সাধারণত developer-দের নিজেদের গায়েও একই boundary থাকে, যাতে তারা নিজেদের IAM ক্ষমতা দিয়ে তাদের বানানো role-এর চেয়ে বেশি কিছু করতে না পারে।

Developer role বানায়, তবে বেড়ার ভেতরেই

Tanvir security team-এর অপেক্ষা না করেই নিজের Lambda function-এর জন্য IAM role বানাতে পারে, কিন্তু প্রতিটা role-এ অনুমোদিত boundary DevBoundary বসাতেই হবে, যেটা শুধু S3, DynamoDB আর CloudWatch Logs allow করে।

পরিস্থিতি

যে পথ খোলা।

Tanvirdeveloper
IAM
নতুন roleorders-fn-role
AWS API
CreateRole + DevBoundary
ধাপ 1 / 3
1

Tanvir চালাল aws iam create-role, সঙ্গে --permissions-boundary দিয়ে DevBoundary-কে দেখিয়ে দিল।

#Boundary, SCP নাকি session policy?

তিনটাই শুধু সীমা টানে। তফাত হলো কীসের গায়ে বসে আর কে বসায়:

Permissions boundarySCPSession policy
কীসের গায়েএকটা IAM user বা roleOrganization-এর 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, নভেম্বর ২০২৬-এ মিলিয়ে দেখা):

  1. কোনো ধরনের policy-তে কোনো explicit Deny → Deny।
  2. RCP-কে allow করতে হবে (বাস্তবে RCPFullAWSAccess সবসময় লাগানো থাকে, তাই RCP request থামায় শুধু Deny দিয়ে)।
  3. SCP-কে allow করতে হবে (management account-এ না)।
  4. Resource-based policy allow করে? IAM user ARN হলে এটাই যথেষ্ট → Allow। role ARN হলে এগিয়ে যাও, কিন্তু Allow-টা মনে রাখো।
  5. Identity-based policy-কে allow করতে হবে (৪ নম্বর ধাপ allow না করে থাকলে)।
  6. Permissions boundary থাকলে সেটাকেও allow করতে হবে।
  7. 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 কাজ করে।

Partner role444455556666
Caller-এর দিকidentity, SCPAllow
Resource-এর দিকbucket policy, RCP
Shared bucket111122223333
GetObject
ধাপ 1 / 4
1

প্রথম যাচাই, 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-এ একটা।

Scenario
Bucket আছে
Caller
Request-এ MFA আছে
Caller-এর identity policy
Bucket policy (caller-এর নাম আছে)
Caller-এর boundary
Session policy
Caller-এর account-এ SCP
Bucket-এর account-এ RCP

Account A: caller-এর দিক

  1. 1. কোথাও Deny?

    Deny নেই

  2. 2. SCP

    allow করে

  3. 3. Identity-based

    একটা Allow মিলেছে

  4. 4. Boundary

    নেই

  5. 5. Session

    Allow

Account B: bucket-এর দিক

  1. 1. কোথাও Deny?

    Deny নেই

  2. 2. RCP

    full access

  3. 3. Bucket policy

    caller-এর নাম: Allow

সিদ্ধান্ত: Allowed

i

একটা 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:DeleteBucket allow করে?), 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 trueDeny-তে 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 → AccessDeniedResource শুধু bucket/*Bucket ARN যোগ করো
Bucket policy allow করলেও cross-account call denyCaller-এর 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 allowaws: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, আর …IfExists true। এই এক নিয়মেই aws:SourceIp-এর চমক (VPC endpoint, তোমার হয়ে service) আর MFA-র Bool বনাম BoolIfExists ফাঁদ বোঝা যায়।
  • aws:SourceIp public address থেকে আসা API request যাচাই করে; endpoint-এর traffic-এর জন্য aws:SourceVpce/aws:SourceVpc, service-এর call-এর জন্য aws:ViaAWSService। Console-এ ঢোকা এটা আটকায় না।
  • বহু-মানের key (aws:TagKeys, aws:CalledVia, aws:PrincipalOrgPaths)-এ ForAnyValue/ForAllValues লাগে; key না থাকলে ForAllValues true, তাই Null যাচাই যোগ করো।
  • ABAC aws:PrincipalTag মেলায় aws:ResourceTag-এর সঙ্গে, aws:RequestTag দিয়ে tag বাধ্যতামূলক করে, আর tag বদলানো পাহারা দিতে হয়।
  • S3: ListBucket bucket ARN-এ, object-এর action bucket/*-এ। Slide-এর arn:awn আসলে arn:aws-এর টাইপো।
  • aws:PrincipalOrgID একটা resource পুরো organization-এর জন্য খোলে; aws:SourceArn/aws:SourceAccount service principal-এর confused deputy আটকায়।
  • Role assume করলে নিজের permission ছাড়তে হয়; resource-based policy-তে থেকে যায়। দুই account হলে caller-এর identity policy আর resource policy দুটোকেই allow করতে হয়।
  • Permissions boundary (user আর role-এ, group-এ কখনো না) হলো ছাদ। দায়িত্ব ভাগ = CreateRole allow শুধু iam:PermissionsBoundary = অনুমোদিত boundary হলে, boundary খোলা বা বদলানো deny, iam:PassRole সরু।
  • পুরো ক্রম: Deny → RCP → SCP → resource-based → identity-based → boundary → session। দুই account হলে flow প্রতি account-এ একবার চলে, আর দুটোকেই allow করতে হয়।

#নিজেকে যাচাই