1/**
2 * The instance, its security group, and an instance profile granting Session
3 * Manager access — so there is no need for an SSH key or an open port 22.
4 */
5
6resource "aws_security_group" "web" {
7 name_prefix = "${local.name_prefix}-web-"
8 description = "Inbound web traffic to the instance"
9 vpc_id = aws_vpc.main.id
10
11 lifecycle {
12 create_before_destroy = true
13 }
14
15 tags = merge(local.common_tags, { Name = "${local.name_prefix}-web-sg" })
16}
17
18resource "aws_vpc_security_group_ingress_rule" "web_http" {
19 security_group_id = aws_security_group.web.id
20 description = "HTTP from the allowed range"
21
22 cidr_ipv4 = var.ingress_cidr
23 ip_protocol = "tcp"
24 from_port = var.app_port
25 to_port = var.app_port
26}
27
28resource "aws_vpc_security_group_egress_rule" "web_egress" {
29 security_group_id = aws_security_group.web.id
30 description = "Outbound for patching and AWS APIs"
31
32 cidr_ipv4 = "0.0.0.0/0"
33 ip_protocol = "-1"
34}
35
36# — Instance identity ——————————————————————————————
37
38data "aws_iam_policy_document" "assume_role" {
39 statement {
40 effect = "Allow"
41 actions = ["sts:AssumeRole"]
42 principals {
43 type = "Service"
44 identifiers = ["ec2.amazonaws.com"]
45 }
46 }
47}
48
49resource "aws_iam_role" "instance" {
50 name_prefix = "${local.name_prefix}-ec2-"
51 assume_role_policy = data.aws_iam_policy_document.assume_role.json
52 tags = local.common_tags
53}
54
55resource "aws_iam_role_policy_attachment" "ssm" {
56 role = aws_iam_role.instance.name
57 policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
58}
59
60resource "aws_iam_instance_profile" "instance" {
61 name_prefix = "${local.name_prefix}-ec2-"
62 role = aws_iam_role.instance.name
63}
64
65resource "aws_instance" "web" {
66 ami = data.aws_ami.al2023.id
67 instance_type = var.instance_type
68 subnet_id = aws_subnet.public.id
69 vpc_security_group_ids = [aws_security_group.web.id]
70 iam_instance_profile = aws_iam_instance_profile.instance.name
71
72 tags = merge(local.common_tags, { Name = "${local.name_prefix}-web" })
73}