How to Implement Just-in-Time Access for Remote Team Cloud Resources
Managing access to cloud resources for remote teams presents a unique security challenge. Team members need sufficient permissions to do their work, but standing privileges create persistent attack vectors. Just-in-time (JIT) access solves this problem by granting temporary credentials only when needed and automatically revoking them afterward.
This guide walks you through implementing JIT access for remote teams across major cloud providers.
What is Just-in-Time Access?
Just-in-time access is a security model where users receive elevated privileges for a limited duration, typically through an approval workflow. Instead of permanent IAM roles or key pairs, users request access to specific resources for a set time period—often 15 minutes to a few hours.
When the access window expires, credentials become invalid automatically. This approach dramatically reduces the blast radius of compromised credentials and helps organizations meet compliance requirements like SOC 2, ISO 27001, and PCI-DSS.
Core Components of a JIT Access System
A functional JIT system requires several moving parts:
- Access Request Portal – Where users request temporary access to resources
- Approval Workflow – Automated or manual approval process
- Credential Issuance – Generation of temporary credentials with expiration
- Access Enforcement – Enforcement of time-limited access
- Audit Logging – Complete record of who accessed what and when
Implementing JIT Access with AWS
AWS provides several mechanisms for JIT access. The most common approach uses IAM roles with session policies and the AWS Security Token Service (STS).
Temporary Credential Generation
import boto3
from datetime import datetime, timedelta
def grant_jit_access(role_arn: str, duration_minutes: int = 60):
"""
Grant temporary access to an IAM role.
"""
sts_client = boto3.client('sts')
# Assume the role with a session policy limiting access
response = sts_client.assume_role(
RoleArn=role_arn,
RoleSessionName=f'jit-session-{datetime.utcnow().timestamp()}',
DurationSeconds=duration_minutes * 60,
Policy={
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::production-data",
"arn:aws:s3:::production-data/*"
]
}]
}
)
return {
'access_key': response['Credentials']['AccessKeyId'],
'secret_key': response['Credentials']['SecretAccessKey'],
'session_token': response['Credentials']['SessionToken'],
'expires': response['Credentials']['Expiration'].isoformat()
}
This function generates temporary credentials valid for the specified duration. The session policy further narrows permissions for the specific task.
Building an Approval Workflow
import json
from datetime import datetime, timedelta
class JITAccessRequest:
def __init__(self, requester: str, resource: str, reason: str):
self.id = f"jit-{datetime.utcnow().timestamp()}"
self.requester = requester
self.resource = resource
self.reason = reason
self.requested_at = datetime.utcnow()
self.status = "pending"
self.approved_by = None
self.approved_at = None
self.expires_at = None
def approve(self, approver: str, duration_minutes: int = 60):
self.status = "approved"
self.approved_by = approver
self.approved_at = datetime.utcnow()
self.expires_at = self.requested_at + timedelta(minutes=duration_minutes)
def is_expired(self) -> bool:
return datetime.utcnow() > self.expires_at
def to_dict(self):
return {
"id": self.id,
"requester": self.requester,
"resource": self.resource,
"reason": self.reason,
"status": self.status,
"approved_by": self.approved_by,
"expires_at": self.expires_at.isoformat() if self.expires_at else None
}
This basic request object tracks the approval lifecycle and expiration. In production, you’d persist these to a database and integrate with notification systems.
Implementing JIT with Azure
Azure AD Privileged Identity Management (PIM) provides built-in JIT capabilities for Azure resources.
Configuring Eligible Assignments
# Connect to Azure AD
Connect-AzureAD
# Get the user and role
$user = Get-AzureADUser -ObjectId "developer@company.com"
$roleDefinition = Get-AzureADDirectoryRoleTemplate | Where-Object {$_.DisplayName -eq "Virtual Machine Contributor"}
# Create an eligible role assignment (requires user to activate)
$schedule = New-Object Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedSchedule
$schedule.StartDateTime = (Get-Date).ToUniversalTime()
$schedule.EndTime = (Get-Date).AddYears(1).ToUniversalTime()
# Assign the role as eligible (not active yet)
Open-AzureADPrivilegedRoleAssignmentRequest `
-Schedule $schedule `
-ResourceId $roleDefinition.Id `
-RoleDefinitionId $roleDefinition.Id `
-SubjectId $user.ObjectId `
-AssignmentType "eligible" `
-Reason "Development work on production VMs"
Users with eligible assignments can activate their role through the Azure portal or API when needed. Activation requires justification and optionally approval from a privileged administrator.
Implementing JIT with GCP
GCP’s IAM offers conditions for time-based access control.
Time-Based IAM Conditions
# bindings in policy.yaml
bindings:
- role: roles/viewer
members:
- user: developer@company.com
condition:
title: allow_weekday_access
expression: |
request.time.getHours() >= 9 &&
request.time.getHours() < 17 &&
request.time.weekday() >= 1 &&
request.time.weekday() <= 5
This condition restricts access to business hours, but for true JIT access, you’ll want to combine IAM with a custom solution or use Binary Authorization.
Purpose-Built JIT Access Tools for Remote Teams
While cloud-native JIT mechanisms work, several dedicated platforms streamline the entire workflow for distributed teams.
Teleport is the most widely adopted open-source JIT access platform. It provides a unified access plane for SSH servers, Kubernetes clusters, databases, and cloud provider consoles. Remote teams particularly benefit from Teleport’s web-based access request portal—developers submit requests in a browser, approvers receive Slack or email notifications, and approved sessions are logged automatically. The open-source tier handles most small team needs; the enterprise version adds hardware key enforcement and SAML integration.
StrongDM sits between users and infrastructure, enforcing JIT workflows without requiring changes to the underlying resources. A developer who needs production database access submits a request, their manager approves it in StrongDM’s interface, and a session proxy grants access for the defined window. Every query executed during that session is logged. This approach works well when you cannot modify the target infrastructure itself.
CyberArk Endpoint Privilege Manager addresses JIT from the workstation side, managing local admin rights on developer machines. For remote teams where employees use personal or semi-managed devices, this layer of JIT access prevents persistent local elevation that attackers frequently exploit.
Sym focuses on the approval workflow layer, sitting on top of existing cloud IAM. It connects Slack to your cloud provider: a developer types /access request prod-db 2h, their manager clicks Approve in Slack, and Sym calls the AWS STS or Azure PIM API to grant the session. The simplicity makes adoption friction minimal.
For teams evaluating these tools, consider the following factors: Does your team span multiple cloud providers? Teleport and StrongDM handle multi-cloud better than native solutions. Do you need database query logging? StrongDM and CyberArk provide session recording at the query level. Is Slack the primary communication tool? Sym’s Slack-native workflow reduces adoption resistance.
Best Practices for Remote Teams
1. Implement Access Reviews
Even with JIT access, conduct regular reviews of who has access to what. Automated reports help identify over-privileged users or abandoned accounts.
2. Require Multi-Factor Authentication
JIT access is only as strong as your authentication. Require MFA for all access requests, especially for production environments.
3. Log Everything
Every access request, approval, and session should be logged. These logs are invaluable for incident response and compliance audits.
def log_access_event(event_type: str, request: JITAccessRequest):
"""Log access events to your SIEM or logging system."""
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"event_type": event_type,
"request_id": request.id,
"requester": request.requester,
"resource": request.resource,
"status": request.status,
"approved_by": request.approved_by
}
# Send to your logging system
print(json.dumps(log_entry))
4. Start Small
Begin with non-production resources to validate your JIT workflow. Once confident, expand to production environments.
5. Provide Clear Documentation
Remote team members need clear instructions on how to request access, what to include in justifications, and what to do if access is denied unexpectedly.
Common Pitfalls to Avoid
- Overly permissive session policies – Time-limited access is useless if the session policy grants full admin rights
- Bypassing JIT for “emergencies” – This defeats the purpose; instead, design fast-track approval workflows
- Poor visibility into active sessions – You need real-time awareness of who has access right now
- Session duration creep – Teams often start with 60-minute sessions and gradually extend to 8 hours “for convenience.” Audit session durations quarterly and push back against unnecessary extensions.
- Ignoring service account JIT – Human accounts get the JIT treatment but long-lived service account keys accumulate. Apply the same time-bound thinking to machine identities using AWS IAM Roles for Service Accounts or GCP Workload Identity Federation.
Frequently Asked Questions
How long should JIT sessions last?
Default to the shortest duration that allows the task to complete. Database migrations might need 4 hours; reading a log file needs 15 minutes. When in doubt, err shorter—developers can request extensions rather than leaving long-lived sessions open by default.
What happens if an approver is unavailable?
Design break-glass procedures for genuine emergencies. A secondary approver group, an on-call rotation, or a time-delayed auto-approval for critical-path resources all prevent JIT from becoming a bottleneck. Document these procedures so remote teams in multiple time zones know how to handle after-hours emergencies.
Does JIT access work for contractors and third-party vendors?
Yes, and it is especially valuable for external parties. Contractors often receive broader access than necessary because provisioning precise scopes is cumbersome. JIT forces the justification conversation every time, resulting in narrower, time-limited access that expires automatically when the work is done.
Related Reading
- How to Implement Geo-Fencing Access Controls for Remote
- How to Implement Least Privilege Access for Remote Team
- Best Cloud Access Security Broker for Remote Teams Using
- Using Microsoft Graph API to create named locations
- How to Secure Remote Team Database Access with Just-in-Time
Built by theluckystrike — More at zovo.one