EC2 instance
For an engineer moving an existing EC2 instance from terraform-aws-modules to compliance.tf. The controls cover IMDSv2, detailed monitoring, EBS optimization, VPC placement, public IP addresses and security group ingress. PCI DSS v4.0 also requires an IAM instance profile and no EC2 key pair. When you finish, terraform plan passes with the compliance.tf source.
Minor fixes · 15-30 minutes per instance · No state moves · Upstream v6.x
Before you start
- A registry token, set up as in Registry tokens. The registry host for each framework is on Registry endpoints.
- An upstream version inside the supported range (v6.x). Older versions: upgrade upstream first, see Version compatibility.
- State: No
terraform state mv. Resource addresses stay the same, because compliance.tf modules keep the upstream resource structure. If a control adds a resource, the plan shows it as an addition. - Not sure if this module should go first? The Migration kit tells you where to start. The Assessment checklist finds risks before you plan.
Change the source
The diff changes the source and adds the settings this module's controls need, so the plan passes. Replace the referenced resources (aws_...) with your own.
module "ec2" {
- source = "terraform-aws-modules/ec2-instance/aws"
+ source = "soc2.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = "~> 6.0"
name = "my-app-server"
instance_type = "t3.micro"
ami = "ami-0123456789abcdef0"
subnet_id = "subnet-0123456789abcdef0"
+ monitoring = true
+ associate_public_ip_address = false
+ ebs_optimized = true
+
+ metadata_options = {
+ http_tokens = "required"
+ }
+
tags = {
Environment = "production"
}
} module "ec2" {
- source = "terraform-aws-modules/ec2-instance/aws"
+ source = "pcidss.compliance.tf/terraform-aws-modules/ec2-instance/aws"
version = "~> 6.0"
name = "my-app-server"
instance_type = "t3.micro"
ami = "ami-0123456789abcdef0"
subnet_id = "subnet-0123456789abcdef0"
+ monitoring = true
+ associate_public_ip_address = false
+ iam_instance_profile = aws_iam_instance_profile.app.name
+
+ metadata_options = {
+ http_tokens = "required"
+ }
+
tags = {
Environment = "production"
}
}Then download the new source and plan. terraform init installs a module whose source changed; -upgrade is only for fetching the same source and version again:
terraform init
terraform planAfter init, .terraform/modules/<module name>/compliancetf-manifest.json names the framework the module was built for.
Fix the plan errors
Each error names the control and links its page, which lists the frameworks that map it. These are the ones this module raises most often.
IMDSv1 is still allowed
The control requires http_tokens = "required" in metadata_options. With optional, the instance still answers IMDSv1 requests. Control: ec2_instance_uses_imdsv2.
Require session tokens.
metadata_options = {
http_tokens = "required"
}Detailed monitoring is off
The control requires monitoring = true. Basic monitoring is the AWS default. Control: ec2_instance_detailed_monitoring_enabled.
Turn on 1-minute CloudWatch metrics. AWS charges for them.
monitoring = trueThe instance has a public IP address
The control requires associate_public_ip_address = false. Control: ec2_instance_not_publicly_accessible.
Turn the public address off and reach the instance through a load balancer, a NAT gateway or Session Manager.
associate_public_ip_address = falseNo IAM instance profile (PCI DSS v4.0 only)
PCI DSS v4.0 maps this control; SOC 2 does not. The instance needs an IAM instance profile. Control: ec2_instance_iam_profile_attached.
Create a role and an instance profile, then attach the profile.
iam_instance_profile = aws_iam_instance_profile.app.nameAn EC2 key pair is set (PCI DSS v4.0 only)
PCI DSS v4.0 maps this control; SOC 2 does not. It fails when key_name is set. Control: ec2_instance_no_amazon_key_pair.
Remove key_name and use AWS Systems Manager Session Manager for shell access.
# key_name removed: connect with Session Manager insteadEBS optimization is off (SOC 2 only)
SOC 2 maps this control; PCI DSS v4.0 does not. Current-generation types such as t3, m5, c5 and r5 are EBS-optimized by default at no extra cost; older types may charge for it. Control: ec2_instance_ebs_optimized.
Set ebs_optimized = true.
ebs_optimized = trueA control that does not apply to this instance can be turned off on the source URL; see Turn controls on and off.
Controls this enforces
SOC 2
- EC2 instances should have detailed monitoring enabled
- EC2 instances should have EBS optimization enabled
- EC2 instances should be in a VPC
- EC2 instances should not have a public IP address
- EC2 instances should use IMDSv2
- VPC security groups should restrict ingress from 0.0.0.0/0 or ::/0 to cassandra ports 7199 or 9160 or 8888
PCI DSS v4.0
- EC2 instances should have detailed monitoring enabled
- EC2 instances should have IAM profile attached
- EC2 instances should be in a VPC
- EC2 instances should not use key pairs in running state
- EC2 instances should not have a public IP address
- EC2 instances should use IMDSv2
- VPC Security groups should only allow unrestricted incoming traffic for authorized ports
Each framework also maps controls that this module does not enforce. Those stay with your team; the module page lists enforced and mapped-only controls apart.
Roll back
- Point the source back at
terraform-aws-modules/ec2-instance/aws, keeping the same version constraint. - Run
terraform init. - Run
terraform plan. Expect no resource changes: the values you added stay in place, but compliance.tf no longer checks them.