Files

178 lines
6.2 KiB
Markdown

# Assignment
The Nautilus DevOps team is strategizing the migration of a portion of their infrastructure to the AWS cloud. Recognizing the scale of this undertaking, they have opted to approach the migration in incremental steps rather than as a single massive transition. To achieve this, they have segmented large tasks into smaller, more manageable units. This granular approach enables the team to execute the migration in gradual phases, ensuring smoother implementation and minimizing disruption to ongoing operations. By breaking down the migration into smaller tasks, the Nautilus DevOps team can systematically progress through each stage, allowing for better control, risk mitigation, and optimization of resources throughout the migration process.
Use Terraform to create a security group under the default VPC with the following requirements:
1) The name of the security group must be nautilus-sg.
2) The description must be Security group for Nautilus App Servers.
3) Add an inbound rule of type HTTP, with a port range of 80, and source CIDR range 0.0.0.0/0.
4) Add another inbound rule of type SSH, with a port range of 22, and source CIDR range 0.0.0.0/0.
Ensure that the security group is created in the us-east-1 region using Terraform. The Terraform working directory is /home/bob/terraform. Create the main.tf file (do not create a different .tf file) to accomplish this task.
Note: Right-click under the EXPLORER section in VS Code and select Open in Integrated Terminal to launch the terminal.
# Solution
# Terraform Security Group — `nautilus-sg`
Create a security group in the **default VPC** in `us-east-1` with HTTP and SSH inbound rules open
to the world.
## Create `main.tf` (heredoc → file)
```bash
cd /home/bob/terraform
cat > main.tf <<'EOF'
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# Look up the existing default VPC
data "aws_vpc" "default" {
default = true
}
resource "aws_security_group" "nautilus_sg" {
name = "nautilus-sg"
description = "Security group for Nautilus App Servers"
vpc_id = data.aws_vpc.default.id
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "nautilus-sg"
}
}
EOF
```
## How to run
```bash
cd /home/bob/terraform
terraform init
terraform apply -auto-approve
```
## How it works
### The heredoc
`cat > main.tf <<'EOF'` writes the file in one shot. The **quoted** `'EOF'` disables shell expansion,
so `$` and backticks in the HCL reach the file literally. The task requires everything in
**`main.tf`** — don't split the provider block into a separate file.
### Finding the default VPC
```hcl
data "aws_vpc" "default" {
default = true
}
```
A **data source** *reads* an existing resource rather than creating one. Setting `default = true`
selects the account's default VPC for the region, and `data.aws_vpc.default.id` then feeds the
security group's `vpc_id`.
This is deliberately a data source, not a resource. The `aws_default_vpc` **resource** would adopt
the default VPC into Terraform state and let Terraform modify (or on destroy, orphan) it — far more
intrusive than needed. Reading it keeps Terraform's ownership limited to the security group itself.
### The security group
- **`name = "nautilus-sg"`** — the group name, exactly as required.
- **`description`** — required by AWS on every security group (Terraform defaults it to "Managed by
Terraform" if omitted). Important: the description is **immutable** — AWS won't let you change it
after creation. If you apply with the wrong text, you must destroy and recreate the group, so get
it right the first time.
- **`vpc_id`** — pins the group to the default VPC per the requirement.
### The ingress rules
Each `ingress` block is one inbound rule:
| Requirement | `protocol` | `from_port` / `to_port` | `cidr_blocks` |
|-------------|-----------|--------------------------|---------------|
| HTTP | `tcp` | 80 / 80 | `0.0.0.0/0` |
| SSH | `tcp` | 22 / 22 | `0.0.0.0/0` |
The "type" the task refers to (HTTP, SSH) is a **console-level label**, not an API field. AWS derives
it from the protocol/port combination — `tcp` + port 80 *is* HTTP, `tcp` + port 22 *is* SSH. That's
why there's no `type` argument in the HCL; setting the right protocol and ports is what makes the
console display those names. The `description` field here is just a human-readable label and doesn't
affect matching.
`from_port` and `to_port` define a **range**; setting both to the same value expresses a single
port. `0.0.0.0/0` means any source IPv4 address.
> Security note: opening SSH (22) to `0.0.0.0/0` is fine for a lab but poor practice in production,
> where you'd restrict it to a bastion host or known CIDR.
### The egress rule
```hcl
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
```
`protocol = "-1"` means **all protocols**, and with ports `0`/`0` this is the standard allow-all
outbound rule. It's included because when Terraform manages a security group with **no** `egress`
block, it strips AWS's default allow-all outbound rule, leaving the group unable to initiate any
outbound traffic. The task doesn't ask about egress, so preserving the normal default is the sane
choice.
## Verify
```bash
aws ec2 describe-security-groups \
--filters Name=group-name,Values=nautilus-sg \
--query 'SecurityGroups[0].{Name:GroupName,Desc:Description,Vpc:VpcId,Ingress:IpPermissions[*].{Proto:IpProtocol,From:FromPort,To:ToPort,Cidr:IpRanges[0].CidrIp}}'
```
Expected — `GroupName: nautilus-sg`, the exact description string, the default VPC's ID, and two
ingress entries: `tcp 80→80 0.0.0.0/0` and `tcp 22→22 0.0.0.0/0`.
> If the description is wrong, `terraform apply` **cannot** fix it in place — run
> `terraform destroy -target=aws_security_group.nautilus_sg` and re-apply with the corrected text.