Links
Comment on page
🔀

Request Routing

Request routing allows you to limit and direct just-in-time access requests, based on who is making the request and which resource is requested.
Request Routing requires a pro-tier P0 subscription.

Configuring Request Routing

To use request routing, go to p0.app and navigate to "Routing". Saving a routing configuration here will configure your organization to use routed approvals, rather than default approvals.

Request Routing Format

When working with Request Routing directly, you should use this reference page for specific definitions of how to format your request properly. This feature of p0 is powerful and customizable, and that's why we've made it accessible via a full API for those who want to use it that way.

Structure of a "Workflow"

We call a collection of routing rules a Workflow, and when you want to make changes to the way your requests are routed in p0 (such as, sending engineers' request to their managers, or restricting access to a particular prod resource to a small group), you do so by submitting a new Workflow.
Keep in mind that you only have one Workflow active at any given time, but that one Workflow can have as many individual routing rules as you want. You do not need to separate out different rule types or anything like that.
Here's an example Workflow that you can copy into your app as a starting point:
- requestor:
type: group
label: Engineering
directory: workspace
resource:
type: integration
service: snowflake
approval:
- type: group
label: Data Ops Team
directory: workspace
options: {allowOneParty: false}

Structure of a "Rule"

The core of workflows are the rules, so let's break them down.

Requestor

The first part of a rule is a "requestor", which matches who makes the request. There are four types of requestors you can choose from:

"Any"

requestor:
type: any
This will match all requestors. Useful for global rules like fall-back restrictions of sensitive resources.

"Some"

requestor:
type: some
This will only allow this rule to match if another separate rule also matches (and otherwise acts like an "any" rule). This rule type will get much more usage as the Request Routing API is further developed (think using this to create optional approvals).

"Group"

requestor:
type: group
id: <group identifier>
label: <human-readable name>
directory: azure-ad|okta|workspace
This rule will match any requestor that is a member of a group in your IdP. Currently, this only supports Google Workspace and Azure AD (but we'll be expanding to Okta in the near future).
id: For Google Workspace, this is the group email address (ie, [email protected]). For Azure, this is the AD group's UUID. For Okta, this is the group ID found in the URL of the group's page in the admin console. See Okta docs.
label: This is any friendly human-readable name you like, although P0 suggests using the same name as displayed in your directory.
directory: For Google Workspace this is "workspace", for Okta this is "okta", and for Azure this is "azure-ad".

"User"

requestor:
type: user
uid: <user's email address>
This rule will match only a specific user, as identified by their email address.

Resource

The second part of a routing rule is the resource this rule should apply to.

"Any"

resource:
type: any
This will match all resources. This is useful, for instance, when you want to route access for a particular user, regardless of what resource or service they are looking to access.

"Some"

resource:
type: some
This will only allow this rule to match if another separate rule also matches (and otherwise acts like an "any" rule). This rule type will get much more usage as the Request Routing API is further developed (think using this to create optional approvals).

"Integration"

resource:
type: integration
service: <target service>
This rule will match a specific type of access request. For instance, maybe you want to create a rule that routes all AWS requests to your DevOps team. Or you want to restrict access to GCP to only a select group.
service: For GCloud, "gcloud", for AWS, "aws", and for Snowflake, "snowflake".
filters (Optional): Filters allow you to apply the rule only to the service components that match the filtering condition.
resource:
type: integration
service: aws|azure-ad|gcloud|k8s|okta|snowflake
filters:
<access-type>:
effect: keep|remove|removeAll
key: <property>
pattern: <regex pattern>
Each filter has an access-type that refers to the type of the requested object. For instance, when "service" is "aws", the filter with access type "policy" will only allow requesting policies whose ARNs match the pattern.
Note that filters do not affect other access types. For example, if you specify an access-type=permission filter for service=gcloud requests, but omit an access-type=role filter, then roles will be unaffected by the filter, i.e. all roles will remain requestable.
Each filter has three potential properties:
  • effect - Describes how this filter is applied
    • keep - This rule will retain objects that match the pattern as requestable
    • remove - This rule will only retain objects that do not match the pattern
    • removeAll - This rule disables the object type entirely.
    • If you want to allow all objects of a type as requestable, omit the filter altogether
  • key - Describes which property of the object the filter must match; only applies if "effect" is one of "keep" or "remove". For instance, if service=aws and access-type=permission-set then the key can be "name" or "arn". If "name", the regex pattern will be matched against the name of permission sets. If "arn", the entire arn is matched.
  • pattern - A regex pattern used to match against the specified property; only applies if "effect" is one of "keep" or "remove"
Patterns are unanchored. Use line-start (^) and line-end ($) markers to anchor patterns.
Valid filter access-type / key combinations are:
service
access-type
key
Notes
aws
tag
<tag key>
Only filters policies
group
name
Filters IAM group names
permission-set
arn | name
Filters Identity Center permission sets
policy
arn
Filters policies with matching ARNs
azure-ad|okta
group
id | label
Filters directory groups
gcloud
permission
id
Filters IAM permissions
role
id
Filters IAM roles based on full ID (e.g. the ID for "Owner" is roles/owner)
snowflake
role
name
Filters roles
k8s
resource
kind|name|
namespace
Filters resources
role
name
Filters roles and cluster roles
Note that filters are not currently available for AWS or GCP resource-level grants, nor for Snowflake SQL grants.
Example of complete filters to cover each access-type in the AWS service:
  1. 1.
    Exclude all permission sets containing "FullAccess"
  2. 2.
    Only allow AWS policies where the tag "P0Grantable" is equal to the string "true", as requestable.
  3. 3.
    Do not allow requesting any AWS groups
resource:
type: integration
service: aws
filters:
permission-set:
effect: remove
key: name
pattern: FullAccess
policy:
effect: keep
key: P0Grantable
pattern: ^true$
group:
effect: removeAll

Approval

The final part of a routing rule is the "approval". Unlike the requestor and resource parts, the approval part is an array of multiple rules, referring to the people/groups/services that can approve (or deny) access requests.

"p0"

approval:
- type: p0
options: { allowOneParty: true|false, requireReason: true|false }
This approval type is analogous to the default approval behavior. This rule routes approvals to the people designated as "Approvers" on the Settings page of your app. The "options" key is optional. You can use it to:
  • allow the requestor to approve their own requests for this flow with the allowOneParty: true setting. Defaults to false.
  • require the requestor to specify a reason when submitting requests with the requireReason: true setting. Defaults to false.

"Group"

approval:
- type: group
id: <group identifier>
label: <human readable name>
directory: azure-ad|okta|workspace
options: { allowOneParty: true|false, requireReason: true|false }
This rule will match any requestor who is a member of a group in your Identity Provider. Currently, p0 supports Google Workspace, Azure AD, and Okta.
id: For Google Workspace, this is the group email address (ie, [email protected]). For Azure, this is the AD group's UUID. For Okta, this is the group ID found in the URL of the group's page in the admin console. See Okta docs.
label: This is any friendly human-readable name you like, although P0 suggests using the same name as displayed in your directory. This label will be printed in approval notifications.
directory: For Google Workspace this is "workspace", for Okta this is "okta", and for Azure this is "azure-ad".
options: See "p0" section

"Auto"

approval:
- type: auto
integration: pagerduty
options: { requireReason: true|false }
This rule automatically approves matching access requests for 1 hour.
integration: currently only "pagerduty" is supported. If the requestors in on-call in PagerDuty their requests will be automatically approved.
options: The "options" key is optional. You can use it to require the requestor to specify a reason when submitting requests with the requireReason: true setting. Defaults to false.

"Deny"

approval:
- type: deny
This rule will deny all requests that match. This supersedes other matching rules: if at least one "deny" rule matches, the request will be denied.

Examples

Routing rules can be used for a variety of use cases.

Different access depending on organizational role

Configure different approvers and different resources for developers and customer-success engineers:
- requestor:
type: group
label: Developers
directory: workspace
resource:
type: any
approval:
- type: group
label: SREs
directory: workspace
options: { allowOneParty: true }
- requestor:
type: group
id: customer-[email protected]
label: Customer Success
directory: workspace
resource:
type: integration
service: snowflake
approval:
- type: group
label: Data Ops
directory: workspace
options: { allowOneParty: false }

Different rules by AWS account

Development AWS account (123456789) allows one-party approvals. Staging AWS account (234567891) allows peer approvals but no one-party approvals. Production AWS account (345678912) requires a manager approver represented by an Okta group. Assumes an AWS Identity Center setup where resource filters allow requesting customer-managed policies in specific AWS accounts, enforced by an ARN match that includes the AWS account ID. Permission sets are implicitly allowed because the permission-set access type filter is not defined.
- requestor:
type: group
id: 00g5j4jojlGZMzfhM69
label: Engineers
directory: okta
resource:
type: integration
service: aws
filters:
policy: { effect: keep, key: arn, pattern: ^arn:aws:iam::123456789:policy/ }
group: { effect: removeAll }
approval:
- type: group
id: 00g5j4jojlGZMzfhM69
label: Engineers
directory: okta
options: { allowOneParty: true }
- requestor:
type: group
id: 00g5j4jojlGZMzfhM69
label: Engineers
directory: okta
resource:
type: integration
service: aws
filters:
policy: { effect: keep, key: arn, pattern: ^arn:aws:iam::234567891:policy/ }
group: { effect: removeAll }
approval:
- type: group
id: 00g5j4jojlGZMzfhM69
label: Engineers
directory: okta
options: { allowOneParty: false, requireReason: true }
- requestor:
type: group
id: 00g5j4jojlGZMzfhM69
label: Engineers
directory: okta
resource:
type: integration
service: aws
filters:
policy: { effect: keep, key: arn, pattern: ^arn:aws:iam::345678912:policy/ }
group: { effect: removeAll }
approval:
- type: group
id: 01f5j4jfjlGZMzfhN99
label: Managers
directory: okta
options: { allowOneParty: false, requireReason: true }

Filter access by AWS policy tag

Restrict which AWS policies can be requested to those with a certain tag value:
- requestor:
type: any
resource:
type: integration
service: aws
filters:
policy: { effect: keep, key: P0Grantable, pattern: ^true$ }
approval:
- type: p0

Org- and resource-specific routing

Allow either the requestor's manager or the service owner to approve requests:
- requestor:
type: group
directory: workspace
resource:
type: some
approval:
- type: group
label: Eng managers
directory: workspace
- requestor:
type: some
resource:
type: integration
service: gcloud
approval:
- type: group
id: gcloud-[email protected]
label: GCloud owners
directory: workspace

Mandatory reason for a specific resource type

Make reason mandatory for AWS requests
- resource:
type: any
approval:
- options: {requireReason: false, allowOneParty: true}
type: p0
requestor:
type: any
- resource:
service: aws
type: integration
approval:
- options: {requireReason: true}
integration: pagerduty
type: auto
requestor:
type: any

Exclude cluster-admin role and only allow default namespace in Kubernetes

- resource:
type: integration
service: k8s
filters:
resource:
effect: keep
key: namespace
pattern: ^default$
role:
effect: remove
key: name
pattern: cluster-admin
approval:
- type: p0
requestor:
type: any