Why devs ship s3:* (and the fix)


AWS FOR THE REAL WORLD
⏱️
Reading time: 10 minutes
🎯
Main Learning: Wildcards come from the tooling, not from laziness. Put least privilege at the account level and let an agent write the policies.
πŸ“

Hey Reader πŸ‘‹πŸ½

I have shipped my share of s3:* at unusual hours and told myself I would refactor it later - which obviously never happened πŸ˜…

So when someone on r/aws asked why developers can't write least privilege policies and put it down to laziness, I was excited to read through all of the comments.
​Almost nobody in there defends wildcards.

They just explain what it actually costs to avoid them: one denied action at a time, ten minutes per deploy, and a deadline that doesn't move - very relatable, especially if you use CloudFormation in any way 😬

In this issue: the five reasons the thread brought up, where the OP still has a point, and the setup I use instead 🫑

Sponsored
Typesense
Search without the cluster
Typesense β€” the open source alternative to Algolia
Terminal: docker run typesense, then a curl search for the misspelled kubernets returning a Kubernetes result

Typo-tolerant search from a single binary. No shard count to pick, no JVM heap to tune, no cluster to keep alive β€” and natural language search is built in.

Smaller learning curve than Elasticsearch  β€’  Django & Laravel Scout integrations

Check it out on GitHub β†’

Sponsored by Typesense, a tool we run ourselves.

A Terraform IAM policy with s3:* and Resource * highlighted in red

πŸ“š This Week's Deep Dive

A security audit found s3:* and AdministratorAccess on nearly every role. The person doing the audit called it laziness. 125 comments explained why it isn't.

The loop, not the intent

"You are out of your mind if you think I'm going to take 30 swings at solving a permissions problem. At 10 minutes per build/deploy, 30 iterations is all day."

AWS denies one action at a time, so you find them one by one. That's the honest math for a single resource.

One SDK call is not one IAM action

s3:GetObject alone gives you a working happy path and a lying error message. Without s3:ListBucket, a missing object returns 403 instead of 404. Add a customer managed KMS key and you need kms:Decrypt on top. Three statements for what the developer experienced as one call.

Access Analyzer doesn't survive the move to prod

Your error paths never ran, so they're not in CloudTrail and not in the generated policy. The ARNs come out hardcoded to your dev bucket names. And the trail still contains the three approaches you abandoned on Tuesday.

πŸ“° This Week in AWS

πŸ”DynamoDB does vector search in single-digit milliseconds

Store embeddings as a plain list of floats, put a vector index on the attribute, query it with the new SearchVectors API. No separate vector database, no sync pipeline. S3 Vectors still wins on price for infrequent queries. Read More β†’

πŸ”€Network Load Balancer got listener rules

The first real routing logic on an NLB. One dual-stack NLB now sends IPv6 clients to IPv6 targets and IPv4 to IPv4, no translation, client IP preserved on both. Source IP type is the only condition so far, but the direction is clear. Read More β†’

πŸ“¦Lambda can run code straight from your own S3 bucket

Set S3ObjectStorageMode to REFERENCE and Lambda skips the copy into its own storage. No code storage quota, faster function activation, no extra Lambda charges. The managed default also went from 75GB to 300GB per region. Read More β†’

That's it for this issue.

If you take one thing away: stop paying the least privilege cost per role. Put the hard boundary at the account level with separate accounts and SCPs, and let your IaC and your agent write the scoped grants.

And read what comes out. A policy nobody reviewed is not least privilege, no matter who typed it πŸ˜…

See you in the next one!

Sandro & Tobi

AWS for the Real World

We teach AWS for the real world - not for certifications. Join more than 10,500 developers learning how to build real-world applications on AWS.

Read more from AWS for the Real World

AWS FOR THE REAL WORLD ⏱️ Reading time: 11 minutes 🎯 Main Learning: Most teams should stay serverless. EKS only pays off at real scale. πŸ“ Blog Post Hey Reader πŸ‘‹πŸ½For years we told everyone the same thing: don't run Kubernetes! And we meant it. Running k8s yourself is a second full-time job. Cluster upgrades, etcd backups, some networking plugin that falls over on a Tuesday and nobody can say why.We're serverless people through and through. Lambda first, a queue behind it, scale to zero, go...

AWS FOR THE REAL WORLD ⏱️ Reading time: 12 minutes 🎯 Main Learning: Most of the complaints in the viral "leaving AWS" post are skill issues β€” but egress pricing is a fair hit. πŸ“ Blog Post Hey Reader πŸ‘‹πŸ½Recently, a post with the title "I returned to AWS and was reminded why I left" hit 810 upvotes on Hacker News last week and went pretty viral with it.I read it twice before forming an opinion. My honest take: most of the complaints are skill issues! πŸ€·β™‚οΈNevertheless, the post is well written and...

AWS FOR THE REAL WORLD ⏱️ Reading time: 10 minutes 🎯 Main Learning: Describe the agent: model, prompt, tools and AWS runs the orchestration loop behind one API call! πŸ“ Blog Post Hey Reader πŸ‘‹πŸ½ If you've ever built an agent on AWS, you know the pain: glue Bedrock, Lambda, and DynamoDB together, grab LangGraph or Strands, then also own the orchestration loop, the memory layer, and your own tracing. πŸ˜… A "simple" agent ends up with multiple layers of pain.AWS just shipped something that takes most...