Skip to main content

Command Palette

Search for a command to run...

๐Ÿ” Project 6: Implementing Just-In-Time (JIT) SSH Access for EC2 on AWS

Published
โ€ข3 min read
S
Cyber Security Engineer skilled in AWS, Palo alto, GRC and Healthcare Management

Time-bound access, automatic revocation, and full auditability

Why This Project Exists

Permanent SSH access to EC2 instances is one of the most common and dangerous cloud misconfigurations.
Open port 22, long-lived keys, and forgotten security group rules create an unnecessary attack surface.

This project demonstrates how to implement Just-In-Time (JIT) access for EC2 using native AWS services, where:

  • SSH access is granted only when needed

  • Access is time-bound

  • Revocation is automatic

  • Every action is auditable

No third-party tools. No manual cleanup.

Architecture Overview

The solution is built using:

  • Amazon EC2 โ€“ Target instance

  • AWS Lambda โ€“ JIT automation

  • AWS Identity and Access Management โ€“ Least-privilege roles

  • AWS CloudTrail โ€“ Audit evidence

  • Amazon CloudWatch โ€“ Execution logs

Design principle:

No standing access. Access exists only while the automation is running.

Lock Down the EC2 Instance (Baseline)

The EC2 instance is launched without any inbound SSH access.
This ensures there is zero standing access by default.

Why this matters:

  • Eliminates permanent exposure

  • Forces all access through controlled mechanisms

EC2 IAM Role โ€“ SSM Only

The EC2 instance is assigned an IAM role with only the SSM managed policy.

Key point:

  • The instance cannot modify its own security group

  • Prevents self-escalation

This separation is intentional and critical.

CloudTrail for Auditability

CloudTrail is configured to log management events only.
This captures security group changes without unnecessary noise or cost.

Why not data events?

  • JIT access modifies infrastructure, not data

  • Precision logging > noisy logging

JIT Lambda Function

A Lambda function is created to control access lifecycle:

  • Add SSH rule for a single IP

  • Wait for a fixed duratio

  • Revoke the rule automatically

    Lambda Configuration via Environment Variables

    All JIT behavior is externalized via environment variables:

    • SECURITY_GROUP_ID

    • ALLOWED_IP

    • DURATION (seconds)

      Why this is important:

      • No hardcoding

      • Easy to audit

      • Easy to change duration safely

Least-Privilege Lambda Execution Role

The Lambda execution role is granted only the permissions required to modify security group ingress.

This enforces:

  • Separation of duties

  • Minimal blast radius

JIT Execution (Grant โ†’ Revoke)

When the Lambda function is executed:

  1. SSH access is granted for the configured IP

  2. Access exists only for the defined duration

  3. SSH access is revoked automatically

    Key log evidence:

    • SSH access granted

    • SSH access revoked

    • Execution duration โ‰ˆ configured timeout

This confirms true JIT behavior, not manual cleanup.

CloudTrail Proof (Audit Evidence)

CloudTrail records both sides of the access lifecycle.

What this proves:

  • Who made the change (Lambda role)

  • What was changed (security group rule)

  • When it happened

  • That it was later revoked

This is audit-grade evidence, not just console screenshots.

What This Project Demonstrates

  • โœ… No standing SSH access

  • โœ… Time-bound, IP-restricted access

  • โœ… Automatic revocation enforced by code

  • โœ… Full auditability via CloudTrail

  • โœ… Least-privilege IAM design

Final Takeaway

Security is not about blocking access โ€” itโ€™s about granting the right access, for the right time, with proof.

This project shows how JIT access can be implemented using native AWS services without introducing operational complexity or permanent risk.

More from this blog

Friday aws Security Projects

8 posts

A weekly hands-on cybersecurity publication featuring real-world security projects with labs, scripts, and evidence across cloud, network, and system security.