Course-এর সূচি

10.2

আমার Bucket কে পড়তে পারবে? IAM, Bucket Policy আর Block Public Access

user policy বনাম resource policy, অন্য account-কে access দেওয়া, ACL আর Object Ownership, আর যে setting-গুলো ডেটা ফাঁস হওয়া ঠেকায়।

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

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

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

  • S3-এ access নিয়ন্ত্রণের হাতিয়ারগুলোর নাম বলতে, আর কোনটা access দেয় আর কোনটা শুধু সীমা টানে সেটা আলাদা করতে: IAM policy, bucket policy, ACL, Block Public Access আর Object Ownership।
  • একটা bucket policy পড়তে আর লিখতে: Effect, Principal, Action, Resource, Condition, আর bucket ARN আর object ARN-এর তফাত।
  • যেকোনো S3 request-এর সিদ্ধান্ত হাতে-কলমে বের করতে: একই account (একটা Allow-ই যথেষ্ট), অন্য account (দুই দিককেই allow করতে হবে), anonymous (শুধু bucket allow করতে পারে), আর তার ওপরে explicit Deny আর Block Public Access।
  • চেনা পরিস্থিতিগুলোর জন্য ঠিক pattern বেছে নিতে: public website, EC2-র application, partner account, পুরো organization, শুধু HTTPS, শুধু নিজের VPC থেকে।
  • Block Public Access-এর চারটা setting, কোন কোন level-এ বসে, আর কেউ হাত না দিলেও একটা public policy কেন হঠাৎ কাজ করা বন্ধ করতে পারে, সেটা বোঝাতে।
  • Object Ownership কী, আর এপ্রিল ২০২৩ থেকে ACL কেন default-এ বন্ধ, সেটা বলতে; আর IAM Access Analyzer for S3 দিয়ে খোলা পড়ে থাকা bucket খুঁজে বের করতে।

#প্রতিটা bucket শুরু হয় private হয়ে

#প্রতিটা request-এ দুটো প্রশ্ন

S3-এ যে request-ই আসুক, তার উত্তর হয় দুই ধাপে, ঠিক AWS-এর অন্য সব request-এর মতো (লেসন ২.২):

  1. কে চাইছে? S3 signature দেখে। Sign করা request আসে একজন principal-এর কাছ থেকে: IAM user, role session (EC2 instance, Lambda function, বা role assume করা কোনো মানুষ), root user, বা কোনো AWS service। Signature ছাড়া request হলো anonymous: browser-এ একটা link খোলা, বা credential ছাড়া curl।
  2. এই principal কি এই resource-এ এই কাজটা করতে পারে? S3 প্রযোজ্য সব policy জড়ো করে সিদ্ধান্ত দেয়: Allow নাকি Deny।

নতুন একটা bucket দ্বিতীয় প্রশ্নের উত্তরে সবাইকে না বলে, শুধু নিজের account-এর সেই principal-রা ছাড়া যাদের IAM permission আছে। Account-এর বাইরের কেউ, বা কোনো anonymous visitor, কিছুই পড়তে পারে না যতক্ষণ না কেউ জেনে-বুঝে অনুমতি দেয়। তার ওপর এপ্রিল ২০২৩ থেকে প্রতিটা নতুন bucket আসে আরও দুটো তালা আগে থেকেই লাগানো অবস্থায়: Block Public Access চালু, আর ACL বন্ধ। দুটোই এই লেসনের পরের দিকে বুঝিয়ে বলা আছে।

#এক নজরে সব হাতিয়ার

হাতিয়ারকোথায় লাগানোAccess দেয়?সাধারণ ব্যবহার
IAM policy (user-based, identity-based)User, group বা roleহ্যাঁনিজের মানুষ আর application
Bucket policy (resource-based)Bucket-এহ্যাঁPublic read, অন্য account, পুরো organization-এর সঙ্গে share, Deny দিয়ে পাহারা
ACL (bucket ACL, object ACL)Bucket বা একটা object-এহ্যাঁ, তবে default-এ বন্ধপুরনো ব্যবস্থা; কালেভদ্রে object ধরে ধরে নিয়ন্ত্রণ
Block Public AccessOrganization, account, bucket, access pointনা, শুধু public অনুমতি থামায়ডেটা ফাঁস ঠেকানো
Object OwnershipBucket-এনা; ঠিক করে upload করা object-এর মালিক কে আর ACL গোনা হবে কি নাBucket owner enforced রেখে দাও
Access point policyএকটা access point-এহ্যাঁশেয়ার করা bucket-এ প্রতিটা team-এর আলাদা দরজা (লেসন ১০.৯)
VPC endpoint policyGateway বা interface endpoint-এশুধু সীমা টানে“এই VPC থেকে শুধু এই bucket-গুলো” (লেসন ১০.১০)
SCP আর RCPOrganization, OU, accountশুধু সীমা টানেপুরো কোম্পানির সীমা (লেসন ২.২, chapter ২০)
KMS key policyএকটা KMS key-তেহ্যাঁ, key-এর জন্যSSE-KMS দিয়ে encrypt করা object পড়তে key-এর অনুমতিও লাগে (লেসন ১০.৮)

Slide-এ পুরো ব্যাপারটা দুই ভাগে বলা: user-based (IAM policy: এই user কোন কোন API call করতে পারবে) আর resource-based (bucket policy, object ACL, bucket ACL)। এই লেসনে আমরা একটা একটা করে ধরব, তারপর সব একসঙ্গে জোড়া দেব।

#User-based access: IAM policy

IAM policy লাগানো থাকে একটা user, group বা role-এ, আর বলে সেই identity কোন resource-এ কোন action করতে পারবে। JSON-টা তুমি লেসন ২.১-এ দেখেছ। S3-এর বেলায় আসল খুঁটিনাটি হলো, কোন action-এর জন্য কোন ARN লাগে:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListTheInvoicesPrefix",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::shop-media-example",
      "Condition": { "StringLike": { "s3:prefix": "invoices/*" } }
    },
    {
      "Sid": "ReadAndWriteInvoices",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::shop-media-example/invoices/*"
    }
  ]
}
  • Bucket-level action, যেমন s3:ListBucket, কাজ করে bucket-এর ARN-এ: arn:aws:s3:::shop-media-example, শেষে কোনো slash নেই।
  • Object-level action, যেমন s3:GetObject, s3:PutObject আর s3:DeleteObject, কাজ করে object-এর ARN-এ: arn:aws:s3:::shop-media-example/invoices/*।
  • দুটোই লাগলে policy-তে দুই রকম ARN-ই রাখো। শুধু …/* থাকলে যে file-এর নাম আগে থেকে জানো সেটা পড়তে পারবে, কিন্তু list করতে গেলে AccessDenied। শুধু bucket ARN থাকলে list হবে, কিন্তু পড়া যাবে না।
  • S3-এর ARN-এ Region বা account ID থাকে না, কারণ bucket-এর নাম পুরো পৃথিবীতে একটাই (লেসন ১০.১)।

#Application পায় role, key কখনো না

User-based access-এর জন্য slide-এ দুটো ছবি আছে: IAM policy সহ একজন IAM user, আর instance role সহ একটা EC2 instance। মনে রাখার মতো pattern হলো দ্বিতীয়টা। EC2-র application-এর disk-এ কখনো access key কপি করে রাখা হয় না; সে instance profile-এর মাধ্যমে একটা IAM role পায়, আর SDK নিজে থেকেই অল্প সময়ের credential তুলে নেয় (লেসন ২.৪)। Lambda function, ECS task আর অন্য service-ও একইভাবে নিজেদের execution role বা task role দিয়ে কাজ করে।

#Resource-based access: bucket policy

#Bucket policy দেখতে কেমন

Bucket policy হলো bucket-এর গায়েই লাগানো একটা JSON policy। Resource-এর ওপর বসে বলে তাকে বলে দিতে হয় কার কথা হচ্ছে: তাই এতে থাকে Principal, যেটা IAM policy-তে থাকে না।

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadForProductPhotos",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::shop-media-example/photos/*"
    }
  ]
}
অংশমানেউদাহরণ
EffectAllow নাকি Deny"Allow"
PrincipalStatement-টা কার জন্য"*" (সবাই, anonymous-সহ), {"AWS": "arn:aws:iam::444455556666:root"} (একটা account), {"AWS": "arn:aws:iam::111122223333:role/shop-web-role"}, {"Service": "logging.s3.amazonaws.com"}
ActionS3-এর কোন API call"s3:GetObject", "s3:*"
ResourceBucket আর/অথবা তার objectarn:aws:s3:::shop-media-example, arn:aws:s3:::shop-media-example/photos/*
Condition (ঐচ্ছিক)Request-এর ওপর বাড়তি পরীক্ষাaws:SecureTransport, aws:SourceIp, aws:SourceVpce, aws:PrincipalOrgID, s3:x-amz-server-side-encryption

কয়েকটা নিয়ম জেনে রাখো:

  • একটা bucket-এর bucket policy একটাই, সর্বোচ্চ ২০ KB। অনেক team একটা bucket share করে বলে policy যখন খুব বড় হয়ে যায়, তখন সমাধান S3 Access Point (লেসন ১০.৯)।
  • Bucket policy-র Resource হতে হবে এই bucket বা তার ভেতরের object।
  • Principal: "*" মানে সত্যিই সবাই, sign করুক বা না করুক। এটা ব্যবহার করো শুধু সত্যিকারের public ডেটার জন্য, অথবা এমন একটা Condition-এর সঙ্গে যেটা পরিধি ছোট করে, যেমন organization ID।
  • Policy বদলাতে পারে শুধু bucket মালিকের account (s3:PutBucketPolicy permission থাকলে)।

#Bucket policy দিয়ে কী কী কাজ হয়

Slide আর নোটে bucket policy-র কাজগুলোর তালিকা আছে। নিচে প্রত্যেকটার আলাদা অংশ আছে:

  • public access দেওয়া, যেমন static website-এর জন্য শুধু পড়ার অনুমতি;
  • অন্য account-কে access দেওয়া (cross-account);
  • HTTPS বাধ্যতামূলক করা আর upload-এ encryption বাধ্যতামূলক করা;
  • network দিয়ে সীমা টানা: শুধু নির্দিষ্ট IP range থেকে, বা শুধু নিজের VPC endpoint দিয়ে;
  • পুরো organization-এর সঙ্গে share করা।

#ACL, পুরনো কায়দা

Bucket policy আসার আগে (২০০৬ সালে) S3-এ ছিল access control list। ACL হলো একটা bucket বা একটা object-এর ওপর দেওয়া অনুমতির তালিকা: “X account READ করতে পারবে”, “AllUsers group READ করতে পারবে”। ACL মোটা দাগের (READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL), এতে condition দেওয়া যায় না, Deny করা যায় না, সর্বোচ্চ ১০০টা grant রাখা যায়, আর প্রতিটা object-এ আলাদা আলাদা বসে থাকে, তাই audit করা ভীষণ কঠিন। Slide-এ object ACL-কে বলা হয়েছে “finer grain”, কারণ প্রতিটা object-এ আলাদা করে বসানো যায়; ঠিক এই কারণেই এদের হিসাব রাখা এত ঝামেলার।

দুটো আগে থেকে ঠিক করা group অনেক নামকরা ডেটা ফাঁসের কারণ: AllUsers (internet-এর যে কেউ) আর AuthenticatedUsers (পৃথিবীর যেকোনো AWS account-এর যে কেউ, শুধু তোমার user না)। এই দুটোর যেকোনোটাকে কিছু দিলে S3 সেটাকে public ধরে।

AWS এখন বলে ACL বন্ধ রাখো আর সব কাজ policy দিয়ে করো। নতুন bucket-এ ACL default-এই বন্ধ; তার মানে কী, সেটা Object Ownership অংশে আছে।

#S3 কীভাবে সিদ্ধান্ত নেয়

#লেসন ২.২-এর নিয়ম, S3-এর ওপর

S3 বাকি AWS-এর মতো একই evaluation logic মানে (লেসন ২.২), শুধু কয়েকটা বাড়তি input আছে। Slide পুরোটা এক বাক্যে বলে: একজন principal object পড়তে পারবে যদি IAM permission allow করে OR resource policy allow করে, AND কোথাও explicit Deny না থাকে। কথাটা সত্যি একই account-এর ভেতরে। পুরো ছবিটা এরকম:

  1. সবার আগে Block Public Access যেসব public অনুমতি আটকানোর জন্য সেট করা, সেগুলো বন্ধ করে দেয় (খুঁটিনাটি পরে)। সে কখনো কিছু দেয় না।
  2. কোথাও explicit Deny থাকলে সে-ই জেতে। Caller-এর IAM policy, bucket policy, SCP বা RCP, বা endpoint policy, যেখানেই Deny মিলুক, evaluation সেখানেই শেষ। কোনো Allow সেটা উল্টাতে পারে না, administrator-এর Allow-ও না।
  3. তারপর S3-এর Allow লাগে, আর কয়টা লাগবে সেটা নির্ভর করে কে চাইছে তার ওপর:
কে চাইছেকাকে allow করতে হবে
Bucket মালিকের account-এর principalIAM policy অথবা bucket policy (union)
অন্য account-এর principalCaller-এর IAM policy এবং bucket policy (দুটোই)
AnonymousBucket policy (বা ACL চালু থাকলে একটা ACL), কারণ এর কোনো IAM দিকই নেই
কেউ allow করেনিImplicit deny: 403 AccessDenied

এর ওপরে organization-এর SCP আর RCP, permissions boundary আর session policy শুধু সীমা টানতে পারে (লেসন ২.২), আর SSE-KMS দিয়ে encrypt করা object-এর বেলায় caller-এর KMS key-এর অনুমতিও লাগে (লেসন ১০.৮)।

কে চাইছে? চার রকম principal, একটা bucket

দোকানের bucket-টা আছে 111122223333 account-এ। একই account-এর একজন IAM user আর একটা EC2 instance, internet-এর একজন নাম-পরিচয়হীন visitor, আর partner account-এর একজন user, সবাই একই জিনিস চাইছে: একটা object পড়তে। প্রত্যেকের বেলায় কোন policy সিদ্ধান্ত নেয়?

পরিস্থিতি

User-based access: user-এর নিজের IAM policy-তেই allow আছে।

দোকানের account111122223333
Courier account444455556666
shop-media-example
IAM user rina
Web app
Visitor
Courier user
GetObject

Principal

rina

Request

GET invoices/…/inv-1043.pdf

কে ঠিক করল

…

ফলাফল

…

ধাপ 1 / 2
1

দোকানের account-এর IAM user রিনা চাইল invoices/2026/10/inv-1043.pdf। সে request-টা নিজের credential দিয়ে sign করে, তাই S3 জানে ঠিক কে চাইছে।

#অন্য account হলে দুই দিক কেন লাগে

“দুই দিককেই allow করতে হবে” নিয়মটা দুই কোম্পানিকেই রক্ষা করে:

  • Bucket-এর মালিককে রাজি হতে হয়, নাহলে যে কেউ অন্যের bucket-এর জন্য একটা IAM policy লিখে সেটা পড়ে ফেলত।
  • Caller-এর account-কে রাজি হতে হয়, নাহলে অচেনা কারও bucket policy তোমার কর্মচারীদের এমন অনুমতি দিয়ে দিত যেটা তোমার security team কখনো অনুমোদন করেনি।

Bucket policy যখন পুরো একটা account-এর নাম লেখে (arn:aws:iam::444455556666:root), তার মানে “ওই account-কে বিশ্বাস করি, তার কোন user বা role এটা পাবে সেটা সে-ই ঠিক করুক”। এতে ওই account-এর প্রতিটা user আপনা থেকে access পেয়ে যায় না। তাদের administrator-কে IAM দিয়ে দিতে হয়।

অন্য account থেকে access: দুই অর্ধেক

Courier-এর account-এর একজন user দোকানের bucket-এর labels/ পড়বে। একই account-এর ভেতরে একটা Allow-ই যথেষ্ট; কিন্তু account আলাদা হলে S3-এর লাগে caller-এর account-এর Allow আর bucket মালিকের Allow, দুটোই।

পরিস্থিতি

Courier user444455556666IAM: allow
Courier-এর IAM444455556666
Amazon S3shop-media-example
দোকানের role111122223333
IAM policy: labels/* allow
ধাপ 1 / 4
1

প্রথম অর্ধেক, caller-এর account-এ: courier-এর admin একটা IAM policy লাগায়, যেটা arn:aws:s3:::shop-media-example/labels/*-এ s3:GetObject allow করে। এটা না থাকলে courier account নিজের user-কেই বাইরে কোথাও যাওয়ার অনুমতি দেয়নি।

#যে 403-এর পেছনে লুকিয়ে থাকে 404

কোনো principal-এর যদি bucket list করার অনুমতি না থাকে (s3:ListBucket নেই) আর সে এমন একটা key চায় যেটা আসলে নেই, S3 উত্তর দেয় 403 AccessDenied, 404 Not Found না। এটা ইচ্ছা করেই: নাহলে বাইরের কেউ খুঁচিয়ে খুঁচিয়ে বের করে ফেলত কোন কোন file-এর নাম আছে। GET-এ 403 পেলে troubleshoot করার সময় আগে দেখো key-টা সত্যিই আছে কি না। s3:ListBucket অনুমতি থাকলে না-থাকা key-তে আসে 404 NoSuchKey।

নিজেকে যাচাই করোপ্রশ্ন

444455556666 account-এর একজন user 111122223333 account-এর একটা bucket-এর object পড়তে চাইছে। Bucket policy 444455556666 account-কে s3:GetObject allow করে। User-এর কোনো IAM policy-ই নেই। কী হবে?

#চেনা access pattern-গুলো

#Website-এর জন্য public read

Slide-এর প্রথম উদাহরণ: web-এর একজন anonymous visitor একটা bucket থেকে file পড়ছে, অনুমতি দিয়েছে bucket policy। দোকান পণ্যের ছবির জন্য ঠিক এটাই করে, আগে দেখানো policy দিয়ে (Principal: "*", s3:GetObject, photos/*)। তিনটা জিনিস ঠিক থাকতে হবে:

  1. Block Public Access আটকাবে না, bucket আর account দুই level-এই (আর organization level-এ কিছু বসানো থাকলে সেখানেও)।
  2. Bucket policy ঠিক prefix-এ "*"-কে s3:GetObject দেয়। শুধু পড়ার অনুমতি দাও, লেখার কখনো না: public s3:PutObject মানে তোমার bucket হয়ে গেল যে কারও file রাখার ফ্রি জায়গা, আর bill আসবে তোমার নামে।
  3. Resource একদম ঠিকঠাক। photos/* public; invoices/ private-ই থাকে। ভুল করে shop-media-example/* লিখে ফেলা, ডেটা ফাঁস এভাবেই হয়।

Website hosting নিজে (endpoint, index আর error document, 403-এর ফাঁদ) লেসন ১০.৩-এর বিষয়। আজকাল বেশিরভাগ website-এর জন্য ভালো design হলো private bucket আর সামনে CloudFront, Origin Access Control দিয়ে, যাতে bucket নিজে কখনো public না হয়; সেটা আসবে chapter ১১-এ।

#EC2-র একটা application

ওপরে বলা হয়েছে: instance-এ একটা IAM role, তাতে শুধু দরকারি prefix-এর জন্য IAM policy। একই account, তাই bucket policy লাগে না। পাহারার জন্য চাইলে bucket policy-তে একটা Deny যোগ করো (যেমন “শুধু আমাদের VPC endpoint দিয়ে”)।

#অন্য account: দুটো pattern

Slide-এ দেখানো আছে bucket policy দিয়ে cross-account access। বাস্তবে উপায় দুটো, আর পরীক্ষা দুটোই জানতে চায়:

Bucket policy + IAM policyBucket-এর account-এ একটা role
কীভাবেBucket policy অন্য account (বা role)-এর নাম লেখে; সেই account-এর admin IAM দিয়ে নিজের user-দের দেয়Bucket-এর মালিক একটা role বানায় যেটা অন্য account assume করতে পারে (লেসন ২.৪)
Caller কাজ করেনিজের পরিচয়ে, নিজের account থেকেBucket মালিকের account-এর role session হয়ে
কোন policy লাগেদুই দিকেইTrust policy + role-এর permission; bucket policy লাগে না
কখন ভালোঅন্য account-এর এমন service যে role বদলাতে পারে না; একজন partner-কে অনেক bucket shareসব permission, audit আর session-এর সীমা মালিকের account-এ রাখতে

দুই pattern-এই মালিক সবচেয়ে ছোট পরিসরটুকু দেবে: একটা prefix, শুধু পড়া, দরকার হলে একটা condition।

#পুরো একটা organization

Bucket policy-তে ৪০টা account ID লেখা, আর প্রতিবার নতুন account যোগ হলে policy বদলানো, এভাবে চলে না। Condition key aws:PrincipalOrgID ব্যবহার করো:

{
  "Sid": "AllAccountsInOurOrganization",
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::shop-shared-config-example/*",
  "Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-a1b2c3d4e5" } }
}

একটা নির্দিষ্ট organization ID সহ Principal: "*" S3-এর চোখে public না, তাই Block Public Access এটা আটকায় না। Organization-এর প্রতিটা account, আগামী বছর যোগ হওয়া account-সহ, পড়তে পারবে, যদি তার নিজের IAM policy-ও allow করে।

#পাহারাদার: bucket policy-তে Deny statement

Bucket policy access দিতে যেমন পারে, কেড়েও নিতে পারে। Explicit Deny যেহেতু সব Allow-কে হারায়, কয়েকটা Deny statement bucket-টাকে নিজেই নিজের নিরাপত্তারক্ষী বানিয়ে দেয়, পরে কেউ যে IAM policy-ই লিখুক না কেন।

#শুধু HTTPS (encryption in transit)

নোটের প্রধান exam trick:

{
  "Sid": "DenyInsecureTransport",
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": [
    "arn:aws:s3:::shop-media-example",
    "arn:aws:s3:::shop-media-example/*"
  ],
  "Condition": { "Bool": { "aws:SecureTransport": "false" } }
}

Request TLS (HTTPS) দিয়ে এলে aws:SecureTransport হয় true, সাধারণ HTTP হলে false। Deny-টা যে কারও কাছ থেকে আসা প্রতিটা সাধারণ HTTP request ধরে ফেলে। TLS আর S3-এর encryption নিয়ে বিস্তারিত লেসন ১০.৮-এ।

#শুধু নিজের network থেকে

  • aws:SourceVpce: শুধু নির্দিষ্ট একটা VPC endpoint দিয়ে আসা request। “Invoice পড়া যাবে শুধু আমাদের VPC-র ভেতর থেকে”, এটা বলার স্বাভাবিক উপায় (gateway endpoint লেসন ১০.১০-এ)। একটা VPC-র যেকোনো endpoint-এর জন্য একই কাজ করে aws:SourceVpc।
  • aws:SourceIp: শুধু নির্দিষ্ট public IP range থেকে আসা request, যেমন অফিসের 198.51.100.0/24। VPC endpoint দিয়ে আসা traffic-এ এটা কাজ করে না, কারণ ওই request-এ মেলানোর মতো কোনো public address থাকে না; সেখানে endpoint-এর key ব্যবহার করো।

এগুলো লেখো “Deny … যদি না” আকারে (StringNotEquals, NotIpAddress), “শুধু এই শর্তে Allow” আকারে না: যার IAM policy আগেই s3:* allow করে, তার বিরুদ্ধে condition-ওয়ালা Allow কিছুই করে না, কিন্তু Deny সবাইকে থামায়।

পাহারাদার হিসেবে Deny statement

Bucket policy access কেড়েও নিতে পারে। দোকান invoice-এর bucket policy-তে দুটো Deny statement যোগ করল: সাধারণ HTTP ফিরিয়ে দাও, আর VPC endpoint দিয়ে না এলে ফিরিয়ে দাও। Deny সব Allow-কে হারায়, administrator-এর Allow-কেও।

পরিস্থিতি

aws:SecureTransport false হলে Deny।

EC2-র web app10.0.1.25
Admin laptop203.0.113.40
Gateway endpointvpce-1a2b3c4d
Amazon S3invoicesHTTPS বাধ্যতামূলক
SecureTransport = false হলে Deny
ধাপ 1 / 5
1

Statement: Effect Deny, Principal "*", Action s3:*, Resource bucket আর তার object, Condition Bool aws:SecureTransport "false"। TLS ছাড়া আসা প্রতিটা request এর সঙ্গে মেলে।

#নিজেকে তালাবন্ধ করে ফেলো না

Action: "s3:*" সহ একটা Deny s3:PutBucketPolicy আর s3:DeleteBucketPolicy-ও deny করে। Condition যদি bucket দেখাশোনার মানুষদেরও বাদ দিয়ে ফেলে, তাহলে policy ঠিক করার আর কেউ থাকে না। দুটো অভ্যাস এটা ঠেকায়:

  • একটা admin role-এর জন্য ছাড় যোগ করো: অন্য condition-এর পাশে "Condition": {"ArnNotEquals": {"aws:PrincipalArn": "arn:aws:iam::111122223333:role/storage-admin"}}।
  • তবুও ঘটে গেলে, account-এর root user সবসময় bucket policy মুছে দিতে পারে। AWS Organizations-এর এমন member account, যার root credential নেই, সেখানে management account কাজটা কেন্দ্রীয়ভাবে করতে পারে, privileged root task হিসেবে।

#Block Public Access

#কেন এটা এল

বছরের পর বছর S3-এর ডেটা ফাঁস খবরের শিরোনাম হয়েছে: ভোটার তালিকা, হাসপাতালের রেকর্ড, প্রতিরক্ষার ফাইল, সব এমন bucket-এ যেটা কেউ একটা ভুল policy বা একটা AllUsers ACL দিয়ে public করে ফেলেছিল। নভেম্বর ২০১৮-তে AWS আনল S3 Block Public Access: এমন setting যেটা policy আর ACL-কে ছাপিয়ে যায়, যাতে bucket যেভাবেই সাজানো থাকুক public access হতেই না পারে। Slide যেমন বলে: কোনো bucket কখনো public হবে না জানলে এগুলো চালু রেখে দাও।

#চারটা setting

Settingকখন কাজ করেকী করে
BlockPublicAclsকেউ ACL লিখতে গেলেPutBucketAcl, PutObjectAcl আর public ACL সহ upload ফিরিয়ে দেয়। আগের ACL-এ হাত দেয় না।
IgnorePublicAclsRequest যাচাইয়ের সময়Bucket আর তার object-এর সব public ACL উপেক্ষা করে, যেন সেগুলো নেই।
BlockPublicPolicyকেউ bucket (বা access point) policy লিখতে গেলেনতুন policy public হলে s3:PutBucketPolicy ফিরিয়ে দেয়। আগের policy-তে হাত দেয় না।
RestrictPublicBucketsRequest যাচাইয়ের সময়Bucket-এর policy public হলে সেটা ব্যবহার করতে পারে শুধু AWS service principal আর মালিকের নিজের account-এর principal। Anonymous user আর অন্য সব account বাদ।

দুই জোড়া: প্রতি জোড়ার একটা থামায় নতুন public অনুমতি, অন্যটা আগে থেকে থাকা অনুমতিকে অকেজো করে। Setting-গুলো একটা আরেকটার ওপর নির্ভর করে না, আর console-এ একটা checkbox আছে, “Block all public access”, যেটা চারটাই চালু করে দেয়।

#কোনটা public গোনা হয়

S3 শুরুতেই ধরে নেয় bucket policy public, তারপর খোঁজে কেন সেটা public না। একটা statement public না, যদি সে শুধু এগুলোর নির্দিষ্ট value-কে access দেয়:

  • নির্দিষ্ট principal: একটা account, user, role, service principal;
  • aws:PrincipalOrgID (তোমার organization);
  • aws:SourceIp, তবে IPv4-এ /8-এর চেয়ে বড় range না (private RFC 1918 range চলবে);
  • aws:SourceVpc, aws:SourceVpce, aws:SourceArn, aws:SourceAccount, aws:SourceOwner, aws:userid, s3:DataAccessPointArn, s3:DataAccessPointAccount।

তাই শুধু Principal: "*" হলো public; aws:SourceVpce = vpce-1a2b3c4d সহ Principal: "*" public না। একটা ACL public, যদি সেটা AllUsers বা AuthenticatedUsers-কে কিছু দেয়।

#Level আর কে কার ওপরে

Block Public Access চারটা level-এ বসানো যায়:

  • Access point: access point বানানোর সময় সেট হয়; পরে আর বদলানো যায় না।
  • Bucket: bucket আর তার access point-গুলোর ওপর খাটে।
  • Account: account-এর এখনকার আর ভবিষ্যতের সব bucket আর access point-এ, সব Region-এ (প্রতিটা Region-এ পৌঁছাতে একটু সময় লাগতে পারে)।
  • Organization (নতুন, নভেম্বর ২০২৫): AWS Organizations-এর একটা policy, যেটা বাছাই করা account বা OU-তে চারটা setting-ই চালু করে দেয়, হয় সব নয় কিছুই না, আর নতুন member account আপনা থেকেই সেটা পায়।

S3 সবসময় সবচেয়ে কড়া combination-টা মানে। Account যদি বলে “আটকাও” আর bucket বলে “public চলবে”, bucket আটকে যায়। একটা public website চালাতে হলে প্রযোজ্য প্রতিটা level-এই অনুমতি দিতে হবে। AWS-এর পরামর্শ: account level-এ চারটাই চালু রাখো, আর যে কয়েকটা bucket সত্যিই public হতে হবে, সেগুলো আলাদা একটা account-এ রাখো।

Default: এপ্রিল ২০২৩ থেকে প্রতিটা নতুন bucket-এ চারটা setting-ই চালু (console, CLI, SDK আর CloudFormation, সব জায়গায়)। পুরনো bucket বদলানো হয়নি। Account level-এর setting কেউ তোমার হয়ে চালু করে দেয় না; সেটা তোমার কাজ।

কাজের সময় Block Public Access

চারটা switch, যারা কখনো কিছু দেয় না: শুধু public অনুমতি থামায় বা উপেক্ষা করে। দুটো কাজ করে কেউ public policy বা ACL লিখতে গেলে, দুটো কাজ করে request যাচাইয়ের সময়।

পরিস্থিতি

BlockPublicPolicy লেখাটাই ফিরিয়ে দেয়: policy কখনো save-ই হয় না।

Admin111122223333
Block Public Access৪টা setting৪টাই চালু
Amazon S3shop-media-example
Visitoranonymous
PutBucketPolicy, Principal "*"
ধাপ 1 / 3
1

নতুন bucket, চারটা setting-ই চালু (এপ্রিল ২০২৩ থেকে এটাই default)। একজন developer তাড়াতাড়ি একটা file share করতে public-read policy paste করল।

#Object Ownership আর ACL

#কোন সমস্যার সমাধান

ACL-এর নিয়মে যে account object upload করে, সে-ই তার মালিক, এমনকি তোমার bucket-এর ভেতরেও। আগের দিনে একজন partner তোমার bucket-এ file upload করলে file-টা হতো partner-এর, আর তার default ACL পুরো control দিত শুধু partner-কে। তুমি এমন একটা file রাখার টাকা দিতে যেটা তুমি পড়তেই পারতে না। ঘুরপথে সমাধান ছিল প্রতিটা uploader-কে bucket-owner-full-control ACL পাঠাতে বাধ্য করা।

S3 Object Ownership (২০২০ সালে, আর “ACL বন্ধ” option যোগ হলো নভেম্বর ২০২১-এ) একটা bucket setting দিয়েই এটা মিটিয়ে দেয়:

SettingACLনতুন object-এর মালিক কে
Bucket owner enforced (এপ্রিল ২০২৩ থেকে default)বন্ধ: access-এ আর কোনো প্রভাবই নেইপ্রতিটা object-এর মালিক bucket-এর মালিক, নতুন-পুরনো সব
Bucket owner preferredচালুUpload-এ bucket-owner-full-control থাকলে bucket-এর মালিক; নাহলে যে লিখেছে
Object writerচালুUpload করা account (একদম শুরুর আচরণ)

Bucket owner enforced হলে:

  • access-এর সিদ্ধান্ত নেয় শুধু policy: IAM, bucket policy, access point policy, endpoint policy, SCP, RCP;
  • ACL ছাড়া, বা bucket-owner-full-control সহ upload গ্রহণ করা হয়; অন্য যেকোনো ACL ব্যর্থ হয় 400 AccessControlListNotSupported দিয়ে;
  • ACL পড়া এখনো যায় (দেখবে পুরো control শুধু মালিকের), আর পরে ACL আবার চালু করা যায়, তাতে পুরনো ACL-গুলো ফিরে আসে।

পুরনো একটা bucket-এ এটা চালুর আগে, ACL এখনো যে access দিচ্ছে (যেমন কিছু file-এ public-read ACL, বা bucket-এ log delivery), সেটা bucket policy-তে সরিয়ে নাও, নাহলে ওই access বন্ধ হয়ে যাবে। AWS-এর পরামর্শ: ACL বন্ধ রাখো, শুধু সেই বিরল ক্ষেত্র ছাড়া যেখানে প্রতিটা object আলাদা করে নিয়ন্ত্রণ করতেই হবে। কিছু পুরনো feature-এর জন্য এখনো target bucket-এ ACL লাগে, যেমন CloudFront-এর legacy standard logging; ওটা দেখবে chapter ১১-এ।

Upload করা object-এর মালিক কে?

Courier-এর system দোকানের bucket-এ delivery-র প্রমাণ upload করে। পুরনো Object writer setting-এ ওই file-গুলোর মালিক হতো courier; Bucket owner enforced-এ, যেটা এপ্রিল ২০২৩ থেকে default, সব কিছুর মালিক দোকান আর ACL বন্ধ।

পরিস্থিতি

যে upload করে সে-ই object-এর মালিক, আর bucket-এর মালিক সেটা পড়তে পারে না।

Courier system444455556666
Amazon S3shop-media-exampleACL চালু: Object writer
দোকানের analyst111122223333
PutObject proofs/DLV-88.jpg
ধাপ 1 / 4
1

একটা পুরনো bucket-এ Object Ownership হলো “Object writer”। Bucket policy courier account-কে proofs/-এ upload করতে দেয়। Courier কোনো ACL ছাড়াই একটা ছবি upload করল।

#খোলা bucket খুঁজে বের করা: IAM Access Analyzer for S3

Policy, ACL, access point আর setting একটা আরেকটার সঙ্গে জড়িয়ে থাকে, আর মানুষ ভুল করে। IAM Access Analyzer for S3 S3 console-এই দেখিয়ে দেয় কোন কোন general purpose bucket তোমার account-এর বাইরে থেকে পৌঁছানো যায়:

  • Public access finding: internet-এর যে কেউ bucket-এ পৌঁছাতে পারে।
  • Cross-account access finding: অন্য AWS account পারে, তোমার organization-এর বাইরের account-সহ।

প্রতিটা bucket-এর জন্য দেখায় কীভাবে share হয়েছে (bucket policy, bucket ACL, access point policy, Multi-Region Access Point policy) আর কতটা access (list, read, write, permissions, tagging)। সেখান থেকে তুমি পারো:

  • এক click-এ একটা bucket-এর সব public access বন্ধ করতে;
  • যে finding ইচ্ছাকৃত (public website, courier-এর share), সেটা archive করতে, যাতে লেখা থাকে কেউ দেখে নিয়েছে; archive করা bucket তালিকায় থেকেই যায়, তাই সবসময় জানো কোনগুলো share করা;
  • auditor-এর জন্য CSV report download করতে।

বাড়তি কোনো খরচ নেই, তবে IAM Access Analyzer-এ যে যে Region-এ bucket আছে, প্রতিটায় একটা external access analyzer বানাতে হয় (zone of trust হিসেবে account)। নতুন বা বদলানো bucket policy আর ACL মোটামুটি ৩০ মিনিটের মধ্যে finding-এ দেখা যায়; account level-এর setting বদলালে ৬ ঘণ্টা পর্যন্ত লাগতে পারে।

#নিজে হাতে সিদ্ধান্ত নিয়ে দেখো

একটা scenario বেছে নাও, তারপর একবারে একটা করে switch বদলাও: caller, IAM policy, bucket policy, HTTPS, ACL আর Block Public Access-এর চারটা setting। দেখো কোন যাচাইয়ে সিদ্ধান্ত হয়।

S3 কি file-টা দেবে? নিজেই সিদ্ধান্ত নাও

shop-media-example bucket-এর (account 111122223333) একটা object-এর জন্য একটা GET। একটা scenario বেছে নাও, অথবা প্রতিটা switch নিজে সেট করো, আর দেখো কোন যাচাইয়ে সিদ্ধান্ত হলো আর কেন।

Scenario
কে চাইছে
Caller-এর IAM policy
Bucket policy
Request গেল
SecureTransport false হলে Deny
Object Ownership
Object ACL AllUsers-কে read দেয়
Block Public Access
  1. ১. Block Public Access

    কাজ করার মতো public অনুমতি নেই

  2. ২. কোথাও Deny?

    কোথাও Deny নেই

  3. ৩. Bucket-এর দিক

    এই caller-এর Allow নেই

  4. ৪. Caller-এর দিক

    IAM policy allow করে

  5. ৫. মিলিয়ে দেখা

    একই account: যেকোনো একটা

সিদ্ধান্ত: Allowed: 200 OK

i

Web app-এর role-এর IAM policy s3:GetObject allow করে। একই account, তাই শুধু এই Allow-ই যথেষ্ট; bucket policy-তে role-এর নাম থাকার দরকার নেই। Caller bucket মালিকের account-এরই, তাই bucket-এর দিক আর caller-এর দিক যোগ হয় (union): একটা Allow থাকলেই, আর কোথাও Deny না থাকলে, চলে।

#কোথায় গোলমাল হয়: 403-এর checklist

লক্ষণসম্ভাব্য কারণসমাধান
Website বা public link 403 দেয়Bucket বা account level-এ Block Public Access চালু, বা public-read policy নেই, বা policy-র Resource prefix ধরছে নাপ্রতিটা level-এ অনুমতি দাও, Resource ঠিক করো; অথবা CloudFront
File পড়া যায়, কিন্তু aws s3 ls-এ AccessDeniedPolicy-তে শুধু bucket/*, bucket ARN-এ s3:ListBucket নেইarn:aws:s3:::bucket-এ s3:ListBucket যোগ করো
List হয়, পড়া যায় নাPolicy-তে শুধু bucket ARNObject ARN bucket/* যোগ করো
না-থাকা key-তে GET করলে 404 না, 403s3:ListBucket নেই, তাই S3 লুকায় key আছে কি নাKey-টা যাচাই করো; উপযুক্ত হলে s3:ListBucket দাও
Partner 403 পায়এক অর্ধেক নেই: caller-এর IAM policy বা bucket policyদুই দিককেই allow করতে হবে
Security-র একটা পরিবর্তনের পর partner access হারালRestrictPublicBuckets চালু হয়েছে আর bucket policy-তে একটা public statement আছেPublic statement সরাও; partner-এর নাম লেখো
সবাই, admin-ও, 403 পায়একটা explicit Deny মিলছে: HTTPS-এর বদলে HTTP, ভুল VPC endpoint, IP conditionClient ঠিক করো, অথবা aws:PrincipalArn দিয়ে ছাড় যোগ করো
Partner-এর upload করা object মালিক পড়তে পারে নাObject Ownership হলো Object writer, object-এর মালিক partnerBucket owner enforced
Upload ব্যর্থ, AccessControlListNotSupportedACL বন্ধ, client ACL পাঠাচ্ছেACL সরাও বা bucket-owner-full-control পাঠাও
শুধু কিছু object-এ 403, সবগুলো SSE-KMSCaller-এর key-তে kms:Decrypt নেইKey-এর অনুমতি দাও (লেসন ১০.৮)

#System design-এ access control

  • Default-এ private, ব্যতিক্রম হলে public। সব জায়গায় account level-এ Block Public Access চালু রাখো; যে কয়েকটা bucket সত্যিই public, সেগুলো আলাদা account-এ রাখো, বা আরও ভালো, private bucket থেকে CloudFront দিয়ে পরিবেশন করো।
  • Prefix ধরে সবচেয়ে কম অনুমতি। কার কী লাগবে সেই হিসেবে key prefix সাজাও (photos/, invoices/, labels/), যাতে policy ঠিক একটা prefix দিতে পারে।
  • Workload-এর জন্য role। EC2, Lambda আর container পায় IAM role; কোথাও কোনো দীর্ঘমেয়াদি key না।
  • Bucket policy হলো পাহারাদার। Allow-গুলো বেশিরভাগ IAM-এ রাখো, আর bucket policy-তে রাখো সেই নিয়মগুলো যেগুলো IAM যা-ই বলুক খাটতেই হবে: শুধু HTTPS, শুধু VPC endpoint দিয়ে, শুধু নিজের organization।
  • Cross-account হবে নাম ধরে। Partner-এর account বা role-এর নাম লেখো; একজন partner-এর সঙ্গে share করতে কখনো Principal: "*" ব্যবহার করো না।
  • ACL বন্ধ। সব জায়গায় Bucket owner enforced; ACL-এ এখনো যে অনুমতি বাকি, সেগুলো policy-তে নিয়ে যাও।
  • সারাক্ষণ নজর রাখো। IAM Access Analyzer-এর finding, আর Block Public Access যাচাই করা AWS Security Hub control, মানুষ যে ভুলগুলো করবেই সেগুলো ধরে ফেলে।
  • Public object-এর বদলে অস্থায়ী link। “একজন customer-কে একটা invoice download করতে দাও”, এর জন্য pre-signed URL (লেসন ১০.৯ আর লেসন ১০.১২), public object না।

#নিজে করে দেখো

Command-গুলোতে দোকানের বানানো bucket shop-media-example, account 111122223333।

# ১. Block Public Access-এর চারটা setting দেখো: আগে bucket level, তারপর account level
aws s3api get-public-access-block --bucket shop-media-example
aws s3control get-public-access-block --account-id 111122223333

# ২. পুরো account-এর জন্য চারটাই চালু করো (পরামর্শ এটাই)
aws s3control put-public-access-block --account-id 111122223333 \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

# ৩. Object Ownership: দেখো, আর পুরনো bucket-এ ACL বন্ধ করো
aws s3api get-bucket-ownership-controls --bucket shop-media-example
aws s3api put-bucket-ownership-controls --bucket shop-media-example \
  --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'

# ৪. File থেকে bucket policy save করো, আবার পড়ো, আর S3-কে জিজ্ঞেস করো এটা public কি না
aws s3api put-bucket-policy --bucket shop-media-example --policy file://policy.json
aws s3api get-bucket-policy --bucket shop-media-example --query Policy --output text
aws s3api get-bucket-policy-status --bucket shop-media-example
# -> "PolicyStatus": { "IsPublic": false }

# ৫. শুধু-HTTPS নিয়মটা পরীক্ষা করো: প্রথমটা 403 দিয়ে ব্যর্থ, দ্বিতীয়টা চলে
curl -s -o /dev/null -w "%{http_code}\n" http://shop-media-example.s3.ap-southeast-1.amazonaws.com/photos/saree-red.jpg
curl -s -o /dev/null -w "%{http_code}\n" https://shop-media-example.s3.ap-southeast-1.amazonaws.com/photos/saree-red.jpg

# ৬. কিছু বদলানোর আগে S3-এর ওপর একটা IAM principal simulate করো
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::111122223333:role/shop-web-role \
  --action-names s3:GetObject \
  --resource-arns arn:aws:s3:::shop-media-example/invoices/2026/10/inv-1043.pdf

# ৭. IAM Access Analyzer: প্রতি Region-এ একবার analyzer বানাও, তারপর S3-এর finding দেখো
aws accessanalyzer create-analyzer --analyzer-name account-external --type ACCOUNT
aws accessanalyzer list-findings-v2 \
  --analyzer-arn arn:aws:access-analyzer:ap-southeast-1:111122223333:analyzer/account-external \
  --filter '{"resourceType": {"eq": ["AWS::S3::Bucket"]}}'

৪ নম্বর ধাপের policy.json হতে পারে এই লেসনের যেকোনো policy। BlockPublicPolicy চালু রেখে public-read policy-টা save করে দেখো: call ব্যর্থ হবে AccessDenied দিয়ে, আর সেটাই setting-এর কাজ।

#সারসংক্ষেপ

মূল কথা

  • প্রতিটা bucket শুরু হয় private। এপ্রিল ২০২৩ থেকে নতুন bucket-এ Block Public Access চালু আর ACL বন্ধ (Bucket owner enforced)।
  • User-based: user, group আর role-এর IAM policy; EC2-র application পায় IAM role, key কখনো না। Resource-based: bucket policy (Principal সহ JSON, bucket প্রতি একটা, ২০ KB), আর পুরনো ACL।
  • Bucket-level action (s3:ListBucket) লাগে arn:aws:s3:::bucket-এ; object action (s3:GetObject) লাগে arn:aws:s3:::bucket/*-এ।
  • Explicit Deny সব জায়গায় জেতে। একই account: IAM অথবা bucket policy। Cross-account: দুটোই, caller-এর IAM policy এবং bucket policy। Anonymous: শুধু bucket allow করতে পারে।
  • Bucket policy-র কাজ: public read (Principal: "*", শুধু পড়া, ঠিক prefix), cross-account, organization (aws:PrincipalOrgID), শুধু HTTPS (aws:SecureTransport false হলে Deny: in transit), upload-এ নির্দিষ্ট encryption বাধ্যতামূলক (at rest, লেসন ১০.৮), network-এর সীমা (aws:SourceVpce, aws:SourceIp)।
  • Block Public Access কখনো কিছু দেয় না: BlockPublicAcls আর BlockPublicPolicy নতুন public অনুমতি ফিরিয়ে দেয়; IgnorePublicAcls আর RestrictPublicBuckets পুরনোগুলো অকেজো করে (policy public হলে শেষেরটা অন্য account-কেও আটকায়)। Level: access point, bucket, account, organization (নভেম্বর ২০২৫ থেকে); সবচেয়ে কড়াটা জেতে।
  • Object Ownership: Bucket owner enforced (default, ACL বন্ধ, সবকিছুর মালিক bucket-এর মালিক), Bucket owner preferred, Object writer। অন্য ACL সহ upload ব্যর্থ হয় AccessControlListNotSupported দিয়ে।
  • IAM Access Analyzer for S3 public আর cross-account bucket-এর তালিকা দেয়, এক click-এ public access বন্ধ করে, ইচ্ছাকৃত finding archive করে; প্রতি Region-এ একটা analyzer লাগে।