14. Amazon S3: Buckets, Objects, Policies and Presigned URLs
14.7 Encryption, Logging, IAM Roles and the S3 Security Checklist
Encryption at rest (संग्रहित माहितीचे कूटबद्धीकरण): every new object is encrypted with SSE-S3 by default. For more control, choose SSE-KMS (keys in AWS KMS, every use logged in CloudTrail). Encryption in transit: always HTTPS – enforce it with the DenyInsecureTransport statement from 14.3.
Access from EC2 – use an IAM role, never access keys on the server. Create a role once, attach it to the instance, and the CLI and SDKs pick up temporary credentials automatically.
- IAM → Roles → Create role → Trusted entity: AWS service → EC2.
- Attach a custom policy (below), name the role
reels-ec2-role. - EC2 → select instance → Actions → Security → Modify IAM role → choose the role.
- On the instance:
aws sts get-caller-identityshowsassumed-role/reels-ec2-role/....
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::ravindra-reels-media-pune/videos/*"
}]
}
Logging and monitoring: enable server access logging (or CloudTrail data events) into a separate log bucket, so you can answer "who downloaded this file, from which IP, when?".
CORS – needed when JavaScript on https://yourdomain.com talks to the bucket directly (for example browser uploads with presigned PUT URLs). Allow only your own origin:
[{ "AllowedOrigins": ["https://yourdomain.com"], "AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["*"], "MaxAgeSeconds": 3000 }]
| S3 security checklist | Done? |
|---|---|
| Account-level Block Public Access ON (except deliberate website buckets) | ☐ |
| Object Ownership = Bucket owner enforced (ACLs disabled) | ☐ |
Bucket policy has no Principal: "*" Allow (except GetObject on website buckets) |
☐ |
DenyInsecureTransport statement added |
☐ |
| Default encryption SSE-S3 or SSE-KMS | ☐ |
| Versioning ON + lifecycle rule for old versions | ☐ |
| Apps use IAM roles with least privilege, scoped to a prefix | ☐ |
| Access logging or CloudTrail data events enabled | ☐ |
| Private content served with short presigned URLs | ☐ |
No secrets, backups or .git inside public buckets |
☐ |
Why this matters for security
Access keys copied onto a server (or pushed to GitHub) are among the most common ways cloud accounts get compromised – bots scan public repositories for them continuously. IAM roles give short-lived credentials that rotate automatically and never sit in a file you might leak.
Ravindra Bagale's Tip
EC2 var aws configure karun aapli personal access key takne – hi students chi sarvaat mothi chuk aahe. Ti key ~/.aws/credentials madhe rahte, aani server compromise zala ki attacker la tumche purna account milte. EC2 var nehmi IAM role, aani laptop var sudha long-term keys shakyato taala. Lakshat theva: role = no keys.
Lab
Create reels-ec2-role with the policy above, attach it to an EC2 instance, and run aws sts get-caller-identity, aws s3 cp into videos/ (works) and into other/ (AccessDenied). Then run through the checklist for your demo bucket and tick every row.
Thodkyaat sangaycha tar
- S3 = buckets (globally unique names) + objects addressed by keys; prefixes only look like folders.
- Everything is private by default; Block Public Access is the master safety switch – keep it ON.
- Bucket policies = Effect / Principal / Action / Resource / Condition; bucket ARN vs
bucket/*. - Static website: public
GetObjectonly; for HTTPS and a domain use CloudFront with OAC. - Versioning + lifecycle protect against deletes and overwrites; deletes create delete markers.
- Presigned URLs give short, temporary access to private objects – keep expiry short.
- EC2 talks to S3 with an IAM role, never with access keys on disk; enforce HTTPS and encryption.
Samjla ka? Nasel tar 14.3 aani 14.6 punha vacha – project madhe he doghe lagnar aahet. Aata pudhe jaauya RDS MySQL kade!