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¶
- RP-PAM finds all policies matching the resource.
- If multiple policies match, the most specific policy wins (user-specific > group-specific > default).
- The policy's
approvalModedetermines 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¶
- Log in as a user with the
pam_approverorpam_adminrole. - Navigate to Access > Approval Queue.
- 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¶
- The request appears in the approval queue of all designated approvers.
- Each approver independently reviews and approves or denies.
- The request is approved when the required number of approvals is met (e.g., 2 of 3).
- If any single approver denies, the entire request is denied immediately.
- 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¶
- Log in as
pam_admin. - Navigate to Settings > Security Policies > Access Policies.
- 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.localapprover.
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¶
- AI Assistant Overview -- Use AI for risk scoring and anomaly detection
- Submitting Access Requests -- End-user request workflow
- Configuration Reference -- Full policy configuration options
RP-PAM v1.0.0 -- Copyright 2026 Ravenphyre. All rights reserved.