Azure Identity Protection & Infrastructure Hardening Project
📌 Project Overview
In this project, I designed and deployed a secure Azure environment with the goal of practicing real-world cloud security architecture. Each step was implemented with the mindset:
I built this because it prevents a specific security risk.
Project Description
This project is designed to simulate real-world cloud security work by deploying:
- A secure network
- A locked-down virtual machine
- Bastion for secure access
- A private-subnet-restricted storage account
Architecture (High-Level)
Resource Group ├─ Virtual Network (vnet-secure) │ ├─ public-subnet
│ └─ private-subnet
├─ NSG-public-subnet
├─ NSG-private-subnet
├─ Virtual Machine (Ubuntu) ├─ Azure Bastion
└─ Storage Account (securestoreXXXX)1️⃣ Created a Resource Group to isolate and manage everything securely
What I did
I created a dedicated Resource Group named Cloud-Security-lab.
Why I did it
- To keep all security-related resources in one controlled container.
- To simplify cost management, access control, and cleanup.
- To ensure everything in this project follows the same region and security boundaries.
What risk it prevents
- Prevents misconfiguration and resource sprawl across multiple resource groups.
2️⃣ Created a Secure Virtual Network (VNet)
What I did
Created a VNet named secure-vnet with address space 10.0.0.0/16 and two subnets:
- public-subnet → 10.0.1.0/24
- private-subnet → 10.0.2.0/24
I disabled any default inbound rules to ensure no unintended access.
Why I did it
- Splitting the network ensures a proper security boundary.
- Public subnet is for controlled entry; private subnet is for internal systems only.
- This mirrors real-world enterprise security architecture.
What risk it prevents
- Prevents lateral movement by attackers.
- Prevents accidental exposure of internal systems.
3️⃣ Created the Secure Linux VM
What I did
Created an Ubuntu 22.04 VM with:
- SSH key authentication (no passwords)
- Connected to public-subnet
- Public IP enabled (temporary; secured later)
- No auto-created NSG (to avoid default insecure rules)
Why I did it
- SSH keys are far more secure than passwords.
- Placing the VM in the public subnet allows controlled access via NSG.
- Managing security manually gives full control.
What risk it prevents
- Prevents brute-force password attacks.
- Avoids insecure auto-generated firewall rules.
- Reduces attack surface significantly.
4️⃣ Created a Custom Network Security Group (NSG)
What I did
Created an NSG named vm-nsg with rules:
Inbound rules:
- Allow SSH only from MY IP
- Port: 22
- Source: My IP address
- Priority: 100
- Removed any Allow-Internet defaults
Attached this NSG to public-subnet.
Why I did it
- Limiting SSH to only my IP dramatically reduces risk.
- Removing default “Allow” rules ensures everything else is blocked.
- Applying NSG at subnet level protects all future VMs too.
What risk it prevents
- Blocks malicious SSH attempts.
- Prevents unintended public exposure.
- Avoids external enumeration of services
5️⃣ Connected to the VM via SSH and Hardened It
What I did
Connected using:
ssh -i ~/.ssh/securevmkey.pem azureadmin@<public-ip>
Then applied security hardening:
- Updated all packages
- Disabled password authentication (
PasswordAuthentication no) - Restarted SSH service
Why I did it
- Updated packages close known vulnerabilities.
- Disabling password login removes a major attack vector.
What risk it prevents
- Prevents credential-based brute force attacks.
- Eliminates outdated or vulnerable packages.
- Ensures secure-by-default SSH access.
6️⃣ Enabled Microsoft Defender for Cloud
What I did
Enabled:
- Cloud Security Posture Management
- Defender for Servers
- Defender for Storage
Also configured:
- Just-in-Time VM Access
- Endpoint Protection
- Vulnerability Assessment Extension
Why I did it
- Defender automatically scans for misconfigurations.
- JIT access prevents unnecessary open ports.
- The VA agent helps detect weaknesses inside the VM.
What risk it prevents
- Prevents persistent open SSH ports.
- Detects malware, vulnerabilities, and insecure settings.
- Improves posture using real-time recommendations.
7️⃣ Created a Secure Storage Account
What I did
Created storage account securestore with:
- Public Access: Disabled
- Secure Transfer: Enabled
- TLS Minimum: 1.2
- Networking:
- Allowed only private-subnet
- Blocked all public access
- Encryption: Microsoft-managed keys
Why I did it
- Storage accounts are a common attack target.
- Blocking public access eliminates internet exposure.
- Only internal VNet systems can use the storage.
What risk it prevents
- Prevents data leakage through public URLs.
- Stops unauthorized clients from connecting.
- Ensures encrypted, compliant data at rest
✅ Network Architecture Diagram
Challenges I Faced & How I Solved Them
These are real issues you faced in this project — collected from our conversation.
❗ Problem #1 SSH Could Not Connect (Timeout Error)
Error:
ssh: connect to host <IP> port 22: Connection timed out
Cause:
My NSG rules were wrong as the VM was not actually allowing SSH from your IP.
How I solved it:
- Verified my public IPv4
- Removed unnecessary inbound rules
- Added rule:
- Port: 22
- Source: My IP Address
- Priority: 100
- Attached the NSG correctly to the public-subnet
Lesson learned:
✔ NSGs must be extremely precise
✔ One wrong rule = entire VM becomes unreachable
❗ Problem #2 Confusion Between Private Endpoint vs Public Access
I was unsure whether to create a private endpoint when setting up the storage account.
What I learned:
- Private endpoints are for maximum security
- Public access must always be disabled
- Only VNet/subnets should be able to talk to the storage account
How I solved it:
- Chose “Selected Networks”
- Allowed only private-subnet
- Blocked all public access
Lesson learned:
✔ Least privilege applies not only to users but also to networks.
❗ Problem #3 Picking the Right Terminal for SSH
I wasn’t sure which terminal to use either my local terminal or the one on Azure portal.
Solution:
- Used your local computer’s Terminal/PowerShell
- Ensured your
.pemkey had correct file permissions - Connected successfully
Lesson learned:
✔ Cloud security still requires strong Linux command-line basics.
❗ Problem #4 NSG Setup Was Showing Multiple Rule Options
I was confused by the dropdowns (Service, Protocol, Port ranges).
Solution:
I configured it manually:
- Service: SSH
- Port: 22
- Protocol: TCP
- Source: My IP
- Action: Allow
Lesson learned:
✔ Always configure NSGs manually to avoid mistakes.
❗ Problem #5 — I Didn’t Know Which Azure Subscription to Use
I was unsure why it said “Azure subscription 1.”
Solution:
That’s normal as free accounts usually only have one subscription.
Just select it.
Lesson learned:
✔ Azure naming is sometimes confusing but harmless.
❗ Problem #6 You Rushed a Few Configurations
A few mistakes (wrong NSG, SSH timeout, missing rules) happened because moved fast.
Lesson learned:
✔ In cloud security, patience prevents vulnerabilities.
✔ Double-checking saves hours of debugging.