Skip to content

Commit b55a82b

Browse files
authored
feat: add initial Terraform configuration for AutoMQ BYOC setup with IAM roles, policies, and EC2 instance (#92)
* feat: add initial Terraform configuration for AutoMQ BYOC setup with IAM roles, policies, and EC2 instance * fix: standardize spacing in S3 bucket module source declarations
1 parent fb62035 commit b55a82b

File tree

5 files changed

+492
-0
lines changed

5 files changed

+492
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
resource "aws_iam_role" "automq_byoc_role" {
2+
name = "automq-byoc-role-${local.name_suffix}"
3+
assume_role_policy = jsonencode({
4+
Version = "2012-10-17"
5+
Statement = [
6+
{
7+
Action = "sts:AssumeRole"
8+
Effect = "Allow"
9+
Sid = ""
10+
Principal = {
11+
Service = "ec2.amazonaws.com"
12+
}
13+
}
14+
]
15+
})
16+
}
17+
18+
resource "aws_iam_policy" "automq_console_policy" {
19+
name = "automq-console-policy-${local.name_suffix}"
20+
policy = jsonencode({
21+
Version = "2012-10-17"
22+
Statement = [
23+
{
24+
Sid = "EC2InstanceProfileManagement"
25+
Effect = "Allow"
26+
Action = [
27+
"iam:PassRole"
28+
]
29+
Resource = "*"
30+
Condition = {
31+
StringLike = {
32+
"iam:PassedToService" = "ec2.amazonaws.com*"
33+
}
34+
}
35+
},
36+
{
37+
Effect = "Allow"
38+
Action = ["ec2:DescribeVolumes", "ec2:DescribeSecurityGroups"]
39+
Resource = "*"
40+
},
41+
{
42+
Effect = "Allow"
43+
Action = [
44+
"cloudwatch:PutMetricData",
45+
"ec2:DescribeSubnets",
46+
"ec2:DescribeVpcs",
47+
"ec2:DescribeTags",
48+
"ec2:DescribeAvailabilityZones",
49+
"route53:CreateHostedZone",
50+
"route53:GetHostedZone",
51+
"route53:ChangeResourceRecordSets",
52+
"route53:ListHostedZonesByName",
53+
"route53:ListResourceRecordSets",
54+
"route53:DeleteHostedZone"
55+
]
56+
Resource = "*"
57+
},
58+
{
59+
Effect = "Allow"
60+
Action = ["eks:DescribeCluster", "eks:ListNodegroups", "eks:DescribeNodegroup"]
61+
Resource = "*"
62+
},
63+
{
64+
Sid = "ConsoleEC2Management"
65+
Effect = "Allow"
66+
Action = [
67+
"ec2:DescribeRouteTables",
68+
"ssm:GetParameters",
69+
"pricing:GetProducts",
70+
"cloudwatch:PutMetricData",
71+
"ec2:DescribeImages",
72+
"ec2:CreateLaunchTemplate",
73+
"ec2:CreateLaunchTemplateVersion",
74+
"ec2:ModifyLaunchTemplate",
75+
"ec2:RebootInstances",
76+
"ec2:RunInstances",
77+
"ec2:StopInstances",
78+
"ec2:TerminateInstances",
79+
"ec2:CreateKeyPair",
80+
"ec2:CreateTags",
81+
"ec2:AttachVolume",
82+
"ec2:DetachVolume",
83+
"ec2:DescribeInstances",
84+
"ec2:DescribeLaunchTemplates",
85+
"ec2:DescribeLaunchTemplateVersions",
86+
"ec2:DescribeVolumes",
87+
"ec2:DescribeSubnets",
88+
"ec2:DescribeKeyPairs",
89+
"ec2:DescribeVpcs",
90+
"ec2:DescribeTags",
91+
"ec2:DeleteKeyPair",
92+
"ec2:CreateVolume",
93+
"ec2:DeleteVolume",
94+
"ec2:DeleteLaunchTemplate",
95+
"ec2:DescribeInstanceTypeOfferings",
96+
"ec2:DescribeSecurityGroups",
97+
"ec2:CreateSecurityGroup",
98+
"ec2:AuthorizeSecurityGroupIngress",
99+
"ec2:AuthorizeSecurityGroupEgress",
100+
"ec2:DeleteSecurityGroup",
101+
"ec2:DescribeVpcEndpoints",
102+
"ec2:DescribeAvailabilityZones",
103+
"autoscaling:CreateAutoScalingGroup",
104+
"autoscaling:DescribeAutoScalingGroups",
105+
"autoscaling:UpdateAutoScalingGroup",
106+
"autoscaling:DeleteAutoScalingGroup",
107+
"autoscaling:AttachInstances",
108+
"autoscaling:DetachInstances",
109+
"autoscaling:ResumeProcesses",
110+
"autoscaling:SuspendProcesses",
111+
"route53:CreateHostedZone",
112+
"route53:GetHostedZone",
113+
"route53:ChangeResourceRecordSets",
114+
"route53:ListHostedZonesByName",
115+
"route53:ListResourceRecordSets",
116+
"route53:DeleteHostedZone",
117+
"elasticloadbalancing:DescribeTargetGroups",
118+
"elasticloadbalancing:DescribeTags",
119+
"elasticloadbalancing:DeleteTargetGroup",
120+
"elasticloadbalancing:DeleteLoadBalancer"
121+
]
122+
Resource = "*"
123+
},
124+
{
125+
Effect = "Allow"
126+
Action = [
127+
"s3:GetLifecycleConfiguration",
128+
"s3:PutLifecycleConfiguration",
129+
"s3:ListBucket"
130+
]
131+
Resource = [
132+
"arn:aws:s3:::${local.data_bucket_name}",
133+
"arn:aws:s3:::${local.ops_bucket_name}"
134+
]
135+
},
136+
{
137+
Effect = "Allow"
138+
Action = [
139+
"s3:PutObject",
140+
"s3:GetObject",
141+
"s3:AbortMultipartUpload",
142+
"s3:PutObjectTagging",
143+
"s3:DeleteObject"
144+
]
145+
Resource = [
146+
"arn:aws:s3:::${local.data_bucket_name}/*",
147+
"arn:aws:s3:::${local.ops_bucket_name}/*"
148+
]
149+
},
150+
{
151+
Effect = "Allow"
152+
Action = [
153+
"fsx:CreateFileSystem",
154+
"fsx:DeleteFileSystem",
155+
"fsx:CreateStorageVirtualMachine",
156+
"fsx:TagResource",
157+
"fsx:DescribeStorageVirtualMachines",
158+
"fsx:UpdateVolume",
159+
"fsx:DescribeFileSystems",
160+
"fsx:DeleteStorageVirtualMachine",
161+
"fsx:UpdateFileSystem",
162+
"fsx:CreateVolume",
163+
"fsx:DescribeVolumes",
164+
"fsx:DeleteVolume"
165+
]
166+
Resource = "*"
167+
}
168+
]
169+
})
170+
}
171+
172+
resource "aws_iam_role_policy_attachment" "automq_console_attach" {
173+
role = aws_iam_role.automq_byoc_role.name
174+
policy_arn = aws_iam_policy.automq_console_policy.arn
175+
}
176+
177+
resource "aws_iam_instance_profile" "automq_byoc_instance_profile" {
178+
name = "automq-byoc-instance-profile-${local.name_suffix}"
179+
role = aws_iam_role.automq_byoc_role.name
180+
}
181+
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = "> 5.0"
6+
}
7+
}
8+
required_version = "~> 1.3"
9+
}
10+
11+
provider "aws" {
12+
region = var.region
13+
}
14+
15+
data "aws_availability_zones" "available_azs" {}
16+
17+
data "aws_vpc" "selected" {
18+
id = var.vpc_id
19+
}
20+
21+
data "aws_subnet" "public" {
22+
id = var.public_subnet_id
23+
}
24+
25+
module "automq_byoc_data_bucket" {
26+
source = "terraform-aws-modules/s3-bucket/aws"
27+
28+
bucket = local.data_bucket_name
29+
force_destroy = true
30+
31+
create_bucket = local.create_data_bucket
32+
33+
block_public_acls = true
34+
block_public_policy = true
35+
ignore_public_acls = true
36+
restrict_public_buckets = true
37+
38+
tags = merge(local.common_tags, {
39+
Name = "automq-data-${local.env_id}"
40+
})
41+
}
42+
43+
module "automq_byoc_ops_bucket_name" {
44+
source = "terraform-aws-modules/s3-bucket/aws"
45+
46+
bucket = local.ops_bucket_name
47+
force_destroy = true
48+
49+
create_bucket = local.create_ops_bucket
50+
51+
block_public_acls = true
52+
block_public_policy = true
53+
ignore_public_acls = true
54+
restrict_public_buckets = true
55+
56+
tags = merge(local.common_tags, {
57+
Name = "automq-ops-${local.env_id}"
58+
})
59+
}
60+
61+
resource "tls_private_key" "key_pair" {
62+
algorithm = "RSA"
63+
rsa_bits = 4096
64+
}
65+
66+
resource "local_file" "private_key" {
67+
content = tls_private_key.key_pair.private_key_pem
68+
filename = "${pathexpand("~/.ssh")}/automq-console-${local.env_id}.pem"
69+
file_permission = "0600"
70+
}
71+
72+
resource "aws_key_pair" "key_pair" {
73+
key_name = "automq-console-${local.env_id}"
74+
public_key = tls_private_key.key_pair.public_key_openssh
75+
}
76+
77+
data "aws_ami" "console_ami" {
78+
most_recent = true
79+
# owners = ["self"]
80+
allow_unsafe_filter = true
81+
82+
filter {
83+
name = "name"
84+
values = [var.image_name]
85+
}
86+
87+
filter {
88+
name = "state"
89+
values = ["available"]
90+
}
91+
}
92+
93+
resource "aws_security_group" "automq_byoc_console_sg" {
94+
name = "automq-byoc-console-sg-${local.env_id}"
95+
vpc_id = var.vpc_id
96+
97+
ingress {
98+
from_port = 8080
99+
to_port = 8080
100+
protocol = "tcp"
101+
cidr_blocks = ["0.0.0.0/0"]
102+
}
103+
104+
ingress {
105+
from_port = 22
106+
to_port = 22
107+
protocol = "tcp"
108+
cidr_blocks = ["0.0.0.0/0"]
109+
}
110+
111+
egress {
112+
from_port = 0
113+
to_port = 0
114+
protocol = "-1"
115+
cidr_blocks = ["0.0.0.0/0"]
116+
}
117+
118+
tags = merge(local.common_tags, {
119+
Name = "automq-byoc-console-sg-${local.env_id}"
120+
})
121+
}
122+
123+
resource "aws_eip" "web_ip" {
124+
instance = aws_instance.automq_byoc_console.id
125+
tags = local.common_tags
126+
}
127+
128+
resource "aws_instance" "automq_byoc_console" {
129+
ami = data.aws_ami.console_ami.id
130+
instance_type = var.automq_byoc_ec2_instance_type
131+
subnet_id = var.public_subnet_id
132+
vpc_security_group_ids = [aws_security_group.automq_byoc_console_sg.id]
133+
iam_instance_profile = aws_iam_instance_profile.automq_byoc_instance_profile.name
134+
key_name = aws_key_pair.key_pair.key_name
135+
associate_public_ip_address = true
136+
137+
root_block_device {
138+
volume_size = 30
139+
volume_type = "gp3"
140+
}
141+
142+
user_data = templatefile("${path.module}/userdata.tpl", {
143+
aws_iam_instance_profile_arn_encoded = urlencode(aws_iam_instance_profile.automq_byoc_instance_profile.arn),
144+
automq_data_bucket = local.data_bucket_name,
145+
automq_ops_bucket = local.ops_bucket_name,
146+
instance_security_group_id = aws_security_group.automq_byoc_console_sg.id,
147+
instance_dns = aws_route53_zone.private_r53.zone_id,
148+
instance_profile_arn = aws_iam_instance_profile.automq_byoc_instance_profile.arn,
149+
environment_id = local.env_id
150+
})
151+
152+
tags = merge(local.common_tags, {
153+
Name = "automq-byoc-console-${local.env_id}"
154+
})
155+
}
156+
157+
resource "aws_ebs_volume" "data_volume" {
158+
availability_zone = data.aws_subnet.public.availability_zone
159+
size = 20
160+
type = "gp3"
161+
162+
tags = merge(local.common_tags, {
163+
Name = "automq-console-data-${local.env_id}"
164+
})
165+
}
166+
167+
resource "aws_volume_attachment" "data_volume_attachment" {
168+
device_name = "/dev/sdh"
169+
volume_id = aws_ebs_volume.data_volume.id
170+
instance_id = aws_instance.automq_byoc_console.id
171+
}
172+
173+
resource "aws_route53_zone" "private_r53" {
174+
name = "${local.name_suffix}.automq.private"
175+
176+
vpc {
177+
vpc_id = var.vpc_id
178+
}
179+
180+
lifecycle {
181+
create_before_destroy = true
182+
}
183+
184+
tags = merge(local.common_tags, {
185+
Name = "automq-private-zone-${local.env_id}"
186+
})
187+
}

0 commit comments

Comments
 (0)