The EC2 general purpose module creates an EC2 instance for your project. Configuration for the EC2 instance includes networking, storage, IAM, and tags.
In order to assign multiple ENIs to a single instance using this module, the "instance_count" variable must be set to 1.
Resources that are created as a part of this module include:
- EC2 instance
- Elastic IP
- Network interface attachment
- IAM role
- IAM instance profile
- KMS RBAC grant
- AWS security group
- Target group attachment
This is an example of how to create an EC2 instance using this module, with generic variables.
module "ec2_test" {
source = "github.com/Coalfire-CF/terraform-aws-ec2"
name = var.instance_name
ami = data.aws_ami.ami.id
ec2_instance_type = var.instance_size
instance_count = var.instance_count
vpc_id = aws_vpc.main.id
subnet_ids = var.subnet_ids
ec2_key_pair = var.key_name
ebs_kms_key_arn = data.terraform_remote_state.kms.outputs.ebs_kms_key_arn
# Storage
root_volume_size = var.instance_volume_size
# Security Group Rules
ingress_rules = {
"rdp" = {
ip_protocol = "tcp"
from_port = "3389"
to_port = "3389"
cidr_ipv4 = var.cidr_for_remote_access
description = "RDP"
}
}
egress_rules = {
"allow_all_egress" = {
ip_protocol = "-1"
from_port = "0"
to_port = "0"
cidr_ipv4 = "0.0.0.0/0"
description = "Allow all egress"
}
}
# Tagging
global_tags = {}
}
user_data = templatefile("${path.module}/../../shellscripts/linux/ud-os-join-ad.sh", {
aws_region = var.aws_region
domain_name = local.domain_name
dom_disname = local.dom_disname
ou_env = var.lin_prod_ou_env
linux_admins_ad_group = var.linux_admins_ad_group
domain_join_user_name = var.domain_join_user_name
sm_djuser_path = "${var.ad_secrets_path}${var.domain_join_user_name}"
is_asg = "false"
})
Ingress Rules:
ingress_rules = {
"rdp" = {
ip_protocol = "tcp"
from_port = "3389"
to_port = "3389"
cidr_ipv4 = var.cidr_for_remote_access
description = "RDP"
}
}
Egress Rules:
egress_rules = {
"allow_all_egress" = {
ip_protocol = "-1"
from_port = "0"
to_port = "0"
cidr_ipv4 = "0.0.0.0/0"
description = "Allow all egress"
}
}
iam_policies = [aws_iam_policy.test_policy_1.arn, ...]
The root ebs volume is handled with the below variables:
However, if additional ebs volumes are required, you can use the below variable:
ebs_block_devices = [
{
device_name = "/dev/sdf"
volume_size = "50"
volume_type = "gp2"
},
...
]
The module also supports attaching a security group or IAM Profile from another instance within the same directory. Let's take an example: AD1 creates a security group that can be used by both AD1 and AD2. So, the AD2 module should use the output of the AD1 module to assign the existing security group. Note, AD2 would now have a dependency on AD1. As shown below, the "additional_security_groups" variable can be used for this purpose.
module "ad2" {
source = "github.com/Coalfire-CF/terraform-aws-ec2"
name = "dc2"
ami = "ami-XXXXXX"
ec2_instance_type = "m5a.large"
ec2_key_pair = var.key_name
root_volume_size = "50"
subnet_ids = [data.terraform_remote_state.network-mgmt.outputs.private_subnets[X]]
vpc_id = data.terraform_remote_state.network-mgmt.outputs.vpc_id
private_ip = "${var.ip_network_mgmt}.${var.directory_ip_2}"
iam_profile = module.ad1.iam_profile
additional_security_groups = [module.ad1.sg_id]
}
Name | Version |
---|---|
terraform | >=1.5 |
aws | >= 5.15.0, < 6.0 |
Name | Version |
---|---|
aws | >= 5.15.0, < 6.0 |
Name | Source | Version |
---|---|---|
security_group | github.com/Coalfire-CF/terraform-aws-securitygroup | v1.0.1 |
Name | Type |
---|---|
aws_ebs_volume.this | resource |
aws_eip.eip | resource |
aws_eip_association.eip_attach | resource |
aws_iam_instance_profile.this_profile | resource |
aws_iam_role.this_role | resource |
aws_iam_role_policy_attachment.iam_policy_attach | resource |
aws_iam_role_policy_attachment.ssm_role_policy_attach | resource |
aws_instance.this | resource |
aws_kms_grant.kms_key_grant | resource |
aws_lb_target_group_attachment.target_group_attachment | resource |
aws_network_interface_attachment.eni_attachment | resource |
aws_network_interface_sg_attachment.additional | resource |
aws_volume_attachment.this | resource |
aws_ec2_instance_type.this | data source |
aws_iam_policy.AmazonSSMManagedInstanceCore | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
add_SSMManagedInstanceCore | Whether or not to apply the SSMManagedInstanceCore to the IAM role | bool |
true |
no |
additional_eni_ids | This variable allows for an ec2 instance to have multiple ENIs. Instance count must be set to 1 | list(string) |
[] |
no |
additional_security_groups | A list of additional security groups to attach to the network interfaces | list(string) |
[] |
no |
ami | ID of AMI to use for the instance | string |
n/a | yes |
associate_eip | Whether or not to associate an Elastic IP | bool |
false |
no |
associate_public_ip | Whether or not to associate a public IP (not EIP) | bool |
false |
no |
assume_role_policy | Policy document allowing Principals to assume this role (e.g. Trust Relationship) | string |
"{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"ec2.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" |
no |
ebs_kms_key_arn | The ARN of the KMS key to encrypt EBS volumes | string |
n/a | yes |
ebs_optimized | Whether or not the instance is ebs optimized | bool |
true |
no |
ebs_volumes | A list of maps that must contain device_name (ex. '/dev/sdb') and size (in GB). Optional args include type, throughput, iops, multi_attach_enabled, final_snapshot, snapshot_id, outpost_arn, force_detach, skip_destroy, stop_instance_before_detaching, and tags | list(object({ |
[] |
no |
ec2_instance_type | The type of instance to start | string |
n/a | yes |
ec2_key_pair | The key name to use for the instance | string |
n/a | yes |
egress_rules | The list of rules for egress traffic. Required fields for each rule are 'protocol', 'from_port', 'to_port', and at least one of 'cidr_blocks', 'ipv6_cidr_blocks', 'security_groups', 'self', or 'prefix_list_sg'. Optional fields are 'description' and those not used from the previous list | map(object({ |
{} |
no |
get_password_data | Whether or not to allow retrieval of the local admin password | bool |
false |
no |
global_tags | a map of strings that contains global level tags | map(string) |
n/a | yes |
http_endpoint | Whether the metadata service is available. Valid values include enabled or disabled | string |
"enabled" |
no |
http_put_response_hop_limit | Number of network hops to allow instance metadata. This should be 2 or higher if using containers on instance and you want containers to access metadata. | number |
1 |
no |
http_tokens | Whether or not the metadata service requires session tokens, required=IMDSv2, optional=IMDSv1 | string |
"required" |
no |
iam_policies | A list of the iam policy ARNs to attach to the IAM role | list(string) |
[] |
no |
iam_profile | A variable to attach an existing iam profile to the ec2 instance(s) created | string |
"" |
no |
ingress_rules | The list of rules for ingress traffic. Required fields for each rule are 'protocol', 'from_port', 'to_port', and at least one of 'cidr_blocks', 'ipv6_cidr_blocks', 'security_groups', 'self', or 'prefix_list_sg'. Optional fields are 'description' and those not used from the previous list | map(object({ |
{} |
no |
instance_count | Number of instances to launch | number |
1 |
no |
instance_metadata_tags | Enables or disables access to instance tags from the instance metadata service. Valid values include enabled or disabled | string |
"enabled" |
no |
keys_to_grant | A list of kms keys to grant permissions to for the role created. | list(string) |
[] |
no |
name | The name of the ec2 instance | string |
n/a | yes |
private_ip | The private ip for the instance | string |
null |
no |
root_volume_size | The size of the root ebs volume on the ec2 instances created | string |
n/a | yes |
root_volume_type | The type of the root ebs volume on the ec2 instances created | string |
"gp3" |
no |
sg_description | This overwrites the default generated description for the security group | string |
"Managed by Terraform" |
no |
source_dest_check | Whether or not source/destination check should be enabled for the primary network interface | bool |
true |
no |
subnet_ids | A list of the subnets to be used when provisioning ec2 instances. If instance count is 1, only the first subnet will be used | list(string) |
n/a | yes |
tags | A mapping of tags to assign to the resource | map(string) |
{} |
no |
target_group_arns | A list of aws_alb_target_group ARNs, for use with Application Load Balancing | list(string) |
[] |
no |
user_data | The User Data script to run | string |
null |
no |
user_data_base64 | Can be used instead of user_data to pass base64-encoded binary data directly. Use this instead of user_data whenever the value is not a valid UTF-8 string. For example, gzip-encoded user data must be base64-encoded and passed via this argument to avoid corruption | string |
null |
no |
user_data_replace_on_change | When used in combination with user_data or user_data_base64 will trigger a destroy and recreate when set to true. Defaults to false if not set | bool |
null |
no |
vpc_id | The id of the vpc where resources are being created | string |
n/a | yes |
Name | Description |
---|---|
iam_profile | The name of the iam profile created in the module |
iam_role_arn | The AWS IAM Role arn created |
iam_role_name | The AWS IAM Role arn created |
instance_id | The AWS Instance id created |
network_interface_id | The network interface ID for the AWS instance |
primary_private_ip_addresses | A list of the primary private IP addesses assigned to the ec2 instance |
sg_id | The id of the security group created |
tags | List of tags of instances |
If you're interested in contributing to our projects, please review the Contributing Guidelines. And send an email to our team to receive a copy of our CLA and start the onboarding process.
Copyright © 2023 Coalfire Systems Inc.