Skip to content

Approval Workflows

Section: Web Portal | Article 26
Audience: System Administrators, Approvers
Last Updated: 2026-04-07


Overview

Every access request in RP-PAM is governed by a policy. Policies define who can request access to a resource, what approval is required, and what constraints apply (maximum duration, time-of-day restrictions, etc.).

This article covers how policies work, how approvers review requests, and how administrators configure approval workflows.


How Policies Work

Each resource is associated with one or more policies. When a user submits an access request, RP-PAM evaluates the applicable policy to determine the approval flow.

Policy Evaluation Order

  1. RP-PAM finds all policies matching the resource.
  2. If multiple policies match, the most specific policy wins (user-specific > group-specific > default).
  3. The policy's approvalMode determines what happens next.

Approval Modes

Mode Description When to Use
auto_approve Access is granted immediately without human review Low-risk resources, self-service access for trusted groups
single_approver One designated approver must approve Standard resources, most common mode
multi_approver Multiple approvers must approve (e.g., 2 of 3) High-risk resources, sensitive credentials
manager_approval The requester's direct manager must approve Org-hierarchy-based approval
time_based_auto Auto-approve during certain hours; require human approval outside those hours Business-hours self-service with after-hours oversight

Approving and Denying Requests

Using the Web Portal

  1. Log in as a user with the pam_approver or pam_admin role.
  2. Navigate to Access > Approval Queue.
  3. The queue shows all pending requests assigned to you.

For each request, you see:

Field Description
Requester The user who submitted the request
Resource The resource being requested
Duration How long they want access
Justification Why they need access
Risk Score AI-generated risk assessment (if AI module is active)
Submitted When the request was submitted
Escalation Time remaining before the request escalates

To approve: 1. Review the request details. 2. Optionally add an approver note (e.g., "Verified ticket JIRA-4521 is valid"). 3. Click Approve.

To deny: 1. Review the request details. 2. You must provide a denial reason (this is shown to the requester). 3. Click Deny.

Using the API

Linux:

# List pending requests in your approval queue
curl -s http://localhost:7101/api/v1/access/approvals/pending \
  -H "Authorization: Bearer $APPROVER_JWT" | jq '.items[] | {requestId, requester, resourceName}'

# Approve a request
curl -s -X POST http://localhost:7101/api/v1/access/approvals/req-e5f6g7h8/approve \
  -H "Authorization: Bearer $APPROVER_JWT" \
  -H "Content-Type: application/json" \
  -d '{ "note": "Verified ticket JIRA-4521" }' | jq .

# Deny a request
curl -s -X POST http://localhost:7101/api/v1/access/approvals/req-e5f6g7h8/deny \
  -H "Authorization: Bearer $APPROVER_JWT" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Ticket JIRA-4521 is for staging, not production" }' | jq .

PowerShell:

# List pending requests
$pending = Invoke-RestMethod -Uri "http://localhost:7101/api/v1/access/approvals/pending" `
  -Headers @{ Authorization = "Bearer $approverJwt" }
$pending.items | Select-Object requestId, requester, resourceName | Format-Table

# Approve
Invoke-RestMethod -Uri "http://localhost:7101/api/v1/access/approvals/req-e5f6g7h8/approve" `
  -Method Post `
  -Headers @{ Authorization = "Bearer $approverJwt" } `
  -ContentType "application/json" `
  -Body '{ "note": "Verified ticket JIRA-4521" }'

# Deny
Invoke-RestMethod -Uri "http://localhost:7101/api/v1/access/approvals/req-e5f6g7h8/deny" `
  -Method Post `
  -Headers @{ Authorization = "Bearer $approverJwt" } `
  -ContentType "application/json" `
  -Body '{ "reason": "Ticket JIRA-4521 is for staging, not production" }'


Multi-Approver Workflows

When a policy uses multi_approver mode, the request requires approval from a specified number of approvers.

How It Works

  1. The request appears in the approval queue of all designated approvers.
  2. Each approver independently reviews and approves or denies.
  3. The request is approved when the required number of approvals is met (e.g., 2 of 3).
  4. If any single approver denies, the entire request is denied immediately.
  5. Once the threshold is met, the remaining approvers see the request as resolved.

Example: 2-of-3 Approval

Approver Action Result
Alice Approves 1 of 2 needed -- still pending
Bob Approves 2 of 2 needed -- approved
Carol (not needed) Request already approved

Escalation Timeouts

Policies can define an escalation timeout. If no approver acts within the timeout period, the request escalates.

Escalation Behaviour

Configuration What Happens
escalateTo: "backup_approvers" The request is added to a secondary approver group's queue
escalateTo: "pam_admin" The request escalates to all pam_admin users
escalateTo: "auto_deny" The request is automatically denied after the timeout
escalateTo: "auto_approve" The request is automatically approved after the timeout (use with caution)

Notifications

  • The original approver receives a reminder notification at 50% and 75% of the timeout.
  • When escalation occurs, the escalation target receives a notification.
  • The requester is notified that their request has escalated.

Configuring Policies (pam_admin)

Using the Web Portal

  1. Log in as pam_admin.
  2. Navigate to Settings > Security Policies > Access Policies.
  3. Click + Create Policy or edit an existing policy.

Policy Configuration Fields

{
  "policyName": "production-server-access",
  "description": "Policy for production server access requests",
  "resourceScope": {
    "resourceTags": ["production"],
    "resourceTypes": ["server"]
  },
  "eligibility": {
    "users": [],
    "groups": ["sg-server-admins", "sg-sre-team"],
    "roles": ["pam_user"]
  },
  "approval": {
    "mode": "single_approver",
    "approvers": ["alice@corp.local", "bob@corp.local"],
    "requiredApprovals": 1,
    "escalationTimeoutMinutes": 60,
    "escalateTo": "pam_admin"
  },
  "constraints": {
    "maxDurationMinutes": 480,
    "requireJustification": true,
    "justificationPattern": "^(JIRA|INC|MW)-",
    "allowedHours": {
      "enabled": false,
      "timezone": "America/New_York",
      "startHour": 6,
      "endHour": 22
    }
  }
}

Using the API

Linux:

curl -s -X POST http://localhost:7101/api/v1/policies \
  -H "Authorization: Bearer $ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "policyName": "production-server-access",
    "description": "Policy for production server access requests",
    "resourceScope": {
      "resourceTags": ["production"],
      "resourceTypes": ["server"]
    },
    "eligibility": {
      "groups": ["sg-server-admins"]
    },
    "approval": {
      "mode": "single_approver",
      "approvers": ["alice@corp.local"],
      "requiredApprovals": 1,
      "escalationTimeoutMinutes": 60,
      "escalateTo": "pam_admin"
    },
    "constraints": {
      "maxDurationMinutes": 480,
      "requireJustification": true
    }
  }' | jq .

PowerShell:

$policy = @{
    policyName    = "production-server-access"
    description   = "Policy for production server access requests"
    resourceScope = @{
        resourceTags  = @("production")
        resourceTypes = @("server")
    }
    eligibility   = @{
        groups = @("sg-server-admins")
    }
    approval      = @{
        mode                      = "single_approver"
        approvers                 = @("alice@corp.local")
        requiredApprovals         = 1
        escalationTimeoutMinutes  = 60
        escalateTo                = "pam_admin"
    }
    constraints   = @{
        maxDurationMinutes    = 480
        requireJustification  = $true
    }
} | ConvertTo-Json -Depth 4

Invoke-RestMethod -Uri "http://localhost:7101/api/v1/policies" `
  -Method Post `
  -Headers @{ Authorization = "Bearer $adminJwt" } `
  -ContentType "application/json" `
  -Body $policy

Policy Field Reference

Field Description Required
policyName Unique identifier for the policy Yes
description Human-readable description No
resourceScope.resourceTags Apply this policy to resources with these tags No
resourceScope.resourceTypes Apply to these resource types (server, group, credential, sshKey) No
eligibility.users Specific users who can request under this policy No
eligibility.groups Groups whose members can request under this policy No
eligibility.roles RP-PAM roles that can request under this policy No
approval.mode auto_approve, single_approver, multi_approver, manager_approval, time_based_auto Yes
approval.approvers List of approver usernames or email addresses Required for single_approver and multi_approver
approval.requiredApprovals Number of approvals needed (for multi_approver) Required for multi_approver
approval.escalationTimeoutMinutes Minutes before the request escalates No (default: no escalation)
approval.escalateTo Escalation target: backup_approvers, pam_admin, auto_deny, auto_approve No
constraints.maxDurationMinutes Maximum access duration allowed No (default: 480)
constraints.requireJustification Require a justification message No (default: true)
constraints.justificationPattern Regex pattern the justification must match (e.g., ticket number format) No
constraints.allowedHours Restrict requests to specific hours of the day No

Time-Based Auto-Approve

The time_based_auto mode combines self-service convenience during business hours with human oversight after hours.

{
  "approval": {
    "mode": "time_based_auto",
    "approvers": ["oncall@corp.local"],
    "requiredApprovals": 1,
    "autoApproveWindow": {
      "timezone": "America/New_York",
      "days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
      "startHour": 8,
      "endHour": 18
    }
  }
}
  • 8:00-18:00 Mon-Fri (ET): Requests are auto-approved.
  • All other times: Requests go to the oncall@corp.local approver.

Audit Trail

Every approval action is recorded in the audit log:

Event Details Logged
Request submitted Requester, resource, duration, justification
Approval Approver, timestamp, optional note
Denial Approver, timestamp, required denial reason
Escalation Original approver, escalation target, timeout duration
Auto-approve Policy name, reason for auto-approval
Provisioning Resource, action taken (e.g., "added to group sg-vpn-users")
Expiry/Revocation Resource, action taken (e.g., "removed from group sg-vpn-users")

Troubleshooting

Problem Cause Solution
Request auto-approved when it should not be Policy mode set to auto_approve Change the policy mode to single_approver or appropriate mode
Approver does not see the request Wrong approver configured in policy Verify the approvers list in the policy matches the approver's username
Escalation not working escalationTimeoutMinutes not set Add an escalation timeout and target to the policy
"No policy found" error on request Resource has no associated policy Create a policy with a resourceScope matching the resource
Multi-approver: only 1 person can see request requiredApprovals is 1 (acts like single_approver) Set requiredApprovals to the desired quorum (e.g., 2) and list all approvers
Justification rejected justificationPattern does not match input Check the regex pattern; ensure the user includes the required format (e.g., ticket number)

Next Steps


RP-PAM v1.0.0 -- Copyright 2026 Ravenphyre. All rights reserved.