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 ──> expired
              │           │
              │           └──> revoked   (requester self-drop or admin)
              ├──> denied
              └──> cancelled            (requester or admin, while pending)

States:
  pending    — Request submitted, awaiting approver review
  approved   — Approver granted the request; elevated roles are active until expiry
  denied     — Approver rejected the request
  expired    — TTL elapsed, elevated roles automatically revoked
  cancelled  — A still-pending request was withdrawn
  revoked    — An approved request was dropped before expiry
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: req_a1b2c3d4e5f6
# State:  pending
# Roles:  ssh-production
# Reason: Deploying hotfix for order processing

# Request with a specific duration
msh request create --roles=ssh-production --duration=1h \
  --reason="Quick production check"

# List your pending and active requests
msh request ls
# ID                ROLES           REASON              STATE     CREATED              EXPIRES
# req_a1b2c3d4e5f6  ssh-production  Deploying hotfix... pending   2026-03-24 10:00:00  -

Reviewing Requests with mezctl

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

# 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
# Cluster:     prod
# Proxy:       proxy.example.com:3080
# User:        alice
# Roles:       access, can-request-production, ssh-production
# Valid until: 2026-03-24 14:00:00 UTC (3h52m remaining)

# Production nodes are now visible and accessible
msh ls
# HOSTNAME       ROLE  STATUS  LABELS                          VERSION
# web-server-01  node  online  env=production,team=platform    0.1.0
# web-server-02  node  online  env=production,team=platform    0.1.0

# 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. The same cancel verb covers both pending requests (which become cancelled) and approved requests still inside their TTL (which become revoked):

Drop access early bash
# Withdraw a pending request, or revoke an active approved one
msh request cancel 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
  deny: {}
Approver role yaml
kind: role
metadata:
  name: can-approve-production
  description: "Can approve production SSH access requests"
spec:
  allow:
    review_roles:
      - ssh-production
  deny: {}
Assign roles bash
# Roles are assigned when the user is created
mezctl users create alice --roles=access,can-request-production
mezctl users create charlie --roles=access,can-approve-production

# For SSO-mapped users, attach the role names via the connector's
# claim/attribute-to-roles mapping (see the SSO guide).

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 access request events. --type takes a single event type, so query each
# stage separately (or omit --type to see everything in the window).
mezctl audit ls --type=access_request.created  --since=24h
mezctl audit ls --type=access_request.approved --since=24h
mezctl audit ls --type=access_request.denied   --since=24h
mezctl audit ls --type=access_request.expired  --since=24h

# Event types emitted across the lifecycle:
#   access_request.created
#   access_request.approved
#   access_request.denied
#   access_request.expired
#   access_request.cancelled
#   access_request.revoked

Next Steps