Access Requests

Status: Available — Access requests with JIT role elevation, multi-reviewer approval workflows, automatic time-based expiry, webhook notifications, and full CLI/API support are implemented and tested.

Mezite supports just-in-time (JIT) access through an access request workflow. Instead of granting permanent elevated SSH privileges, users request temporary access to specific roles. Designated approvers review and approve (or deny) requests, and the elevated access automatically expires after a configured duration. Every step is recorded in the audit log.


JIT Access Escalation Concept

Just-in-time access is a security pattern where users operate with minimal SSH privileges by default and request elevated access only when needed. For example, a developer might have SSH access to staging nodes at all times but must request temporary access to production nodes through an approval workflow.

  • Temporary — Elevated access has a fixed duration and expires automatically.
  • Audited — Every request, approval, denial, and expiration is recorded.
  • Approved — A designated approver must explicitly grant the request before access is activated.
  • Scoped — Requests are for specific roles, not blanket access.

Request Lifecycle

An access request moves through a defined set of states:

Request lifecycle text
create ──> PENDING ──> APPROVED ──> ACTIVE ──> EXPIRED
                   └──> DENIED

States:
  PENDING   — Request submitted, awaiting approver review
  APPROVED  — Approver granted the request, elevated roles activated
  DENIED    — Approver rejected the request
  ACTIVE    — User is currently using the elevated access
  EXPIRED   — Time-to-live elapsed, elevated roles automatically revoked
Request flow diagram text
requester             Mezite auth service          approver
     |                        |                        |
     |-- msh request create ->|                        |
     |   (role: ssh-prod,     |-- notification ------->|
     |    reason: "deploy")   |                        |
     |                        |                        |
     |                        |<-- approve ------------|
     |                        |    (mezctl)         |
     |                        |                        |
     |<-- access granted -----|                        |
     |   (4h TTL)             |                        |
     |                        |                        |
     |   ... user SSH's ...   |                        |
     |                        |                        |
     |-- access expires ----->|                        |
     |   (automatic)          |-- audit event -------->|

Creating Requests with msh

Create access request bash
# Request access to a role
msh request create --roles=ssh-production --reason="Deploying hotfix for order processing"

# Output:
# Access request created:
#   ID:       req_a1b2c3d4e5f6
#   Roles:    ssh-production
#   Reason:   Deploying hotfix for order processing
#   Status:   PENDING
#   Expires:  4h (if approved)
#
# Waiting for approval...

# Request with a specific duration (must be <= role's max_duration)
msh request create --roles=ssh-production --duration=1h \
  --reason="Quick production check"

# List your pending and active requests
msh request ls
# ID                  ROLES              STATUS    CREATED                 REASON
# req_a1b2c3d4e5f6    ssh-production     PENDING   2026-03-24T10:00:00Z    Deploying hotfix...

Reviewing Requests with mezctl

Review access requests bash
# List pending requests (as an approver)
mezctl access-requests ls --state=pending
# ID                  USER    ROLES              REASON                    CREATED
# req_a1b2c3d4e5f6    alice   ssh-production     Deploying hotfix...       2026-03-24T10:00:00Z

# Approve the request
mezctl access-requests approve req_a1b2c3d4e5f6

# Deny the request (with optional reason)
mezctl access-requests deny req_a1b2c3d4e5f6 --reason="Use staging environment instead"

Time-Bound Grants

Once approved, the elevated access has a fixed time-to-live (TTL). When the TTL expires, the elevated role is automatically revoked. No manual cleanup is required.

Time-bound access lifecycle bash
# After approval, the requester's session includes the elevated role
msh status
# User:    alice
# Roles:   access, can-request-production, ssh-production (expires in 3h52m)

# Production nodes are now visible and accessible
msh ls
# NAME              ADDR            LABELS
# web-server-01     10.0.1.50:22    env=production,team=platform
# web-server-02     10.0.1.51:22    env=production,team=platform

# Connect normally during the access window
msh ssh --login=ubuntu web-server-01

# When the access expires, the role is automatically removed
# The next msh command will reflect the change
msh ls
# (production nodes no longer visible)

Users can also voluntarily drop elevated access early:

Drop access early bash
# Relinquish the elevated role before it expires
msh request drop req_a1b2c3d4e5f6

RBAC Setup for Access Requests

Access requests require three roles: the requestable role (the target SSH access), a requester role (who can submit requests), and an approver role (who can review requests).

Requester role yaml
kind: role
metadata:
  name: can-request-production
  description: "Can request temporary production SSH access"
spec:
  allow:
    request:
      roles:
        - ssh-production
      max_duration: 4h
      reason_required: true
  deny: {}
Approver role yaml
kind: role
metadata:
  name: can-approve-production
  description: "Can approve production SSH access requests"
spec:
  allow:
    review_requests:
      roles:
        - ssh-production
  deny: {}
Assign roles bash
# Assign requester role to developers
mezctl users update alice --add-roles=can-request-production

# Assign approver role to team leads
mezctl users update charlie --add-roles=can-approve-production

Audit Trail

Every step of the access request lifecycle generates an audit event, providing a complete record of who requested what, who approved it, and when access expired.

Query access request audit events bash
# View all access request events
mezctl audit ls --type=access_request.created,access_request.approved,access_request.denied,access_request.expired --last=24h

# TIME                    TYPE                        USER       DETAILS
# 2026-03-24T10:00:00Z    access_request.created      alice      roles=[ssh-production], reason="Deploying..."
# 2026-03-24T10:02:15Z    access_request.approved     charlie    request=req_a1b2c3d4, approved for alice
# 2026-03-24T14:02:15Z    access_request.expired      system     request=req_a1b2c3d4, alice lost ssh-production

Next Steps