EC2 instance is managed by AWS Systems Manager or not running
EC2 instances are assessed for enrollment as Systems Manager managed nodes. Running instances lacking Systems Manager registration are marked as unmanaged; instances in stopped, terminated, or pending states are noted separately.
Risk
Unmanaged instances lack centralized patching, inventory, and secure remote access. This increases exposure to brute force on SSH/RDP, delayed patching, and poor visibility. Exploits can enable lateral movement and persistence, degrading confidentiality, integrity, and availability.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks ec2_instance_managed_by_ssmRecommendation
Enroll all instances as Systems Manager managed nodes. Prefer Session Manager over SSH/RDP, restrict inbound admin ports, and use least privilege roles. Ensure connectivity to SSM endpoints (or private endpoints), automate patching and inventory, and monitor activity for defense-in-depth.
Remediation
CLI
aws ec2 stop-instances --instance-ids <INSTANCE_ID>Terraform
# Terraform: make the instance SSM-managed by attaching the required IAM role
resource "aws_iam_role" "<example_resource_name>" {
name = "<example_resource_name>"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "ec2.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "<example_resource_name>_ssm" {
role = aws_iam_role.<example_resource_name>.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" # CRITICAL: grants SSM permissions required for management
}
resource "aws_iam_instance_profile" "<example_resource_name>" {
name = "<example_resource_name>"
role = aws_iam_role.<example_resource_name>.name
}
resource "aws_instance" "<example_resource_name>" {
ami = "ami-<example_resource_id>"
instance_type = "t3.micro"
iam_instance_profile = aws_iam_instance_profile.<example_resource_name>.name # CRITICAL: attaches the SSM-enabled role to the instance
}NativeIaC
# CloudFormation: make the instance SSM-managed by attaching the required IAM role
Resources:
<example_resource_name>Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore # CRITICAL: grants SSM permissions required for management
<example_resource_name>InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref <example_resource_name>Role
<example_resource_name>Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-<example_resource_id>
InstanceType: t3.micro
IamInstanceProfile: !Ref <example_resource_name>InstanceProfile # CRITICAL: attaches the SSM-enabled role to the instanceOther
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
from prowler.providers.aws.services.ssm.ssm_client import ssm_client
class ec2_instance_managed_by_ssm(Check):
def execute(self):
findings = []
for instance in ec2_client.instances:
report = Check_Report_AWS(metadata=self.metadata(), resource=instance)
report.resource_arn = instance.arn
report.resource_tags = instance.tags
report.status = "PASS"
report.status_extended = (
f"EC2 Instance {instance.id} is managed by Systems Manager."
)
report.resource_id = instance.id
# instances not running should pass the check
if instance.state in ["pending", "terminated", "stopped"]:
report.status_extended = f"EC2 Instance {instance.id} is unmanaged by Systems Manager because it is {instance.state}."
elif not ssm_client.managed_instances.get(instance.id):
report.status = "FAIL"
report.status_extended = (
f"EC2 Instance {instance.id} is not managed by Systems Manager."
)
findings.append(report)
return findings