Remote Work Tools

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:

  1. Access Request Portal – Where users request temporary access to resources
  2. Approval Workflow – Automated or manual approval process
  3. Credential Issuance – Generation of temporary credentials with expiration
  4. Access Enforcement – Enforcement of time-limited access
  5. 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

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.

Built by theluckystrike — More at zovo.one