EC2 instances should have IAM profile attached
EC2 instances without an IAM instance profile cannot use temporary credentials from STS. This pushes developers toward embedding long-lived access keys in application config, environment variables, or user data scripts. Leaked keys mean emergency rotation, and rotating hardcoded credentials across distributed config files is its own operational incident.
Instance profiles grant short-lived credentials that rotate automatically and are scoped by an IAM role's policy. AWS Systems Manager Agent, CloudWatch Agent, and CodeDeploy Agent all depend on instance profile credentials to function. Missing profiles also block SSM Session Manager access, forcing teams to open SSH over port 22.
Retrofit consideration
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
This control is enforced automatically with Compliance.tf modules. Start free trial
If you use terraform-aws-modules/ec2-instance/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = ">=6.0.0"
ami_ssm_parameter = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64"
instance_type = "t4g.nano"
subnet_id = "subnet-abc123"
}Use AWS provider resources directly. See docs for the resources involved: aws_instance.
resource "aws_instance" "this" {
ami = "ami-abc12345"
instance_type = "t4g.nano"
subnet_id = element(["subnet-abc123", "subnet-def456"], 0)
vpc_security_group_ids = ["sg-abc12345"]
iam_instance_profile = "example-instance-profile"
}What this control checks
The aws_instance resource must include the iam_instance_profile argument pointing to a valid aws_iam_instance_profile resource. A configuration passes when iam_instance_profile is set to a non-empty value (name or ARN). It fails when the argument is omitted or unset. The referenced aws_iam_instance_profile must itself reference an aws_iam_role via the role argument. For launch templates, aws_launch_template should include an iam_instance_profile block with either name or arn specified. For Auto Scaling groups using launch templates, the profile must be defined in the template rather than on individual instances.
Common pitfalls
Instance profile vs. IAM role confusion
An IAM role alone does not satisfy this control. You must create an aws_iam_instance_profile resource that wraps the role, then reference the profile in aws_instance.iam_instance_profile. Having a role defined without the instance profile wrapper is one of the most common Terraform mistakes on this control.
Empty or placeholder profiles
Attaching an instance profile with a role that has no policies technically passes this control but provides no actual permissions. Some teams create stub profiles to clear compliance checks without granting the permissions applications need. The result is runtime failures that are easy to misattribute until someone checks the role.
Launch template override gaps
When an Auto Scaling group uses mixed instance types with launch template overrides, the iam_instance_profile block must be defined in the base aws_launch_template, not in an override. Overrides do not support changing the instance profile, so if it's missing from the base template, launched instances have no profile attached.
Spot and on-demand fleet instances
Instances launched via aws_spot_instance_request or EC2 Fleet require the same iam_instance_profile argument. These resource types get overlooked when teams apply this control to aws_instance resources and assume coverage is complete.
Audit evidence
Auditors look for AWS Config rule evaluation results from the managed rule ec2-instance-profile-attached showing all EC2 instances as compliant. A supplementary report listing all running instances alongside their attached instance profile ARN (from aws ec2 describe-instances filtered on IamInstanceProfile) is direct supporting evidence. CloudTrail events for AssociateIamInstanceProfile and RunInstances confirm when profiles were attached and whether new launches include them.
For continuous compliance, AWS Security Hub findings mapped to this control, or external CSPM scan results showing zero non-compliant EC2 instances, work as ongoing evidence.
Framework-specific interpretation
PCI DSS v4.0: Requirements 7 and 8 together cover what access should exist and how it's authenticated. Instance profiles satisfy both: each instance gets a distinct identity tied to a scoped role, eliminating shared long-lived credentials and producing a per-instance authentication record that examiners can trace.
HIPAA Omnibus Rule 2013: The Security Rule at 164.312(a)(1) requires access controls that restrict system access to authorized users and processes. For EC2 workloads touching ePHI in other AWS services, an instance profile replaces shared static credentials with temporary, role-scoped keys, meeting the minimum necessary standard for that machine-level access.
NIST SP 800-53 Rev 5: Maps to AC-2 (Account Management), AC-3 (Access Enforcement), and IA-2 (Identification and Authentication). Instance profiles give each EC2 instance a managed identity within IAM, with credentials that rotate automatically and a role policy enforcing the access boundaries AC-3 requires. Under AC-2, there's no static key lifecycle to manage.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
- Compliance.tf Control:
ec2_instance_iam_profile_attached - AWS Config Managed Rule:
EC2_INSTANCE_PROFILE_ATTACHED - Checkov Check:
CKV2_AWS_41 - Powerpipe Controls:
aws_compliance.control.ec2_instance_iam_profile_attached,aws_compliance.control.ec2_instance_publicly_accessible_iam_profile_attached - Prowler Check:
ec2_instance_profile_attached
Last reviewed: 2026-03-09