case study
AWS Infrastructure & Web Application Environment
In this project, I built the core AWS infrastructure and application environment for the ProjectZero Threat Intelligence Dashboard. I configured IAM permissions, designed a segmented VPC with public and private subnets, implemented routing and internet connectivity, and deployed a secured jumpbox for controlled administrative access. I then deployed the web server within the private network and prepared it with Node.js, Astro, and Tailwind CSS to support the threat intelligence application.
##I AM Basics
I configured IAM groups and permissions to separate administrative and employee access within the ProjectZero environment. I created role specific groups and implemented a custom IAM policy to provide scoped EC2 permissions, demonstrating centralized access management and least privilege principles.
1.Configure Jumpbox IAM Group
I created the projectzero-jumpbox-group and assigned the required EC2 permissions to support management of the jumpbox infrastructure.
2.Configure Employee IAM Group
I created the projectzero-employees-group to separate standard employee permissions from administrative and infrastructure specific access.
3.Create and Assign Custom EC2 Policy
I created a custom IAM policy defining the EC2 actions required by the environment instead of granting broader administrative access. I then attached the policy to the appropriate IAM group.
Why: This demonstrates how permissions can be scoped to the actions users actually require, reducing unnecessary access and supporting the principle of least privilege.
Created a dedicated IAM group for ProjectZero employee access:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2DeployBasic",
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:CreateTags",
"ec2:DescribeInstances",
"ec2:DescribeImages",
"ec2:DescribeKeyPairs",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:DescribeInstanceTypes",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeAccountAttributes",
"ec2:DescribeNetworkInterfaces",
"ec2:CreateNetworkInterface",
"ec2:AttachNetworkInterface"
],
"Resource": "*"
}
]
}##Networking (VPC)
I built the ProjectZero AWS network architecture using a dedicated VPC with segmented public, private web, and private database subnets. I configured internet connectivity and routing to control how resources communicate internally and externally, providing the network foundation for the ProjectZero cloud environment.
Why: The VPC provides the network boundary where I can control IP addressing, subnet segmentation, routing, and access between AWS resources.
1.Create ProjectZero Production VPC
I created the projectzero-prod-vpc using the 10.0.0.0/16 IPv4 CIDR range to provide an isolated network for the ProjectZero production environment.
2.Create Internet Gateway
I created the projectzero-prod-igw Internet Gateway to provide internet connectivity for resources placed in the public subnet.
3.Attach Internet Gateway to VPC
I attached the projectzero-prod-igw Internet Gateway to the projectzero-prod-vpc, making it available as a routing target for public network traffic.
##Create Subnets
I segmented the ProjectZero VPC into separate public, private web, and private database subnets to isolate resources based on their role and network access requirements.
Why: Subnet segmentation separates internet facing resources from internal application and database resources, allowing routing and security controls to be applied independently to each network tier.
1.Public Subnet
I created the public subnet using the 10.0.0.0/24 CIDR range for resources that require public network connectivity.
2.Private Web Subnet
I created the private web subnet using the 10.0.1.0/24 CIDR range to isolate internal web tier resources from direct internet access.
3.Private Database Subnet
I created the private database subnet using the 10.0.2.0/24 CIDR range to provide a separate network segment for database resources.
##Configure Routing Tables
I configured separate public and private route tables to control how traffic is routed between the ProjectZero subnets and external networks. The public subnet was given internet access through the Internet Gateway, while the private web and database subnets remained on the private route table without a direct internet route.
Why: This routing design keeps the web and database tiers isolated from direct internet access while allowing resources in the public subnet to communicate externally.
1.Public Route Table
I created projectzero-prod-public-rt, added a default 0.0.0.0/0 route through the ProjectZero Internet Gateway, and associated the route table with the public subnet.
2.Private Route Table
I created projectzero-prod-private-rt and associated both the Private Web Subnet and Private DB Subnet with it. Unlike the public route table, no direct route to the Internet Gateway was configured.
3.Verify Network Configuration
I verified the completed VPC architecture and confirmed that the public, private web, and private database subnets were associated with their intended route tables. The public subnet routes internet bound traffic through the Internet Gateway, while the web and database subnets remain on private routing.
#Compute (EC2) - Deploy Jumpbox
I deployed and secured a public EC2 jumpbox to provide controlled administrative access to resources in the ProjectZero private subnets. I configured the instance, networking, SSH access, security groups, and Fail2ban protection, then verified secure access and used the jumpbox as the management path to private resources. I also configured a NAT Gateway and private routing to provide outbound internet connectivity for private instances without exposing them directly to the internet.
1.Configure Jumpbox Instance
I configured the projectzero-prod-jumpbox EC2 instance using Ubuntu Server 24.04 LTS, a t3.micro instance type, and my existing SSH key pair for secure authentication.
2.Configure Storage
I kept the default 8 GB gp3 root volume because the jumpbox only required minimal storage for administrative access and security tooling.
3.Configure Fail2ban
I added a user data script to automatically install and configure fail2ban when the jumpbox launched. The SSH jail monitors failed authentication attempts and temporarily blocks addresses that exceed the configured retry limit, helping protect the public facing jumpbox from SSH brute force attacks.
#!/bin/bash
apt-get update
apt-get install -y fail2ban
# Configure fail2ban
cat > /etc/fail2ban/jail.local <<EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3
bantime = 7200
EOF
# Start and enable fail2ban
systemctl enable fail2ban
systemctl start fail2ban4.Launch Jumpbox Instance
I launched the jumpbox with the configured Ubuntu image, public subnet, SSH key pair, security group, and fail2ban user-data script.
-Name: projectzero-prod-jumpbox
-AMI: Ubuntu Server 24.04 LTS
-Instance type: t3.micro
-Key pair: My-Desktop-Key-Pair
-VPC: projectzero-prod-vpc
-Subnet: Projectzero-Prod-Public-Subnet
-Security group: projectzero-prod-jumpbox-sg
-User data: fail2ban installation script
5.Verify Fail2ban Installation
I connected to the public jumpbox using SSH with the configured key pair, then verified that the fail2ban service was successfully installed, enabled, and running.
ssh -i "My-Desktop-Key-Pair.pem" ubuntu@13.53.244.30
Fail2ban monitors failed SSH authentication attempts and automatically blocks IP addresses that exceed the configured retry limit.
6.Access Private Resources
I configured the jumpbox as the controlled access point for reaching EC2 instances in the private subnets. This keeps private resources inaccessible directly from the internet while still providing an administrative path through the public jumpbox.
To access a private instance:
1.SSH into the public jumpbox.
2.From the jumpbox, connect to the private instance using its private IP address.
3.Use SSH agent forwarding so the local SSH key does not need to be stored on the jumpbox.
Why: SSH agent forwarding allows authentication to private instances through the jumpbox while keeping the private key on the local machine.
7.Configure Jumpbox Hostname
I changed the hostname to projectzero-prod-jumpbox so the system could be easily identified when administering the ProjectZero environment.
8.Deploy Nat Gateway
I deployed a NAT Gateway in the public subnet and assigned it an Elastic IP to provide outbound internet connectivity for resources located in the private subnets.
Why: The NAT Gateway allows private instances to reach external services, such as package repositories and software updates, without requiring those instances to have public IP addresses.
9.Configure Private Route Table
I updated the projectzero-prod-private-rt route table with a 0.0.0.0/0 route pointing to the NAT Gateway.
This routes internet bound traffic from the associated private subnets through the NAT Gateway while keeping the instances themselves private.
10.Configure Web Server Security Group
I reviewed the projectzero-prod-websvr-sg security group and updated its inbound rules to allow the network access required for configuring and updating the web server.
11.Verify Private Internet Access
I connected to the private web server and tested outbound connectivity by sending ICMP traffic to 8.8.8.8. The successful replies confirmed that the private instance could reach the internet through the NAT Gateway.
Why: This verified that the private subnet routing and NAT configuration were working as intended without assigning a public IP address to the private instance.
#Deploy & Configure Web Server
In this section, I deployed the ProjectZero web server as an Ubuntu EC2 instance within the private web subnet. I configured network access so the server could only be reached through the jumpbox, verified SSH connectivity using its private IP address, and configured the system hostname for consistent identification within the ProjectZero environment.
1.Deploy projectzero-prod-websvr
I deployed projectzero-prod-websvr as an Ubuntu EC2 instance in the Private Web Subnet to host the ProjectZero threat-intelligence application. The server was configured without a public IP so it could not be accessed directly from the internet.
Instance Configuration
-Name: projectzero-prod-websvr
-AMI: Ubuntu Server 24.04 LTS
-Instance Type: t3.small
-Key Pair: My-Desktop-Key-Pair
-VPC: projectzero-prod-vpc
-Subnet: Private Web Subnet
-Public IP: Disabled
2.Configure Web Server Network Access
I placed the web server in the private subnet and configured its security group to allow SSH access only from the ProjectZero jumpbox. This keeps the server isolated from direct internet access while maintaining a controlled administrative path through the jumpbox.
Security Group
-Security group name: projectzero-prod-websvr-SG
-Description: Security group for projectzero-prod-websvr
Configure inbound rules:
-SSH (22): Allow from projectzero-prod-jumpbox-SG.
-Type: SSH
-Source type: Custom
-Source: Select the security group of projectzero-prod-jumpbox
Since the web server is in a private subnet, we only allow SSH from the jumpbox security group. This ensures the web server is not directly accessible from the internet.
Configure Storage
-Leave storage settings as default (8 GiB gp3).
3.Connect to Web Server Through Jumpbox
I connected from the ProjectZero jumpbox to the private web server using its private IP address, verifying that administrative access to the server was available through the jumpbox.
SSH from Jumpbox to Web Server
ssh -i ~/.ssh/My-Desktop-Key-Pair.pem ubuntu@<websvr-private-ip>
4.Configure Web Server Hostname
I updated the server hostname to projectzero-prod-websvr to clearly identify the instance within the ProjectZero environment.
# Set the hostname using hostnamectl (modern method)
sudo hostnamectl set-hostname projectzero-prod-websvr
# Update /etc/hosts to include the new hostname
sudo sed -i 's/127.0.0.1 localhost/127.0.0.1 localhost projectzero-prod-websvr/' /etc/hosts
# Verify the hostname has been changed
hostnamectl#Prepare Web Application Environment
I prepared the ProjectZero web application environment by installing Node.js and npm, initializing the Astro application, and configuring Tailwind CSS for the dashboard interface. This established the frontend foundation for building and deploying the ProjectZero Threat Intelligence Dashboard.
1.Install Node.js and npm
I installed Node.js and npm on projectzero-prod-websvr to provide the runtime and package management required by the Astro application.
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash
sudo apt install -y nodejs
2.Initialize Astro Application
I created the threat-intel-app project directory and initialized the Astro application that would be used for the ProjectZero Threat Intelligence Dashboard.
Create Project Directory
mkdir -p ~/threat-intel-app
cd ~/threat-intel-app
Initialize Astro Project
npm create astro@latest .
Project Configuration
-Template: Choose Empty
-Install dependencies: Yes
-TypeScript: Yes
-Git repository: Yes
3.Configure Tailwind CSS
I installed and configured Tailwind CSS within the Astro project to provide the styling framework for the ProjectZero Threat Intelligence Dashboard.
Install Tailwind CSS
npm install -D tailwindcss@3 postcss autoprefixer
Initialize Tailwind Configuration
npx tailwindcss init -p
This creates:
- tailwind.config.mjs - Tailwind configuration
- postcss.config.mjs - PostCSS configuration
Configure Tailwind for Astro
I configured Tailwind to scan the Astro project files for utility classes used by the application.
Update the content array to include Astro files:
nano tailwind.config.mjs
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}Add Tailwind Directives to CSS
I created a global stylesheet and added the required Tailwind directives to enable Tailwind styling throughout the Astro application.
mkdir -p src/styles
nano src/styles/global.css
Add Tailwind directives:
@tailwindbase;
@tailwindcomponents;
@tailwindutilities;Import Global Styles into Astro I imported the global stylesheet into the Astro application so Tailwind styles would be available to the dashboard interface.
nano src/pages/index.astro
I added the global stylesheet import:
---
import '../styles/global.css';
---
<html>
<head>
<title>Threat Intelligence Application</title>
</head>
<body>
<h1 class="text-3xl font-bold">Welcome</h1>
</body>
</html>#Why This Matters
This section establishes the secure infrastructure foundation for the ProjectZero environment. IAM permissions enforce controlled access, network segmentation separates public and private resources, and the jumpbox provides a restricted administrative path to internal systems. NAT routing gives private resources outbound connectivity without exposing them directly to the internet, while the private web server provides an isolated environment for hosting the application. Together, these components create the foundation required for the security, database, monitoring, and application components introduced in the following sections.



































