সরাসরি পর্বে যান
পর্ব ৩২ · ৮১-এর মধ্যে · মডিউল ৬

IAM policy evaluation — allow, deny, least privilege আর ভুল অনুমতি ধরা

IAM Policy Evaluation — Allow, Deny, Least Privilege and Finding Excess Permissions

Taught in Bangla, this lesson walks through how a cloud decides a request: default deny, explicit deny and the full chain of identity policies, boundaries, session policies and organisation guardrails, two-sided consent for cross-account access, wildcards and conditions, differences in Azure and Google Cloud, practising least privilege from access logs and analyzers, reading access denied errors layer by layer, and reviewing AI-written policies, with an evaluation simulator.

এই পর্বে যা শিখবেন

  • একটি অনুরোধের ওপর cloud কীভাবে সিদ্ধান্ত নেয়, ধাপে ধাপে বলতে পারা
  • ছয় ধরনের নিয়মের কোনটি অনুমতি দেয়, আর কোনটি শুধু সীমা টানে
  • Wildcard কতটা ছড়ায় তা মাপা, আর condition দিয়ে অনুমতি সরু করা
  • Access log আর analyzer দিয়ে বাড়তি অনুমতি খুঁজে নিরাপদে বাদ দেওয়া
  • “Access denied” দেখে সমস্যার স্তর ধরা, আর AI-এর লেখা policy যাচাই করা

১ · গুদামঘরের গেট — default deny আর explicit deny

একটি কাল্পনিক অনলাইন বাজার অ্যাপের কথা ভাবুন। রাতে report বানানোর একটি প্রোগ্রাম চলে। একদিন ভোরে দেখা গেল, report হয়নি। Log-এ শুধু একটি লাইন: AccessDenied. একই সপ্তাহে নিরাপত্তা দল জানাল, ওই প্রোগ্রামের role চাইলে পুরো storage মুছে দিতে পারে। অথচ তার কাজ শুধু কয়েকটি ফাইল পড়া।

প্রথমটি কম অনুমতির সমস্যা, দ্বিতীয়টি বেশি অনুমতির। দুটোর সমাধান একই জায়গায়: বুঝতে হবে cloud একটি অনুরোধের ওপর ঠিক কীভাবে রায় দেয়। পর্ব ৩১-এ দেখেছেন identity, role আর policy কী। এই পর্বে দেখব সেগুলো একসাথে কীভাবে কাজ করে, অর্থাৎ policy evaluation.

একটি গার্মেন্টস কারখানার গুদামঘর ভাবুন। গেটের রক্ষী প্রত্যেককে আটকান। নাম তালিকায় না থাকলে ঢোকা যায় না, কোনো কারণ দেখানোরও দরকার নেই। এটি default deny. ফ্লোর ম্যানেজার লিখে দিলে ঢোকা যায়, এটি Allow. কিন্তু মালিকের অফিস থেকে যদি নোটিশ আসে “অমুক গুদামে আজ কেউ নয়”, তাহলে ম্যানেজারের চিঠি থাকলেও লাভ নেই। এটি explicit Deny.

রক্ষী কী দেখে রায় দেন? প্রতিটি API অনুরোধের সাথে চারটি তথ্য আসে, যাকে বলে request context:

অংশপ্রশ্নউদাহরণ
Principalকে চাইছে?report-app-role
Actionকী করতে চায়?s3:GetObject
Resourceকোন জিনিসে?example-bucket/reports/a.csv
Contextকোন অবস্থায়?উৎস IP, MFA, tag, সময়, region

এবার নিয়মের গঠন। AWS-এর ভাষায় একটি policy হলো JSON দলিল, যার ভেতরে এক বা একাধিক statement থাকে। নিচেরটি মাত্র একটি কাজের অনুমতি দেয়:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadReports",
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::example-bucket/reports/*"
    }
  ]
}

Version-এর তারিখটি policy ভাষার সংস্করণ, আজকের তারিখ নয়, তাই এটি বদলাবেন না। Sid একটি নাম, যা error আর log পড়তে সাহায্য করে। Resource-এর লম্বা ঠিকানাকে বলে ARN. বাকি দুটি লাইনই আসল কথা: কোন Effect, কোন Action.

সব statement মিলিয়ে একটি অনুরোধের ফল তিনটির একটি হয়:

Implicit deny

কোনো statement মেলেনি, তাই “না”। পরে কেউ Allow যোগ করলে এই “না” উঠে যায়।

কেউ কিছু বলেনি

Allow

অন্তত একটি Allow মিলেছে, আর কোনো স্তরে আটকায়নি। তবেই অনুরোধ এগোয়।

সবগুলো স্তর রাজি

Explicit deny

কোনো Deny statement মিলেছে। কোনো Allow এটিকে ওলটাতে পারে না।

কেউ স্পষ্ট “না” বলেছে
Explicit Deny > Allow > Implicit deny
Statement-এর ক্রম গুরুত্বহীন: আগে বা পরে, Deny মিললেই শেষ

এই শেষ কথাটি firewall থেকে আলাদা। পর্ব ২৭-এ দেখেছেন network ACL-এ প্রথম মিলে যাওয়া নিয়মই শেষ কথা, তাই ক্রম জরুরি। IAM-এ তা নয়। Engine সব statement দেখে, তারপর রায় দেয়।

২ · পুরো শিকল — ছয় ধরনের নিয়ম একসাথে

বড় প্রতিষ্ঠানে একটি অনুরোধের ওপর শুধু একটি policy খাটে না। কারখানার উদাহরণেই ফিরি। ম্যানেজারের চিঠি, গুদামের নিজের তালিকা, পদের সর্বোচ্চ সীমা, আজকের গেটপাস আর মালিকের সাধারণ নোটিশ, সবই একসাথে কাজ করে। AWS-এর নামগুলো দিয়ে তালিকাটি এমন:

নিয়মকোথায় বসেকাজঅনুমতি দেয়?
Identity policyuser, group বা role-এর গায়েএই পরিচয় কী কী করতে পারেহ্যাঁ
Resource policyresource-এর গায়ে, যেমন bucket policyকে এই জিনিসে কী করতে পারেহ্যাঁ
Permission boundaryএকটি user বা role-এর গায়েএই পরিচয় সর্বোচ্চ কতদূর যেতে পারেনা, শুধু সীমা
Session policyএকটি temporary session-এএই session-এ আরও কমানোনা, শুধু সীমা
SCP (guardrail)organisation, OU বা account-এওই account-এর পরিচয়গুলোর সর্বোচ্চ সীমা (management account আর service-linked role-এ খাটে না)না, শুধু সীমা
RCP (guardrail)organisation, OU বা account-এওই account-এর resource-গুলোর সর্বোচ্চ সীমা (লেখার সময়ে কিছু service-এ)না, শুধু সীমা

এগুলোর সাথে থাকে condition, যা যেকোনো statement-এর গায়ে বসে। আর পর্ব ২৮-এর endpoint policy-ও একটি বাড়তি সীমা, যদি অনুরোধ ওই endpoint দিয়ে আসে। “Guardrail” শব্দটির অর্থ রাস্তার পাশের বেড়া। সে গাড়ি চালায় না, শুধু খাদে পড়া আটকায়।

একটি অনুরোধের সিদ্ধান্ত-পথ

Simplified AWS-style policy evaluation flow

IAM policy evaluation-এর flowchart নাহ্যাঁনা হ্যাঁহ্যাঁহ্যাঁ অনুরোধ এল শুরুর অবস্থা: default deny কোথাও explicit Deny? Guardrail-এর ভেতরে? Resource policy Allow? Identity policy Allow? Boundary-র ভেতরে? Session policy-র ভেতরে? ALLOW হ্যাঁনাহ্যাঁ নানানা DENY ALLOW* DENY * শুধু same-account-এ, কিছু ব্যতিক্রমসহ। Cross-account-এ দুই দিকের Allow চাই। যে স্তর প্রযোজ্য নয়, সেটি বাদ পড়ে। Guardrail-এ SCP আর RCP, দুটোই আছে।
ছবি ৩২.১ — সরলীকৃত চিত্র। Provider-এর ডকুমেন্টেশনে আরও ব্যতিক্রম আছে, আর নিয়ম সময়ের সাথে বদলাতে পারে।

ছবিটি মনে রাখার একটি সহজ সূত্র আছে। শুধু identity-র দিক থেকে দেখলে যে কাজগুলো সত্যিই করা যায়, সেগুলো হলো সব স্তরের ছেদ (intersection), অর্থাৎ effective permission:

কার্যকর অনুমতি = Identity ∩ Boundary ∩ Session ∩ Guardrail − Explicit Deny

ছোট একটি হিসাব দেখুন। Identity policy দিল {Get, Put, Delete}. Boundary-র সীমা {Get, Put, List}. Session policy-র সীমা {Get, List}. তিনটির ছেদ শুধু {Get}. Identity-তে Delete থাকলেও boundary-তে নেই। Boundary-তে List থাকলেও identity-তে নেই। যে স্তর একেবারে নেই, সেটিকে হিসাব থেকে বাদ দিন। আর identity-তে Allow না থাকলে, শুধু boundary থাকায় কিছুই পাওয়া যায় না।

এবার একটি অনুরোধকে পুরো পথ ধরে হাঁটাই। একজন developer us-east-1 region-এ একটি VM চালু করতে চান। তাঁর নিজের policy-তে অনুমতি আছে, কিন্তু প্রতিষ্ঠানের নিয়মে শুধু একটি region অনুমোদিত। নিচের guardrail-টি সেই নিয়ম:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyOutsideApprovedRegion",
      "Effect": "Deny",
      "NotAction": ["iam:*", "sts:*", "organizations:*", "support:*"],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": ["ap-southeast-1"]
        }
      }
    }
  ]
}

NotAction মানে “এই কয়টি বাদে সব”। IAM-এর মতো global service-এর কোনো নির্দিষ্ট region নেই, তাই সেগুলো বাদ রাখতে হয়। এখানে তালিকাটি ছোট করে দেখানো হয়েছে। বাস্তবে সব global service-এর তালিকা মিলিয়ে নিন, নইলে guardrail বৈধ কাজও আটকাবে।

  1. অনুরোধRunInstancesus-east-1
  2. IdentityAllowec2:*
  3. Boundaryভেতরেec2:*, s3:*
  4. GuardrailDenyঅন্য region
Engine-এর খাতা
যা দেখা হচ্ছে
সেখানে ফল
Allow জমা
এখনকার রায়
  1. অনুরোধ এল। Principal dev-role, action ec2:RunInstances, region us-east-1, MFA আছে। শুরুর রায়: default deny.
  2. প্রযোজ্য policy জড়ো হলো। Identity, boundary আর guardrail পাওয়া গেল। Session policy নেই। VM চালুর এই অনুরোধে কোনো resource policy-ও খাটছে না, তাই সেটি হিসাবের বাইরে।
  3. Identity policy. DevEc2 statement-এ ec2:* আছে, তাই Allow মিলল। কিন্তু এখনো রায় নয়, শুধু একটি “হ্যাঁ” জমা হলো।
  4. Permission boundary. DevBoundary বলে এই role ec2:* আর s3:*-এর বাইরে যেতে পারবে না। অনুরোধটি সীমার ভেতরে, দ্বিতীয় “হ্যাঁ”।
  5. Session policy. এই session-এ কোনো session policy দেওয়া হয়নি, তাই স্তরটি বাদ পড়ল। কোনো স্তর না থাকা মানে সে বাধা দিচ্ছে না।
  6. Guardrail. ec2:RunInstances NotAction-এর তালিকায় নেই, তাই statement-টি এই action-এ খাটে। Condition: us-east-1 অনুমোদিত তালিকায় নেই, অর্থাৎ শর্ত সত্য। Deny মিলে গেল।
  7. রায়: DENY. দুটি “হ্যাঁ” থাকলেও একটি explicit Deny সব বাতিল করল। সমাধান guardrail খোলা নয়, অনুমোদিত region-এ চালানো। আমরা বোঝার জন্য স্তর ধরে হাঁটলাম; আসল engine আগে সব Deny খোঁজে, ফল একই।

৩ · একই account না অন্য account — কার সম্মতি লাগে

এখানে একটি পার্থক্য পরীক্ষায় আর বাস্তবে দুই জায়গাতেই ধরা পড়ে। Same-account-এ resource আর identity, দুই দিকের যেকোনো একটির Allow সাধারণত যথেষ্ট, যদি অন্য কোনো স্তর না আটকায়। কিন্তু cross-account-এ দুই দিকই Allow করতে হবে।

নিজের কারখানার গুদামে ঢুকতে আপনার ম্যানেজারের চিঠিই যথেষ্ট, অথবা গুদামের তালিকায় আপনার নাম থাকলেও চলে। কিন্তু অন্য কোম্পানির গুদামে ঢুকতে হলে দুটোই লাগবে। আপনার কোম্পানি বলবে “যেতে পারেন”, আর ওই কোম্পানির গুদাম বলবে “আসতে দেব”।

অবস্থাIdentity policyResource policyফল
Same-accountAllowচুপALLOW
Same-accountচুপAllow (user বা session-এর নামে)ALLOW
Cross-accountAllowচুপDENY
Cross-accountচুপAllowDENY
Cross-accountAllowAllowALLOW
যেকোনোAllowDenyDENY (explicit)

Same-account-এর দ্বিতীয় সারিতে একটি সূক্ষ্মতা আছে। Resource policy কাকে নাম ধরে Allow করছে (user, role, নাকি একটি session), আর boundary বা session policy আছে কি না, তার ওপর ফল বদলাতে পারে। নতুন নকশায় ডকুমেন্টেশন মিলিয়ে নিন। KMS key-ও আলাদা: key policy অনুমতি না দিলে same-account-এও শুধু identity policy যথেষ্ট নয়। সে কথা পর্ব ৩৩-এ।

Cross-account-এর একটি bucket policy দেখুন। লক্ষ করুন, এখানে Principal আছে। Identity policy-তে এটি থাকে না, কারণ সেখানে principal হলো যার গায়ে policy লাগানো।

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPartnerRoleToRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111122223333:role/partner-reader"
      },
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::example-bucket/shared/*"
    }
  ]
}

এই policy একা যথেষ্ট নয়। Account 111122223333-এর ভেতরেও partner-reader role-এর identity policy-তে একই কাজের Allow থাকতে হবে। আরেকটি পথ হলো পর্ব ৩১-এর assume role, অর্থাৎ অন্য account-এর role ধারণ করা। তখন role-এর trust policy বলে কে তাকে ধারণ করতে পারবে, আর ধারণকারীর দিকে sts:AssumeRole-এর Allow লাগে। এটিও দুই পক্ষের সম্মতি। Trust policy-তে "Principal": "*" দেখলে সাথে সাথে থামুন। ওটি প্রায় সবসময় ভুল।

Provider-এর ভাষায় “same-account” আর “cross-account”-এর সীমা হলো account. তাই account-ই বড় দেয়াল। Production আর development আলাদা account-এ রাখার একটি বড় কারণ এটিই। সে নকশা পর্ব ৩৫-এ। আর bucket-কে ভুলে public করা ঠেকাতে Block Public Access বাড়তি বেড়া হিসেবে থাকে, পর্ব ২১ দেখুন।

৪ · Wildcard ছড়ায়, condition সরু করে

Policy-তে wildcard দুটি: * মানে যেকোনো অক্ষরের সারি, ? মানে ঠিক একটি অক্ষর। s3:Get* লিখলে “Get” দিয়ে শুরু সব S3 action ধরা পড়ে। লেখা সহজ, কিন্তু চোখে দেখে বোঝা কঠিন এটি কতদূর ছড়াল। তাই নিচের কোডে ২০টি action-এর ছোট একটি নমুনা তালিকায় প্রতিটি pattern মেপে দেখি। আসল তালিকা অনেক বড়, তাই এই শতাংশগুলো শুধু এই নমুনার জন্য।

// How far does each pattern reach? A small sample of action names.
const actions = ['s3:GetObject', 's3:GetBucketPolicy', 's3:GetObjectTagging', 's3:PutObject',
  's3:PutBucketPolicy', 's3:DeleteObject', 's3:DeleteBucket', 's3:ListBucket',
  'ec2:DescribeInstances', 'ec2:DescribeImages', 'ec2:RunInstances', 'ec2:TerminateInstances',
  'iam:GetRole', 'iam:ListRoles', 'iam:PassRole', 'iam:PutRolePolicy', 'iam:CreateAccessKey',
  'sqs:SendMessage', 'sqs:ReceiveMessage', 'sqs:PurgeQueue'];
const toRegex = p => new RegExp('^' + p.replaceAll('.', '[.]').replaceAll('*', '.*').replaceAll('?', '.') + '$');
const expand = (p, list) => list.filter(a => toRegex(p).test(a));

const patterns = ['*', 's3:*', 's3:Get*', 's3:*Object', 's3:?etObject', 'ec2:Describe*', 'iam:*', 'iam:P*'];
for (const p of patterns) {
  const hit = expand(p, actions);
  const pct = (100 * hit.length / actions.length).toFixed(0);
  console.log(p.padEnd(15), String(hit.length).padStart(2), pct.padStart(4) + '%');
}
console.log('s3:*Object ->', expand('s3:*Object', actions).join(' '));
console.log('iam:P*     ->', expand('iam:P*', actions).join(' '));

// The provider adds a new action next year (invented name).
const later = [...actions, 's3:GetFutureThing'];
console.log('s3:Get* before', expand('s3:Get*', actions).length, 'after', expand('s3:Get*', later).length);
console.log('exact list stays', ['s3:GetObject'].length);

একটি *-এর জায়গা বদলালেই ফল আলাদা। s3:Get* দেয় ৩টি, s3:* দেয় ৮টি, আর শুধু * দেয় ২০টির ২০টি, অর্থাৎ 100%. s3:*Object মোটেই নিরীহ নয়: নমুনায় সে পড়া আর লেখার সাথে s3:DeleteObject-ও ধরেছে। আর iam:P* ছোট দেখালেও ধরেছে iam:PassRole ও iam:PutRolePolicy, দুটিই পর্যালোচনায় লাল দাগের action.

শেষের দুই লাইন সবচেয়ে জরুরি। Provider নতুন action যোগ করলে s3:Get* নিজে থেকেই 3 থেকে 4 হলো, যদিও policy কেউ ছোঁয়নি। ওই নাম আমাদের বানানো, ঘটনাটি বাস্তব। নির্দিষ্ট তালিকা আগের মতোই থাকে।

সব * ভুল নয়। কিছু action কোনো নির্দিষ্ট resource-এ খাটে না, যেমন অনেক Describe ধরনের action, তাই সেখানে "Resource": "*" ছাড়া উপায় থাকে না। পড়ার action-এ wildcard সাধারণত কম ঝুঁকির, যদিও সেখান থেকেও তথ্য বেরোতে পারে। আসল সতর্কতা লেখা, মোছা আর অনুমতি বদলানোর action-এ।

এবার উল্টো দিক। Condition একটি statement-কে নির্দিষ্ট পরিস্থিতিতে আটকে দেয়। Condition মিথ্যা হলে statement-টি যেন নেই। চারটি জনপ্রিয় ধরন:

কীসের ওপরAWS-এর key (উদাহরণ)কাজসতর্কতা
Source networkaws:SourceIp, aws:SourceVpceশুধু অফিস বা নির্দিষ্ট endpoint থেকেPrivate endpoint দিয়ে এলে অনেক সময় SourceIp থাকে না; service আপনার হয়ে ডাকলে IP আলাদা হয়
MFAaws:MultiFactorAuthPresentবিপজ্জনক কাজে MFA চাইস্থায়ী access key-এর অনুরোধে এই key থাকেই না
Tagaws:ResourceTag/project, aws:PrincipalTag/projectনিজের project-এর জিনিসে শুধুTag বদলানোর অনুমতিও তখন নিয়ন্ত্রণ করতে হয়
সময়aws:CurrentTimeএকটি তারিখ পর্যন্ত সাময়িক অনুমতিসময় UTC-তে লিখুন, মেয়াদ পরে মুছুন

Tag-ভিত্তিক এই পদ্ধতির নাম ABAC. RBAC-এ প্রতিটি project-এর জন্য আলাদা role বানাতে হয়। ABAC-এ একটি নিয়মই বলে “যার project-tag যা, সে শুধু সেই tag-এর জিনিসে কাজ করবে”। নিচে তিনটি ধরন একসাথে:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "StartStopOwnProjectVms",
      "Effect": "Allow",
      "Action": ["ec2:StartInstances", "ec2:StopInstances"],
      "Resource": "arn:aws:ec2:*:123456789012:instance/*",
      "Condition": {
        "StringEquals": {
          "aws:ResourceTag/project": "${aws:PrincipalTag/project}"
        }
      }
    },
    {
      "Sid": "DenyDeleteWithoutMfa",
      "Effect": "Deny",
      "Action": ["s3:DeleteObject", "s3:DeleteBucket"],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": { "aws:MultiFactorAuthPresent": "false" }
      }
    },
    {
      "Sid": "TemporaryAuditRead",
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::example-bucket/audit/*",
      "Condition": {
        "DateLessThan": { "aws:CurrentTime": "2026-12-31T23:59:59Z" }
      }
    }
  ]
}

দ্বিতীয় statement-এর BoolIfExists খেয়াল করুন। শুধু Bool লিখলে স্থায়ী access key-এর অনুরোধে key-টি অনুপস্থিত থাকে, condition মেলে না, আর Deny খাটে না। এই একটি শব্দ না থাকলে নিয়মটি চুপচাপ ফাঁকা হয়ে যায়। Condition-এর ভেতরে দুটি key থাকলে দুটিই সত্য হতে হয়, আর একটি key-এর একাধিক মান থাকলে যেকোনো একটি মিললেই চলে। প্রথমটি AND, দ্বিতীয়টি OR.

এবার একটি ছোট evaluator চালিয়ে দেখুন। এটি আসল engine নয়, শুধু একটি policy-র ভেতরের যুক্তি: default deny, Deny-র জয়, wildcard আর condition. প্রতিটি অনুরোধের নিচে কারণের সারি ছাপা হবে।

const match = (pat, s) => new RegExp('^' + pat.replaceAll('.', '[.]').replaceAll('*', '.*').replaceAll('?', '.') + '$').test(s);
const ARN = 'arn:aws:s3:::example-bucket/*';
const policy = [
  { sid: 'ReadReports', effect: 'Allow', action: 's3:Get*', resource: ARN },
  { sid: 'UploadFromOffice', effect: 'Allow', action: 's3:PutObject', resource: ARN,
    when: { ipPrefix: '10.20.' } },
  { sid: 'DeleteByOps', effect: 'Allow', action: 's3:Delete*', resource: ARN,
    when: { team: 'ops' } },
  { sid: 'DenyDeleteNoMfa', effect: 'Deny', action: 's3:Delete*', resource: '*',
    when: { mfa: false } },
];
const condOk = (w = {}, r) =>
  (w.ipPrefix === undefined || r.ip.startsWith(w.ipPrefix)) &&
  (w.team === undefined || r.team === w.team) &&
  (w.mfa === undefined || r.mfa === w.mfa);
function evaluate(r) {
  const res = 'arn:aws:s3:::example-bucket/' + r.key, trace = [];
  let allowed = false;
  for (const s of policy) {
    if (!match(s.action, r.action) || !match(s.resource, res)) continue;
    if (!condOk(s.when, r)) { trace.push(s.sid + ': condition false'); continue; }
    trace.push(s.sid + ': ' + s.effect);
    if (s.effect === 'Deny') return ['DENY (explicit)', trace];
    allowed = true;
  }
  return [allowed ? 'ALLOW' : 'DENY (implicit)', trace];
}
const base = { key: 'r.csv', ip: '203.0.113.9', team: 'dev', mfa: true };
for (const [action, extra] of [['s3:GetObject', {}], ['s3:PutObject', { ip: '10.20.3.4' }],
  ['s3:PutObject', {}], ['s3:DeleteObject', { team: 'ops' }],
  ['s3:DeleteObject', { team: 'ops', mfa: false }], ['s3:ListBucket', {}]]) {
  const [result, trace] = evaluate({ ...base, ...extra, action });
  console.log(action, JSON.stringify(extra), '=>', result);
  console.log('   ', trace.join(' | ') || 'no statement matched');
}

ছয়টি অনুরোধ, তিন রকম ফল। প্রথম দুটি ALLOW. তৃতীয়টিতে উৎস IP অফিসের নয়, তাই UploadFromOffice: condition false, আর ফল DENY (implicit). Condition মিথ্যা হলে statement বাদ পড়ে, Deny হয়ে যায় না।

চতুর্থ আর পঞ্চম অনুরোধ পাশাপাশি পড়ুন। দুটিতেই DeleteByOps: Allow মিলেছে। MFA থাকলে Deny-র condition মিথ্যা, তাই ALLOW. MFA না থাকলে DenyDeleteNoMfa: Deny, ফল DENY (explicit). Allow আগে মিলেছিল, তবু টেকেনি। শেষ অনুরোধে s3:ListBucket-এর জন্য no statement matched, অর্থাৎ শুদ্ধ default deny.

৫ · Azure আর Google কোথায় আলাদা

এতক্ষণের নামগুলো AWS-এর, কারণ সেখানে স্তরগুলো সবচেয়ে আলাদা করে দেখা যায়। ধারণা তিনটিই এক: default deny, ন্যূনতম অনুমতি, আর ওপর থেকে guardrail. তফাত আসে গঠনে। নিচের সারসংক্ষেপ লেখার সময়ের, service-ভেদে বদলাতে পারে, তাই provider-এর ডকুমেন্টেশন মিলিয়ে নিন।

বিষয়AWSAzureGoogle Cloud
অনুমতি কোথায় লেখাPolicy JSON, identity বা resource-এর গায়েRole assignment: কে, কোন role, কোন scopeAllow policy-তে binding: কে, কোন role
উত্তরাধিকারIdentity-তে নেই; SCP organisation থেকে নামেManagement group → subscription → resource group → resourceOrganization → folder → project → resource
Allow যোগ হয়?একই স্তরের Allow যোগ হয়, স্তরগুলোর ছেদ হয়হ্যাঁ, সব role assignment যোগ হয় (additive)হ্যাঁ, ওপরের allow নিচে নামে; নিচে তা তোলা যায় না
স্পষ্ট “না”Deny statementDeny assignment, role assignment-এর ওপরে জেতে; সাধারণত platform-এর feature এগুলো বানায়IAM deny policy, allow-এর আগে দেখা হয়
GuardrailSCP, RCPAzure Policy (মূলত resource-এর গঠন ও সেটিং)Organization Policy (resource-এর সেটিং), deny policy
ConditionCondition blockRole assignment condition (কিছু ক্ষেত্রে)IAM Conditions
বড় ফাঁদ* অনুমতিSubscription scope-এ OwnerProject-এ Owner বা Editor (basic role)

সবচেয়ে বড় মানসিক বদল inheritance-এ। Azure আর Google-এ ওপরের স্তরে দেওয়া অনুমতি নিচের সব জায়গায় নামে। ফলে একটি project-এ দেখে মনে হতে পারে কারও অনুমতি নেই, অথচ folder স্তরে দেওয়া আছে। তাই সেখানে “কে কী পারে” জানতে শুধু resource নয়, ওপরের সব স্তর দেখতে হয়।

Azure-এর role definition-এ NotActions থাকে। নাম দেখে Deny মনে হলেও এটি Deny নয়। এটি শুধু ওই role থেকে কিছু action বিয়োগ করে। অন্য role সেই action দিলে তা পাওয়া যাবে। আর Linux permission-এর মতো সরল model থেকে আসা পাঠকদের জন্য: cloud-এর স্তরগুলো ফাইলের owner-group-other-এর চেয়ে অনেক বেশি, তবু মূল প্রশ্ন একই।

৬ · Least privilege বাস্তবে — ছোট শুরু, log দেখে কমানো

Least privilege মানে কাজের জন্য যতটুকু দরকার ততটুকুই অনুমতি। বলা সহজ। কঠিন হলো, একটি নতুন service-এর দরকার কতটুকু, সেটি শুরুতে কেউ ঠিক জানেন না। তাই একে একবারের কাজ না ভেবে একটি চক্র ভাবুন। সময়ের সাথে অনুমতি জমতেই থাকে, একে বলে permission creep. মেসের ভাড়াটিয়া চলে যাওয়ার পরও চাবি ফেরত না নিলে যা হয়, এটিও তাই।

ধাপকী করবেনকোন উপাদান
১. ছোট শুরুজানা কাজগুলোই দিন; development পরিবেশে চালাননির্দিষ্ট action, নির্দিষ্ট ARN
২. ব্যবহার দেখাকোন action আসলেই ডাকা হলো, দেখুনAudit log, last accessed data
৩. Policy বানানোব্যবহারের ভিত্তিতে খসড়া তৈরিLog থেকে policy generation
৪. যাচাইLint আর simulator চালানPolicy linter, policy simulator
৫. বাদ দেওয়াঅব্যবহৃত অনুমতি সরান, denied log দেখুনStaging, তারপর production
৬. আবারনিয়মিত পর্যালোচনাAnalyzer-এর সতর্কতা

তিন provider-এই এই কাজের সরঞ্জাম আছে। নাম ও সুবিধা বদলায়, তাই ব্যবহারের আগে ডকুমেন্টেশন দেখুন:

কাজAWSAzureGoogle Cloud
কে কী করলCloudTrailActivity LogCloud Audit Logs
অব্যবহৃত অনুমতিLast accessed data, IAM Access AnalyzerAccess reviews, role assignment-এর তালিকাIAM recommender
Policy পরীক্ষাIAM Policy SimulatorPortal-এর Check accessPolicy Simulator, Policy Troubleshooter
কে কোথায় অনুমতি পেয়েছেIAM Access AnalyzerPortal-এর Access control (IAM) দৃশ্যPolicy Analyzer
Policy lintAccess Analyzer-এর policy validationসাধারণত IaC scanner দিয়ে, পর্ব ৫৫ দেখুন

এবার মূল হিসাবটি নিজে করি। একটি role-কে s3:* আর sqs:* দেওয়া আছে। নমুনা তালিকায় তা ১৪টি action. ৯০ দিনের log-এর সাথে মিলিয়ে দেখি কোনটি রাখা যায়, কোনটি নিয়ে জিজ্ঞেস করতে হবে, আর কোনটি বাদ।

// Compare granted actions with an access log. Sample data, 90-day window.
const catalog = ['s3:GetObject', 's3:PutObject', 's3:DeleteObject', 's3:ListBucket',
  's3:GetBucketPolicy', 's3:PutBucketPolicy', 's3:PutBucketAcl', 's3:DeleteBucket',
  'sqs:SendMessage', 'sqs:ReceiveMessage', 'sqs:DeleteMessage', 'sqs:PurgeQueue',
  'sqs:SetQueueAttributes', 'sqs:DeleteQueue'];
const granted = ['s3:*', 'sqs:*'];
const log = `3 s3:GetObject|5 s3:ListBucket|8 sqs:ReceiveMessage|8 sqs:DeleteMessage
12 s3:DeleteObject|20 s3:GetObject|33 s3:PutObject|41 sqs:ReceiveMessage|41 sqs:DeleteMessage
55 s3:ListBucket|60 s3:PutObject|72 s3:GetObject|85 sqs:ReceiveMessage|85 sqs:DeleteMessage
88 s3:PutObject|89 s3:ListBucket|90 s3:GetObject`.split(/[|\n]/).map(l => l.split(' '));

const expand = p => catalog.filter(a => a === p || (p.endsWith('*') && a.startsWith(p.slice(0, -1))));
const allowed = [...new Set(granted.flatMap(expand))];
const seen = {};
for (const [day, action] of log) {
  seen[action] = seen[action] || { hits: 0, last: 0 };
  seen[action].hits++;
  seen[action].last = Math.max(seen[action].last, Number(day));
}
const plan = { KEEP: [], ASK: [], REMOVE: [] };
for (const a of allowed) {
  const s = seen[a];
  if (!s) plan.REMOVE.push(a);
  else if (s.hits < 2) plan.ASK.push(a + ' (hits ' + s.hits + ', last day ' + s.last + ')');
  else plan.KEEP.push(a);
}
for (const k of Object.keys(plan)) console.log(k, plan[k].length, '\n  ' + plan[k].join('\n  '));
const pct = (100 * plan.REMOVE.length / allowed.length).toFixed(1);
console.log('granted', allowed.length, 'removable', plan.REMOVE.length, '=', pct + '%');

ফল: KEEP 5, ASK 1, REMOVE 8. শেষ লাইন granted 14 removable 8 = 57.1%, অর্থাৎ অর্ধেকের বেশি অনুমতি ৯০ দিনে একবারও লাগেনি। হাতে মিলিয়ে নিন: 8 ÷ 14 = 0.571.

আসল শিক্ষা ASK সারিতে: s3:DeleteObject (hits 1, last day 12). একবার মাত্র ব্যবহার হয়েছে, কিন্তু সেটি হয়তো তিন মাসে একবারের পরিষ্কারের কাজ। Log শুধু বলে কী ঘটেছে, কী ঘটবে তা বলে না। বছরে একবারের কাজ ৯০ দিনের log-এ না-ও থাকতে পারে। তাই বাদ দেওয়ার আগে role-এর মালিককে জিজ্ঞেস করতে হয়।

একই role-কে এবার ধাপে ধাপে কড়া করি। লক্ষ্য শুধু action কমানো নয়, resource-ও সরু করা, আর কোনো ডাউনটাইম ছাড়া কাজটি শেষ করা।

report-app-role-এর অবস্থা
Action (নমুনা ১৪টির মধ্যে)
Resource
যা জানা গেল
Production
  1. শুরুর অবস্থা। s3:* আর sqs:*, resource *. App দিব্যি চলছে, আর সে কারণেই কেউ এটিতে হাত দেননি।
  2. ৯০ দিনের log. ৫টি action নিয়মিত ডাকা হয়, ১টি মাত্র একবার, ৮টি একবারও নয়। তথ্য হাতে এলো, কিন্তু এখনো কিছু বদলায়নি।
  3. মালিককে জিজ্ঞেস। s3:DeleteObject নিয়ে জানা গেল এটি ত্রৈমাসিক পরিষ্কারের কাজ, তাই রাখতে হবে। এই ধাপটি বাদ দিলে তিন মাস পরে রহস্যময় ব্যর্থতা আসত।
  4. Action-এর খসড়া। ৮টি বাদ, থাকল ৬টি। এখনো resource *, তাই কাজটি অর্ধেক।
  5. Resource সরু করা। *-এর জায়গায় একটি bucket আর একটি queue-এর ARN বসল। মনে রাখুন, s3:ListBucket খাটে bucket-এর ARN-এ, আর object-এর action খাটে bucket/*-এ।
  6. যাচাই ও চালু। Simulator-এ ৬টি allowed, ৮টি implicitDeny. Staging-এ এক দিন চলল, তারপর production-এ নতুন version. পুরোনো version রেখে দেওয়া হলো, যাতে দ্রুত ফেরা যায়, আর denied log-এ alert বসল। সাত দিনে কোনো অস্বীকার নেই, ফলে পুরোনোটি মোছা হলো।

শেষ policy-টি এমন দাঁড়াল। Resource আলাদা বলে statement-ও আলাদা:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListReportBucket",
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::example-bucket"
    },
    {
      "Sid": "ReadWriteDeleteReports",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::example-bucket/reports/*"
    },
    {
      "Sid": "ConsumeJobQueue",
      "Effect": "Allow",
      "Action": ["sqs:ReceiveMessage", "sqs:DeleteMessage"],
      "Resource": "arn:aws:sqs:ap-southeast-1:123456789012:report-jobs"
    }
  ]
}

Lint আর simulator — পরীক্ষার দুই হাতিয়ার

Policy linting মানে code চালানোর আগেই লেখা যাচাই। এটি বানান ভুল, অচল action, *-সহ ঝুঁকিপূর্ণ নকশা ধরে। Policy simulator আসল কাজ না করে বলে দেয় একটি পরিচয়ের একটি অনুরোধে কী রায় হতো। নিচের দুটি AWS CLI কমান্ড শুধু উদাহরণ, চালাতে account লাগবে। এগুলো কিছু বদলায় না, তবে নিজের দায়িত্বে পরীক্ষার account-এ চালান। শেষে role বা ফাইল রেখে দিলে মুছে ফেলুন।

# Lint: check a policy file before it is attached
aws accessanalyzer validate-policy \
  --policy-type IDENTITY_POLICY \
  --policy-document file://report-app-final.json \
  --query 'findings[].[findingType,issueCode]' --output text

# Simulate: what would happen, without doing it
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:role/report-app-role \
  --action-names s3:GetObject s3:DeleteBucket \
  --resource-arns "arn:aws:s3:::example-bucket/reports/a.csv" \
  --query 'EvaluationResults[].[EvalActionName,EvalDecision]' \
  --output text

নমুনা আউটপুট, চালিয়ে পাওয়া নয় (version-ভেদে আলাদা হতে পারে):

s3:GetObject     allowed
s3:DeleteBucket  implicitDeny

Simulator-এর সীমাও জানা দরকার। সে আসল অনুরোধ পাঠায় না, আর সব স্তর সবসময় হিসাবে আসে না; যেমন resource policy-র ফল দেখতে সেটি আলাদা করে দিতে হতে পারে। তাই simulator “হ্যাঁ” বললেও একবার throwaway পরিবেশে আসল কাজটি চালিয়ে দেখুন।

Policy as code: Policy ফাইল Git-এ থাকলে প্রতিটি বদল review হয়, আর pipeline স্বয়ংক্রিয়ভাবে বলতে পারে “Action: * থাকলে merge বন্ধ”। Linter, simulator আর নিয়মের পরীক্ষা তখন CI-র অংশ হয়ে যায়। OPA-র মতো tool আর plan review নিয়ে বিস্তারিত পর্ব ৫৫-এ।

৭ · “Access denied” পড়া — স্তর ধরে ধরে

অনেকে access denied দেখলেই বড় অনুমতি দিয়ে দেন। কাজ চলে, কিন্তু নিরাপত্তা হারায়। বদলে error-টি পড়ুন। AWS-এর অনেক service-এ এখন message-এই স্তরের ইঙ্গিত থাকে। নমুনা বার্তা (service-ভেদে আলাদা হতে পারে):

An error occurred (AccessDenied) when calling the GetObject operation:
User: arn:aws:sts::123456789012:assumed-role/report-app-role/i-0abc
is not authorized to perform: s3:GetObject
on resource: "arn:aws:s3:::example-bucket/reports/a.csv"
because no identity-based policy allows the s3:GetObject action

এখানে চারটি উত্তর একসাথে আছে: কে, কী, কোথায়, আর কোন স্তর। “User” অংশে যে নাম, সেটিই আসল পরিচয়। সেটি আপনার ধারণার সাথে না মিললে সমস্যা policy-তে নয়, credential-এ। শেষের বাক্যাংশটি ধরে স্তর চিনুন:

বাক্যাংশ (সাধারণ রূপ)স্তরপ্রথম কাজ
no identity-based policy allowsIdentityনির্দিষ্ট action আর ARN যোগ
no resource-based policy allowsResourceBucket বা key-এর policy দেখা
no permissions boundary allowsBoundaryBoundary-র মালিকের সাথে কথা
no session policy allowsSessionSession তৈরির কোড দেখা
explicit deny in a service control policyGuardrailঅনুমোদিত পথ খোঁজা, guardrail না খোলা
explicit deny in an identity-based policyIdentity-র DenyDeny statement আর তার condition পড়া
no VPC endpoint policy allowsNetwork পথEndpoint policy দেখা

সবসময় এত ভালো বার্তা মেলে না। অনেক app শুধু code-টুকু log করে, বাকিটা ফেলে দেয়। তখন স্তর ধরে খুঁজতে হয়। নিচের স্টেপারে ভোরের সেই report প্রোগ্রামের সমস্যাটিই ধরি।

  1. ErrorAccessDeniedapp log
  2. কেcallerপরিচয় ঠিক
  3. কীaudit logআসল action
  4. স্তরidentityAllow নেই
  5. সমাধানএকটি ARNসরু Allow
খোঁজের খাতা
যা দেখছেন
যা পেলেন
সন্দেহের তালিকা
  1. লক্ষণ। App log-এ শুধু download failed: AccessDenied. কে, কোন action, কোন স্তর, কিছুই নেই। তাই কোনো অনুমান নয়, আগে তথ্য।
  2. কে? aws sts get-caller-identity বলল app report-app-role-এ চলছে, যেমন হওয়ার কথা। ভুল credential-এর সন্দেহ বাদ।
  3. কী? Audit log-এ errorCode ধরে খোঁজা হলো। অবাক করা ফল: অস্বীকৃত কাজটি kms:Decrypt, S3-এর কিছু নয়। Object-টি KMS key দিয়ে encrypted, তাই পড়তে দুটি অনুমতি লাগে।
  4. Simulator. s3:GetObject allowed, kms:Decrypt implicitDeny. কোনো explicitDeny নয়, তাই guardrail বা Deny statement খোঁজার দরকার পড়ল না।
  5. স্তর ধরা পড়ল। Identity policy-তে KMS-এর কোনো Allow নেই। Key policy আগে থেকেই account-এর IAM policy-কে মানে, তাই সমস্যা identity-তেই। Key policy অন্যরকম হলে সেটিও বদলাতে হতো।
  6. সরু সমাধান। kms:* নয়, শুধু kms:Decrypt, শুধু একটি key-এর ARN. চাইলে kms:ViaService condition দিয়ে শুধু S3-এর পথে সীমিত করা যায়।
  7. যাচাই। App আবার চলল, report তৈরি হলো, audit log-এ নতুন অস্বীকার ০। চিকিৎসার পর এই শেষ ধাপটিই নিশ্চিত করে রোগ সেরেছে।

পুরো টিম বা account-এর ছবি পেতে audit log-কে একসাথে পড়া যায়। আসল CloudTrail JSON-এ আসে; এখানে সেটি সরল করা এক লাইনের নমুনা। পদ্ধতিটি পর্ব ৯-এর।

set -euo pipefail
export LC_ALL=C
# Sample audit log: time, role, action, result, reason. All values are fictional.
cat > audit.log <<'LOG'
2026-03-02T09:14:05Z report-app s3:GetObject Success -
2026-03-02T09:14:07Z report-app kms:Decrypt AccessDenied no-identity-policy
2026-03-02T09:19:07Z report-app kms:Decrypt AccessDenied no-identity-policy
2026-03-02T10:02:11Z dev-role ec2:RunInstances AccessDenied explicit-deny-guardrail
2026-03-02T10:03:40Z dev-role ec2:RunInstances AccessDenied explicit-deny-guardrail
2026-03-02T10:04:02Z dev-role ec2:RunInstances Success -
2026-03-02T11:30:15Z ci-deploy iam:PassRole AccessDenied no-identity-policy
2026-03-02T12:45:51Z report-app kms:Decrypt AccessDenied no-identity-policy
2026-03-02T13:05:09Z backup-job s3:PutObject AccessDenied no-resource-policy
2026-03-02T13:05:39Z backup-job s3:PutObject AccessDenied no-resource-policy
LOG

echo "denied / total:"
awk '$4 == "AccessDenied" { d++ } END { print d " / " NR }' audit.log

echo "top denied (count role action reason):"
grep ' AccessDenied ' audit.log |
  awk '{ print $2, $3, $5 }' | sort | uniq -c | sort -k1,1nr -k2,2

echo "by layer:"
awk '$4 == "AccessDenied" { print $5 }' audit.log | sort | uniq -c | sort -k1,1nr -k2,2

প্রথমে 8 / 10: দশটি অনুরোধের আটটি অস্বীকৃত। তারপর তালিকার শীর্ষে 3 report-app kms:Decrypt no-identity-policy, অর্থাৎ একই অভাব বারবার ফিরছে। 2 dev-role ec2:RunInstances explicit-deny-guardrail দেখায় guardrail তার কাজ করছে; পরের অনুরোধটি সফল, মানে ঠিক region-এ চালানো হয়েছে। এটি সমস্যা নয়, নকশা।

শেষ অংশ স্তরওয়ারি হিসাব: 4 no-identity-policy, 2 explicit-deny-guardrail, 2 no-resource-policy. অস্বীকারের এই গণনা দুই দিকেই কাজে লাগে। হঠাৎ বেড়ে গেলে হয় কোনো নতুন release ভেঙেছে, নয়তো কেউ এমন কিছু করার চেষ্টা করছেন যা তাঁর করার কথা নয়। সে নজরদারি পর্ব ৩৪-এ।

তিনটি পরিচিত ধাঁধা। (ক) s3:ListBucket না থাকলে অস্তিত্বহীন object চাইলে অনেক সময় 404-এর বদলে 403 আসে, তাই “অনুমতি নেই” দেখে ভুল জায়গায় খুঁজতে পারেন। (খ) IAM-এর বদল সব জায়গায় পৌঁছাতে কিছুটা সময় লাগতে পারে, একে বলে eventual consistency. তাই বদলের পরপরই একবারের ব্যর্থতায় ঘাবড়াবেন না। (গ) Audit log-ও কয়েক মিনিট দেরিতে আসতে পারে, আর object-স্তরের ঘটনা আলাদা করে চালু করতে হতে পারে।

৮ · বাড়তি অনুমতির সাধারণ ভুল — review-এর তালিকা

এই তালিকা policy পর্যালোচনার জন্য। প্রতিটি সারি পড়ুন একজন reviewer-এর চোখে: এখানে বাড়তি অনুমতি কী, আর সরু রূপটি কী।

যা দেখছেনকেন লাল দাগযা করবেন
"Action": "*" + "Resource": "*"Administrator-এর সমান। একটি credential ফাঁস মানে পুরো accountদরকারি action আর ARN-এর তালিকা; মানুষের জন্য অস্থায়ী admin role
iam:PassRole + "Resource": "*"এটি অন্য service-কে role দেওয়ার ক্ষমতা। ক্ষমতা তাই নিজের চেয়ে বড় হতে পারেনির্দিষ্ট role-এর ARN, সাথে iam:PassedToService
iam:*, বা policy বদলানোর actionঅনুমতি বদলানোর অনুমতি আসলে সব অনুমতির চাবিআলাদা admin role; delegated কাজে permission boundary বাধ্যতামূলক
s3:* + "Resource": "*"সব bucket, মোছা আর policy বদলানো সহনির্দিষ্ট bucket, নির্দিষ্ট action
"Principal": "*"Resource বা role সবার জন্য খোলা হতে পারেনির্দিষ্ট principal; প্রয়োজনে organisation-এর condition
Allow-এর সাথে NotAction“এগুলো বাদে সব” মানে ভবিষ্যতের নতুন action-ও AllowAllow-এ পজিটিভ তালিকা; NotAction শুধু ভেবেচিন্তে Deny-তে
পুরোনো role, পুরোনো access keyব্যবহার নেই, কিন্তু দরজা খোলাLast used দেখে নিষ্ক্রিয়, তারপর মোছা

iam:PassRole নিয়ে একটু বেশি বলা দরকার, কারণ নামটি নিরীহ শোনায়। আপনি যখন একটি VM-কে instance role দেন, বা একটি function-কে role দেন, তখন আসলে আপনি নিজের হাতে থাকা অধিকারে অন্য একটি পরিচয় একটি service-এর হাতে তুলে দিচ্ছেন। তাই pass role আসলে delegation. প্রশ্নটি হলো: কোন role, কোন service-কে? কারখানার ভাষায়, যিনি অন্যের নামে গেটপাস ইস্যু করতে পারেন, তাঁর তালিকায় ঠিক কোন পাস আছে, তা লেখা থাকা চাই। সরু রূপটি এমন:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PassOnlyReportRoleToEc2",
      "Effect": "Allow",
      "Action": ["iam:PassRole"],
      "Resource": "arn:aws:iam::123456789012:role/report-app-role",
      "Condition": {
        "StringEquals": { "iam:PassedToService": "ec2.amazonaws.com" }
      }
    }
  ]
}

আরও গভীরে: “Deny জেতে” নিয়মটি নতুন নয়। XACML মানদণ্ডে (OASIS, ২০০৩ সাল থেকে) এর নাম deny-overrides combining algorithm. AWS-এর Zelkova গবেষণায় (Backes ও সহকর্মীরা, FMCAD ২০১৮) policy-কে গাণিতিক সূত্রে বদলে SMT solver দিয়ে প্রশ্ন করা হয়, যেমন “এই bucket কি বাইরের কেউ পড়তে পারেন?” পরীক্ষা কয়েকটি উদাহরণ দেখে, কিন্তু এই পদ্ধতি সম্ভাব্য সব অনুরোধের ওপর উত্তর দেওয়ার চেষ্টা করে। Access Analyzer-এর ভিত্তিতেও এই ধরনের automated reasoning আছে বলে AWS প্রকাশ্যে জানিয়েছে।

পরীক্ষা ও ইন্টারভিউতে:

  • Allow আর Deny একসাথে মিললে? Explicit Deny জেতে, statement-এর ক্রম যাই হোক।
  • Implicit আর explicit deny-র তফাত? Implicit মানে কোনো Allow নেই, Allow যোগ করলে উঠে যায়। Explicit কোনো Allow ওলটাতে পারে না।
  • SCP কি অনুমতি দেয়? না। SCP আর permission boundary শুধু সর্বোচ্চ সীমা টানে, Allow লাগে identity বা resource policy থেকে।
  • Cross-account-এ কার Allow লাগে? দুই পক্ষের: caller-এর identity policy আর resource-এর দিকের policy.
  • Access denied পেলে প্রথম কাজ? বড় অনুমতি নয়; আগে দেখুন কে, কোন action, কোন resource, কোন স্তর।

৯ · AI-এর যুগে IAM policy

AI-কে শুধু “access denied ঠিক করে দিন” বললে সে প্রায়ই সবচেয়ে সহজ পথ নেয়: *. Error চলে যায়, আর সবাই খুশি। আসল সমস্যাটি তখনই শুরু হয়, কারণ ভুল অনুমতি কোনো error দেয় না। সে চুপচাপ বসে থাকে। Cloud-এর বাকি কাজেও AI একই ধরনের ভুল করে, তাই পুরো তালিকাটি মনে রাখুন:

AI-এর ভুলকেন ক্ষতিকরযাচাই
Action: *, Resource: *Error ঢেকে ঝুঁকি বাড়ায়Linter, আর log-এর সাথে মিলিয়ে দেখা
অস্তিত্বহীন action বা condition keyPolicy চলে, কিন্তু নিয়ম কাজ করে নাLinter ও provider-এর action তালিকা
Deny-তে Bool, IfExists নেইকিছু অনুরোধে Deny খাটে নাSimulator-এ দুই রকম credential
Bucket-কে public করা, 0.0.0.0/0 খোলাIdentity ঠিক, পথ খোলাPublic access block, SG পর্যালোচনা
Key hardcode করা, latest tag, বাতিল API versionফাঁস আর অনিশ্চিত আচরণSecret scanner, version নির্দিষ্ট করা
বানানো flag, খরচ উপেক্ষাকমান্ড ভাঙে বা বিল বাড়েDocs, budget alert
terraform destroy, kubectl delete, rm -rf সতর্কতা ছাড়াঅপূরণীয় ক্ষতিterraform plan, --dry-run আর throwaway পরিবেশ

AI-কে সবচেয়ে ভালো কাজে লাগান policy পর্যালোচনায়। আসল account id, key বা token কখনো prompt-এ দেবেন না। নিচের কাঠামোয় নকল নাম ব্যবহার করুন:

তুমি একজন cloud security reviewer. নিচের IAM policy একটি app role-এর। App শুধু [একটি bucket-এর একটি prefix] পড়ে আর লেখে। [নকল account id দিয়ে policy JSON পেস্ট করুন] ১. প্রতিটি statement-এ কোন action আর resource কাজের জন্য দরকার নেই, বলো। ২. Wildcard থাকলে সেটি কতদূর ছড়াতে পারে, ব্যাখ্যা করো। ৩. একটি সরু policy দাও, প্রতিটি action-এর কারণসহ। ৪. কোন action বা condition key তুমি নিশ্চিত নও, আলাদা করে জানাও, যাতে আমি provider-এর docs-এ মিলিয়ে নিতে পারি। ৫. কোন log বা simulator পরীক্ষা দিয়ে আমি এটি যাচাই করব, বলো।

AI-এর লেখা policy হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১Deny কেন সবসময় Allow-কে হারায়? উল্টোটা হলে কী সমস্যা হতো?

Policy ভাষার নকশাকারদের সামনে প্রশ্নটি ছিল: দুটি নিয়ম পরস্পরবিরোধী হলে কে জিতবে? XACML মানদণ্ড (OASIS, ২০০৩ সাল থেকে) এই সিদ্ধান্তকে “combining algorithm” নাম দেয়, আর deny-overrides তার একটি রূপ। Cloud IAM সেই পথই নিয়েছে, তার একটি গভীর কারণ আছে।

বড় প্রতিষ্ঠানে নিয়ম লেখেন অনেক মানুষ। নিরাপত্তা দল organisation-এর নিয়ম লেখে, একটি product দল নিজের policy লেখে, আবার একজন developer ছোট একটি ব্যতিক্রম যোগ করেন। Allow যদি Deny-কে হারাতে পারত, তাহলে যেকোনো নিচের স্তরের একজন মানুষ ওপরের নিরাপত্তা নিয়ম এড়িয়ে যেতে পারতেন। Deny-র জয় তাই শুধু যুক্তির নিয়ম নয়, এটি প্রতিষ্ঠানের ক্ষমতার কাঠামো। ওপরের স্তর জানে তার বেড়া নিচ থেকে খোলা যাবে না।

এর দুটি ব্যবহারিক ফল আছে। প্রথমত, ক্রমের ওপর নির্ভরতা চলে যায়। হাজার statement-এর জগতে “কে আগে” হিসাব রাখা অসম্ভব, আর deny-overrides-এ রায় ক্রম-নিরপেক্ষ। এটি audit আর স্বয়ংক্রিয় বিশ্লেষণকেও সহজ করে। দ্বিতীয়ত, Deny-র দাম আছে। একটি বেশি চওড়া Deny একটি জরুরি কাজ আটকে দিতে পারে, আর সেটি খোলার পথও নেই। তাই Deny কম ব্যবহার করাই ভালো রীতি: সাধারণ নিয়ন্ত্রণ আসে Allow না দিয়ে, আর Deny রাখা হয় “কখনোই না” ধরনের সীমার জন্য, যেমন অননুমোদিত region, বা MFA ছাড়া মোছা।

Azure-এর দিকে তাকালে বৈচিত্র্য বোঝা যায়। সেখানে সাধারণ role-এ Deny নেই, অনুমতি শুধু যোগ হয়। স্পষ্ট “না”-এর জন্য আলাদা deny assignment, যা সাধারণত platform-এর হাতে থাকে। পথ আলাদা, লক্ষ্য একই: সবচেয়ে কড়া “না” যেন সহজে ওলটানো না যায়।

মূল উপলব্ধি: Deny-র জয় একটি প্রযুক্তিগত সিদ্ধান্তের চেয়ে বেশি কিছু: এটি নিরাপত্তা-দায়িত্বের স্তরবিন্যাসকে সিস্টেমে লিখে রাখা। তবে শক্তিশালী হাতিয়ার বলেই একে কম আর সাবধানে ব্যবহার করতে হয়।

প্র ০২Least privilege ১৯৭৫ সালের ধারণা। এত পুরোনো একটি কথা cloud-এ আজও এত কঠিন কেন?

Jerome Saltzer আর Michael Schroeder ১৯৭৫ সালে “The Protection of Information in Computer Systems” প্রবন্ধে কয়েকটি নকশা-নীতি লেখেন। তার একটি “least privilege”: প্রতিটি প্রোগ্রাম আর ব্যবহারকারী কাজের জন্য ন্যূনতম অধিকার নিয়ে চলবে। “fail-safe defaults” নীতিটিও সেখানেই, যা আজকের default deny-এর পূর্বসূরি। পঞ্চাশ বছর পরেও কথাটি ঠিক, তবে বাস্তবায়ন কেন কঠিন?

প্রথম কারণ আয়তন। একটি বড় cloud provider-এর service শত শত, আর action হাজার হাজার। কোন কাজের জন্য ঠিক কোন action লাগে, সেটি প্রায়ই পরিষ্কার নয়। একটি console-এর ক্লিক ভেতরে কয়েকটি API ডাকতে পারে। দ্বিতীয় কারণ অসমতা। বেশি অনুমতি কোনো শব্দ করে না, কিন্তু কম অনুমতি সাথে সাথে কাজ ভাঙে। ফলে developer-এর ওপর চাপ সবসময় একদিকে: “আপাতত বড় অনুমতি দিন, পরে কমাব।” সেই “পরে” খুব কমই আসে।

তৃতীয় কারণ সময়। মানুষের ভূমিকা বদলায়, service-এর কাজ বদলায়, কিন্তু অনুমতি সাধারণত শুধু বাড়ে। একে বলে permission creep. চতুর্থ কারণ মালিকানা। একটি পুরোনো role কার, কেউ জানেন না, তাই কেউ মুছতে সাহস করেন না, পাছে কোনো ত্রৈমাসিক কাজ ভাঙে।

তাহলে উপায় কী? আধুনিক পদ্ধতি হলো মানুষের মাথায় ভরসা না রেখে ব্যবহার থেকে শেখা। Log থেকে policy তৈরি, অব্যবহৃত অনুমতির স্বয়ংক্রিয় তালিকা, স্থায়ী key-এর বদলে অস্থায়ী credential, আর মানুষের জন্য সাময়িক উচ্চ-অধিকার, যাকে বলে just-in-time access. Guardrail ধরে নেয় ভুল হবেই, তাই ক্ষতির সীমা টানে। দলের সংস্কৃতিও জরুরি: প্রতিটি role-এর মালিক আর উদ্দেশ্য লেখা থাকলে পর্যালোচনা সহজ হয়।

মূল উপলব্ধি: Least privilege কোনো নিখুঁত অবস্থা নয়, এটি একটি চলমান প্রকৌশল-চক্র। লক্ষ্য হলো বাড়তি অনুমতিকে ক্রমাগত ছোট করা, আর কিছু বাকি থাকলে তার blast radius সীমিত রাখা।

প্র ০৩একটি বাড়তি অনুমতি কীভাবে একটি ছোট ত্রুটিকে বড় ঘটনায় বদলে দিতে পারে? ২০১৯ সালের Capital One ঘটনা থেকে কী শেখা যায়?

Capital One ২০১৯ সালে জানায়, যুক্তরাষ্ট্র আর কানাডার ১০ কোটিরও বেশি গ্রাহক ও আবেদনকারীর তথ্য অননুমোদিতভাবে নেওয়া হয়েছিল। মার্কিন আদালতের নথি, নিয়ন্ত্রকের পদক্ষেপ আর কোম্পানির প্রকাশ্য বিবৃতি থেকে যতটুকু জানা যায়, সেখানে একটি ভুল-কনফিগার করা web application firewall আর cloud-এ চলা একটি পরিচয়ের প্রয়োজনের চেয়ে বেশি অনুমতি, দুটোই ভূমিকা রেখেছিল বলে ব্যাপকভাবে বর্ণনা করা হয়। পুরো কারিগরি বিবরণ সব প্রকাশিত নয়, তাই আমরা শুধু প্রতিরক্ষার শিক্ষাটুকু নেব।

শিক্ষাটি একটি হিসাব। একটি ঘটনার ক্ষতি মোটামুটি দুটি জিনিসের ওপর নির্ভর করে: কোনো ত্রুটি কাজে লাগানো গেল কি না, আর সেই ত্রুটির পেছনে পরিচয়টি কতটা করতে পারে। প্রথমটি শূন্যে নামানো প্রায় অসম্ভব, কারণ সফটওয়্যারে ত্রুটি থাকেই। দ্বিতীয়টি আমাদের নিয়ন্ত্রণে। একটি web server-এর role যদি শুধু নিজের দরকারি একটি prefix পড়তে পারে, তাহলে সেখানে ত্রুটি হলেও ক্ষতি ওই prefix-এ আটকে যায়। সেই role সব bucket দেখতে পারলে একই ত্রুটির দাম হয় বহু গুণ বেশি।

এখান থেকে কয়েকটি প্রতিরোধ আসে। Workload-এর role-কে সরু রাখা, বিশেষ করে bucket-এর তালিকা দেখা আর সব bucket পড়ার অধিকার। Web-মুখী server-এর জন্য instance metadata-র কড়া সংস্করণ চালু রাখা, যেমন AWS-এর IMDSv2, যা SSRF-ধরনের ঝুঁকি কমাতে সাহায্য করে। অস্বাভাবিক ব্যবহারে alert, যেমন যে role কখনো বড় তালিকা দেখে না, হঠাৎ দেখতে শুরু করল। আর গুরুত্বপূর্ণ ডেটায় আলাদা encryption key, যাতে শুধু storage-এর অনুমতিতে পড়া না যায়।

মূল উপলব্ধি: বাড়তি অনুমতি নিজে ঘটনা ঘটায় না, কিন্তু অন্য যেকোনো ত্রুটির দাম বাড়িয়ে দেয়। Least privilege হলো ভবিষ্যতের অজানা ত্রুটির ক্ষতি আজই ছোট করে রাখা।

প্র ০৪একটি policy কি গাণিতিকভাবে “প্রমাণ” করা যায়? Simulator, linter আর automated reasoning-এর তফাত কী?

তিনটি সরঞ্জাম তিন রকম প্রশ্নের উত্তর দেয়। Linter লেখা দেখে: JSON ঠিক আছে কি না, action-এর নাম আছে কি না, পরিচিত ঝুঁকির নকশা আছে কি না। এটি বানান-পরীক্ষকের মতো। Simulator একটি নির্দিষ্ট অনুরোধ নিয়ে রায় বলে: এই role, এই action, এই ARN. এটি unit test-এর মতো। আপনি যা জিজ্ঞেস করেননি, সে সম্পর্কে কিছু বলে না।

Automated reasoning তৃতীয় ধরনের। AWS-এর Zelkova গবেষণায় (Backes ও সহকর্মীরা, FMCAD ২০১৮) policy-কে যুক্তির সূত্রে অনুবাদ করে SMT solver-কে প্রশ্ন করা হয়, যেমন “এমন কোনো অনুরোধ কি আছে, যা বাইরের কেউ পাঠালে Allow হবে?” Solver একটি উদাহরণ পরীক্ষা করে না, সে সম্ভাব্য অসীম অনুরোধের জগৎ নিয়ে যুক্তি করে। “নেই” উত্তরটি তাই একটি পরীক্ষার পাসের চেয়ে অনেক শক্ত কথা। AWS প্রকাশ্যে জানিয়েছে তাদের Access Analyzer-এর মতো service-এ এই ধরনের প্রযুক্তি কাজে লাগে।

তবে “প্রমাণ” শব্দটির সীমা আছে। প্রমাণ হয় একটি নির্দিষ্ট সম্পত্তি সম্পর্কে, “এই bucket public নয়” ধরনের। কিন্তু policy আপনার উদ্দেশ্যের সাথে মেলে কি না, solver সেটি জানে না, কারণ উদ্দেশ্য কোথাও লেখা নেই। যে role-কে ভুলবশত নিজের account-এর সব bucket দেওয়া হলো, সেটি “বাইরের কেউ পড়তে পারে না” প্রমাণে পাস করবে, অথচ least privilege ভাঙবে। এই কারণেই লেখা উদ্দেশ্যের সাথে বাস্তব ব্যবহার মেলাতে log আর মালিকের বক্তব্য দুটোই লাগে।

এক কথায়, এগুলো একে অপরের বিকল্প নয়। বাস্তব pipeline-এ linter চলে প্রতিটি বদলে, policy-as-code নিয়ম প্রতিষ্ঠানের সীমা মেনে চলা যাচাই করে (পর্ব ৫৫), simulator গুরুত্বপূর্ণ অনুরোধের regression test হয়, আর analyzer চলমান পরিবেশের ওপর নজর রাখে।

মূল উপলব্ধি: প্রমাণ আপনাকে বলে নিয়মটি কী করে; সেটি আপনি যা চেয়েছিলেন তা কি না, সে দায়িত্ব মানুষেরই থাকে।

প্র ০৫হাজারটি role, নাকি tag-এর একটি নিয়ম? RBAC আর ABAC-এর মধ্যে কীভাবে বাছবেন, আর ABAC-এর ফাঁদ কোথায়?

RBAC-এর আধুনিক রূপটি David Ferraiolo আর Richard Kuhn-এর ১৯৯২ সালের প্রবন্ধ থেকে পরিচিত, পরে NIST-এর কাজের মধ্য দিয়ে তা মানদণ্ডে আসে। ধারণাটি সরল: মানুষকে সরাসরি অনুমতি না দিয়ে পদকে অনুমতি দিন। ছোট প্রতিষ্ঠানে এটি চমৎকার কাজ করে। সমস্যা শুরু হয় আকার বাড়লে। প্রতিটি দল, প্রতিটি পরিবেশ আর প্রতিটি project মিলিয়ে role-এর সংখ্যা গুণ হতে থাকে। ১০টি দল আর ৩টি পরিবেশ মানেই ৩০টি role, আর প্রতিটি নতুন দলে আরও ৩টি। একে অনেকে role explosion বলেন।

ABAC এখানে অন্য পথ নেয়। NIST SP 800-162 (২০১৪) এর একটি সংজ্ঞা ও নির্দেশিকা দেয়। অনুমতি ঠিক হয় বৈশিষ্ট্য মিলিয়ে: caller-এর project tag আর resource-এর project tag সমান হলে চলবে। ফলে ৩০টি role-এর জায়গায় একটি নিয়ম থাকতে পারে। নতুন দল এলে নিয়ম না বদলে শুধু tag দিলেই হয়। Cloud-এ নতুন resource প্রতি মিনিটে তৈরি হয় বলে এই সুবিধা বড়।

কিন্তু ফাঁদও স্পষ্ট। প্রথমত, tag নিজেই এখন অনুমতি। যে কেউ নিজের বা resource-এর tag বদলাতে পারলে অনুমতির সীমাও বদলাতে পারে। তাই tag বসানো ও বদলানোর অধিকার কড়া করতে হয়, নতুন resource-এ tag বাধ্যতামূলক করতে হয়। দ্বিতীয়ত, সব service আর action সব condition key সমর্থন করে না, তাই নিয়ম কোথাও চুপচাপ না-ও খাটতে পারে। তৃতীয়ত, পর্যালোচনা কঠিন হয়। RBAC-এ “এই role-এ কে কে আছেন” তালিকা করা যায়; ABAC-এ “এই resource কে পড়তে পারেন” জানতে সব পরিচয়ের tag হিসাব করতে হয়। চতুর্থত, tag-এর বানানে একটি ভুল মানে অনুমতি হারানো বা ভুল জায়গায় পাওয়া।

বাস্তবে তাই দুটির মিশ্রণই বেশি দেখা যায়। কাজের ধরন (developer, auditor) আসে role থেকে, আর সীমা (কোন project, কোন পরিবেশ) আসে tag থেকে। ঝুঁকিপূর্ণ কাজে, যেমন production মোছা, স্পষ্ট নির্দিষ্ট role আর guardrail রাখা নিরাপদ।

মূল উপলব্ধি: ABAC role-এর সংখ্যা কমায়, কিন্তু জটিলতা মুছে দেয় না, tag-এর শৃঙ্খলায় সরিয়ে নেয়। তাই tag নিয়ন্ত্রণে না থাকলে ABAC-ও নিয়ন্ত্রণে থাকে না।

অনুশীলন

এগুলোর জন্য কোনো cloud account লাগবে না। কাগজে হিসাব করুন, পাতার কোড বদলে দেখুন।

  1. কার্যকর অনুমতি হিসাব: একটি role-এর identity policy দেয় {s3:GetObject, s3:PutObject, s3:DeleteObject, sqs:SendMessage}. Boundary-র সীমা s3:*. Session policy-র সীমা {s3:GetObject, s3:PutObject, sqs:SendMessage}. Guardrail-এ s3:PutObject-এর Deny আছে। শেষে কতটি action করা যাবে? Identity policy-র কত শতাংশ টিকল?

    Identity ∩ Boundary = {Get, Put, Delete}, কারণ sqs:SendMessage s3:*-এর বাইরে। এর সাথে session মেলালে {Get, Put}, কারণ Delete session-এ নেই। Guardrail-এর Deny সরায় Put. শেষে থাকে {s3:GetObject}: ১টি action. শতাংশ: ১ ÷ ৪ = ২৫%.

  2. Policy সমালোচনা: একটি রাতের backup job শুধু example-bucket/backup/-এ ফাইল লেখে। তার policy-র একমাত্র statement: "Effect": "Allow", "Action": ["s3:*", "iam:PassRole"], "Resource": "*". কী কী ভুল, আর কী লিখবেন?

    তিনটি ভুল। (ক) s3:* দিচ্ছে মোছা আর bucket policy বদলানো, অথচ কাজ শুধু লেখা। (খ) "Resource": "*" সব bucket খুলে দিচ্ছে। (গ) iam:PassRole-এর এই job-এ কোনো কাজই নেই, আর সব role-এ এটি পর্যালোচনায় লাল দাগ। সরু রূপ: "Action": ["s3:PutObject"], "Resource": "arn:aws:s3:::example-bucket/backup/*". Multipart upload বা KMS encryption থাকলে সেগুলোর দরকারি action log দেখে যোগ করুন। Backup-এর ক্ষেত্রে মোছার অনুমতি না থাকা বাড়তি সুবিধা: job-এর credential ফাঁস হলেও পুরোনো backup মোছা যায় না।

  3. ফলাফল অনুমান: একটি policy-তে তিনটি statement: S1 Allow ec2:Describe*, resource *. S2 Allow ec2:StopInstances, শর্ত: resource-এর project tag আর caller-এর project tag সমান। S3 Deny ec2:*, শর্ত: region ap-southeast-1 নয়। চারটি অনুরোধের ফল আর ধরন বলুন: (ক) DescribeInstances, ap-southeast-1. (খ) DescribeInstances, us-east-1. (গ) StopInstances, ap-southeast-1, tag আলাদা। (ঘ) TerminateInstances, ap-southeast-1.

    (ক) ALLOW: S1 মিলল, S3-এর শর্ত মিথ্যা। (খ) DENY explicit: S1 মিললেও S3 জেতে। (গ) DENY implicit: S2-এর শর্ত মিথ্যা, তাই S2 বাদ, আর কোনো Allow নেই। (ঘ) DENY implicit: কোনো Allow নেই, S3-এর শর্তও মিথ্যা। লক্ষ করুন (গ) আর (ঘ) দুটিই “না”, কিন্তু explicit নয়। ঠিক এই কারণে পরে Allow যোগ করলে এগুলো বদলাবে, (খ) বদলাবে না।

  4. Log থেকে স্তর: পাতার denied_report.sh কোডে একটি লাইন যোগ করে শুধু no-resource-policy-এর সারিগুলো দেখান। তারপর বলুন: (ক) backup-job-এর জন্য আপনি প্রথমে কোথায় দেখবেন? (খ) dev-role-এর জন্য কি কোনো অনুমতি বাড়ানো উচিত?

    লাইনটি: grep ' no-resource-policy$' audit.log. এটি দুটি সারি দেখাবে। (ক) Bucket-এর resource policy. no-resource-policy ধরনের অস্বীকার প্রায়ই cross-account-এর লক্ষণ, তাই আগে দেখুন backup-job আর bucket একই account-এ কি না। আলাদা হলে bucket policy-তে ওই role-কে নির্দিষ্ট action দিন। (খ) না। dev-role-এর অস্বীকার guardrail-এর, আর পরের অনুরোধ সফল। অর্থাৎ নিয়ম কাজ করছে। প্রশিক্ষণ বা ডকুমেন্টেশন ঠিক করুন, guardrail নয়।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি access denied ডিবাগের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 📄 পুরো error বার্তা বা log সংগ্রহ করা
  2. 🪪 আসল পরিচয় নিশ্চিত করা (কে ডাকছে)
  3. 🔎 Action আর resource মিলিয়ে দেখা (কী, কোথায়)
  4. 🧱 দায়ী স্তর খোঁজা (Deny, guardrail, identity, resource)
  5. ✂️ সবচেয়ে সরু পরিবর্তন করা
  6. ✅ আবার চালিয়ে log-এ নিশ্চিত হওয়া

একটি role-এর একটি statement s3:GetObject Allow করে। আরেকটি statement একই object-এ s3:* Deny করে, আর কোনো condition নেই। একই account-এ s3:GetObject অনুরোধের ফল কী?

  • ALLOW, কারণ Allow বেশি নির্দিষ্ট
  • DENY, কারণ explicit Deny জেতে
  • যে statement আগে লেখা, তার ফল
  • Policy বৈধ নয়, error আসবে

একটি role-এর identity policy কোনো অনুমতি দেয় না, কিন্তু তার permission boundary-তে s3:* Allow লেখা। Role-টি s3:GetObject ডাকলে কী হবে (কোনো resource policy নেই)?

  • ALLOW, কারণ boundary-তে Allow আছে
  • DENY (explicit)
  • DENY (implicit)
  • ফল অনিশ্চিত, সময়ভেদে বদলাবে

Account A-র একটি role-এর identity policy Account B-র একটি bucket-এ s3:GetObject Allow করে। Bucket-এর resource policy-তে এই role-এর কথা নেই। কোনো Deny নেই। ফল কী?

  • ALLOW, কারণ caller-এর Allow আছে
  • DENY (explicit), resource policy থেকে
  • ALLOW, যদি object ছোট হয়
  • DENY, কারণ resource-এর পক্ষের Allow নেই

পাঁচটি action: s3:GetObject, s3:PutObject, s3:DeleteObject, s3:GetBucketPolicy, s3:ListBucket. Pattern s3:*Object এদের কয়টির সাথে মেলে?

  • ৩টি
  • ২টি
  • ৪টি
  • ৫টি

৯০ দিনের log-এ একটি role-এর একটি action মাত্র একবার দেখা গেছে। এটি নিয়ে সবচেয়ে ভালো পদক্ষেপ কোনটি?

  • সাথে সাথে মুছে ফেলা, কারণ প্রায় ব্যবহার হয় না
  • Role-এর মালিকের কাছে কারণ জেনে সিদ্ধান্ত নেওয়া, আর বাদ দিলে denied log নজরে রাখা
  • Log উপেক্ষা করে policy যেমন আছে রাখা
  • Action-টির জায়গায় wildcard বসানো

একটি service-এ access denied এসেছে। Error বার্তায় আছে with an explicit deny in a service control policy. সবচেয়ে সঠিক ব্যাখ্যা কোনটি?

  • Identity policy-তে আরও Allow যোগ করলে ঠিক হবে
  • Resource policy থেকে আসা implicit deny
  • Organisation-এর guardrail আটকেছে; account-এর ভেতরের কোনো Allow এটি ওলটাতে পারবে না
  • Credential-এর মেয়াদ শেষ হয়েছে

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. শুরু default deny; explicit Deny সবার ওপরে; statement-এর ক্রম গুরুত্বহীন।
  2. কার্যকর অনুমতি স্তরগুলোর ছেদ; boundary, session policy আর guardrail শুধু সীমা টানে।
  3. Cross-account-এ দুই পক্ষের Allow চাই; same-account-এ সাধারণত এক পক্ষই যথেষ্ট।
  4. Wildcard নীরবে ছড়ায়, condition সরু করে; iam:PassRole আর "Principal": "*" আলাদা করে দেখুন।
  5. Least privilege একটি চক্র: ছোট শুরু, log, lint, simulator, ধাপে ধাপে বাদ। Access denied পড়ুন: কে, কী, কোথায়, কোন স্তর।

পরের পর্বে: Report প্রোগ্রামের সমস্যা শেষে গিয়ে ঠেকেছিল একটি KMS key-তে। এবার সেই key-এর ভেতরে তাকাব: envelope encryption কীভাবে কাজ করে, rotation কেন, আর secret কোথায় রাখবেন।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান