<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ontrack</title>
    <description>The latest articles on DEV Community by ontrack (@ontrack).</description>
    <link>https://dev.to/ontrack</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3741018%2F307b9992-977f-4b87-9fa0-17448c43c6f4.png</url>
      <title>DEV Community: ontrack</title>
      <link>https://dev.to/ontrack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ontrack"/>
    <language>en</language>
    <item>
      <title>I Stopped Learning Cloud Networking as Services</title>
      <dc:creator>ontrack</dc:creator>
      <pubDate>Sat, 05 Sep 2026 11:55:18 +0000</pubDate>
      <link>https://dev.to/ontrack/i-stopped-learning-cloud-networking-as-services-3b3o</link>
      <guid>https://dev.to/ontrack/i-stopped-learning-cloud-networking-as-services-3b3o</guid>
      <description>&lt;h2&gt;
  
  
  I Stopped Learning Cloud Networking as Services
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The moment I started thinking about packets instead of memorizing cloud products.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a while, cloud networking felt like a list of services I needed to memorize.&lt;/p&gt;

&lt;p&gt;VPC.&lt;/p&gt;

&lt;p&gt;Subnet.&lt;/p&gt;

&lt;p&gt;Route table.&lt;/p&gt;

&lt;p&gt;Security group.&lt;/p&gt;

&lt;p&gt;NAT Gateway.&lt;/p&gt;

&lt;p&gt;Internet Gateway.&lt;/p&gt;

&lt;p&gt;Network ACL.&lt;/p&gt;

&lt;p&gt;The more services I learned, the more complicated networking seemed.&lt;/p&gt;

&lt;p&gt;Then I changed the way I looked at it.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What does this AWS service do?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where is the packet going?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question made cloud networking much easier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start with the packet
&lt;/h2&gt;

&lt;p&gt;Imagine a Linux server trying to reach another server.&lt;/p&gt;

&lt;p&gt;The packet has:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Source IP
Destination IP
Protocol
Source port
Destination port
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The machine then has to figure out where to send it.&lt;/p&gt;

&lt;p&gt;Linux gives us tools to inspect that process.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip addr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;shows the interfaces and addresses.&lt;/p&gt;

&lt;p&gt;And:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip route
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;shows how the operating system decides where traffic should go.&lt;/p&gt;

&lt;p&gt;You can think of the route table as a set of directions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination
    ↓
Route
    ↓
Next hop
    ↓
Network interface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That same way of thinking works surprisingly well in the cloud.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then move the idea into a VPC
&lt;/h2&gt;

&lt;p&gt;Take a simple architecture:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC
└── Private Subnet
    └── EC2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The EC2 instance needs to reach something outside its subnet.&lt;/p&gt;

&lt;p&gt;Don't start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which AWS service do I need?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where is the destination?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What route should the packet follow?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might eventually discover a path such as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2
  ↓
Subnet
  ↓
Route Table
  ↓
NAT Gateway
  ↓
Internet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the architecture isn't a collection of AWS services anymore.&lt;/p&gt;

&lt;p&gt;It's a packet path.&lt;/p&gt;

&lt;p&gt;That mental shift matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Linux already taught us most of this
&lt;/h2&gt;

&lt;p&gt;Before cloud networking, Linux was already teaching us the fundamentals.&lt;/p&gt;

&lt;p&gt;You had:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip addr
ip route
ss
ping
traceroute
dig
iptables
nftables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Each tool answers a different networking question.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dig example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can I resolve the name?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip route
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where will my machine send the traffic?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ss -tulpn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What is actually listening on this machine?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These questions don't disappear when you move into AWS.&lt;/p&gt;

&lt;p&gt;They simply become part of a larger system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cloud networking adds another layer
&lt;/h2&gt;

&lt;p&gt;This is where things become interesting.&lt;/p&gt;

&lt;p&gt;A request might travel through several layers:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
    ↓
Linux networking
    ↓
Cloud network interface
    ↓
Subnet
    ↓
Route table
    ↓
Cloud security controls
    ↓
Network gateway
    ↓
Destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If something fails, don't immediately change everything.&lt;/p&gt;

&lt;p&gt;Find the layer where the packet stopped.&lt;/p&gt;

&lt;p&gt;That is much more useful than guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The firewall is only one piece
&lt;/h2&gt;

&lt;p&gt;A common troubleshooting mistake is assuming:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The security group must be blocking it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;But networking can fail before the firewall even becomes the problem.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DNS failure
     ↓
Wrong destination IP
     ↓
Missing route
     ↓
Network filtering
     ↓
Linux firewall
     ↓
Application not listening
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;All of these can produce what looks like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The server can't connect."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The symptom is similar.&lt;/p&gt;

&lt;p&gt;The cause isn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  The question I use now
&lt;/h2&gt;

&lt;p&gt;When something can't connect, I start with five questions:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. What is the destination IP?

2. Which route should handle it?

3. What is the next hop?

4. Where can the traffic be allowed or blocked?

5. What is supposed to receive the connection?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This works whether I'm looking at a Linux server or a cloud environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this changed how I learn AWS
&lt;/h2&gt;

&lt;p&gt;I stopped trying to memorize isolated definitions.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"A NAT Gateway does X."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I think:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"A private workload needs an outbound path."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"A route table contains routes."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I think:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"The packet needs a decision about where to go."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"A security group allows traffic."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I think:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Something needs to decide whether this connection is permitted."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The terminology becomes easier once the problem makes sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real advantage of Linux knowledge
&lt;/h2&gt;

&lt;p&gt;Cloud platforms abstract away a huge amount of networking.&lt;/p&gt;

&lt;p&gt;That's convenient.&lt;/p&gt;

&lt;p&gt;But abstraction can also hide what's happening.&lt;/p&gt;

&lt;p&gt;Linux gives you a place where you can see many of the fundamentals directly:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interfaces
addresses
routes
sockets
DNS
firewall rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That knowledge becomes extremely valuable when cloud networking doesn't behave the way you expect.&lt;/p&gt;

&lt;p&gt;You can go one layer deeper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;I don't think cloud engineers need to memorize every networking service.&lt;/p&gt;

&lt;p&gt;I'd rather understand how a packet moves.&lt;/p&gt;

&lt;p&gt;Start here:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Who sent it?

Where is it going?

What route handles it?

What happens next?

What can block it?

Who receives it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once you start thinking this way, VPCs stop looking like complicated cloud diagrams.&lt;/p&gt;

&lt;p&gt;They start looking like something much simpler:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A collection of decisions about where packets are allowed to go.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that is a much better way to learn cloud networking.&lt;/p&gt;

&lt;p&gt;Thanks&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>infrastructure</category>
      <category>networking</category>
    </item>
    <item>
      <title>The Terraform Advantage</title>
      <dc:creator>ontrack</dc:creator>
      <pubDate>Sat, 05 Sep 2026 11:49:32 +0000</pubDate>
      <link>https://dev.to/ontrack/the-terraform-advantage-55ib</link>
      <guid>https://dev.to/ontrack/the-terraform-advantage-55ib</guid>
      <description>&lt;h2&gt;
  
  
  The Terraform Advantage: Infrastructure That Can Explain Itself
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Why I think Terraform is more than an infrastructure deployment tool.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I first started working with Terraform, I thought its main advantage was simple:&lt;/p&gt;

&lt;p&gt;It creates cloud infrastructure without making me click through the AWS console.&lt;/p&gt;

&lt;p&gt;That's useful.&lt;/p&gt;

&lt;p&gt;But the more I use it, the more I think that's actually one of the least interesting things about Terraform.&lt;/p&gt;

&lt;p&gt;The real advantage is that Terraform gives infrastructure something that manual infrastructure often doesn't have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A clear explanation of what should exist, why it exists, and what will change before the change happens.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with clicking everything
&lt;/h2&gt;

&lt;p&gt;Imagine creating an AWS environment manually.&lt;/p&gt;

&lt;p&gt;You create a VPC.&lt;/p&gt;

&lt;p&gt;Then subnets.&lt;/p&gt;

&lt;p&gt;Then route tables.&lt;/p&gt;

&lt;p&gt;Then security groups.&lt;/p&gt;

&lt;p&gt;Then EC2 instances.&lt;/p&gt;

&lt;p&gt;Then IAM roles.&lt;/p&gt;

&lt;p&gt;Then load balancers.&lt;/p&gt;

&lt;p&gt;A few weeks later, someone asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why does this security group allow that traffic?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might have to search through the AWS console and try to remember.&lt;/p&gt;

&lt;p&gt;With Terraform, the answer can be sitting in a &lt;code&gt;.tf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "web" {
  name = "web-server"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The configuration isn't just instructions.&lt;/p&gt;

&lt;p&gt;It's documentation that can actually create the infrastructure.&lt;/p&gt;

&lt;p&gt;That's a powerful difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Terraform makes infrastructure reviewable
&lt;/h2&gt;

&lt;p&gt;One of my favorite Terraform commands is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before changing infrastructure, Terraform shows what it intends to do.&lt;/p&gt;

&lt;p&gt;That changes the workflow completely.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"I think this change is safe."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can have:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Here is exactly what Terraform wants to change."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 2 to add, 1 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That gives engineers an opportunity to stop and ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why is Terraform destroying this resource?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question can prevent a very bad production deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Infrastructure becomes part of the codebase
&lt;/h2&gt;

&lt;p&gt;This is where Terraform becomes especially useful.&lt;/p&gt;

&lt;p&gt;Your application has:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Git
Pull requests
Code review
CI/CD
Tests
History
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Why shouldn't infrastructure have the same treatment?&lt;/p&gt;

&lt;p&gt;With Terraform, infrastructure can live alongside the same engineering workflow.&lt;/p&gt;

&lt;p&gt;A change can look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
    ↓
Change Terraform
    ↓
Git commit
    ↓
Pull request
    ↓
terraform plan
    ↓
Review
    ↓
Apply
    ↓
Infrastructure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now infrastructure changes aren't mysterious console actions.&lt;/p&gt;

&lt;p&gt;They are changes that can be reviewed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The same infrastructure can be recreated
&lt;/h2&gt;

&lt;p&gt;Another reason I prefer Terraform is repeatability.&lt;/p&gt;

&lt;p&gt;Imagine you manually build a development environment.&lt;/p&gt;

&lt;p&gt;Then someone asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can we create the same environment for testing?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With manual infrastructure, you have to remember what you created.&lt;/p&gt;

&lt;p&gt;With Terraform, the configuration already describes it.&lt;/p&gt;

&lt;p&gt;You can use variables for different environments:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environment = "development"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;environment = "production"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The architecture can remain consistent while the values change.&lt;/p&gt;

&lt;p&gt;This makes Terraform especially useful when you need development, staging, and production environments that follow the same design.&lt;/p&gt;




&lt;h2&gt;
  
  
  Terraform doesn't care only about one cloud
&lt;/h2&gt;

&lt;p&gt;Another major advantage is that Terraform isn't limited to one infrastructure platform.&lt;/p&gt;

&lt;p&gt;A single Terraform workflow can manage resources across different providers.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS
Azure
Kubernetes
GitHub
Cloudflare
DNS providers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That doesn't mean every organization needs multi-cloud infrastructure.&lt;/p&gt;

&lt;p&gt;It means you don't necessarily need a completely different infrastructure workflow every time another platform enters the environment.&lt;/p&gt;

&lt;p&gt;Terraform's provider model is one of the reasons it can manage both cloud and non-cloud services through a common configuration approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  Modules turn infrastructure into building blocks
&lt;/h2&gt;

&lt;p&gt;Terraform also becomes much more interesting when you start using modules.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly writing the same infrastructure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC
Subnets
Security Groups
IAM
Load Balancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you can package a common architecture into a module.&lt;/p&gt;

&lt;p&gt;Then another project can reuse it.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "network" {
  source = "./modules/network"

  environment = "production"
  cidr_block  = "10.0.0.0/16"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now infrastructure can be treated like a reusable software component.&lt;/p&gt;

&lt;p&gt;That can dramatically reduce duplication.&lt;/p&gt;




&lt;h2&gt;
  
  
  Terraform doesn't eliminate mistakes
&lt;/h2&gt;

&lt;p&gt;This is important.&lt;/p&gt;

&lt;p&gt;Terraform isn't magic.&lt;/p&gt;

&lt;p&gt;You can still write bad Terraform.&lt;/p&gt;

&lt;p&gt;You can still destroy the wrong resource.&lt;/p&gt;

&lt;p&gt;You can still create overly permissive security groups.&lt;/p&gt;

&lt;p&gt;You can still lose control of your state.&lt;/p&gt;

&lt;p&gt;Terraform simply gives you better tools for managing those risks.&lt;/p&gt;

&lt;p&gt;That's why I don't think the real question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can Terraform make infrastructure perfect?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It can't.&lt;/p&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can Terraform make infrastructure easier to understand, review, reproduce, and control?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For me, the answer is yes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part I value most
&lt;/h2&gt;

&lt;p&gt;If I had to choose one reason to use Terraform, it wouldn't be multi-cloud.&lt;/p&gt;

&lt;p&gt;It wouldn't even be automation.&lt;/p&gt;

&lt;p&gt;It would be &lt;strong&gt;visibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When infrastructure is written as code, I can open the repository and start understanding the environment.&lt;/p&gt;

&lt;p&gt;I can see:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What exists
What depends on what
Which resources belong together
What changed
Who changed it
What Terraform plans to do next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is difficult to achieve with infrastructure that exists only through console clicks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Terraform changes the mindset
&lt;/h2&gt;

&lt;p&gt;The biggest change isn't technical.&lt;/p&gt;

&lt;p&gt;It's mental.&lt;/p&gt;

&lt;p&gt;Without infrastructure as code, the mindset can become:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"How do I create this server?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With Terraform, it becomes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"What should the infrastructure look like?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is a much better question.&lt;/p&gt;

&lt;p&gt;You stop thinking only about individual servers and start thinking about the entire desired environment.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Network
   ↓
Security
   ↓
Compute
   ↓
Storage
   ↓
Application
   ↓
Monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Terraform can represent those relationships as code.&lt;/p&gt;




&lt;h2&gt;
  
  
  So, is Terraform the best?
&lt;/h2&gt;

&lt;p&gt;I don't think there is one infrastructure tool that is objectively the best for every organization.&lt;/p&gt;

&lt;p&gt;CloudFormation can make sense for AWS-focused teams.&lt;/p&gt;

&lt;p&gt;Pulumi can be attractive if you want to use general-purpose programming languages.&lt;/p&gt;

&lt;p&gt;OpenTofu is another important option in the Terraform ecosystem.&lt;/p&gt;

&lt;p&gt;The right tool depends on the environment, team, requirements, and existing workflows.&lt;/p&gt;

&lt;p&gt;But Terraform remains my preferred choice when I want infrastructure that is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Declarative
Repeatable
Reviewable
Version-controlled
Reusable
Provider-independent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And that's why I keep coming back to it.&lt;/p&gt;

&lt;p&gt;Terraform isn't just a way to create infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It gives infrastructure a language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And once infrastructure can be expressed as code, it becomes much easier to review, improve, reproduce, and understand.&lt;/p&gt;

&lt;p&gt;That's the real Terraform advantage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;thanks ontrack&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>infrastructure</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Automating AWS IAM with Python</title>
      <dc:creator>ontrack</dc:creator>
      <pubDate>Sat, 05 Sep 2026 11:41:55 +0000</pubDate>
      <link>https://dev.to/ontrack/automating-aws-iam-with-python-31d2</link>
      <guid>https://dev.to/ontrack/automating-aws-iam-with-python-31d2</guid>
      <description>&lt;h2&gt;
  
  
  Hello There , here some docs about Automating AWS IAM with Python: Practical Patterns for Safer Access
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Practical IAM automation patterns using Boto3, role design, and least-privilege principles.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Managing AWS IAM manually works when you have a few resources and a small team.&lt;/p&gt;

&lt;p&gt;Then the environment grows.&lt;/p&gt;

&lt;p&gt;A few roles become dozens. Temporary access becomes permanent. Someone creates a policy with &lt;code&gt;*&lt;/code&gt; because "it was only for testing." Another person copies an existing role and changes two permissions. Eventually, nobody is completely sure which role exists for which workload.&lt;/p&gt;

&lt;p&gt;That is where IAM automation becomes useful.&lt;/p&gt;

&lt;p&gt;Python and Boto3 can turn IAM from something we click through in the AWS Console into something we can define, review, reproduce, and automate.&lt;/p&gt;

&lt;p&gt;The goal isn't simply to automate IAM API calls.&lt;/p&gt;

&lt;p&gt;The goal is to make access predictable and intentionally limited.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why automate IAM?
&lt;/h2&gt;

&lt;p&gt;IAM is configuration, but it is also security configuration.&lt;/p&gt;

&lt;p&gt;That makes manual changes particularly uncomfortable.&lt;/p&gt;

&lt;p&gt;Imagine deploying three environments:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development
staging
production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Each environment has applications that need access to different AWS resources.&lt;/p&gt;

&lt;p&gt;Without automation, you might end up manually creating:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app-dev-role
app-staging-role
app-production-role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then attaching policies to each one.&lt;/p&gt;

&lt;p&gt;The problem isn't creating the roles.&lt;/p&gt;

&lt;p&gt;The problem is keeping them consistent.&lt;/p&gt;

&lt;p&gt;Automation gives us a repeatable process:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python configuration
        ↓
Validate desired access
        ↓
Create/update IAM role
        ↓
Create/update policy
        ↓
Attach policy
        ↓
Verify configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now IAM changes can be reviewed like code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The IAM model we actually need
&lt;/h2&gt;

&lt;p&gt;Before writing Python, it helps to separate two concepts that are often confused.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trust policy
&lt;/h3&gt;

&lt;p&gt;The trust policy answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who is allowed to assume this role?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, an EC2 instance, Lambda function, or another AWS account might be allowed to assume a role.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissions policy
&lt;/h3&gt;

&lt;p&gt;The permissions policy answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What can the role do after it is assumed?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3:GetObject
s3:ListBucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;These are different responsibilities.&lt;/p&gt;

&lt;p&gt;A role can have the correct permissions but an overly broad trust policy.&lt;/p&gt;

&lt;p&gt;It can also have a tightly restricted trust policy but excessive permissions.&lt;/p&gt;

&lt;p&gt;Good IAM design requires both sides to be intentional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up Boto3
&lt;/h2&gt;

&lt;p&gt;Install Boto3:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install boto3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then create an IAM client:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3

iam = boto3.client("iam")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Boto3 uses the AWS credential/provider chain rather than requiring credentials to be hard-coded into the Python script.&lt;/p&gt;

&lt;p&gt;For example, you can work with a configured AWS profile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3

session = boto3.Session(profile_name="dev")
iam = session.client("iam")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Avoid putting access keys directly into source code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 1: Define policies as Python data
&lt;/h2&gt;

&lt;p&gt;Instead of scattering IAM JSON throughout the program, define policies as Python dictionaries.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backup_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::company-backups"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::company-backups/*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This gives us something important:&lt;/p&gt;

&lt;p&gt;IAM configuration becomes data.&lt;/p&gt;

&lt;p&gt;Once permissions are represented as data, we can validate them, test them, generate them, and store them in Git.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 2: Create the role separately from its permissions
&lt;/h2&gt;

&lt;p&gt;Let's create a role for our application.&lt;/p&gt;

&lt;p&gt;First, define the trust relationship:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import boto3

iam = boto3.client("iam")

trust_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

response = iam.create_role(
    RoleName="backup-reader",
    AssumeRolePolicyDocument=json.dumps(trust_policy),
    Description="Role used by the backup application"
)

print(response["Role"]["Arn"])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The important part is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Principal": {
    "Service": "ec2.amazonaws.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We are saying that EC2 is allowed to assume the role.&lt;/p&gt;

&lt;p&gt;This does not mean the EC2 workload automatically has access to S3.&lt;/p&gt;

&lt;p&gt;The role still needs permissions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 3: Attach only the permissions the application needs
&lt;/h2&gt;

&lt;p&gt;Now we can create a managed policy.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::company-backups"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::company-backups/*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create the policy:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response = iam.create_policy(
    PolicyName="BackupReaderPolicy",
    PolicyDocument=json.dumps(policy),
    Description="Read-only access to the company backup bucket"
)

policy_arn = response["Policy"]["Arn"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then attach it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iam.attach_role_policy(
    RoleName="backup-reader",
    PolicyArn=policy_arn
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  A complete small example
&lt;/h2&gt;

&lt;p&gt;Putting the pieces together:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import boto3

ROLE_NAME = "backup-reader"
POLICY_NAME = "BackupReaderPolicy"

iam = boto3.client("iam")

trust_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

permissions_policy = {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::company-backups"
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::company-backups/*"
        }
    ]
}

role = iam.create_role(
    RoleName=ROLE_NAME,
    AssumeRolePolicyDocument=json.dumps(trust_policy),
    Description="Read-only backup access"
)

policy = iam.create_policy(
    PolicyName=POLICY_NAME,
    PolicyDocument=json.dumps(permissions_policy),
    Description="Read-only access to backup objects"
)

iam.attach_role_policy(
    RoleName=ROLE_NAME,
    PolicyArn=policy["Policy"]["Arn"]
)

print(f"Created role: {role['Role']['Arn']}")
print(f"Created policy: {policy['Policy']['Arn']}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This works as a demonstration, but I would not stop here for production.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because running it twice can fail when the role or policy already exists.&lt;/p&gt;

&lt;p&gt;That brings us to a more interesting problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  IAM automation should be idempotent
&lt;/h2&gt;

&lt;p&gt;A good automation script should be safe to run repeatedly.&lt;/p&gt;

&lt;p&gt;Consider:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python iam_setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The first run creates everything.&lt;/p&gt;

&lt;p&gt;What should happen on the second run?&lt;/p&gt;

&lt;p&gt;Ideally:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Role already exists
        ↓
Check its configuration
        ↓
Policy already exists
        ↓
Check/update its version
        ↓
Verify attachment
        ↓
Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EntityAlreadyExistsException
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is one of the biggest differences between a quick automation script and a useful infrastructure tool.&lt;/p&gt;

&lt;p&gt;A simple existence check can be implemented like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def role_exists(iam, role_name):
    try:
        iam.get_role(RoleName=role_name)
        return True
    except iam.exceptions.NoSuchEntityException:
        return False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if role_exists(iam, ROLE_NAME):
    print(f"{ROLE_NAME} already exists")
else:
    iam.create_role(
        RoleName=ROLE_NAME,
        AssumeRolePolicyDocument=json.dumps(trust_policy)
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This pattern can be extended to policies, attachments, tags, and trust relationships.&lt;/p&gt;




&lt;h2&gt;
  
  
  Role design: one role, one responsibility
&lt;/h2&gt;

&lt;p&gt;A useful rule for IAM design is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A role should represent a workload or responsibility, not a collection of unrelated permissions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, avoid creating:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ApplicationEverythingRole
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S3
DynamoDB
EC2
RDS
IAM
Lambda
CloudWatch
Secrets Manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Instead, consider roles based on actual workload responsibilities:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orders-api-role
backup-reader-role
monitoring-role
deployment-role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then permissions follow the workload.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orders-api-role
    ├── DynamoDB access
    ├── SQS access
    └── CloudWatch logging

backup-reader-role
    └── S3 read access

monitoring-role
    └── CloudWatch read access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This makes access easier to understand and audit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't confuse "working" with "least privilege"
&lt;/h2&gt;

&lt;p&gt;This is probably the most important lesson in IAM automation.&lt;/p&gt;

&lt;p&gt;Suppose your application receives:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AccessDenied
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The fastest solution is tempting:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Action": "*",
"Resource": "*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The application works.&lt;/p&gt;

&lt;p&gt;But the security model is now much worse.&lt;/p&gt;

&lt;p&gt;Instead, identify the exact API call that failed.&lt;/p&gt;

&lt;p&gt;If the application needs:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3:GetObject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;give it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Action": "s3:GetObject"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;not:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Action": "s3:*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And if possible, restrict the resource:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Resource": "arn:aws:s3:::company-backups/*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;rather than:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Resource": "*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Least privilege is not about making policies tiny for the sake of being tiny.&lt;/p&gt;

&lt;p&gt;It is about making the permissions match the actual job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use conditions when they make sense
&lt;/h2&gt;

&lt;p&gt;Actions and resources are only part of the IAM policy.&lt;/p&gt;

&lt;p&gt;Conditions can provide another layer of control.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Condition": {
    "StringEquals": {
        "aws:RequestedRegion": "ap-northeast-2"
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the permission can be constrained by context.&lt;/p&gt;

&lt;p&gt;Conditions can be useful for things such as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source VPC endpoints
requested regions
resource tags
principal tags
MFA requirements
request attributes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The exact condition should depend on the threat model and workload.&lt;/p&gt;

&lt;p&gt;The important idea is:&lt;/p&gt;

&lt;p&gt;Don't automatically treat every permission as unconditional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tags make automated IAM easier to manage
&lt;/h2&gt;

&lt;p&gt;If you create IAM resources programmatically, tag them.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tags = [
    {
        "Key": "ManagedBy",
        "Value": "Python"
    },
    {
        "Key": "Environment",
        "Value": "Production"
    },
    {
        "Key": "Application",
        "Value": "Backup"
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iam.create_policy(
    PolicyName=POLICY_NAME,
    PolicyDocument=json.dumps(permissions_policy),
    Description="Read-only backup access",
    Tags=tags
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you can answer questions such as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which IAM resources are managed automatically?
Which application owns this policy?
Which environment is this role for?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  A better architecture: configuration first
&lt;/h2&gt;

&lt;p&gt;For larger projects, I wouldn't hard-code every role inside Python.&lt;/p&gt;

&lt;p&gt;Instead, imagine a configuration file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;roles:

  backup-reader:
    trusted_service: ec2.amazonaws.com

    permissions:
      - actions:
          - s3:GetObject
        resources:
          - arn:aws:s3:::company-backups/*

      - actions:
          - s3:ListBucket
        resources:
          - arn:aws:s3:::company-backups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Python becomes the engine that translates this configuration into AWS resources.&lt;/p&gt;

&lt;p&gt;The architecture becomes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YAML / JSON
     ↓
Validation
     ↓
Python
     ↓
Boto3
     ↓
AWS IAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now changing access doesn't necessarily mean changing application logic.&lt;/p&gt;

&lt;p&gt;You change the desired configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Add a "plan" mode before making changes
&lt;/h2&gt;

&lt;p&gt;This is another pattern I strongly recommend.&lt;/p&gt;

&lt;p&gt;Before changing IAM, show what the script intends to do.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IAM PLAN

Role:
  backup-reader

Trust:
  ec2.amazonaws.com

Permissions:
  s3:GetObject
  s3:ListBucket

Resources:
  arn:aws:s3:::company-backups/*
  arn:aws:s3:::company-backups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then require an explicit flag:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python iam.py --plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;versus:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python iam.py --apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This gives you a chance to catch mistakes before they become AWS changes.&lt;/p&gt;

&lt;p&gt;It also makes the tool much easier to integrate into CI/CD.&lt;/p&gt;




&lt;h2&gt;
  
  
  Treat IAM changes like code
&lt;/h2&gt;

&lt;p&gt;Once IAM is automated, put the configuration in Git.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iam-automation/
├── policies/
│   ├── backup-reader.json
│   └── monitoring.json
├── roles/
│   ├── backup-reader.json
│   └── monitoring.json
├── iam.py
├── requirements.txt
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now a permission change can go through:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
   ↓
Git commit
   ↓
Pull request
   ↓
Review
   ↓
Validation
   ↓
CI/CD
   ↓
AWS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is a major improvement over:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Someone opens AWS Console
        ↓
Clicks around
        ↓
Changes a policy
        ↓
Nobody knows why
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Validate before deploying
&lt;/h2&gt;

&lt;p&gt;Automation can make bad changes very quickly.&lt;/p&gt;

&lt;p&gt;So automation needs guardrails.&lt;/p&gt;

&lt;p&gt;AWS IAM Access Analyzer can validate IAM policies and help identify overly permissive access.&lt;/p&gt;

&lt;p&gt;A useful pipeline could therefore look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Policy definition
       ↓
JSON/schema validation
       ↓
IAM policy validation
       ↓
Security review
       ↓
Plan
       ↓
Apply
       ↓
Verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Python script shouldn't be the only safety mechanism.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't create long-lived credentials for automation
&lt;/h2&gt;

&lt;p&gt;Another important distinction:&lt;/p&gt;

&lt;p&gt;Automating IAM doesn't mean creating access keys everywhere.&lt;/p&gt;

&lt;p&gt;For AWS workloads, prefer temporary credentials and IAM roles where possible.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2
  ↓
IAM Role
  ↓
Temporary credentials
  ↓
AWS API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;rather than:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2
  ↓
Hard-coded access key
  ↓
AWS API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This reduces the number of secrets you have to manage.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I would automate first
&lt;/h2&gt;

&lt;p&gt;If you're building your first IAM automation project, don't try to automate the entire AWS account on day one.&lt;/p&gt;

&lt;p&gt;Start small.&lt;/p&gt;

&lt;p&gt;I'd automate these operations first:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Create role
2. Configure trust policy
3. Create customer-managed policy
4. Attach policy
5. Add tags
6. Verify configuration
7. Detect drift
8. Produce a plan before changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;9. Policy version management
10. Access review
11. Unused permission detection
12. CI/CD integration
13. Multi-account support
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This progression keeps the project understandable while giving you room to grow it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A practical mental model
&lt;/h2&gt;

&lt;p&gt;When designing IAM automation, I use five questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Who?
&lt;/h3&gt;

&lt;p&gt;Who should be able to assume this role?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2?
Lambda?
Another AWS account?
Human identity?
CI/CD system?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2. What?
&lt;/h3&gt;

&lt;p&gt;What actions does the workload actually perform?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3:GetObject?
dynamodb:GetItem?
logs:PutLogEvents?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  3. Where?
&lt;/h3&gt;

&lt;p&gt;Which resources should those actions apply to?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Specific bucket?
Specific table?
Specific log group?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  4. Under what conditions?
&lt;/h3&gt;

&lt;p&gt;Can the permission be restricted further?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Region?
Tags?
Network path?
MFA?
Principal attributes?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  5. How do we prove it?
&lt;/h3&gt;

&lt;p&gt;Can we validate and monitor the access?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Policy validation
Access Analyzer
CloudTrail
Code review
Automated tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you can answer those five questions, your IAM design is usually heading in the right direction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;IAM automation isn't really about Python.&lt;/p&gt;

&lt;p&gt;Python is simply the tool that lets us turn our access model into something repeatable.&lt;/p&gt;

&lt;p&gt;The bigger idea is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Manual IAM
    ↓
Defined IAM
    ↓
Automated IAM
    ↓
Validated IAM
    ↓
Auditable IAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Boto3 gives us the API layer. The important engineering work is deciding what access should exist and why.&lt;/p&gt;

&lt;p&gt;Start with the workload.&lt;/p&gt;

&lt;p&gt;Define the trust relationship.&lt;/p&gt;

&lt;p&gt;Define the minimum permissions.&lt;/p&gt;

&lt;p&gt;Restrict the resources.&lt;/p&gt;

&lt;p&gt;Add conditions where useful.&lt;/p&gt;

&lt;p&gt;Put the configuration in Git.&lt;/p&gt;

&lt;p&gt;Validate before applying.&lt;/p&gt;

&lt;p&gt;And make the automation safe to run more than once.&lt;/p&gt;

&lt;p&gt;The best IAM automation isn't the script that creates the most roles.&lt;/p&gt;

&lt;p&gt;It's the one that makes it difficult to accidentally create too much access.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html" rel="noopener noreferrer"&gt;AWS IAM — Policies and permissions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started-reduce-permissions.html" rel="noopener noreferrer"&gt;AWS IAM — Least-privilege permissions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/boto3/latest/reference/services/iam.html" rel="noopener noreferrer"&gt;Boto3 IAM documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/boto3/latest/guide/iam-examples.html" rel="noopener noreferrer"&gt;Boto3 IAM examples&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>aws</category>
      <category>python</category>
      <category>security</category>
    </item>
  </channel>
</rss>
