Course-এর সূচি

4.3

User Data, AMI, IMDS ও Launch Template

প্রথম boot-এই সব সেটআপ করে ফেলা, golden image বানানো, IMDSv2 দিয়ে নিরাপদে metadata পড়া, আর launch template দিয়ে একই রকম Instance বারবার চালানো।

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

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

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

  • এমন একটা user data script লিখতে পারবে, যেটা প্রথম boot-এই instance সাজিয়ে দেয়; আর জানবে script কখন চলে, কে চালায়, log কোথায় যায়।
  • AMI-র ভেতরে কী থাকে, AMI কোথা থেকে আসে, আর একটা AMI কেন একটা Region-এই আটকে থাকে, বুঝিয়ে বলতে পারবে।
  • golden AMI বানাবে নাকি user data দিয়ে boot-এর সময় সাজাবে, সেটা ঠিক করতে পারবে, আর দুটো মিলিয়ে ব্যবহার করতে পারবে।
  • IMDSv2 দিয়ে নিরাপদে instance metadata পড়তে পারবে, আর বোঝাতে পারবে IMDSv2 বাধ্যতামূলক করলে SSRF দিয়ে credential চুরি কেন আটকে যায়।
  • launch template আর তার version ব্যবহার করতে পারবে, আর বলতে পারবে launch configuration কেন পুরনো হয়ে গেছে।

#ফাঁকা server থেকে তৈরি server

instance চালু হলেই সেটা কাজের হয়ে যায় না। disk-এ যা আছে, ততটুকুই তার কাজ। একটা web server-এর লাগে web server program, তোমার application, তার setting, একটা monitoring agent, security patch। এগুলো disk-এ পৌঁছানোর তিনটা উপায় আছে:

  1. হাতে হাতে: launch-এর পর login করে নিজে command টাইপ করো। ধীর, ভুল হওয়ার সুযোগ বেশি, আর রাত ৩টায় Auto Scaling group দশটা server চালু করলে তো এটা অসম্ভব।
  2. boot-এর সময়, user data দিয়ে: launch করার সময় EC2-কে একটা script দিয়ে দাও, instance প্রথম boot-এ সেটা চালাবে। একে বলে bootstrapping।
  3. আগে থেকেই, একটা image-এ: সব কিছু একবার install করে disk-টা AMI (Amazon Machine Image) হিসেবে রেখে দাও, তারপর প্রতিটা নতুন server চালু করো সেই তৈরি image থেকে। একে বলে baking।

এরপর একটা launch template পুরো রেসিপিটা লিখে রাখে (কোন AMI, কোন instance type, কোন security group, কোন user data), যাতে প্রতিবার launch হুবহু এক রকম হয়। আর instance চলার সময় instance metadata service (IMDS) তাকে জানায় সে কে, আর তার IAM role-এর credential তার হাতে তুলে দেয়।

#User data: প্রথম boot-এর script

User data হলো সেই লেখা, যেটা instance launch করার সময় তুমি EC2-কে দাও। Linux-এ সাধারণত এটা একটা shell script, যার শুরুতে থাকে #!। চাইলে এটা একটা #cloud-config file-ও হতে পারে, যেখানে command-এর বদলে setting লেখা থাকে। operating system-এর ভেতরের একটা program, cloud-init (Amazon Linux, Ubuntu, Red Hat আর বেশির ভাগ Linux AMI-তে থাকে), metadata service থেকে এটা এনে চালায়।

#!/bin/bash
dnf install -y httpd
echo "<h1>Hello from $(hostname -f)</h1>" > /var/www/html/index.html
systemctl enable --now httpd

User data কীভাবে চলে:

বৈশিষ্ট্যকী বোঝায়
একবারই চলেdefault নিয়মে শুধু instance-এর প্রথম boot-এ। reboot, stop/start বা hibernate থেকে ফেরা, কোনোটাতেই আবার চলে না।
root হিসেবে চলেsudo লাগে না। package install করা, যেকোনো জায়গায় লেখা, service চালু করা, সবই পারে।
boot-এর শেষ দিকে চলেnetwork চালু হওয়ার পর, boot-এর প্রায় শেষে। তাই script শেষ হওয়ার আগেই instance “running” দেখাতে পারে।
আকারের সীমাকাঁচা data 16 KB পর্যন্ত (base64 encode করার আগে)। এর বেশি লাগলে script দিয়ে S3 থেকে বড় একটা script নামিয়ে নাও।
Logscript যা print করে, সব যায় /var/log/cloud-init-output.log-এ।
শুধু stop অবস্থায় বদলানো যায়instance stop থাকলেই কেবল user data বদলানো যায়, আর বদলালেও নতুন script নিজে থেকে চলে না।
instance থেকে পড়া যায়instance-এর যেকোনো process metadata service থেকে এটা পড়তে পারে, আর যার instance-এর attribute দেখার permission আছে সে API দিয়েও পড়তে পারে। তাই user data-য় কখনো password বা key রাখবে না।

Windows-এও একই ব্যাপার, তবে কাজটা করে EC2Launch v2 agent। script বসাতে হয় <powershell> আর </powershell> tag-এর মাঝে, আর তার log থাকে C:\ProgramData\Amazon\EC2Launch\log\-এ।

user data দিয়ে সাধারণত যা করা হয়: update আর package install, application-এর file নামানো, এই environment-এর জন্য config file লেখা, কোনো monitoring বা configuration tool-এ নাম লেখানো, cluster-এ যোগ দেওয়া।

user data সহ একটা instance-এর প্রথম boot

তুমি user data-য় একটা script দিয়ে instance launch করলে। দেখো script-টা কে চালায়, কখন চালায়, আর script ভাঙলে বা instance restart হলে কী হয়।

পরিস্থিতি

তুমিconsole বা CLI
EC2 Instancei-0abc
cloud-initOS-এর ভেতরে চলে
IMDS169.254.169.254
Package repository
launch + user data
ধাপ 1 / 8
1

তুমি একটা instance launch করলে, আর user data-র ঘরে একটা bash script বসিয়ে দিলে (সর্বোচ্চ 16 KB)। EC2 script-টা instance-এর সাথে রেখে দেয়; এখনো কিছু চলেনি।

#user data-য় কোথায় গোলমাল হয়

  • script মাঝপথে ভেঙে যায়। Internet-এ যাওয়ার পথ ছাড়া download (private subnet, কিন্তু NAT gateway বা VPC endpoint নেই), টাইপের ভুল, বন্ধ হয়ে থাকা mirror। instance তবুও running দেখায়, দুটো status check-ই পাস করে। কারণ এই check-গুলো দেখে hardware ঠিক আছে কি না আর operating system সাড়া দিচ্ছে কি না; তোমার script কাজ করল কি না, সেটা দেখে না। তাই script শুরু করো set -euo pipefail দিয়ে, যাতে প্রথম error-এই থেমে যায়; /var/log/cloud-init-output.log পড়ো; আর load balancer-এর health check রাখো, যাতে যে server কখনো তৈরিই হয়নি সেটা ধরা পড়ে।
  • “বদলালাম, কিন্তু কিছুই হলো না।” প্রথম boot-এর পর user data আর চলে না। প্রতিবার boot-এ কিছু চালাতে চাইলে script রাখো /var/lib/cloud/scripts/per-boot/-এ, অথবা cloud-init-কে বলে দাও user script always চালাতে (Windows-এ <persist>true</persist> যোগ করো)। চালু server-এ একবারের কোনো বদলের জন্য Systems Manager Run Command ব্যবহার করো, অথবা নতুন একটা AMI বানাও।
  • user data-য় secret। user data-র সব কিছু instance থেকে পড়া যায়, আর যার instance-এর attribute দেখার permission আছে সে-ও পড়তে পারে। তাই script-কে দিয়ে boot-এর সময় secret আনাও Secrets Manager বা Systems Manager Parameter Store থেকে, instance-এর IAM role ব্যবহার করে।
  • ধীর boot। যে script code compile করে বা কয়েক GB নামায়, সেটার কারণে প্রতিটা নতুন instance কাজের হতে অনেক মিনিট লেগে যায়। ঠিক তখনই AMI bake করার সময়।

#AMI: যে image থেকে instance boot হয়

প্রতিটা instance কোনো না কোনো AMI থেকে launch হয়। কোন operating system থাকবে, root disk-এ আগে থেকে কী কী install করা থাকবে, সেটা ঠিক করে দেয় AMI।

#AMI-র ভেতরে কী থাকে

AMI একটা মাত্র file না। এটা AWS-এ register করা একটা record, যেটা কয়েকটা জিনিসকে একসাথে বেঁধে রাখে:

  • এক বা একাধিক EBS snapshot: root volume-এর (operating system, software, file) একটা নির্দিষ্ট মুহূর্তের কপি, সাথে বাড়তি data volume থাকলে সেগুলোরও। (পুরনো instance-store-backed AMI-তে snapshot-এর বদলে root volume-এর একটা template থাকে S3-এ; এখন এগুলো খুব কম দেখা যায়, আর এদের instance stop করা যায় না।)
  • একটা block device mapping: launch-এর সময় কোন কোন volume বানাতে হবে, তাদের size আর type কী, কোন device নাম পাবে।
  • launch permission: কে এটা দিয়ে launch করতে পারবে: শুধু তোমার account, নির্দিষ্ট কিছু account, একটা organization বা organizational unit, নাকি সবাই (public)।
  • আরও কিছু তথ্য: architecture (x86_64 বা arm64), boot mode, virtualization type, নাম, বর্ণনা, tag।

AMI-র নিজের জন্য কোনো টাকা লাগে না। টাকা লাগে তার পেছনের snapshot storage-এর জন্য (আর Marketplace থেকে নিলে software-এর জন্য)।

#AMI কোথা থেকে আসে

উৎসউদাহরণখেয়াল রাখো
AWS-এর দেওয়াAmazon Linux 2023, Windows Server, Ubuntu, Red HatAWS বা vendor নিজেই দেখভাল আর patch করে; সাধারণত শুরু এখান থেকেই
AWS Marketplacefirewall appliance, hardened OS, license-সহ databasevendor-রা বিক্রি করে; কিছু AMI-র জন্য instance-এর দামের ওপর ঘণ্টা হিসেবে বাড়তি টাকা লাগে
Community (public) AMIযে কেউ public করে শেয়ার করেছেসুবিধাজনক, কিন্তু কেউ যাচাই করেনি; ভরসা করার আগে owner কে, দেখে নাও
তোমার নিজেরতোমার golden image, ওপরের কোনো একটা থেকে বানানোশেয়ার না করা পর্যন্ত শুধু তোমার account-এ দেখা যায়

প্রতিটা Region-এ AMI ID আলাদা, আর AWS যখনই কোনো image patch করে, নতুন ID দেয়। তাই ID কোডে বসিয়ে না রেখে public Systems Manager parameter থেকে সবচেয়ে নতুনটা খুঁজে নাও, যেমন /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64। যে Region-এ জিজ্ঞেস করবে, সেখানকার এখনকার ID এটা বলে দেবে।

#নিজের AMI বানানো

  1. একটা base AMI দিয়ে শুরু করো

    ভরসাযোগ্য একটা base image থেকে instance launch করো, যেমন Amazon Linux 2023।

  2. নিজের মতো সাজাও

    package, তোমার application, agent আর security setting install করো। instance-নির্দিষ্ট যা কিছু, সেগুলো মুছে ফেলো: অস্থায়ী file, যে SSH host key সবার সাথে শেয়ার হোক চাও না, log, credential।

  3. image বানাও

    instance-এর ওপর create image চালাও। EC2 তার EBS volume-গুলোর snapshot নেয় আর নতুন একটা AMI register করে। default নিয়মে EC2 আগে instance-টা reboot করে, যাতে file system ঠিকঠাক অবস্থায় থাকে। --no-reboot দিলে downtime হয় না, কিন্তু লেখা চলার মাঝখানে snapshot উঠে যাওয়ার ঝুঁকি থাকে।

  4. এটা থেকে launch করো

    নতুন AMI থেকে যত instance চালু হবে, সবাই ঠিক ওই disk নিয়েই শুরু করবে। নামের মধ্যে একটা version রাখো (web-2026-10-24), যাতে দরকার হলে আগেরটায় ফিরে যেতে পারো।

#AMI থাকে একটা Region-এ

একটা AMI বানানো হয় নির্দিষ্ট একটা AWS Region-এর জন্য, আর তার ID শুধু সেখানেই আছে। এটা দিয়ে অন্য Region-এ instance launch করা যায় না। তবে AMI-টা গন্তব্য Region-এ কপি করে নিতে পারো, তারপর সেই কপি থেকে launch করো।

কপি করার সময় যা জানা দরকার:

  • copy-image চালাতে হয় গন্তব্য Region-এ। এটা AMI আর তার snapshot ওপারে কপি করে নিয়ে যায়। কপিটা পায় নতুন AMI ID।
  • এরপর থেকে দুটো AMI একদম আলাদা। মূল Region-এ নতুন version বানালে সেটা আবার কপি করতে হবে।
  • launch permission কপি হয় না; অন্য account-এর দরকার হলে কপিটা আবার শেয়ার করো।
  • কপির সময় encrypt না করা AMI-কে encrypt করে নিতে পারো, বা অন্য key দিয়ে আবার encrypt করতে পারো। কিন্তু কপি করে encryption সরানো যায় না।
  • অন্য account তোমার সাথে কোনো AMI শেয়ার করলে, নিজের মালিকানায় একটা কপি পাওয়ার উপায়ও এই কপি করা।

Golden AMI বনাম প্রতিটা instance-কে শুরু থেকে সাজানো

একটা Auto Scaling group-এর তিনটা নতুন web server দরকার। boot-এর সময় সব install করা আর আগে থেকে তৈরি image থেকে launch করা, দুটো তুলনা করো। তারপর সেই image অন্য Region-এ নিয়ে যাও।

পরিস্থিতি

us-east-1
Auto Scaling group
Package repository
web-1
web-2
web-3
ধাপ 1 / 3
1

হঠাৎ traffic বেড়ে গেল, group একটা সাধারণ Amazon Linux AMI থেকে তিনটা instance launch করল। প্রত্যেকটা একটা লম্বা user data script চালাচ্ছে।

#অন্য account-এর সাথে AMI শেয়ার করা

AMI শেয়ার করা হয় তার launch permission বদলে: একটা account ID, একটা organization বা একটা organizational unit যোগ করে। AMI থেকে যায় তোমার account-এই; অন্য account এটা দিয়ে launch করতে পারে, অথবা কপি করে নিজের একটা কপি রাখতে পারে।

  • encrypted snapshot-ওয়ালা AMI শেয়ার করা যায় শুধু তখনই, যখন সেটা একটা customer managed key দিয়ে encrypt করা, আর অন্য account-কে সেই key ব্যবহারের permission-ও দিতে হয়। default AWS managed key (aws/ebs) দিয়ে encrypt করা snapshot শেয়ার করা যায় না: আগে customer managed key দিয়ে AMI-টা কপি করে নাও।
  • encrypted AMI কখনো public করা যায় না।
  • account-এ AMI public শেয়ার করা আটকে রাখা যায় (নতুন account-এ এটা শুরু থেকেই চালু থাকে)। এতে ভুল করে ভেতরে secret-ওয়ালা কোনো image সবার জন্য খুলে দেওয়ার ভয় থাকে না।

#AMI deregister করা

কোনো image আর না লাগলে সেটা deregister করো। তিনটা কথা মাথায় রাখো:

  • চালু instance-এর কিছু হয় না। তাদের নিজেদের volume আগেই তৈরি হয়ে গেছে।
  • এটা থেকে নতুন launch fail করে, Auto Scaling-এর launch-ও, যদি launch template এখনো এর নাম ধরে রাখে। তাই আগে template বদলাও।
  • এর snapshot নিজে থেকে মোছে না। সেগুলো থেকে যায়, আর বিলও আসতে থাকে, যতক্ষণ না তুমি মুছছ (নতুন console আর API-তে AMI-র সাথে একসাথে মুছে ফেলার option আছে)। retention rule দিয়ে Recycle Bin চালু রাখলে ভুল করে deregister করা AMI ফেরতও আনা যায়।

#Bake নাকি bootstrap? Golden AMI

baking আর bootstrapping একই হিসাবের দুই প্রান্ত:

user data দিয়ে bootstrapgolden AMI bake
boot-এর সময়ধীর: প্রতিটা instance সব কিছু install করেদ্রুত: disk আগে থেকেই তৈরি
সব এক রকম কি নাএকেক instance-এ package-এর version একটু একটু আলাদা হতে পারেপ্রতিটা instance হুবহু এক
launch-এর সময় কীসের ওপর নির্ভরপ্রতিবার package mirror আর network লাগেকিছুই নামাতে হয় না, তাই mirror বন্ধ থাকলেও scaling আটকায় না
কিছু বদলাতে হলেscript বদলাও; পরের launch থেকেই নতুনটানতুন AMI বানাও, test করো, সবখানে ছড়াও
কীসের জন্য ভালোছোট, দ্রুত ধাপ আর environment অনুযায়ী যা বদলায়ধীর, ভারী, কম বদলানো অংশ

সাধারণত উত্তর হলো দুটোই:

  • operating system, patch, runtime, agent আর application bake করো একটা golden AMI-তে।
  • bootstrap করো শুধু সেটুকু, যা একেক launch-এ আলাদা: environment-এর নাম, একটা config file, কোনো service-এ নাম লেখানো, একটা secret আনা।

“instance তৈরি হতে অনেক সময় লাগে” বা “scale-out খুব ধীর”, পরীক্ষায় এমন প্রশ্নের standard উত্তর এটাই: software আগে থেকে install করা একটা golden AMI বানাও, আর user data ছোট রাখো। (ধীর অংশটা যদি memory-তে cache গরম হওয়া হয়, তাহলে কাজে লাগে hibernation; লেসন 4.5 দেখো।)

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

একটা টিম us-east-1-এ একটা AMI ব্যবহার করে। এখন তাদের একই server ap-southeast-2-এ চালু করতে হবে। কী করা উচিত?

#এক নজরে EC2 Image Builder

হাতে হাতে golden AMI বানানোও একটা ঝামেলার কাজ, আর মানুষ সেটা নিয়মিত করতে ভুলে যায়। EC2 Image Builder কাজটাকে একটা pipeline বানিয়ে নিজে নিজে চালায়:

  1. একটা recipe-তে থাকে একটা base image আর কিছু component: build-এর ধাপ (install, configure, harden) আর test-এর ধাপ।
  2. Image Builder একটা অস্থায়ী build instance চালু করে, build component-গুলো চালায়, AMI বানায়, তারপর একটা test instance চালু করে test চালায়।
  3. distribution setting নতুন AMI-টা অন্য Region-এ কপি করে, অন্য account-এর সাথে শেয়ার করে, এমনকি কোনো launch template-কেও নতুন AMI-র দিকে ঘুরিয়ে দিতে পারে।
  4. pipeline চলে schedule ধরে (যেমন প্রতি সপ্তাহে), অথবা base image-এ update এলেই। ফলে তোমার golden AMI security patch-এর সাথে তাল মিলিয়ে চলে।

Image Builder নিজে বিনামূল্যে; টাকা লাগে সে যে instance, snapshot আর storage ব্যবহার করে তার জন্য। এটা container image-ও বানাতে পারে। পরীক্ষায়: “AMI বানানো, patch করা আর test করা automate করতে হবে” → EC2 Image Builder।

#instance metadata service (IMDS)

instance-এ চলা software-এর প্রায়ই instance-টা সম্পর্কেই কিছু জানা দরকার হয়: তার ID, private IP, সে কোন Availability Zone-এ আছে, আর সবচেয়ে জরুরি, তার IAM role-এর credential। instance metadata service এসব প্রশ্নের উত্তর দেয় একটা বিশেষ address-এ, যেটা শুধু instance-এর ভেতর থেকেই পাওয়া যায়:

  • http://169.254.169.254 (IPv4, একটা link-local address; এর দিকে যাওয়া packet কখনো host ছেড়ে বের হয় না);
  • http://[fd00:ec2::254] (IPv6, Nitro instance-এ, চালু করে নিলে)।

এর জন্য কোনো টাকা লাগে না, Internet-ও লাগে না।

#এটা কী কী জানায়

Path (/latest/-এর নিচে)কী পাওয়া যায়
meta-data/instance-id, meta-data/ami-id, meta-data/instance-typeinstance-টা কে, আর কী থেকে launch হয়েছে
meta-data/local-ipv4, meta-data/public-ipv4, meta-data/macতার address-গুলো
meta-data/placement/availability-zoneসে কোথায় চলছে
meta-data/iam/security-credentials/<role-name>instance-এর IAM role-এর অস্থায়ী credential: একটা access key, একটা secret key আর একটা session token
user-datauser data script
dynamic/instance-identity/documentএকটা signed document, যেটা প্রমাণ করে এটা কোন instance, কোন account, কোন Region

role-এর credential-ই হলো সেই উপায়, যাতে EC2-এ চলা application disk-এ কোনো key না রেখেই AWS-এর permission পায়। তুমি instance-এ একটা IAM role লাগিয়ে দাও (একটা instance profile-এর মাধ্যমে, অধ্যায় ২), আর AWS CLI ও AWS library নিজেরাই IMDS থেকে key নিয়ে আসে। key-গুলোর মেয়াদ কয়েক ঘণ্টা, আর মেয়াদ ফুরানোর আগেই AWS নতুন key দিয়ে দেয়।

এই কারণেই IMDS আক্রমণের লক্ষ্যও বটে: instance থেকে যে-ই 169.254.169.254-এ একটা request পাঠাতে পারবে, সে role-এর key নিয়ে চলে যেতে পারবে।

#IMDSv1 আর IMDSv2

IMDS-এর সাথে কথা বলার দুটো উপায় আছে:

IMDSv1IMDSv2
কীভাবেpath-এ একটা সাধারণ GETআগে TTL header দিয়ে একটা PUT /latest/api/token পাঠিয়ে session token নাও; তারপর প্রতিটা GET-এর header-এ token দাও
token-এর মেয়াদtoken-ই নেই১ সেকেন্ড থেকে ৬ ঘণ্টা (21,600 সেকেন্ড), যে চাইছে সে ঠিক করে
SSRF থেকে বাঁচায়নাহ্যাঁ
token-এর উত্তরে hop limitপ্রযোজ্য নাহ্যাঁ, default 1
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/placement/availability-zone

প্রতিটা instance-এ http-tokens নামে একটা setting থাকে:

  • optional: দুটো version-ই চলে (IMDSv1 তখনো খোলা);
  • required: শুধু IMDSv2 চলে; বৈধ token ছাড়া request এলে উত্তর আসে 401 Unauthorized।

AWS এখন জোরালোভাবে required-এর দিকেই ঝুঁকেছে: console-এর launch wizard আর অনেক নতুন AMI (Amazon Linux 2023-সহ) default হিসেবেই শুধু IMDSv2 রাখে, ২০২৪-এর মাঝামাঝির পর আসা instance type-গুলোও তাই, আর প্রতিটা Region-এ পুরো account-এর জন্য default ঠিক করে দেওয়া যায়।

#IMDSv2 কেন SSRF দিয়ে credential চুরি আটকায়

Server-side request forgery (SSRF) হলো এমন একটা bug, যেখানে application attacker-এর দেওয়া URL নিজে গিয়ে নিয়ে আসে: “এই link-এর preview দেখাও” feature, image নামানোর tool, webhook test করার tool। attacker দেয় http://169.254.169.254/latest/meta-data/iam/security-credentials/…। request-টা যাচ্ছে instance-এর ভেতর থেকেই, তাই IMDS উত্তর দিয়ে দেয়।

  • IMDSv1 চালু থাকলে ওই একটা GET-এই role-এর key ফেরত আসে। application উত্তরটা দেখায় বা log-এ লেখে, আর attacker পৃথিবীর যেকোনো জায়গা থেকে key-গুলো ব্যবহার করে, মেয়াদ শেষ না হওয়া পর্যন্ত। ২০১৯ সালে একটা বড় ব্যাংকে ঠিক এভাবেই ১০ কোটির বেশি গ্রাহকের data ফাঁস হয়েছিল।
  • IMDSv2 required থাকলে ওই GET-এ কোনো token নেই, তাই উত্তর আসে 401। সাধারণ SSRF bug-এ attacker শুধু একটা GET-এর URL ঠিক করে দিতে পারে; server-কে দিয়ে আগে বিশেষ header-সহ একটা PUT পাঠানো, তারপর সেই token আবার ব্যবহার করানো, এটা সে পারে না। তা ছাড়া X-Forwarded-For header থাকলে IMDSv2 token-এর request-ই নেয় না, তাই ভুলভাবে খোলা রাখা reverse proxy দিয়েও বেশির ভাগ চেষ্টা আটকে যায়।

#Hop limit

token-এর উত্তর পাঠানো হয় এমন একটা IP time-to-live দিয়ে, যেটা hop limit-এর সমান (1 থেকে 64; default 1)। প্রতিটা network hop পার হলে এটা এক করে কমে। তাই hop limit 1 হলে উত্তরটা instance-এর নিজের software পর্যন্ত পৌঁছায়, কিন্তু এক hop দূরের কোনো কিছুর কাছে পৌঁছানোর আগেই মারা যায়: bridge network-এ চলা একটা container, বা খোলা proxy কিংবা ভুল route কাজে লাগানো অন্য কোনো মেশিন।

  • hop limit 1: যে instance-এ container চলে না, তার জন্য নিরাপদ default।
  • hop limit 2: instance-এর container-গুলোর যদি IMDSv2 ব্যবহার করতেই হয় (যেমন কিছু container host আর Kubernetes node)। তবে দীর্ঘমেয়াদে ভালো সমাধান হলো প্রতিটা container-কে instance-এর role না দিয়ে তার নিজের role দেওয়া।

metadata service থেকে role-এর credential, আর attacker কীভাবে সেটা চুরি করতে চায়

web app-এর একটা IAM role আছে, যেটা দিয়ে একটা S3 bucket পড়া যায়। এই role-এর অস্থায়ী key দেয় IMDS, 169.254.169.254-এ, যেটা শুধু instance-এর ভেতর থেকেই পাওয়া যায়।

পরিস্থিতি

Attacker203.0.113.66
Web approle: app-role
Containerএকই instance-এ
IMDS169.254.169.254
S3 bucketগ্রাহকের data
PUT /latest/api/token
ধাপ 1 / 5
1

app-এর ভেতরের AWS library প্রথমে HTTP PUT দিয়ে একটা session token চায়, আর বলে দেয় token কতক্ষণ টিকবে (এখানে ৬ ঘণ্টা, এটাই সর্বোচ্চ)।

#IMDSv2 বাধ্যতামূলক করা

  • চালু instance-এ: aws ec2 modify-instance-metadata-options --http-tokens required (restart লাগে না)।
  • নতুন instance-এর জন্য: launch template-এ metadata version: V2 only দাও, account-এর default ঠিক করে দাও, অথবা এমন AMI ব্যবহার করো যেটা শুধু-IMDSv2 হিসেবে register করা।
  • পুরো organization জুড়ে: একটা IAM policy বা service control policy দিয়ে বলে দেওয়া যায়, IMDSv2 required না হলে instance launch করা যাবে না, আর পরে সেটা ফিরিয়ে বদলানোও যাবে না।
  • বদলানোর আগে: token ছাড়া কতগুলো metadata request এসেছে, তার CloudWatch metric দেখলে বোঝা যায় কোন instance এখনো IMDSv1 ব্যবহার করছে। পুরনো software আগে update করতে হতে পারে; এখনকার AWS CLI আর library আগে থেকেই IMDSv2 ব্যবহার করে।
  • কোনো instance-এর metadata একদমই না লাগলে endpoint-টা পুরো বন্ধ করে দিতে পারো।

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

EC2-এ চলা একটা web application-এ SSRF bug আছে। security টিম চায়, application না বদলেই, attacker যেন এটা দিয়ে instance role-এর credential চুরি করতে না পারে। প্রথমে কী করা উচিত?

#Launch template

launch template একটা instance launch করার সব parameter জমা রাখে, যাতে কাউকে আর হাতে হাতে launch wizard পূরণ করতে না হয়। এতে থাকতে পারে:

  • AMI ID, instance type আর key pair;
  • network setting: subnet, security group, public IP দেবে কি না;
  • storage: volume-এর size, type, encryption;
  • IAM instance profile, user data, metadata option (IMDSv2 required, hop limit), tag;
  • কেনার option (Spot), placement group, capacity reservation, আরও অনেক কিছু।

প্রতিটা ঘরই ঐচ্ছিক। template আংশিকও হতে পারে; যা বাদ থাকে, সেটা launch-এর সময় দিয়ে দেওয়া যায়।

launch template ব্যবহার করে:

  • একটা সাধারণ run-instances call বা console (“launch instance from template”);
  • EC2 Auto Scaling group (অধ্যায় ৬), এমনকি যে group-এ নানা instance type, Spot আর On-Demand মেশানো;
  • EC2 Fleet আর Spot Fleet (লেসন 4.4);
  • যেসব service তোমার হয়ে instance চালু করে, যেমন কিছু container আর batch service।

#Version আর default version

একটা launch template-এর থাকে নম্বর দেওয়া version, আর কোনো version কখনো edit করা যায় না। কিছু বদলাতে চাইলে তুমি নতুন একটা version বানাও, সাধারণত আগের কোনো version থেকে, শুধু দরকারি ঘরগুলো বদলে।

  • একটা version হলো default (শুরুতে version 1)। কোনটা default হবে, তুমিই ঠিক করো, আর যেকোনো সময় বদলাতে পারো।
  • template থেকে কিছু launch করার সময় চাওয়া যায় নির্দিষ্ট একটা version নম্বর, $Default, অথবা $Latest (সবচেয়ে নতুন version)।
  • নতুন version বানালে চালু instance-এ কোনো বদল হয় না, আর Auto Scaling group যা launch করে সেটাও বদলায় না, যদি না group $Latest ব্যবহার করে।
  • Auto Scaling নতুন instance চালু করে নতুন version দিয়ে, কিন্তু পুরনো instance-গুলো পুরনো configuration-এই থাকে, যতক্ষণ না সেগুলো বদলানো হয়, যেমন একটা instance refresh দিয়ে।

production-এর জন্য নিরাপদ নিয়ম: group ব্যবহার করবে $Default (বা নির্দিষ্ট একটা নম্বর); তুমি নতুন version বানাবে, test করবে, তারপর সেটাকে default বানিয়ে চালু করবে। আগের অবস্থায় ফেরা মানে শুধু default আবার আগেরটায় ফিরিয়ে দেওয়া।

Launch template-এর version আর একটা Auto Scaling group

group প্রতিটা instance launch করে web-lt থেকে। template বদলাতে থাকলে group কোন version ব্যবহার করে, খেয়াল করো।

পরিস্থিতি

us-east-1
Auto Scaling group
web-ltlaunch template
EC2 Auto Scaling
web-av1
web-bv1
$Default = 1v1v1

Launch template web-lt: version-গুলো

VersionAMIinstance typeIMDS tokenচিহ্ন
1ami-0aaat3.microoptional$Default · $Latest
ধাপ 1 / 4
1

version 1-এ আছে AMI, instance type, security group আর user data। group-কে বলা আছে template-এর $Default version ব্যবহার করতে, যেটা এখন 1।

#Launch template বনাম launch configuration

Auto Scaling group-কে কীভাবে instance চালু করতে হবে, সেটা বলার পুরনো উপায় ছিল launch configuration। এটা এখন legacy:

Launch templateLaunch configuration
বদলানোনতুন version, একটা default version, আগেরটায় ফেরা যায়বদলানোই যায় না; নতুন একটা বানিয়ে group-কে সেটায় সরাতে হয়
কারা ব্যবহার করেAuto Scaling, EC2 Fleet, Spot Fleet, সরাসরি launchশুধু Auto Scaling
এক group-এ নানা instance type, Spot + On-Demandহ্যাঁনা
নতুন instance type আর featureহ্যাঁ২০২৩ থেকে নতুন কোনো instance type যোগ হয়নি
বানানো যায় কি নাসবসময়অক্টোবর ২০২৪-এর পর তৈরি account বানাতেই পারে না

পরীক্ষায় দুটোর মধ্যে বেছে নিতে বললে উত্তর সবসময় launch template।

#Design-এ সব কিছু কীভাবে মেলে

একটা web tier-এর সাধারণ production setup:

  1. EC2 Image Builder প্রতি সপ্তাহে চলে: সবচেয়ে নতুন Amazon Linux 2023 থেকে শুরু করে, patch, runtime আর application install করে, test চালায়, আর একটা golden AMI বানায়। application যত Region-এ চলে, সবখানে সেটা কপি হয়ে যায়।
  2. নতুন একটা launch template version নতুন AMI-র দিকে দেখায়, hop limit 1 সহ IMDSv2 বাধ্যতামূলক করে, IAM instance profile লাগায়, আর সাথে রাখে ছোট একটা user data script, যেটা boot-এর সময় environment-এর নাম লেখে আর Secrets Manager বা Parameter Store থেকে secret নিয়ে আসে।
  3. test-এর পর সেই version হয় default। Auto Scaling group ($Default-এ সেট করা) নতুন সব instance সেটা দিয়ে চালু করে, আর একটা instance refresh ধীরে ধীরে পুরনোগুলো বদলে দেয়।
  4. কিছু গোলমাল হলে default আগের version-এ ফিরিয়ে দাও, আবার refresh করো।

ফলাফল: দ্রুত তৈরি, হুবহু এক রকম, patch করা server; কোনো disk-এ কোনো key নেই; role-এর credential SSRF থেকে সুরক্ষিত; আর এক ধাপেই আগের অবস্থায় ফেরা যায়।

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

# 1. একটা user data script: error হলে থামে, IMDSv2 ব্যবহার করে, AZ-এর নামসহ একটা পেজ লেখে
cat > web.sh <<'EOF'
#!/bin/bash
set -euo pipefail
dnf install -y httpd
TOKEN=$(curl -sX PUT http://169.254.169.254/latest/api/token \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 300")
AZ=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/placement/availability-zone)
echo "<h1>Hello from $(hostname -f) in $AZ</h1>" > /var/www/html/index.html
systemctl enable --now httpd
EOF

# 2. সবচেয়ে নতুন Amazon Linux 2023 AMI থেকে launch, IMDSv2 বাধ্যতামূলক
#    (run-instances-এ CLI নিজেই user data base64 করে নেয়)
aws ec2 run-instances --instance-type t3.micro \
  --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
  --security-group-ids $SG --subnet-id $SUBNET --user-data file://web.sh \
  --metadata-options HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled

# 3. Instance-এর ভেতরে: script কেমন চলল দেখো, আর IMDS-এর দুই version চেষ্টা করো
sudo tail -n 20 /var/log/cloud-init-output.log
curl -s http://169.254.169.254/latest/meta-data/instance-id         # IMDSv1: v2 required থাকলে 401
TOKEN=$(curl -sX PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 60")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id

# 4. চালু একটা Instance-এ IMDSv2 বাধ্যতামূলক করো
aws ec2 modify-instance-metadata-options --instance-id $ID --http-tokens required --http-endpoint enabled

# 5. সাজানো Instance থেকে AMI bake করো, তারপর অন্য Region-এ কপি করো (গন্তব্য Region-এ চালাতে হয়)
AMI=$(aws ec2 create-image --instance-id $ID --name web-2026-10-24 --query ImageId --output text)
aws ec2 copy-image --region eu-west-1 --source-region us-east-1 --source-image-id $AMI \
  --name web-2026-10-24 --encrypted

# 6. AMI ব্যবহার করা একটা launch template, তারপর নতুন version আর নতুন default
aws ec2 create-launch-template --launch-template-name web-lt --launch-template-data \
  "{\"ImageId\":\"$AMI\",\"InstanceType\":\"t3.micro\",\"MetadataOptions\":{\"HttpTokens\":\"required\"}}"
aws ec2 create-launch-template-version --launch-template-name web-lt --source-version 1 \
  --launch-template-data '{"InstanceType":"t3.small"}'
aws ec2 modify-launch-template --launch-template-name web-lt --default-version 2

# 7. পরিষ্কার করা: আলাদা করে না বললে deregister snapshot মোছে না
aws ec2 deregister-image --image-id $AMI --delete-associated-snapshots

launch template-এ user data তোমাকেই base64 করে দিতে হয় (base64 -w0 web.sh); run-instances নিজেই করে নেয়।

#সারসংক্ষেপ

মূল কথাগুলো

  • User data হলো একটা script, যেটা EC2 instance-এর হাতে দেয়; cloud-init সেটা চালায় একবারই, প্রথম boot-এ, root হিসেবে। সীমা 16 KB; log থাকে /var/log/cloud-init-output.log-এ; reboot বা stop/start-এর পর আর চলে না; এতে কখনো secret রাখবে না।
  • AMI = EBS snapshot + block device mapping + launch permission। উৎস: AWS, Marketplace, community, তোমার নিজের। AMI-র জন্য টাকা লাগে না; টাকা লাগে তার snapshot-এর জন্য।
  • AMI থাকে একটা Region-এ: অন্য Region-এ নিতে কপি করো (নতুন ID, launch permission কপি হয় না, পথেই encrypt করা যায়)। শেয়ার করো launch permission দিয়ে; encrypted হলে customer managed key-ও শেয়ার করতে হয়।
  • Deregister করলে চালু instance-এর কিছু হয় না, যে launch এর নাম ধরে আছে সেটা ভাঙে, আর snapshot (সাথে তার বিল) থেকে যায়, যতক্ষণ না তুমি মুছছ।
  • ভারী, সবার জন্য এক অংশগুলো golden AMI-তে bake করো, যাতে launch দ্রুত আর হুবহু এক হয়; user data দিয়ে bootstrap করো শুধু launch-ভেদে আলাদা জিনিস। EC2 Image Builder AMI বানানো, test আর বিতরণ automate করে।
  • 169.254.169.254-এর IMDS instance-কে তার পরিচয় আর IAM role-এর credential দেয়। IMDSv2-তে লাগে PUT দিয়ে আনা একটা session token (সর্বোচ্চ ৬ ঘণ্টা), যেটা SSRF দিয়ে credential চুরি আটকায়; hop limit (default 1) token-কে container বা অন্য host পর্যন্ত যেতে দেয় না। launch template, account default বা policy দিয়ে এটা বাধ্যতামূলক করো।
  • Launch template পুরো launch-এর রেসিপি রাখে, এর আছে বদলানো যায় না এমন নম্বর দেওয়া version আর একটা default version, আর এটা ব্যবহার করে Auto Scaling, EC2 Fleet আর Spot Fleet। Launch configuration পুরনো, legacy।