DEV Community

Cover image for Solved: What are the best CPA affiliates you have worked with?
Darian Vance
Darian Vance

Posted on • Originally published at wp.me

Solved: What are the best CPA affiliates you have worked with?

šŸš€ Executive Summary

TL;DR: EC2 instances often lose IAM role permissions because their associated IAM Instance Profile is detached, not due to the role itself. This issue commonly stems from misconfigured automation, such as old CI/CD scripts or Infrastructure as Code drift, which can be diagnosed by auditing CloudTrail events.

šŸŽÆ Key Takeaways

  • EC2 instances attach to an IAM Instance Profile, which acts as a container for the IAM Role; understanding this distinction is critical for CLI/SDK/IaC operations.
  • The primary method to identify the culprit behind instance profile disassociation is by auditing AWS CloudTrail for the DisassociateIamInstanceProfile event.
  • To prevent IaC drift and ensure permanent IAM role association, explicitly define the iam\_instance\_profile argument within your Infrastructure as Code definitions (e.g., Terraform aws\_instance resource).

Tired of your EC2 instances mysteriously losing their IAM role permissions? We break down the common culprits and provide battlefield-tested fixes, from quick CLI commands to permanent infrastructure-as-code solutions.

My EC2 Instance Keeps Losing its IAM Role. Here’s How to Fix It for Good.

I remember a 3 AM page like it was yesterday. The core payment processing service, running on our trusty prod-payments-api-01 EC2 cluster, suddenly couldn’t write to its SQS queue. A junior engineer, bless his heart, had been trying to fix it for an hour—restarting the service, checking the application code, even rebooting the instance. When I finally logged in, a quick check of the instance metadata confirmed my suspicion: the IAM role was just… gone. It turns out, an old deployment script was ā€œhelpfullyā€ detaching the instance profile on every run. It’s one of those silent killers in an infrastructure that can drive you absolutely insane until you understand what’s really happening under the hood.

The ā€œWhyā€: It’s Not the Role, It’s the Profile

Here’s the thing most people get tripped up on: you don’t attach an IAM Role directly to an EC2 instance. You attach an IAM Instance Profile, which acts as a container for the role. When you use the AWS console, this relationship is mostly hidden from you for convenience. But when you’re working with the CLI, SDKs, or Infrastructure as Code (IaC), this distinction is critical. The problem usually isn’t that the role itself is being deleted or changed; it’s that the link between the instance and the role—the instance profile association—is being broken, often by a rogue script or a misconfigured automation process.

The Fixes: From Band-Aid to Lockdown

Depending on how much time you have and how deep the problem runs, here are three ways I’ve tackled this in the wild.

1. The ā€œGet-It-Working-Nowā€ Fix (And Why It’s a Trap)

When production is on fire, you just need to stop the bleeding. The quickest way to restore permissions is to manually re-associate the IAM instance profile with the running EC2 instance. It’s a temporary fix, because whatever automated process caused the problem will likely just do it again on the next run, but it gets you back online.

You can do this with a single AWS CLI command:

aws ec2 associate-iam-instance-profile --instance-id i-0123456789abcdef0 --iam-instance-profile Name="YourInstanceProfileName"
Enter fullscreen mode Exit fullscreen mode

Warning: This is a band-aid, not a cure. If you find yourself running this command more than once, you don’t have a glitch; you have a systemic flaw in your deployment or configuration management process. Move on to the next fix immediately.

2. The Real Fix: Auditing Your Automation

This is where the real work gets done. 99% of the time, the instance profile is being detached by your own tooling. You need to hunt down the culprit. Start by looking at AWS CloudTrail for the DisassociateIamInstanceProfile event. This will tell you exactly who or what (which user, role, or service) made the API call.

The most common offenders are:

  • Old CI/CD Scripts: Look for scripts (Bash, Python) that use the AWS CLI or SDKs to manage instances. An old deployment script might be running an aws ec2 modify-instance-attribute command without specifying the instance profile, effectively clearing it.
  • Terraform/CloudFormation Drift: If you have an aws_instance resource defined in Terraform, but you don’t specify the iam_instance_profile argument, the next time someone runs terraform apply, Terraform will see the existing profile as ā€œdriftā€ and remove it to match your (incomplete) code.

Here’s a simplified Terraform example of what not to do:

# BAD: This will remove the instance profile on the next apply if it was added manually.
resource "aws_instance" "app_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  # iam_instance_profile is missing!
}
Enter fullscreen mode Exit fullscreen mode

And here is the correct way to define it in your code so it’s permanent:

# GOOD: The instance profile is explicitly managed by IaC.
resource "aws_iam_instance_profile" "app_profile" {
  name = "app_server_profile"
  role = aws_iam_role.app_role.name
}

resource "aws_instance" "app_server" {
  ami                  = "ami-0c55b159cbfafe1f0"
  instance_type        = "t3.micro"
  iam_instance_profile = aws_iam_instance_profile.app_profile.name
}
Enter fullscreen mode Exit fullscreen mode

3. The ā€˜Lock It Down’ Option: Service Control Policies (SCPs)

Sometimes, you can’t find the source, or the organization is too large to audit every deployment script effectively. If the issue is widespread and causing serious damage, you can bring out the big guns: a Service Control Policy (SCP) at the AWS Organizations level. This is the ā€œnuclearā€ option because it applies to an entire Organizational Unit (OU) or account and overrides even admin permissions.

You can create an SCP that explicitly denies the ability to detach instance profiles.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyIamInstanceProfileDisassociation",
      "Effect": "Deny",
      "Action": [
        "ec2:DisassociateIamInstanceProfile",
        "ec2:ReplaceIamInstanceProfileAssociation"
      ],
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Applying this SCP to an OU means that no user or role within that OU’s accounts can perform those actions. It’s incredibly effective at stopping the bleeding but can have unintended consequences if legitimate processes need to swap profiles. Use it as a powerful guardrail, not a replacement for proper IaC hygiene.

Choosing Your Battle

Here’s a quick breakdown to help you decide which path to take.

Solution Effort Risk Long-Term Viability
1. Manual Re-association Low Low (but high chance of recurrence) Poor
2. Audit Automation (IaC/CI/CD) Medium Low Excellent (This is the goal)
3. SCP Lockdown Medium High (potential for side effects) Good (as a guardrail)

Ultimately, the goal is always to get to a state where your infrastructure is fully and accurately described in code (Fix #2). The other methods are just tools to help you get there without losing your mind—or your job—in the process.


Darian Vance

šŸ‘‰ Read the original article on TechResolve.blog


ā˜• Support my work

If this article helped you, you can buy me a coffee:

šŸ‘‰ https://buymeacoffee.com/darianvance

Top comments (0)