# What Is P0?

P0 Security is a cloud-native Privileged Access Management platform. Enforce just-in-time access and least-privilege governance across multi-cloud environments.

Welcome to the P0 documentation. We're glad you're here.

P0 Security is a next-generation Privileged Access Management (PAM) platform purpose-built for today's hybrid, multi-cloud, and developer-driven environments. It unifies governance, just-in-time (JIT) access, and access orchestration across all identity types, human, non-human, and AI agents, while eliminating the complexity and fragmentation of legacy tooling.

At the core of P0 is a continuously updated Identity Graph that connects identity data from your directories, identity providers, cloud identity services, and key applications. It gives teams a clear, accurate view of every identity, what it can access, and how those permissions are granted. P0 leverages this identity graph to enable fine-grained, ephemeral access, policy-based automation, and continuous risk-aware governance, whether you're managing cloud workloads, on-prem infrastructure, or developer tools like GitHub and Jenkins.

With agentless JIT, integrated workflows (Slack, CLI, GitHub), and support for modern app architectures, P0 delivers powerful access control without slowing teams down, redefining PAM for the cloud-native, AI-augmented era.

## Get started

New to P0? Start here based on your role:

| Your goal                           | Start here                                                                                                                                                   |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Set up P0 for your organization** | [P0 Onboarding guide](/getting-started/p0-security-onboarding): account setup, integrations, and first scan                                                  |
| **Enable just-in-time access**      | [Getting started with just-in-time access](/getting-started/getting-started-with-just-in-time-access): install, configure approvals, make your first request |
| **Discover your access posture**    | [Getting started with Posture](/getting-started/getting-started-with-posture): connect your cloud, run your first scan, and triage findings                  |
| **Explore your access inventory**   | [Getting started with Access Inventory](/getting-started/getting-started-with-access-inventory): connect your cloud and query your access graph              |
| **Request access to a resource**    | [Requesting access](/access-management/just-in-time-access/requesting-access): request access via Slack, the web app, or the CLI                             |
| **Use the P0 CLI**                  | [Installing the P0 CLI](/p0-cli/installing-p0-cli): install and authenticate the command-line tool                                                           |

**P0 Capabilities:**

<table data-card-size="large" data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a data-mention href="/pages/fQpbbGMQOmIuAkMUWvaH">/pages/fQpbbGMQOmIuAkMUWvaH</a></td><td>The P0 Dashboard offers a unified view of your onboarded infrastructure, summarizing discovered identities, key posture findings, JIT access metrics, and high-frequency requests in a single pane of glass. It helps teams continuously improve access posture and reduce time-to-access, while also delivering clear, leadership-friendly reporting to show progress and risk reduction.</td><td></td><td></td></tr><tr><td><a data-mention href="/pages/Gtv7FF0r3wGs1iPQlkiM">/pages/Gtv7FF0r3wGs1iPQlkiM</a></td><td>Lists identities, entitlements, and resources in your cloud.</td><td>Analyze relationships between these assets to answer questions like who has overprivileged access, access to sensitive resources, or discover complex lateral movement paths.</td><td><a href="/files/YZ8d0Xt93rPI8TvMbrYq">/files/YZ8d0Xt93rPI8TvMbrYq</a></td></tr><tr><td><a data-mention href="/pages/e2hny5Ivp27MvmR6YIiR">/pages/e2hny5Ivp27MvmR6YIiR</a></td><td>Discover access vulnerabilities in your cloud.</td><td>P0 analyzes access across systems, including IdPs, clouds, and managed services (like Kubernetes) to discover access security vulnerabilities.</td><td><a href="/files/KImQQHa8C2mzHConKJmq">/files/KImQQHa8C2mzHConKJmq</a></td></tr><tr><td><a data-mention href="/pages/WsKD3kAwkLlLemZ66gzA">/pages/WsKD3kAwkLlLemZ66gzA</a></td><td>Give members of your organization access to perform specific tasks for just as long as they need it.</td><td>On average, members gain access within 5 minutes of request, including approval time.</td><td><a href="/files/1iNb1xN2YZYoyK8lV6w0">/files/1iNb1xN2YZYoyK8lV6w0</a></td></tr><tr><td><a data-mention href="/pages/6HPbVZFQzDkPANdeZLvV">/pages/6HPbVZFQzDkPANdeZLvV</a></td><td>Runtime authorization for what your AI agents can do across sensitive systems.</td><td>The P0 AuthZ Control Plane for Agents provides runtime authorization across the full agent action chain. P0 verifies the originator and the agent behind every MCP tool call, evaluates policy before each action through the self-hosted P0 AI Gateway, and ties every action to a named person, a specific agent, and the policy that governed it.</td><td></td></tr><tr><td><a data-mention href="/pages/KpIZuocJSZsC39c6tb36">/pages/KpIZuocJSZsC39c6tb36</a></td><td>Manage rotation of static service-account credentials.</td><td>P0 discovers service-account owners, creates fresh credentials and manages your credential vault. P0 integrates with your ticketing system to ensure that owners update credentials in 3rd-party systems before rotation.</td><td><a href="/files/FXbdyR31dvkLdnmSpoNd">/files/FXbdyR31dvkLdnmSpoNd</a></td></tr></tbody></table>


# P0 Dashboard

Track access security with automated reporting. View identities, posture findings, JIT access metrics, and request trends from the P0 dashboard.

P0 provides automated reporting so you can track your progress toward improving access security.

### Features

* Track access-vulnerability findings burndown over time
* View top access vulnerabilities at a glance
* View the breakdown of IAM assets in your environment
* Track your organization's use of just-in-time access, and ensure rapid time-to-access

<figure><img src="/files/fFIhzxqmlrTyizWNCm43" alt="P0 dashboard showing posture findings chart, inventory identity breakdown, and just-in-time access metrics including approval time and request frequency" width="563"><figcaption></figcaption></figure>

### Explore dashboard data sources

The dashboard surfaces data from across P0's capabilities. Dive deeper into each area:

* [Access inventory](/inventory/access-inventory): Search and analyze identities, entitlements, and resources
* [Posture overview](/posture/posture-overview): Review access-vulnerability findings and track remediation
* [Just-in-time access](/access-management/just-in-time-access): Monitor access requests, approvals, and usage metrics

### Get started

New to P0? Follow the [Getting started with Access Inventory](/getting-started/getting-started-with-access-inventory) or [Getting started with Posture](/getting-started/getting-started-with-posture) guide to connect your cloud and populate the dashboard.


# Access Inventory

Discover production assets, identities, and access risks across AWS, Google Cloud, Kubernetes, Okta, and Google Workspace with P0's access inventory.

Use P0's access inventory to view your production assets, all the identities that can access them, and associated access risks.

*IAM assessment is currently available for AWS, Google Cloud, Kubernetes, Okta, and Google Workspace.*

### Features

* Combines IAM data from disparate sources, including your identity provider, your IAM policies, and your cloud access logs
* Evaluates issues based on risks of individual privileges, using P0's comprehensive open-source [IAM Privilege Catalog](https://catalog.p0.dev)
* Detects lateral movement across identities and clouds

### How it works in P0

P0 connects to your IAM systems, reading your configuration.

<div data-full-width="false"><figure><img src="/files/CUPaxJvJkGcUtKNn5vOn" alt="P0 data collection progress indicator showing Collecting Data at 3% while fetching IAM policy data" width="375"><figcaption></figcaption></figure></div>

P0 builds a complete end-to-end access graph for your environment:

<figure><img src="/files/YZ8d0Xt93rPI8TvMbrYq" alt="Access inventory graph visualization showing identities, entitlements, and resources connected by lateral movement paths" width="563"><figcaption></figcaption></figure>

You can query your access graph to find sensitive access to specific resources, specific risks, or more:

<figure><img src="/files/Sq4QCPWWtLJ14mnLW61K" alt="Inventory query results table filtered by storage exfiltration risk showing principals, roles, and affected resources" width="563"><figcaption></figcaption></figure>

### Related documentation

* [Access inventory details](/inventory/access-inventory): Search your inventory, view asset lists, and explore the access graph
* [Query search](/inventory/query-search): Write queries to find specific identities, entitlements, and resources
* [Posture overview](/posture/posture-overview): See access-vulnerability findings detected from your inventory data

### Get started with P0's access inventory

Getting set up and collecting your organization's inventory takes about 15 minutes.

1. Sign up for a P0 account at [p0.app/create-account](https://p0.app/create-account).
2. Follow the instructions in [Creating an Environment](/environments/creating-an-environment).
3. For a complete walkthrough, see the [Getting started with Access Inventory](/getting-started/getting-started-with-access-inventory) guide.


# Posture

Automatically scan your cloud environment for access risks. P0 Security detects overprivileged accounts, stale credentials, and security vulnerabilities.

With Posture, P0 automatically scans your environment for access risks.

### Features

* Detects access vulnerabilities from authentication, authorization, and lateral movement
* Automatically determines finding assignees based on fine-grained resource ownership
* Provides automated remediation suggestions and lets users document acceptable risks

### How it works

P0 automatically scans your access graph for issues after collecting your [Access Inventory](/readme/access-inventory).

<figure><img src="/files/KImQQHa8C2mzHConKJmq" alt="Posture findings list showing monitors ranked by severity with finding counts for unused privileges, IAM roles, and service accounts" width="563"><figcaption></figcaption></figure>

For each finding, you can view the attack path, assign findings, and review auto-generated fixes.

<figure><img src="/files/KXPFDuxRg6azC1eIJCgz" alt="Split view showing a posture monitor with findings list on the left and the selected finding&#x27;s attack path and details on the right" width="563"><figcaption></figcaption></figure>

### Related documentation

* [Posture overview](/posture/posture-overview): Filter, export, and manage posture findings in detail
* [Monitor results](/posture/monitor-results): View individual monitor results and take bulk actions
* [Finding details](/posture/finding-details): Inspect attack paths, assign findings, and review suggested fixes

### Getting started

P0 automatically collects posture findings after you follow [Creating an Environment](/environments/creating-an-environment). For a Posture-focused walkthrough that covers running your first scan and triaging findings, see [Getting started with Posture](/getting-started/getting-started-with-posture). The same scan also powers [Access Inventory](/inventory/access-inventory). To explore your access graph, see [Getting started with Access Inventory](/getting-started/getting-started-with-access-inventory).


# Just-In-Time Access

Grant tailored, short-lived privileges to specific cloud resources on demand. Reduce standing access and enforce least privilege with P0 Security's JIT access.

Use just-in-time access to give tailored, short-lived privileges to specific resources on demand.

### Benefits of just-in-time access

* Reduce your IAM attack surface by only holding privileges when they are in use.
* Grant access more quickly; the mean time between making an access request and gaining access using P0, including approval, is 5 minutes.
* Request and grant access based on operations (like reading a bucket), eliminating the need to craft custom roles and policies, and preventing incorrect access grants.

### How it works in P0

Once you connect P0 to your organization's Slack and an IAM resource, any member of your organization can request access by typing `/p0 request` in Slack. No further set-up is required.

Here's what it looks like:

<figure><img src="/files/hWevj6Ab2ol9xFuNjwon" alt="Animated demo of a just-in-time access request flow using the /p0 request Slack command, showing request, approval, and access grant" width="543"><figcaption></figcaption></figure>

Requests can be approved by managers, resource owners, or automatically by integrations such as PagerDuty. You can discuss justification for each request in Slack. Access requests, together with their justifications, approval, grant, and revocation histories are recorded by P0, and can be exported to your SIEM.

### Related documentation

* [Just-in-time access overview](/access-management/just-in-time-access): Configure and manage JIT access workflows
* [Requesting access](/access-management/just-in-time-access/requesting-access): Learn how to request access via Slack or the web app
* [Approving access](/access-management/just-in-time-access/approving-access): Set up approval workflows and pre-approvals
* [Request routing](/access-management/just-in-time-access/request-routing): Route, auto-approve, or deny requests based on policies
* [P0 CLI commands](/p0-cli/p0-commands-and-usage): Request and manage access from the command line

### Get started with just-in-time access

Getting started with just-in-time access takes about 15 minutes. Follow the [quick-start guide](/getting-started/getting-started-with-just-in-time-access).


# P0 Connectors

Understand P0 connectors: stateless, versioned runtimes you deploy in your own cloud account to broker just-in-time access, so no standing credentials sit on laptops or in P0's SaaS.

A **connector** is a small piece of P0 software that runs inside your own cloud account and brokers just-in-time access to your infrastructure. It's the part that actually reaches your resources (signing in to a host, provisioning a database grant, and so on), so that neither your engineers' laptops nor P0's SaaS ever hold standing credentials to your fleet.

P0's default access paths are agentless and driven entirely by your cloud provider's native IAM. Connectors exist for the cases where that isn't enough: where a cloud-native path is fragile, where provider IAM limits what an external service can do, or where you want an access path that keeps working even when a managed agent, or P0 itself, is unavailable.

***

## What a connector is

A connector is a minimal runtime you deploy in your own cloud account, a container (for example on Cloud Run or ECS) or a serverless function. It has a deliberately small surface:

* It's **the only component that holds credentials to your target fleet**, and those credentials never leave your environment. Signing keys and per-host secrets live in your own KMS and secrets manager.
* It's **stateless**, runs from a **published, versioned image**, and can **scale to zero** between sessions when deployed as a function.
* It exposes **no inbound interface** other than a listener that mutually authenticates (mTLS) against P0's certificate authority.
* It installs through **P0's infrastructure-as-code** as a one-line operation, and updates by bumping an image or module version.

Conceptually, the connector *is* your security perimeter running P0-authored logic. It sits inside your trust boundary rather than reaching in from outside it.

### Where it sits

<figure><img src="/files/Egfnc6F4DrbAGsm7W0cC" alt="Diagram showing the P0 connector inside the customer&#x27;s cloud trust boundary, alongside KMS and secrets manager and existing cloud-native paths, between the P0 control plane and the target fleet"><figcaption></figcaption></figure>

The connector lives *next to* your cloud-native paths, not in front of them. Adopting a connector doesn't remove SSM, Bastion, or OS Login. They keep working, and the connector is an extra route to the same hosts.

***

## How a request flows

Using SSH as the worked example, a request for `p0 ssh prod-web-01` looks like this. The same shape (request, approve, mint short-lived credential, hand it to the connector) generalizes to other resource types.

<figure><img src="/files/xS8ZleJCl0RRvh96HSu0" alt="Sequence diagram of an SSH request: generate ephemeral keypair, request access and justification, evaluate policy and approval, sign public key, verify cert and fetch host credential, then log in and start the session"><figcaption></figcaption></figure>

The important properties: the engineer's private key never leaves their machine; the certificate is short-lived; the signing material and per-host credentials stay in your cloud; and the connector, not the laptop and not P0, is the only thing that ever authenticates to the host.

***

## Why we built connectors

### 1. A second, independent path in

This is the core motivation. A connector path needs only that `sshd` is running and the host is reachable on the network. It doesn't depend on an in-host agent or a managed access service, so it stays available across the failure modes that most often take the cloud-native path down.

<figure><img src="/files/Be1z67bl9qIBP4FmRyFK" alt="Diagram comparing the cloud-native path, which needs an in-host agent and breaks if it dies, with the connector path, which needs sshd and network and survives agent failure"><figcaption></figcaption></figure>

| Failure mode                              | Cloud-native path                                           | Connector path                                                           |
| ----------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------ |
| In-host agent dies or won't start at boot | Blocked, often only fixable by re-provisioning the instance | Unaffected, if `sshd` is up                                              |
| Managed access service degraded           | Blocked                                                     | Unaffected                                                               |
| P0 control plane unreachable              | Blocked                                                     | Can continue within policy, signing material already lives in your cloud |
| No network route to the host              | Blocked                                                     | Blocked, a connector doesn't solve reachability                          |

Because the connector and your signing material both live in your cloud, it's possible to define a break-glass path that keeps functioning even if P0's control plane is temporarily unreachable. Whether and how that's enabled is a policy decision made with your team.

### 2. Credentials never touch laptops, and never leave your cloud

The connector is the single mediator that authenticates to your fleet, and it reads its credentials from your own vault. Your engineers never own a credential to the target hosts, and neither does P0's SaaS. Per-host credentials are short-lived and rotate on a schedule you control.

### 3. It works within your IAM instead of around it

Running P0's logic inside your environment sidesteps the provider-IAM limits that would otherwise constrain what an external service can do, without granting P0 broad standing permissions. The connector operates with least-privilege, scoped credentials that stay in your account.

### 4. A minimal, consistent, up-to-date footprint

Every connector ships as the same kind of artifact: a small, stateless, published image installed through IaC and versioned centrally. That keeps the deployment story identical across integrations and makes staying current a version bump rather than a migration.

***

## What a connector isn't *not*

* **Not a bastion or jump host.** No human ever logs into the connector. It provisions access; it is not a machine you land an interactive session on.
* **Not a proxy in front of your cloud-native paths.** It runs beside them as an independent route, and doesn't intercept or replace SSM, Bastion, or OS Login.
* **Not a fix for network reachability.** You bring your own network path to the target host; the connector must be able to reach `sshd`, but it doesn't create connectivity where none exists.
* **Not a standing root account.** The on-host principal it uses is tightly constrained (see the [Security model](#security-model)).

***

## Security model

There are two trust boundaries: between your engineer's machine and P0, and between P0 and your connector. Everything past the connector, its conversation with the fleet and with your vault, stays inside your cloud account.

The connector exposes no inbound surface except a listener that mutually authenticates against P0's certificate authority. It has no persistent state, and per-host credentials are short-lived and rotated on a configurable schedule.

**The on-host principal.** To bridge an external identity into a Linux session, the connector uses a dedicated system account on the target host (commonly seen as `p0-user`). Every product in this category has an equivalent privileged on-host principal (it is intrinsic to the problem), and P0 bounds it deliberately:

* It is **not a general-purpose root account.** Its `sudoers` policy enumerates only the specific commands it may run (ephemeral user provisioning and file operations on a fixed set of paths), or it is locked to a single **signed bootstrap script** that is integrity-checked at every invocation.
* It **has no interactive shell.** A try to land a shell as this account fails; only the permitted commands or bootstrap script run.
* **Every invocation is logged**, both in the host's audit log and in the connector's stream to your SIEM.

Handled honestly: if that on-host principal were fully compromised on a host, an attacker could create or remove local users and change file ownership within the configured paths, but couldn't modify the integrity-checked bootstrap script, and couldn't pivot to other hosts, because credentials are per-host and short-lived. That's a materially smaller blast radius than a generic root SSH key. It's not zero, and we don't claim otherwise.

***

## One integration, several connectors

A connector is a general primitive, not a single product. A given integration is usually a small **constellation of cooperating connectors**, each doing one job:

* an **IAM-layer security perimeter** that manages cloud-native access,
* an **SSH connector** for host access,
* a **database-engine connector** that provisions grants over SQL,
* a **cloud-API connector** that creates managed identities through a provider's admin API.

Keeping each piece separate and single-purpose is deliberate: every connector carries only the permissions it needs, and each can be validated independently. It also means a connector for a new system is a small, well-scoped addition rather than a change to everything around it.

You can see this pattern in the integrations that ship today:

* The [GCP IAM management security perimeter](/integrations/resource-integrations/google-cloud/security-perimeter) and the [Microsoft Entra ID security perimeter](/integrations/directory-integrations/microsoft-entra-id/viewing-security-perimeter-logs) are the IAM-layer connectors for those clouds.
* The [Azure jump host management connector](/integrations/resource-integrations/microsoft-azure/jump-host-management) dispatches privileged session commands to your jump host VMs.
* The PostgreSQL and MySQL integrations deploy a `p0-connector` to broker database grants. See [Installing an RDS database](/integrations/resource-integrations/postgresql-new/installing-an-rds-database).

***

## FAQ

**Do my engineers connect&#x20;*****to*****&#x20;the connector?** No. No human logs into the connector. It brokers access; it's not something you open a session against.

**Does P0 hold credentials to my hosts?** No. Signing keys and per-host credentials live in your own KMS and secrets manager. The connector reads them there, inside your account.

**Do I still need SSM, Bastion, or OS Login?** You can keep them. The connector runs alongside your cloud-native paths as an additional, independent route. It doesn't replace them.

**Does a connector solve private-network reachability?** No. You bring your own network path to the target; the connector must be able to reach the host, but it doesn't create connectivity.

**What happens if a connector is compromised?** The blast radius stays small: per-host credentials that are short-lived, no lateral movement to other hosts, no interactive shell on the on-host account, and full audit logging of everything it does.

**Does access keep working if P0 is temporarily unreachable?** It can, within policy. Because the signing material lives in your cloud, you can define a break-glass path through the connector that does not depend on P0's control plane being reachable. This is configured with your team.

**How is a connector installed and kept up to date?** Through P0's infrastructure-as-code, as a one-line install. Updates are an image or module version bump.

***

## Related documentation

* [Google Cloud security perimeter](/integrations/resource-integrations/google-cloud/security-perimeter): Install the IAM-layer connector for GCP.
* [Viewing Security perimeter logs](/integrations/directory-integrations/microsoft-entra-id/viewing-security-perimeter-logs): Read the Entra security perimeter connector's logs.
* [Azure jump host management](/integrations/resource-integrations/microsoft-azure/jump-host-management): Configure the jump host connector.
* [Just-in-time access](/readme/just-in-time-access): The access model connectors broker.


# P0 AuthZ Control Plane for Agents

Verify the human and the agent, enforce least-privilege policy on every MCP tool call, and keep a complete audit trail with P0 AuthZ Control Plane™ for Agents and self-hosted MCP Gateway.

Organizations have always needed least-privileged controls over what identities can do in sensitive systems. AI agents do not change that requirement, they dramatically intensify it. Agents act autonomously across more systems, around the clock, at machine speed. And they do so using the same broad permissions and static credentials that enterprises already struggle to govern for human users and\
non-human identities.

This creates three core risks to the business:

* **Loose delegation:** The agent inherits delegated authority without a defined scope, ownership or boundaries. The agent gets whatever access the weakest link allows.
* **Standing privilege:** The agent gets broad, standing access that long outlives any given task they are invoked to complete. Leaving that access path wide open to malicious activity.
* **Broken attribution:** When something goes wrong, nobody can explain who asked, what happened or why it was allowed.

#### How agents break traditional access management models

Agents introduce two structural changes that traditional identity access models do not handle:&#x20;

* **Multiple identities at play.** Every agent action involves at least two identities: the originator and the agent itself, and they should rarely hold the same authority. Treating them as one (agent-as-user or agent-as-service-account) collapses the distinction and grants either end with too much access and obscures human accountability.
* **Complex action chain.** Where user access workflows are fairly straightforward, agents require at least four distinct control points, with multi-agent workflows extending this even further. Policy applied at any single layer leaves gaps across the others.

#### Benefits of the AuthZ Control Plane for Agents

Whether agents are triggered by humans, service accounts, workloads or other agents, every action needs identity and context that carries through the full access chain. With P0, every agentic access workflow is evaluated, scoped and governed at runtime.

* **Discover**. Inventory all agents and MCP servers, managed or\
  unmanaged.
  * Discover all intermediate agents, identities, tools and resources
  * Understand permissions, access paths and delegated authority
  * Identify shadow agents, standing access and emerging risk
* **Control.** Authorize what they can access, when and with whose authority.
  * Enforce runtime authorization before actions occur
  * Apply Zero Standing Privilege and Just-in-time access
  * Control agent behavior through policy, context and approvals
* **Prove.** Show what happened, ensure accountability and monitor for policy drift.
  * Capture the full action chain across requester, agent, tool and resource
  * Explain why access was granted, denied or revoked
  * Deliver audit-ready evidence, accountability and compliance

### How P0 Security controls agentic access at runtime

The P0 AuthZ Control Plane for Agents enforces policy at runtime in two critical ways that most tools do not: by understanding the full identity context behind every action and carrying that through each control point to enforces policy across the entire action chain at runtime.

* **Blended identity context** - Ties the agent to the human, service account, workload or agent that initiated the action for comprehensive context
* **End-to-end policy enforcement** - Applies policy to the blended identity across each control point in action chain before access occurs

P0’s agentic security offering is composed of two distinct but complementary pieces. Understanding where each sits in your stack prevents confusion when evaluating or deploying them.

**Layer 1: P0 OAuth Server and P0 AI Gateway**\
Sits in the data path between your agents and your MCP servers. Intercepts every tool call, verifies identity, enforces policy and writes to the audit log. Self-hosted in your environment so your sensitive data never leaves your perimeter.

**Layer 2: P0 AuthZ Control PlaneTM for Agents**\
The policy engine and authorization layer that tells the gateway what to allow, flag or block at runtime. Defines roles, manages JIT approvals, surfaces governance exceptions and provides the audit and identity inventory. Hosted as SaaS.

P0 Security covers these four control points in every agent action chain:

| Control point                 | Question                             |
| ----------------------------- | ------------------------------------ |
| **1. User authentication**    | Who is the accountable human?        |
| **2. Agent authentication**   | Which agent is acting?               |
| **3. Tool authorization**     | Can this agent use this tool?        |
| **4. Resource authorization** | What can it do in the target system? |

**Blended identity.** The gateway federates with your existing IdP (Okta, Entra ID, or any OIDC provider) to verify the user, and issues each agent client its own credentials. On each session it produces a signed token that cryptographically binds the user and the agent together. That token travels with every MCP tool call, and the agent never receives the credentials to the upstream system.

**Enforcement layers.**&#x20;

* At layer 1, the gateway enforces at the MCP protocol layer, evaluating conditions on each MCP tool call. This applies to any MCP server, but may be too coarse for complex services.&#x20;
* At layer 2, when P0 has an IAM integration with the upstream service (Postgres, GCP, AWS, Azure, Kubernetes), enforcement happens *inside* that service via a session-bound temporary user, role, or policy, so the service itself controls and enforces the agent's effective entitlements. This unlocks the full extent of the service's native access control for any agent.

### Related documentation

* [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway): Architecture and installation of the self-hosted enforcement components
* [Agentic Gateway integration](/integrations/resource-integrations/agentic-gateway): Register the gateway and configure the MCP servers it fronts
* [P0 CLI commands](/p0-cli/p0-commands-and-usage): Connect agents and manage access from the command line

### Get started with agentic authorization

P0 delivers agentic authorization as a Helm chart you deploy into your own Kubernetes environment. Start with [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway), then configure your upstream servers with the [Agentic Gateway integration](/integrations/resource-integrations/agentic-gateway). To scope a rollout for your organization, [contact P0](https://www.p0.dev/).


# Service-Account Key Rotation

Manage rotation of static service account credentials for third-party systems. P0 discovers owners, creates fresh credentials, and coordinates updates.

For most production cases, P0 recommends configuring service-account authentication using [workload identity federation](https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-63c.pdf). However, certain third-party systems (such as business intelligence tools) may require access to your production cloud, and only support access via static credentials. For these identities, P0 will manage rotation of these credentials, avoiding use of stale credentials.

### How it works

1. You set a credential rotation policy within P0. For example, you may require that credentials are rotated every 30 days, and no credentials are ever more than 40 days old.
2. P0 uses your [Access Inventory](/readme/access-inventory) to automatically detect credentials that have upcoming rotation due dates.
3. P0 determines account owners within your organization based on associated resources. For example, P0 might use the technical contact configured in the credential's managing cloud account.
4. P0 stages updated credentials for each account that needs rotation within a vault you connect. For example, AWS KMS, GCP GSM, or HashiCorp Vault.
5. P0 assigns tickets in your tracking system for owners to update credentials in third-party systems.
6. When each rotation ticket is closed, P0 revokes the previous credential.

<figure><img src="/files/FXbdyR31dvkLdnmSpoNd" alt="Credential rotation dashboard showing assignees with overdue and upcoming rotation tickets, with options to view details or send reminders" width="563"><figcaption></figcaption></figure>

### Related documentation

* [Access inventory](/readme/access-inventory): P0 uses your inventory data to detect credentials approaching rotation deadlines
* [Tracker integrations](/integrations/tracker-integrations): Connect your ticketing system for automated rotation ticket assignment
* [Resource integrations](/integrations/resource-integrations): Connect the cloud environments whose credentials you want to rotate

### Getting started with service-account key rotation

Key rotation requires an enterprise P0 license. Contact [P0 sales](mailto:sales@p0.dev) to get started.


# P0 Onboarding

Deploy P0 Security, integrate your cloud environments, and establish just-in-time access for human and non-human identities. For security and DevOps teams.

Welcome to **P0 Security**.

This guide provides a structured pathway for deploying P0, integrating your cloud environments, and establishing secure, just-in-time (JIT) access for both human and non-human identities. It is designed for Security Engineers, DevOps practitioners, and engineering leaders seeking a precise and unified approach to modern access governance.

## Table of Contents

1. [Prerequisites](#prerequisites)
2. [Account Setup](#account-setup)
3. [Core Capabilities](#core-capabilities)
   * [Getting Started with Inventory & Posture](#️-getting-started-with-inventory--posture)
   * [Getting Started with Just-in-Time Access](#️-getting-started-with-just-in-time-access)
4. [Next Steps and Resources](#next-steps-and-resources)

## Prerequisites

Before onboarding, confirm the following:

* A corporate email address for registration.
* Permissions to establish cloud integrations (AWS, GCP, Azure, etc.).
* The ability to assign or manage custom IAM roles within your provider.
* *(Optional)* Slack workspace access if leveraging Slack-based requests.
* *(Optional)* Microsoft Teams access if leveraging Teams-based requests.

## Account Setup

1. **Choose an Identity Provider**
   * Select the authentication method for your organization.
   * See [Supported Identity Providers](/getting-started/p0-security-onboarding/supported-identity-providers) for available options.
   * For Okta sign-in, contact P0 Security before proceeding.
2. **Create Your P0 Account**
   * Register with your organizational email at <https://p0.app/create-account>.
   * Sign in using your chosen identity provider.
3. **Initial Organization Configuration**
   * Complete the onboarding wizard.
   * Define your organization name.
   * Invite foundational team members.

## Core Capabilities

P0 offers two primary capabilities: gaining visibility into your cloud environments and managing just-in-time access. You can set them up in any order.

### ⬇️ Getting Started with Inventory & Posture

To begin discovering, analyzing, and securing your cloud identity and access posture, you will need to connect your cloud environments to P0. This involves creating an integration and running an initial scan to populate your inventory.

For a complete walkthrough, see the detailed guides:

* [**Getting Started with Access Inventory**](/getting-started/getting-started-with-access-inventory)
* [**Getting Started with Posture**](/getting-started/getting-started-with-posture)

### ⬇️ Getting Started with Just-in-Time Access

To enable secure, temporary access to your cloud resources, you will need to configure integrations, set up approval workflows, and make your first request. This process includes installing P0 on specific IAM resources and assigning security reviewers.

For a step-by-step tutorial, refer to the detailed guide:

* [**Getting Started with Just-in-Time Access Guide**](/getting-started/getting-started-with-just-in-time-access)

## Next Steps and Resources

You are now positioned to:

* Extend integrations (IAM, databases, developer tools).
* Connect P0 to your corporate directory.
* Automate workflows and advanced routing.
* Enable continuous risk analysis and remediation.

## Support

📧 <support@p0.dev>

## Recommended Reading

* [Creating an Environment](/environments/creating-an-environment)
* [Access Inventory & Posture Guides](/inventory/access-inventory)

**P0 Security:** Delivering secure cloud access at engineering velocity.\
Welcome to unified access governance.


# Supported Identity Providers

P0 Security supports many identity providers for authenticating to the P0 web app and CLI. Select the identity provider that matches your organization's authentication strategy.

## Available identity providers

| Identity Provider      | Setup Required | Description                                                   |
| ---------------------- | -------------- | ------------------------------------------------------------- |
| **Google**             | None           | Sign in with your Google Workspace or personal Google account |
| **Microsoft Entra ID** | None           | Sign in with your Microsoft work or school account            |
| **Okta**               | Yes            | Sign in with your organization's Okta instance                |
| **Email/Password**     | None           | Create a P0-specific account with email and password          |

## Google

Google authentication works automatically with any Google account.

**To sign in with Google:**

1. Navigate to <https://p0.app/create-account>.
2. Click **Google**.
3. Select your Google account and authorize P0.

## Microsoft Entra ID

Microsoft Entra ID authentication works automatically with any Microsoft work or school account.

**To sign in with Microsoft Entra ID:**

1. Navigate to <https://p0.app/create-account>.
2. Click **Entra ID**.
3. Enter your Microsoft credentials and authorize P0.

## Okta

Okta authentication requires your organization's Okta administrator to configure an OIDC application for P0.

{% hint style="info" %}
Contact P0 Security to get started with Okta sign-in. Our team will guide you through the setup process.
{% endhint %}

Once configured, your users can sign in using their Okta credentials on both the P0 web app and CLI.

**To set up Okta sign-in:**

See [Okta sign-in setup](/getting-started/p0-security-onboarding/supported-identity-providers/okta-sign-in-setup) for detailed configuration instructions.

## Email/Password

Create a standalone P0 account using any email address.

**To create an account with email and password:**

1. Navigate to <https://p0.app/create-account>.
2. Click **Sign up with email**.
3. Enter your email address and create a password.
4. Verify your email address via the confirmation link.

{% hint style="warning" %}
Email/password accounts don't integrate with your corporate identity provider. Consider using Google, Microsoft, or Okta authentication for centralized identity management.
{% endhint %}

## Choosing an identity provider

When selecting an identity provider, consider:

* **Centralized identity management**: Google, Microsoft, and Okta integrate with your existing directory, enabling automatic user provisioning and deprovisioning.
* **Security policies**: Corporate identity providers enforce your organization's security policies, including multi-factor authentication and conditional access.
* **User experience**: Users can sign in with credentials they already know.

{% hint style="info" %}
This page describes how users authenticate **to P0 Security**. For integrating your identity provider's directory with P0 for access management and inventory, see [Directory Integrations](/integrations/directory-integrations).
{% endhint %}


# Okta Sign-In Setup

This guide describes how to configure Okta as an identity provider for signing in to P0 Security. After completing this setup, your users can authenticate to the P0 web app at <https://p0.app> and the P0 CLI using their Okta credentials.

{% hint style="info" %}
This guide covers **signing in to P0 with Okta**. This is different from the [Okta Directory Integration](/integrations/directory-integrations/okta), which enables P0 to manage access and inventory within your Okta instance.
{% endhint %}

**Approximate setup time:** 15 minutes

## Prerequisites

* An existing P0 Security account
* Administrative access to your Okta instance with one of the following roles:
  * Super Administrator
  * Application Administrator

## Overview

Setting up Okta sign-in for P0 involves:

1. [Contact P0 Security](#step-1-contact-p0-security)
2. [Create an application integration in Okta](#step-2-create-an-application-integration)
3. [Configure OIDC parameters](#step-3-configure-oidc-parameters)
4. [Verify client credentials](#step-4-verify-client-credentials)
5. [Share configuration with P0](#step-5-share-configuration-with-p0)

## Step 1: Contact P0 Security

Before configuring Okta, contact P0 Security to start the setup process:

* **Email:** <support@p0.dev>

P0 confirms your organization is ready for Okta sign-in configuration.

## Step 2: Create an application integration

1. Log in to the Okta Admin Portal.

{% hint style="info" %}
The admin URL is your subdomain plus `-admin` (for example, `companyname-admin.okta.com`). If you have customized your domain, access the admin console using your un-customized domain.
{% endhint %}

2. Select **Applications** > **Applications** from the menu.
3. Click **Create App Integration**.

   <figure><img src="/files/ykenTr2aA4Hd2dvnPXa6" alt="Okta Admin Applications page with the Create App Integration button highlighted" width="375"><figcaption></figcaption></figure>
4. In the "Create a new app integration" modal:

   * Select **OIDC - OpenID Connect** as the Sign-in method.
   * Select **Native Application** as the Application type.

   <figure><img src="/files/BYgWuhFJ3ZW8HQxqmBAk" alt="Okta Create a new app integration modal with OIDC - OpenID Connect and Native Application selected" width="375"><figcaption></figcaption></figure>
5. Click **Next**.

## Step 3: Configure OIDC parameters

On the "New Native App Integration" page, configure the following settings:

1. **App integration name:** Enter `P0 Security`.
2. **Logo** *(optional)*: Upload the P0 logo if desired.

<div align="left"><figure><img src="/files/9TYMcM4j9d9HbwDjqgx7" alt="P0 Security application logo" width="150"><figcaption></figcaption></figure></div>

3. **Grant type:** Enable the following grant types:
   * Authorization Code
   * Device Authorization
   * Token Exchange

<figure><img src="/files/vnHNKXrVojHgIqM9WwJ3" alt="Okta New Native App Integration settings showing grant type options with Authorization Code, Device Authorization, and Token Exchange enabled" width="375"><figcaption></figcaption></figure>

4. **Sign-in redirect URIs:** Add the following URI:

   ```
   https://p0.app/oidc/auth/_redirect
   ```
5. **Assignments:** Configure access for your organization:
   * To enable P0 for everyone, select **Allow everyone in your organization to access**.
   * To restrict access to specific groups, select **Limit access to selected groups** and choose the appropriate Okta groups.

     <figure><img src="/files/ErdFA4Mglaoj7UKIhVxQ" alt="Okta app integration settings showing sign-in redirect URIs, sign-out redirect URIs, and Assignments section" width="375"><figcaption></figcaption></figure>
6. Click **Save**.

## Step 4: Verify client credentials

After creating the application, verify the client credentials settings:

1. Navigate to the **General** tab of your new P0 Security application.
2. In the **Client Credentials** section, confirm:
   * **Client authentication** is set to **None**
   * **Proof Key for Code Exchange (PKCE)** is enabled

<figure><img src="/files/BAGJrHWmbdLtWqHveawK" alt="Okta P0 Security app General tab showing Client Credentials with Client authentication set to None and PKCE enabled" width="333"><figcaption></figcaption></figure>

## Step 5: Share configuration with P0

Share the following information with P0 Security to complete the setup:

1. **Okta organization URL:** Your Okta domain (for example, `mycompany.okta.com`)
2. **Client ID:** Found in the **Client Credentials** section of the **General** tab

{% hint style="info" %}
These values aren't secrets and are safe to share over email or Slack.
{% endhint %}

Send these values to <support@p0.dev> or your P0 account executive. P0 configures your organization and confirms when Okta sign-in is ready.

## Signing in with Okta

Once P0 confirms the configuration is complete, users can sign in:

**Web app:**

1. Navigate to <https://p0.app>.
2. Click **Sign in with Okta**.
3. Authenticate with your Okta credentials.

**CLI:**

1. Run `p0 login`.
2. Complete authentication in the browser window that opens. The CLI automatically uses Okta once your organization is configured.

{% hint style="success" %}
Your organization is now configured to sign in to P0 Security using Okta.
{% endhint %}

## Related topics

* [Supported identity providers](/getting-started/p0-security-onboarding/supported-identity-providers)
* [Okta Directory Integration](/integrations/directory-integrations/okta): For managing access and inventory within Okta
* [Installing P0 CLI](/p0-cli/installing-p0-cli)


# Request Access Quickstart

Request your first just-in-time access to a cloud resource through Slack, Microsoft Teams, the P0 web app, or the CLI. A quickstart for developers and engineers.

This quickstart walks you through requesting your first just-in-time access to a cloud resource. By the end, you will have submitted an access request using Slack, Microsoft Teams, the P0 web app, or the P0 CLI.

{% hint style="info" %}
This guide is for developers and engineers who need to request access to resources. If you are an administrator setting up P0, start with the [Getting started with just-in-time access](/getting-started/getting-started-with-just-in-time-access) guide instead.
{% endhint %}

## Before you start

Confirm the following:

* Your organization has a P0 account and at least one [resource integration](/integrations/resource-integrations) installed
* You can sign in to [p0.app](https://p0.app) with your organizational email
* *(For Slack requests)* The P0 Slack bot is installed in your workspace
* *(For Microsoft Teams requests)* The [P0 Microsoft Teams integration](/integrations/notifier-integrations/microsoft-teams) is installed in your organization

## Step 1: Choose your request method

P0 supports four ways to request access. Select the one that fits your workflow:

| Method              | Best for                                                      | What you need                                                                                   |
| ------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| **Slack**           | Quick requests without leaving your chat workflow             | P0 Slack bot in your workspace                                                                  |
| **Microsoft Teams** | Quick requests without leaving your chat workflow             | [P0 Microsoft Teams integration](/integrations/notifier-integrations/microsoft-teams) installed |
| **Web app**         | Browsing available resources before requesting                | Access to [p0.app](https://p0.app)                                                              |
| **CLI**             | Scripted workflows or requesting and using access in one step | [P0 CLI installed](/p0-cli/installing-p0-cli)                                                   |

## Step 2: Request access

{% tabs %}
{% tab title="Slack" %}

1. Open Slack and navigate to any channel.
2. Type `/p0 request` and press Enter. The P0 request modal opens.
3. Select the **resource type** (such as AWS, Google Cloud, or Kubernetes).
4. Select the specific **resource** and **access level** you need.
5. Enter a **reason** for your request. This helps approvers understand the context.
6. Select a **duration** for how long you need access.
7. Click **Request**.

P0 sends you a direct message with your request details and routes the request to the appropriate approver.

{% hint style="info" %}
If you know exactly what you need, skip the modal with a slash command:

```
/p0 request gcloud role my-project viewer --reason "Investigating production issue"
```

See [requesting access via Slack](/access-management/just-in-time-access/requesting-access#using-slack-slash-commands) for the full command syntax.
{% endhint %}
{% endtab %}

{% tab title="Microsoft Teams" %}

1. Open Microsoft Teams and navigate to any channel or chat.
2. Type `@P0 Security request` and send the message. The P0 request card opens.
3. Select the **resource type** (such as AWS, Google Cloud, or Kubernetes).
4. Select the specific **resource** and **access level** you need.
5. Enter a **reason** for your request. This helps approvers understand the context.
6. Select a **duration** for how long you need access.
7. Click **Request**.

P0 sends you a message with your request details and routes the request to the appropriate approver.

{% hint style="info" %}
Your P0 administrator must install the [Microsoft Teams integration](/integrations/notifier-integrations/microsoft-teams) before you can use this method.
{% endhint %}
{% endtab %}

{% tab title="Web app" %}

1. Sign in to [p0.app](https://p0.app).
2. Navigate to **Access Management** in the left sidebar.
3. Click the **Request Access** button in the top right corner.
4. Select the **resource type**, **resource**, and **access level** you need.
5. Enter a **reason** and select a **duration**.
6. Click **Request**.

Your request appears in the **Pending** section of the Access Management Activity page.

See [web request modal](/access-management/just-in-time-access/requesting-access/web-request-modal) for more details.
{% endtab %}

{% tab title="CLI" %}

1. Install the P0 CLI if you haven't already. See [installing the P0 CLI](/p0-cli/installing-p0-cli).
2. Authenticate, replacing `<your-org>` with your P0 organization ID:

   ```bash
   p0 login <your-org>
   ```
3. Request access. For example, to request an AWS IAM role:

   ```bash
   p0 request aws role MyReadOnlyRole \
     --account 123456789012 \
     --reason "Investigating S3 access issues"
   ```
4. To request access and wait until it's provisioned before running a command, add the `--wait` flag:

   ```bash
   p0 request aws role MyReadOnlyRole \
     --account 123456789012 \
     --reason "Investigating S3 access issues" \
     --wait
   ```

See [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request) for the full command reference and all supported providers.
{% endtab %}
{% endtabs %}

## Step 3: Get approved and use your access

After you submit your request:

1. **Wait for approval.** P0 routes your request to the appropriate approver based on your organization's [access policies](/access-management/just-in-time-access/request-routing). You receive a notification when access is approved or denied.
2. **Use your access.** Once approved, P0 provisions access automatically. Depending on the resource, expect a short propagation delay (10 seconds to one minute).
3. **Access expires automatically.** When the approved duration ends, P0 revokes access. You can also click **Relinquish** in your P0 Slack or Microsoft Teams message to give up access early.

{% hint style="warning" %}
Most IAM systems have a propagation delay of 10 to 30 seconds after access is provisioned before you can use it.
{% endhint %}

## Troubleshooting

| Problem                                             | Solution                                                                                                                                                                                                                   |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/p0 request` does not respond in Slack             | Confirm that the P0 Slack bot is installed. Ask your P0 administrator to check the [Slack integration](/integrations/notifier-integrations/slack).                                                                         |
| P0 Security bot does not respond in Microsoft Teams | Confirm that the P0 Microsoft Teams integration is installed and the app is available to users. Ask your P0 administrator to check the [Microsoft Teams integration](/integrations/notifier-integrations/microsoft-teams). |
| "This resource doesn't exist" error                 | Your organization's access policy may not cover this resource. Contact your P0 administrator. See [access policies](/access-management/just-in-time-access/request-routing).                                               |
| CLI returns an authentication error                 | Run `p0 login` to re-authenticate. See [p0 login troubleshooting](/p0-cli/troubleshooting/p0-login).                                                                                                                       |
| Access approved but not working                     | Wait 30 seconds for IAM propagation. If access still does not work, check the [requesting access](/access-management/just-in-time-access/requesting-access) guide for resource-specific details.                           |

## What's next

* [Request access on behalf of another user](/access-management/just-in-time-access/requesting-access/for-another-party)
* [Use the P0 CLI for AWS role assumption](/p0-cli/p0-commands-and-usage/p0-aws-role-assume)
* [Use the P0 CLI for SSH access](/p0-cli/p0-commands-and-usage/p0-ssh)
* [Browse the full requesting access guide](/access-management/just-in-time-access/requesting-access)


# Getting Started with Just-in-Time Access

Install P0 Security, configure approval workflows, and make your first just-in-time access request. A step-by-step guide for security and DevOps teams.

## Visual overview

The following diagram illustrates an example Just-in-Time Access workflow at a high level.

<figure><img src="/files/mzJ7umR8GlSddWzNV5Qk" alt="JIT access workflow diagram showing P0 CLI and P0 Service connecting to Okta AWS Account Federation App and AWS IAM to grant access to resources like S3, EKS, RDS, EC2, and KMS"><figcaption></figcaption></figure>

## Steps to get started

This guide provides the following sections to help you get up and running with P0's [Just-in-time access](/access-management/just-in-time-access):

1. [Set up an account and a security reviewer](#set-up-an-account-and-a-security-reviewer)
2. [Install P0 on an IAM resource](#install-p0-on-an-iam-resource)
3. [Make your first access request](#make-your-first-access-request)

{% hint style="info" %}
This process takes about 15 minutes.
{% endhint %}

{% hint style="info" %}
This document uses the following terms:

* **Requestor:** Person who requests access to a resource via P0's Slack bot.
* **Approver:** Person who approves these access requests via P0's Slack bot.
  {% endhint %}

## Set up an account and a security reviewer

To create your P0 account and set up an approver to approve access requests:

1. Create a free P0 account at[ https://p0.app/create-account](https://p0.app/create-account). All you need is an email address.
2. Set up a cloud integration through the guided onboarding flow (select **Access Orchestration**). You may skip this step and instead follow the instructions to install a resource [in the next step.](#install-p0-on-an-iam-resource)
3. Once you complete the onboarding, under **P0 Management**, add one or more "Security Reviewers". Security Reviewers can approve access requests.

<figure><img src="/files/5WKRruuzLbFVrtheq0sA" alt="P0 Management Access control panel with Security Reviewers section highlighted, showing fields for adding reviewer email addresses"><figcaption></figcaption></figure>

{% hint style="info" %}
To further configure access request requestors, approvers, or change settings such as the ability to approve your own access requests, navigate to **Policy Studio** (or go to `https://p0.app/o/<your organization>/policies`). You can edit the existing default rule or create new rules.
{% endhint %}

## Install P0 on an IAM resource

If you already configured a resource as part of the guided onboarding, you may skip this step. Otherwise, you will need to install an IAM resource to which users can request Just-in-time access.

To do this, navigate to **Integrations** and select the integration you wish to install from the list of "Resource" integrations.

<figure><img src="/files/fuHXaw3vcMnGRfGQQwnP" alt="P0 Integrations page with the Resources section highlighted, listing AWS, Azure, Google Cloud, GitHub, Custom, Kubernetes, Snowflake, PostgreSQL, and SSH"><figcaption></figcaption></figure>

Once you have selected a resource, follow the instructions in the app to provide P0 with permissions to grant and revoke access on that resource via the **IAM Management** installation. For more information, follow one of the resource-specific installation guides below.

{% content-ref url="/pages/oOcOnLUMfBQoti6jD1po" %}
[Google Cloud](/integrations/resource-integrations/google-cloud)
{% endcontent-ref %}

{% content-ref url="/pages/baaaYyZ5nS00f0uGiG18" %}
[AWS](/integrations/resource-integrations/aws)
{% endcontent-ref %}

{% content-ref url="/pages/L3Cnca6oWCOCnTjRmkKb" %}
[Snowflake](/integrations/resource-integrations/snowflake)
{% endcontent-ref %}

{% content-ref url="/pages/PmNajuau9q2r5PTTC5b3" %}
[Kubernetes](/integrations/resource-integrations/kubernetes)
{% endcontent-ref %}

{% content-ref url="<https://github.com/p0-security/p0-docs/blob/main/integrations/resource-integrations/postgresql/README.md>" %}
<https://github.com/p0-security/p0-docs/blob/main/integrations/resource-integrations/postgresql/README.md>
{% endcontent-ref %}

## Make your first access request

Once you've set up P0, you can make your first access request. You can try this out entirely on your own, if you enabled one-party approvals in [Set up an account and a security reviewer](#set-up-an-account-and-a-security-reviewer). Otherwise, grab a colleague to help you, and designate one person as the requestor and the other as the approver:

{% hint style="info" %}

* You can use the [P0 Security Command-line Interface](https://www.npmjs.com/package/@p0security/cli) (CLI) as an alternate method to request permissions, and then approve using the P0 website app.
* P0 is in the process of adding additional IAM request methods, including a Microsoft Teams bot.
  {% endhint %}

{% tabs %}
{% tab title="Via the p0.app" %}

1. Navigate to any page under Access Management `https://p0.app/o/<your organization>/access-management/activity` and click the Request Access button in the top right.

<figure><img src="/files/KQZIsDbH6r70LQPdQ5Ou" alt="Access Management Activity page showing Active and Pending sections with the Request Access button in the top right"><figcaption></figcaption></figure>

2. Populate the request details. For example:

<figure><img src="/files/SBcobOoTFmtyVTgCkjTj" alt="Request Access dialog with fields for Resource, Access Type, Account, Resource ARN, Policies, Reason, and duration filled in for an AWS S3 request" width="375"><figcaption></figcaption></figure>

3. The approver can see the request on the Access Management Activity page in the Pending section.

   <figure><img src="/files/OG01KaKEvTlS1n8ciShp" alt="Access Management Activity page showing a pending request for AmazonS3ReadOnlyAccess with Approve and Deny buttons"><figcaption></figcaption></figure>

   After a few moments, the access requestor receives a notification in the **p0-requests** channel that access was granted.

{% hint style="warning" %}
Most IAM systems have a delay of around 10 to 30 seconds after access is configured before access propagates to the resource and usage is enabled.
{% endhint %}

4. Once the access propagates to the resource, the request progresses to the Active section.

<figure><img src="/files/gsiAJEtdHmhJTGoZLyoz" alt="Access Management Activity page showing an active granted request for AmazonS3ReadOnlyAccess with expiration time and Revoke button"><figcaption></figcaption></figure>

{% hint style="info" %}
Access automatically ends after the expiration period is over, or when the requestor clicks the **Relinquish** button in their P0 DM.
{% endhint %}
{% endtab %}

{% tab title="Via Slack" %}

1. Have the requestor open Slack, navigate to the **p0-requests** channel, and enter `/p0 request` in the Slack channel:

<figure><img src="/files/XtpKX2s78kuSbbc9WlhE" alt="Slack sidebar with the p0-requests channel highlighted for entering access request commands" width="376"><figcaption></figcaption></figure>

2. Populate the request details. For example:

   <figure><img src="/files/NhHbetPl3twqgkS6D8R5" alt="Slack P0 request dialog with Google Cloud resource, Role access type, storage.objectViewer role selected, and a reason for access" width="375"><figcaption></figcaption></figure>
3. The approver receives a Slack notification via a DM from **P0 Security**. Navigate to that DM chat, choose an expiration, and click **Approve**.

   <figure><img src="/files/A3eajWgPoWRMT3QRRPuv" alt="Slack approval DM from P0 Security with expiry dropdown showing options from 5 minutes to 30 days, and Approve and Deny buttons" width="563"><figcaption></figcaption></figure>

   After a few moments, the access requestor receives a notification in the **p0-requests** channel that access was granted.

{% hint style="warning" %}
Most IAM systems have a delay of around 10 to 30 seconds after access is configured before access propagates to the resource and usage is enabled.
{% endhint %}

4. Once the access propagates to the resource, the requestor can validate the access.

{% hint style="info" %}
Access automatically ends after the expiration period is over, or when the requestor clicks the **Relinquish** button in their P0 DM.
{% endhint %}

<figure><img src="/files/UBv1bygiiaVVFR19k0uz" alt="Slack DM from P0 Security showing granted access notification with a Relinquish button to revoke access early" width="563"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

## What's next

If you run into any issues, reach out to <support@p0.dev> for assistance.

Now that you can make access requests, you can:

* Add [additional IAM integrations](/integrations/resource-integrations)
* Connect P0 to [your directory](/integrations/directory-integrations)
* Add [auto approvals](/integrations/approval-integrations)
* Start exploring P0's [Access Inventory](/getting-started/getting-started-with-access-inventory) and [Posture](/getting-started/getting-started-with-posture) capabilities
* [Configure access policies](/access-management/just-in-time-access/request-routing) to route, automatically approve, and automatically deny requests based on the requestor and resource


# Configure Your First Access Policy

Create an access policy in P0 Security's Policy Studio to control who can request access, what they can access, and who approves. A step-by-step tutorial for security administrators.

By default, P0 routes all access requests to your Security Reviewers. As your team grows, you need more control: route requests to the right approver, restrict access to sensitive resources, or allow automatic approvals for low-risk environments.

*Access policies* let you define these rules. In this tutorial, you create your first access policy that routes requests from your engineering team to a specific approver group.

## What you'll learn

After completing this tutorial, you are able to:

* Navigate to Policy Studio and edit your policy configuration
* Write a policy rule with requestor, resource, and approval sections
* Test your policy with a real access request
* Understand how P0 evaluates multiple policy rules

{% hint style="info" %}
This tutorial takes about 10 minutes.
{% endhint %}

## Before you start

Ensure you have the following:

* A P0 account with Owner permissions
* At least one [resource integration](/integrations/resource-integrations) installed (such as AWS, Google Cloud, or Kubernetes)
* A [Slack notifier](/integrations/notifier-integrations/slack) connected to receive approval notifications
* A [directory integration](/integrations/directory-integrations) installed (Google Workspace, Okta, or Microsoft Entra ID) with at least one group that contains your team members

{% hint style="info" %}
If you haven't set up P0 yet, complete the [Getting started with just-in-time access](/getting-started/getting-started-with-just-in-time-access) tutorial first.
{% endhint %}

## Step 1: Open Policy Studio

1. Sign in to [p0.app](https://p0.app).
2. Navigate to **Policy Studio** in the left sidebar, or go to `https://p0.app/o/<your-organization>/policies`.

You see a YAML editor where you can define your policy configuration. If this is your first time here, the editor may contain a default configuration or be empty.

{% hint style="info" %}
A *policy configuration* is a collection of one or more policy rules. You have one active policy configuration at any time, but it can contain as many individual rules as you need.
{% endhint %}

## Step 2: Understand the policy structure

Every policy rule has three parts:

| Part          | Purpose                            | Example              |
| ------------- | ---------------------------------- | -------------------- |
| **Requestor** | Who is making the request          | The engineering team |
| **Resource**  | What they are requesting access to | An AWS integration   |
| **Approval**  | Who can approve the request        | The SRE team         |

Here is a minimal policy rule:

```yaml
- requestor:
    type: group
    id: engineering@yourcompany.com
    label: Engineering
    directory: workspace
  resource:
    type: any
  approval:
    - type: group
      id: sre@yourcompany.com
      label: SRE Team
      directory: workspace
```

This rule means: when anyone in the **Engineering** group requests access to any resource, route the approval to the **SRE Team** group.

## Step 3: Create your first policy

Replace the content in Policy Studio with the following configuration, substituting your own values:

```yaml
- requestor:
    type: group
    id: <your-team-group-id>
    label: <Your Team Name>
    directory: workspace
  resource:
    type: any
  approval:
    - type: group
      id: <your-approver-group-id>
      label: <Approver Team Name>
      directory: workspace
      options:
        allowOneParty: false
```

Replace the placeholder values:

| Placeholder                | What to enter                                                                                                                                                                                                         |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<your-team-group-id>`     | The group identifier for the requestors. For Google Workspace, use the group email (such as `engineering@yourcompany.com`). For Okta, use the group ID from the Okta admin console. For Entra ID, use the group UUID. |
| `<Your Team Name>`         | A human-readable name for the requestor group (such as `Engineering`)                                                                                                                                                 |
| `<your-approver-group-id>` | The group identifier for the approvers, in the same format as above                                                                                                                                                   |
| `<Approver Team Name>`     | A human-readable name for the approver group (such as `SRE Team`)                                                                                                                                                     |

{% hint style="warning" %}
Set the `directory` value based on your identity provider: `workspace` for Google Workspace, `okta` for Okta, or `azure-ad` for Microsoft Entra ID.
{% endhint %}

The `allowOneParty: false` option prevents requestors from approving their own requests. Set this to `true` to allow self-approval.

Click **Save** to activate your policy configuration.

## Step 4: Test your policy

Verify that your policy works by submitting a test access request.

{% tabs %}
{% tab title="Via Slack" %}

1. Open Slack and navigate to the **p0-requests** channel.
2. Enter `/p0 request` and fill in the request details for a resource covered by your policy.
3. Confirm that the approval notification goes to a member of your approver group, not the default Security Reviewers.
   {% endtab %}

{% tab title="Via p0.app" %}

1. Navigate to **Access Management** and click the **Request Access** button.
2. Fill in the request details for a resource covered by your policy.
3. Confirm that the approval notification goes to a member of your approver group, not the default Security Reviewers.
   {% endtab %}
   {% endtabs %}

{% hint style="info" %}
If no policy rule matches a request, P0 blocks the request with the message: *"This resource doesn't exist, or your organization doesn't allow this principal to access this resource."* Ensure your policy configuration covers all requestors who need access.
{% endhint %}

## Step 5: Add a rule for a specific service

Now extend your configuration by adding a second rule that restricts a specific service to a dedicated approver. Add the following rule after your first one:

```yaml
- requestor:
    type: group
    id: <your-team-group-id>
    label: <Your Team Name>
    directory: workspace
  resource:
    type: integration
    service: aws
  approval:
    - type: group
      id: <aws-approver-group-id>
      label: <AWS Approver Team>
      directory: workspace
      options:
        allowOneParty: false
        requireReason: true
```

This rule routes AWS-specific requests to a dedicated approver group and requires the requestor to provide a reason. Your first rule still handles requests for all other services.

Click **Save** to activate the updated configuration.

{% hint style="info" %}
When multiple rules match a request, P0 combines the approvers. Approval from any one matched approver is sufficient to grant access. See [how P0 evaluates access policies](/access-management/just-in-time-access/request-routing#evaluation-of-access-policies) for the full evaluation logic.
{% endhint %}

## Summary

You created an access policy configuration in Policy Studio that:

* Routes your team's access requests to a specific approver group
* Adds a service-specific rule for AWS with a required reason
* Replaces the default Security Reviewer approval flow with targeted routing

## What's next

Now that you have a working policy, you can:

* [Deny access](/access-management/just-in-time-access/request-routing#deny) to sensitive resources by adding `type: deny` approval rules
* [Filter by resource attributes](/access-management/just-in-time-access/request-routing#integration) to restrict which specific roles, policies, or permission sets users can request
* [Set up auto-approval](/access-management/just-in-time-access/request-routing#auto) with PagerDuty or Incident.io for on-call engineers
* [Allow standing access](/access-management/just-in-time-access/request-routing#always-allowed) for low-risk resources with `type: persistent` rules
* Review the complete [access policies reference](/access-management/just-in-time-access/request-routing) for all configuration options


# Getting Started with Posture

Connect your cloud environment, run your first posture scan, and triage access risk findings with P0 Security's posture management product.

With [Posture](/readme/posture), P0 automatically scans your cloud environment for access risks, such as overprivileged accounts, unused privileged access, and risky lateral-movement paths. This guide walks you through your first scan and shows you how to review, triage, and remediate the findings P0 surfaces.

## Steps to get started

This guide provides the following sections to help you get up and running with Posture:

1. [Set up an account](#set-up-an-account)
2. [Connect your cloud and run your first scan](#connect-your-cloud-and-run-your-first-scan)
3. [Review your posture findings](#review-your-posture-findings)
4. [Investigate and triage a finding](#investigate-and-triage-a-finding)
5. [Create a custom monitor](#create-a-custom-monitor)

{% hint style="info" %}
Setup takes about 15 minutes. Your first scan then runs in the background and may take additional time to complete, depending on the size of your environment.
{% endhint %}

{% hint style="info" %}
This guide uses the following terms:

* **Monitor:** A rule that P0 evaluates against your access graph to detect a class of access risk. P0 provides built-in monitors, and you can define your own.
* **Finding:** A single issue that a monitor detects in your environment.
  {% endhint %}

## Set up an account

To create your P0 account:

1. Create a free P0 account at <https://p0.app/create-account>. All you need is an email address.
2. Set up a cloud integration through the guided onboarding flow (select **Privilege Governance**). You can skip this step and instead connect your cloud in the [next step](#connect-your-cloud-and-run-your-first-scan).

## Connect your cloud and run your first scan

Posture findings come from a scan of your cloud environment. To connect a cloud provider, create an environment, and run your first scan, follow the steps in [Creating an Environment](/environments/creating-an-environment).

{% hint style="info" %}
If you already use P0 for just-in-time access, you still need to complete this step. Data collection for Posture requires different permissions in your cloud provider than access orchestration does.
{% endhint %}

When the scan completes, P0 evaluates its built-in monitors against your access graph and populates your findings. Select **Dashboard** to confirm that your first scan has finished.

{% hint style="info" %}
A single environment and scan power both products. The same data also feeds [Access Inventory](/inventory/access-inventory), a queryable view of every identity, entitlement, and resource P0 collected. To explore it, see [Getting started with Access Inventory](/getting-started/getting-started-with-access-inventory).
{% endhint %}

## Review your posture findings

Select **Posture** in the P0 app sidebar to see the results of each monitor.

<figure><img src="/files/En5gA1PKFJUuR8KQeqoO" alt="Posture overview page showing findings summary with urgent, new, and average age metrics, filter controls, and a list of monitors with severity and count"><figcaption><p>The Posture overview lists each monitor with its severity and finding count.</p></figcaption></figure>

By default, this page shows all open findings, ranked by severity. To narrow the list:

* Select the filter icon to reveal the filter controls.
* Use the **Status** dropdown to filter by finding status: `Open`, `Ignored`, or `Resolved`.
* Enable the **Unassigned** checkbox to show only findings that aren't assigned.
* Narrow results to a specific target scope, such as an AWS account, Azure subscription, or GCP project.

To work through a single monitor, select it to open its [Monitor Results](/posture/monitor-results) page. This page shows the monitor's description, its history of new and resolved findings, and the full list of findings.

{% hint style="info" %}
Start with your highest-severity monitors. P0 resolves findings automatically once they no longer appear in a later scan, so focus your first session on the issues that matter most.
{% endhint %}

## Investigate and triage a finding

Select **view** next to a finding to open its [details](/posture/finding-details). From here, you can understand the risk and decide how to act on it.

<figure><img src="/files/2zdfyiAEzfqElwIxNG8P" alt="Finding details page showing attack path visualization, actions for Assign, Ignore, and Review fix, and risk details for an AWS IAM policy" width="563"><figcaption><p>A finding's details page shows its attack path and the actions you can take.</p></figcaption></figure>

For each finding, you can:

* **Review the attack path.** P0 shows how an actor holding the identity can gain risky access to your system.
* **Review fix.** For P0-provided monitors, P0 generates cloud shell commands that resolve the finding, such as replacing an overly permissive policy with a least-privilege one.
* **Assign.** If you've connected P0 to [Jira](/integrations/tracker-integrations/jira), assign the finding for resolution. P0 creates a ticket containing the finding description, its context, and any resolution commands.
* **Ignore.** Document an acceptable risk. The finding no longer appears in your results unless you filter by `Ignored` status.
* **Add notes.** Record a business justification or other context directly on the finding.

{% hint style="info" %}
You can assign, ignore, or review fixes for several findings at once from a monitor's results page using bulk actions.
{% endhint %}

## Create a custom monitor

Beyond P0's built-in monitors, you can define custom monitors to enforce your organization's own access policies. A custom monitor starts from a query in the [Access Inventory](/inventory/access-inventory):

1. In the Inventory, select a **show** option and enter a **where** query.
2. When the results match what you expect, select **Save Search**.
3. Enable the **Create a monitor for this search?** toggle, then add a title, description, and severity.

P0 evaluates your custom monitor on every scan, and its results appear alongside the built-in monitors in [Monitor Results](/posture/monitor-results). For full details, see [Creating custom monitors](/inventory/access-inventory#creating-custom-monitors).

## What's next

If you run into any issues, contact <support@p0.dev> for help.

Now that you can review and triage posture findings, you can:

* Run [custom queries to explore your environment](/inventory/query-search)
* Connect P0 to a [ticketing system](/integrations/tracker-integrations) to assign findings automatically
* Connect P0 to [your directory](/integrations/directory-integrations) to enrich identity data
* Add more cloud accounts and resources by [creating additional environments](/environments/creating-an-environment)
* Start using [P0's just-in-time access](/getting-started/getting-started-with-just-in-time-access)


# Getting Started with Access Inventory

Connect your cloud environment, navigate the Access Inventory page, run your first query, investigate access risks, and save a monitor with P0 Security.

[Access Inventory](/readme/access-inventory) gives you a single, queryable view of your entire IAM configuration. P0 combines data from your identity provider, your IAM policies, and your access logs into one access graph, then scores every privilege against P0's open-source [IAM Privilege Catalog](https://catalog.p0.dev).

This guide walks you through your first session with Access Inventory:

1. [Connect a resource and run your first scan](#step-1-connect-a-resource-and-run-your-first-scan)
2. [Open the Inventory page and confirm your data](#step-2-open-the-inventory-page-and-confirm-your-data)
3. [Run your first query](#step-3-run-your-first-query)
4. [Investigate a result](#step-4-investigate-a-result)
5. [Save a search as a monitor](#step-5-save-a-search-as-a-monitor)

{% hint style="info" %}
Initial setup takes about 15 minutes. IAM assessment is currently available for AWS, Google Cloud, Kubernetes, Okta, and Google Workspace.
{% endhint %}

## Who this guide is for

This guide is for administrators and security engineers who are setting up P0 for the first time and want to explore their cloud access. You need an understanding of cloud IAM concepts (identities, roles, and policies) and administrative access to at least one cloud provider.

## Prerequisites

Before you start, make sure you have:

* A P0 account. Create a free account at [p0.app/create-account](https://p0.app/create-account).
* Administrative access to a supported cloud provider (AWS, Google Cloud, Kubernetes, Okta, or Google Workspace).
* Permission to create an environment in your P0 organization.

## Step 1: Connect a resource and run your first scan

Access Inventory builds its graph from the resources you connect. To collect your first set of data, create an environment and run an inventory scan.

1. Sign in to [p0.app](https://p0.app).
2. Follow the steps in [Creating an Environment](/environments/creating-an-environment) to install P0 on a supported resource and start a scan.

P0 reads your IAM configuration and displays a collection progress indicator while it works. A single environment and scan power both products: the same data also feeds [Posture](/readme/posture), which flags access risks such as overprivileged accounts and risky lateral-movement paths. To review and triage those findings, see [Getting started with Posture](/getting-started/getting-started-with-posture).

{% hint style="info" %}
A scan can take several minutes to complete, depending on the size of your environment. You can continue to the next step once collection finishes.
{% endhint %}

## Step 2: Open the Inventory page and confirm your data

After your scan completes, confirm that P0 collected your data.

1. In the P0 dashboard, select the **Inventory** page.
2. Review the asset table. An empty search matches everything in your IAM configuration, so you see every collected item listed by default.
3. Use the **Show** dropdown to switch between **credentials**, **entitlements**, **identities**, and **resources**. Each option displays a different slice of your access graph.

If the table shows identities and resources from the provider you connected, your inventory is ready to query. If the table is empty, return to [Step 1](#step-1-connect-a-resource-and-run-your-first-scan) and confirm that your scan finished.

## Step 3: Run your first query

A query has two controls:

* **Show**: selects the kind of data to display (credentials, entitlements, identities, or resources).
* **Where**: a free-form search box that filters results to the term you enter.

Try a search to find access of interest:

1. Set **Show** to **identities**.
2. In the **Where** field, enter a term that appears in your data, such as a username, a resource name, or a permission. P0 returns the identities connected to that term.
3. To target a specific type of data, add a type prefix. For example, enter `risk:CRITICAL` to show only items that expose a critical IAM risk.

You can also refine a query without typing. Hover over any item in the results, then select **show** or **hide** to add that item to your query.

To learn the query language from scratch, see [Query Language Basics](/inventory/query-search/query-language-basics). For the full query syntax (including exact matches, attribute matches, and path expressions), see the [Search Reference](/inventory/query-search/search-reference).

## Step 4: Investigate a result

Each result links to a detailed view that explains why it matches your query.

1. In the results table, select **view** on any item to open its details. For more on what each field means, see [Result Details](/inventory/result-details).
2. Review the **Risks** section to see the access risks reachable from the item and the privileges that expose them.
3. Switch to the graph visualization to see the access paths that connect identities, entitlements, and resources. Select any node to view its properties.

The graph reveals lateral movement, the chains of access that let one identity reach a resource through federation, group membership, or cross-account roles.

## Step 5: Save a search as a monitor

When a query surfaces a risk you want to track over time, save it as a custom monitor. P0 re-runs the query on every scan and reports the results in [Monitor Results](/posture/monitor-results).

1. Build a query that returns the results you want to track, and confirm the displayed results match your expectations.
2. Select **Save Search**.
3. Enable the **Create a monitor for this search?** toggle.
4. Enter a title, description, and severity for the monitor, then save.

For more detail on building and managing inventory queries, see [Access Inventory](/inventory/access-inventory).

## What's next

You now know how to connect data, query your inventory, investigate access, and save a monitor. From here, you can:

* Connect P0 to [your directory](/integrations/directory-integrations) to enrich identity data.
* [Analyze your security findings](/posture/monitor-results) from built-in and custom monitors.
* Connect P0 to a [ticketing system](/integrations/tracker-integrations) to track remediation.
* [Get started with Just-in-Time Access](/getting-started/getting-started-with-just-in-time-access) to grant time-limited access to the resources you discovered.

If you run into any issues, contact <support@p0.dev>. We're here to help.


# Getting Started with the P0 CLI

Install the P0 CLI, authenticate, send your first permission request, and open your first SSH session with just-in-time access, all from the command line.

This tutorial walks you through the P0 command-line interface (CLI) from installation to your first permission request and SSH session. By the end, you have installed the CLI, authenticated with your organization, sent a Google Cloud role request, and connected to a machine over SSH with just-in-time access.

## Steps to get started

1. [Install the P0 CLI](#install-the-p0-cli)
2. [Authenticate with your organization](#authenticate-with-your-organization)
3. [Send your first permission request](#send-your-first-permission-request)
4. [Discover SSH targets](#discover-ssh-targets)
5. [Open your first SSH session](#open-your-first-ssh-session)
6. [Copy files with SCP](#copy-files-with-scp)

{% hint style="info" %}
This process takes about 10 minutes, assuming your organization has already configured an SSH integration.
{% endhint %}

## Prerequisites

Before you begin, confirm the following:

* **P0 account**: You have an account at [p0.app](https://p0.app) and belong to an organization.
* **SSH integration**: Your administrator has installed the SSH access control integration for at least one cloud provider (AWS, Google Cloud, or Azure). See the [SSH integration guide](/integrations/resource-integrations/ssh) for setup instructions.
* **Node.js v22+**: Required for npm installation. Check with `node --version`.

{% hint style="info" %}
If you prefer a standalone binary that bundles Node.js, see the platform-specific installation guides for [macOS](/p0-cli/installing-p0-cli/macos) and [Windows](/p0-cli/installing-p0-cli/windows).
{% endhint %}

**Provider-specific prerequisites:**

| Provider     | Required tools                                                                                                                                                                                                                        |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AWS          | [AWS CLI v2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) + [Session Manager plugin](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html) |
| Google Cloud | [gcloud CLI](https://cloud.google.com/sdk/docs/install) (the CLI runs `gcloud auth login` automatically when needed)                                                                                                                  |
| Azure        | [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) (authenticated with `az login`)                                                                                                                            |

## Install the P0 CLI

Install the CLI globally with npm:

```bash
npm install -g @p0security/cli
```

Verify the installation:

```bash
p0 --version
```

You should see the installed version number. Run `p0 help` to view all available commands.

{% hint style="info" %}
For alternative installation methods, including standalone macOS and Windows binaries, see [Installing p0 CLI](/p0-cli/installing-p0-cli).
{% endhint %}

## Authenticate with your organization

Log in to your P0 organization. Replace `<your-org>` with your organization ID (visible in your P0 URL at `p0.app/o/<your-org>`):

```bash
p0 login <your-org>
```

Your browser opens to your organization's SSO provider (Google, Okta, Microsoft, or another configured provider). After you authenticate, the CLI confirms:

```
You are now logged in to the <your-org> organization, and can use the p0 CLI.
```

{% hint style="info" %}
The CLI stores your session in `~/.p0/identity.json`. If your session expires, the CLI automatically re-launches the browser login flow the next time you run a command.
{% endhint %}

## Send your first permission request

The P0 CLI can request any permission that your organization supports: cloud IAM roles, resources, SSH access, and more. This section walks through requesting a Google Cloud IAM role as an example.

### Find available roles

List Google Cloud roles that contain "storage" in the name:

```bash
p0 ls gcloud role storage
```

The output displays matching roles available to you, such as `storage.objectViewer`, `storage.admin`, and others.

{% hint style="info" %}
Use the `--like` flag for multi-term searches. For example, `--like storage,admin` returns roles matching both "storage" and "admin".
{% endhint %}

### Request the role

Request the `storage.objectViewer` role on a Google Cloud project. Replace `<your-project>` with your Google Cloud project ID:

```bash
p0 request gcloud role storage.objectViewer \
  --project <your-project> \
  --reason "Review storage bucket contents" \
  --wait
```

The `--wait` flag blocks until the request is approved and access is provisioned. You see output similar to:

```
Will wait up to 5 minutes for this request to complete...
Your request was approved
Waiting for access to be provisioned
Access to role storage.objectViewer has been provisioned
```

Once provisioned, you can use `gcloud` commands under the granted role immediately.

{% hint style="info" %}
Without `--wait`, the CLI submits the request and returns immediately. You receive a notification (through Slack or your configured channel) when access is approved and provisioned.
{% endhint %}

{% hint style="warning" %}
Google Cloud IAM changes have a propagation delay of 30 seconds to one minute. If a `gcloud` command fails immediately after provisioning, wait briefly and retry.
{% endhint %}

### Other request types

The `p0 request` command supports providers beyond Google Cloud. Run `p0 request --help` to see all options:

| Provider     | Example                                                            |
| ------------ | ------------------------------------------------------------------ |
| AWS          | `p0 request aws role MyReadOnlyRole --account 123456789012`        |
| Google Cloud | `p0 request gcloud role storage.objectViewer --project my-project` |
| Okta         | `p0 request okta group engineering-team`                           |

For the full command reference, see [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request).

## Discover SSH targets

Before connecting, list the SSH destinations available to you:

```bash
p0 ls ssh session destination
```

This displays instances your organization has registered with P0. To filter by cloud provider, add the `--provider` flag:

{% tabs %}
{% tab title="AWS" %}

```bash
p0 ls ssh session destination --provider aws
```

{% endtab %}

{% tab title="Google Cloud" %}

```bash
p0 ls ssh session destination --provider gcloud
```

{% endtab %}

{% tab title="Azure" %}

```bash
p0 ls ssh session destination --provider azure
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Items marked with `*` indicate instances you already have active access to. Listing a destination does not grant access. You still need approval.
{% endhint %}

To see more results, use the `--size` flag:

```bash
p0 ls ssh session destination --size 50
```

## Open your first SSH session

Connect to an instance by name. Replace `<instance-name>` with a destination from the previous step:

{% tabs %}
{% tab title="AWS" %}

```bash
p0 ssh <instance-name> \
  --provider aws \
  --reason "Testing P0 CLI access"
```

{% endtab %}

{% tab title="Google Cloud" %}

```bash
p0 ssh <instance-name> \
  --provider gcloud \
  --reason "Testing P0 CLI access"
```

{% endtab %}

{% tab title="Azure" %}

```bash
p0 ssh <instance-name> \
  --provider azure \
  --reason "Testing P0 CLI access"
```

{% endtab %}
{% endtabs %}

The CLI performs these steps automatically:

1. Generates a temporary SSH key pair.
2. Submits a just-in-time access request to P0 (including your `--reason`).
3. Waits for approval (up to 5 minutes).
4. Provisions access on the cloud provider.
5. Establishes the SSH connection.

You see output similar to:

```
Will wait up to 5 minutes for this request to complete...
Your request was approved
Waiting for access to be provisioned
```

Once provisioning completes, you are connected to the instance.

{% hint style="warning" %}
Most cloud providers have a propagation delay of 10 to 30 seconds after access is approved before the connection succeeds. The CLI retries automatically during this window.
{% endhint %}

{% hint style="info" %}
Use the `--sudo` flag to request sudo access on the remote machine:

```bash
p0 ssh <instance-name> --provider aws --sudo --reason "Install security patch"
```

{% endhint %}

### Run a one-off command

To execute a single command without an interactive session, append it after the destination:

```bash
p0 ssh <instance-name> --provider gcloud -- "df -h /var"
```

### Forward a local port

Use SSH port forwarding to securely access remote services:

```bash
p0 ssh <instance-name> --provider aws -- -L 5432:localhost:5432
```

This forwards local port 5432 to the remote instance's port 5432, useful for connecting to databases.

## Copy files with SCP

The `p0 scp` command works like standard `scp` but includes automatic access requests. Prefix the remote path with the instance name and a colon:

**Download a file from the remote instance:**

```bash
p0 scp <instance-name>:/var/log/app.log ./app.log \
  --provider aws \
  --reason "Collect logs for debugging"
```

**Upload a file to the remote instance:**

```bash
p0 scp ./config.yaml <instance-name>:/tmp/config.yaml \
  --provider gcloud \
  --reason "Deploy updated configuration"
```

## Verify it worked

Confirm your request history by checking the **Access Management > History** page at `https://p0.app/o/<your-org>/access-management/history`. You should see your completed permission request and SSH access request with the reasons you provided.

## Troubleshooting

| Symptom                                                 | Cause                         | Fix                                                                                                                          |
| ------------------------------------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `The organization ID is required`                       | Missing org argument          | Run `p0 login <your-org>` with your org ID                                                                                   |
| `This organization is not configured for SSH access`    | No SSH integration installed  | Ask your admin to install the [SSH integration](/integrations/resource-integrations/ssh)                                     |
| `Could not find any instances matching...`              | Incorrect destination name    | Run `p0 ls ssh session destination` to list valid names                                                                      |
| `Your request was denied`                               | Approver denied the request   | Check your policies or contact your approver                                                                                 |
| Request times out after 5 minutes                       | No approver responded         | Verify your organization's [request routing policies](/access-management/just-in-time-access/request-routing) are configured |
| `Access did not propagate through <provider> in time`   | Cloud provider delay exceeded | Retry the command. Transient delays resolve on retry                                                                         |
| `Hint: The instance name appears to include a username` | Used `user@host` format       | Use the instance name only, without a username prefix                                                                        |

For detailed troubleshooting, see [p0 ssh troubleshooting](/p0-cli/troubleshooting/p0-ssh).

## What's next

Now that you can request permissions and SSH into machines from the command line, explore these capabilities:

* [Request access to AWS, Azure, Okta, and more](/p0-cli/p0-commands-and-usage/p0-request) with `p0 request`
* [Integrate P0 SSH with your native SSH config](/integrations/resource-integrations/ssh) to use `ssh <instance-name>` directly
* [Request access for a colleague](/access-management/just-in-time-access/requesting-access/for-another-party) with `p0 grant`
* [Create pre-approvals](/access-management/just-in-time-access/approving-access/pre-approving-access) for frequently accessed instances with `p0 allow`
* [Configure routing rules](/access-management/just-in-time-access/request-routing) to auto-approve access for on-call engineers
* Explore all [CLI commands and usage](/p0-cli/p0-commands-and-usage)


# Get Started with the P0 Terraform Provider

Configure the P0 Terraform provider, authenticate with an API token, and install your first integration as code with an end-to-end AWS just-in-time access example.

This guide shows you how to manage P0 integrations as code with the [P0 Terraform provider](https://registry.terraform.io/providers/p0-security/p0/latest/docs). You configure the provider, authenticate with a P0 API token, and install an AWS account for just-in-time (JIT) access from end to end. By the end, you have a working Terraform configuration that you can extend to any P0 integration.

Managing P0 with Terraform keeps your access infrastructure version-controlled, reviewable, and repeatable across environments—the same workflow your team already uses for the rest of your cloud.

## Steps to complete

1. [Generate a P0 API key](#generate-a-p0-api-key)
2. [Configure the P0 provider](#configure-the-p0-provider)
3. [Initialize Terraform](#initialize-terraform)
4. [Stage the AWS integration](#stage-the-aws-integration)
5. [Create the IAM role P0 uses](#create-the-iam-role-p0-uses)
6. [Finish the installation](#finalize-the-installation)
7. [Apply and verify](#apply-and-verify)

{% hint style="info" %}
This process takes about 15 minutes, assuming you already have an AWS account and permission to create IAM roles.
{% endhint %}

## Prerequisites

Before you begin, confirm the following:

* **P0 account** — You have an account at [p0.app](https://p0.app) and the **Owner** role in your organization. You need the Owner role to generate API keys.
* **Terraform 1.0 or later** — Install the [Terraform CLI](https://developer.hashicorp.com/terraform/install) and confirm the version with `terraform version`.
* **AWS account** — You have an AWS account and credentials with permission to create IAM roles, along with the [AWS Terraform provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) configured in your project.

## Generate a P0 API key

The provider authenticates to P0 with an API key, supplied as an API token.

1. Follow [Generating an API key](/p0-management/generating-an-api-key) to create a key in the P0 dashboard.
2. Copy the key when it appears. P0 shows the key only once.
3. Export the key as the `P0_API_TOKEN` environment variable so the provider can read it:

   ```bash
   export P0_API_TOKEN="your-api-key"
   ```

{% hint style="warning" %}
Never commit your API key to version control. Use an environment variable or a secrets manager, and rotate keys regularly.
{% endhint %}

## Configure the P0 provider

Declare the provider in a `.tf` file. The `source` is `p0-security/p0`, and the `org` attribute is your P0 organization identifier.

```hcl
terraform {
  required_providers {
    p0 = {
      source  = "p0-security/p0"
      version = "~> 0.40"
    }
  }
}

provider "p0" {
  org = "my-org"
}
```

The provider reads your API token from the `P0_API_TOKEN` environment variable set in the previous step. To pass the token explicitly instead, set the `api_token` attribute—but prefer the environment variable to keep secrets out of your configuration.

## Initialize Terraform

Download the provider and prepare your working directory:

```bash
terraform init
```

Terraform installs the P0 provider and reports `Terraform has been successfully initialized!`.

## Stage the AWS integration

P0 installs an AWS integration in two phases. First, you stage the account so P0 can generate the trust policy and inline policy for the IAM role it uses to manage access.

Add the `p0_aws_iam_write_staged` resource with your AWS account ID:

```hcl
resource "p0_aws_iam_write_staged" "prod" {
  id = "123456789012"
}
```

After you apply this resource, it exposes a `role` attribute that has the role name, trust policy, and inline policy that AWS requires in the next step.

## Create the IAM role P0 uses

Create the AWS IAM role from the staged outputs. P0 assumes this role to manage just-in-time access in your account.

```hcl
resource "aws_iam_role" "p0_iam_manager" {
  name               = p0_aws_iam_write_staged.prod.role.name
  assume_role_policy = p0_aws_iam_write_staged.prod.role.trust_policy

  inline_policy {
    name   = p0_aws_iam_write_staged.prod.role.inline_policy_name
    policy = p0_aws_iam_write_staged.prod.role.inline_policy
  }
}
```

## Complete the installation

Complete the installation with the `p0_aws_iam_write` resource. The `depends_on` argument ensures Terraform creates the IAM role before P0 verifies the installation.

```hcl
resource "p0_aws_iam_write" "prod" {
  id         = p0_aws_iam_write_staged.prod.id
  depends_on = [aws_iam_role.p0_iam_manager]

  login = {
    type = "iam"
    identity = {
      type = "email"
    }
  }
}
```

The `login` block tells P0 how users sign in to the account. This example uses IAM login with email-based identity matching, where each IAM user name is the user's email address. For Identity Center or federated login options, see the [`p0_aws_iam_write` resource reference](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/aws_iam_write).

## Apply and verify

Apply the full configuration:

```bash
terraform apply
```

Review the plan and confirm. Terraform stages the account, creates the IAM role, and finalizes the integration in dependency order.

To verify the installation succeeded, check the resource state:

```bash
terraform state show p0_aws_iam_write.prod
```

The `state` attribute reads `installed` when the integration is fully active:

```
state = "installed"
```

You can also open **Integrations** in the P0 dashboard and confirm the AWS account appears as installed. Users can now request just-in-time access to the account. See [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access) for the request workflow.

## Full example

The following configuration installs an AWS account for just-in-time access from end to end:

```hcl
terraform {
  required_providers {
    p0 = {
      source  = "p0-security/p0"
      version = "~> 0.40"
    }
  }
}

provider "p0" {
  org = "my-org"
}

# Step 1: Stage the account and generate the IAM policies P0 needs.
resource "p0_aws_iam_write_staged" "prod" {
  id = "123456789012"
}

# Step 2: Create the IAM role P0 assumes to manage access.
resource "aws_iam_role" "p0_iam_manager" {
  name               = p0_aws_iam_write_staged.prod.role.name
  assume_role_policy = p0_aws_iam_write_staged.prod.role.trust_policy

  inline_policy {
    name   = p0_aws_iam_write_staged.prod.role.inline_policy_name
    policy = p0_aws_iam_write_staged.prod.role.inline_policy
  }
}

# Step 3: Finalize the installation after the role exists.
resource "p0_aws_iam_write" "prod" {
  id         = p0_aws_iam_write_staged.prod.id
  depends_on = [aws_iam_role.p0_iam_manager]

  login = {
    type = "iam"
    identity = {
      type = "email"
    }
  }
}
```

{% hint style="success" %}
Once `p0_aws_iam_write.prod` reaches the `installed` state, your AWS account is managed entirely as code. Commit the configuration to version control and reuse it across accounts and environments.
{% endhint %}

## Troubleshooting

| Issue                                             | Cause                                             | Fix                                                                                                      |
| ------------------------------------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `terraform init` fails to find the provider       | The `source` is wrong                             | Confirm the source is `p0-security/p0` and run `terraform init` again.                                   |
| Authentication or `401` errors on apply           | The API token or `org` is wrong                   | Confirm `P0_API_TOKEN` is exported in your shell and that `org` matches your P0 organization identifier. |
| Apply fails creating the IAM role                 | The AWS provider lacks permission to create roles | Confirm your AWS credentials allow `iam:CreateRole` and `iam:PutRolePolicy`.                             |
| `p0_aws_iam_write` stays in the `configure` state | The IAM role was not created before finalizing    | Keep the `depends_on` argument so Terraform creates the role first, then run `terraform apply` again.    |

## Next steps

* **Install more integrations** — The provider supports AWS, Google Cloud, Azure, SSH, Kubernetes, databases, SIEM exports, and more. Browse the full [resource catalog](https://registry.terraform.io/providers/p0-security/p0/latest/docs) in the Terraform Registry.
* **Install Kubernetes access** — For EKS clusters, see [Terraform installation](/integrations/resource-integrations/kubernetes/terraform-installation).
* **Manage access policies as code** — Define request routing and approvals with the [`p0_routing_rule` resource](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/routing_rule). See [Configure access policies](/getting-started/configuring-access-policies) for the concepts.


# Automate access requests with the API

Request, approve, deny, and revoke just-in-time access programmatically with the P0 Command and Access Requests APIs. Drive access from bots, CI/CD pipelines, and internal tooling instead of the P0 da

This guide shows you how to drive P0 just-in-time access from your own code. You use the [Command API](/access-management/just-in-time-access/just-in-time-api/command-api) to create an access request, check its status, and then use the [Access Requests API](/access-management/just-in-time-access/just-in-time-api/access-requests-api) to approve, deny, or revoke it.

Automating these steps lets you wire P0 into bots, CI/CD pipelines, and internal security tooling — for example, requesting a short-lived role during a deployment, or auto-approving access when an alert fires. Every request still runs through your organization's access policies, guardrails, and audit trail, exactly as it does in the dashboard.

## Prerequisites

Before you begin, confirm the following:

* **A P0 organization** — You know your organization slug (`orgId`), shown in the P0 dashboard URL and in the CLI as your org name.
* **An API key** — You have generated a key and stored it securely. The key must belong to a user with the **Owner** role. See [Generating an API key](/p0-management/generating-an-api-key).
* **A configured resource integration** — At least one integration (AWS, Google Cloud, Azure, SSH, and so on) is installed, so there is something to request. See [Resource integrations](/integrations/resource-integrations).
* **A JSON tool** — The examples use [`curl`](https://curl.se/) and [`jq`](https://jqlang.github.io/jq/) to send requests and read responses.

{% hint style="info" %}
API keys carry the **Owner** role, which can create, approve, deny, and revoke requests. In production, route approvals through your [access policies](/access-management/just-in-time-access/request-routing) rather than approving every request with the same automation key.
{% endhint %}

## Set your base URL and authentication

Every endpoint lives under your organization's base URL and authenticates with a bearer token:

```bash
export P0_ORG="your-org-slug"
export P0_API_KEY="your-api-key"
export P0_BASE_URL="https://api.p0.app/o/${P0_ORG}"
```

Include the key in the `Authorization` header on every request:

```bash
curl -H "Authorization: Bearer ${P0_API_KEY}" "${P0_BASE_URL}/..."
```

## Create an access request

Send a `POST` request to the Command API at `/o/{orgId}/command`. The body has two fields:

| Field        | Type             | Description                                                                                                                             |
| ------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `argv`       | array of strings | The request arguments, matching the [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request) CLI command with the leading `p0` removed. |
| `scriptName` | string           | The client name to record. Use `"p0"`.                                                                                                  |

The `argv` array mirrors the CLI exactly. The command `p0 request aws role MyReadOnlyRole --account 123456789012 --reason "..."` becomes the array below:

```bash
curl -s -X POST "${P0_BASE_URL}/command" \
  -H "Authorization: Bearer ${P0_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "argv": [
      "request", "aws", "role", "MyReadOnlyRole",
      "--account", "123456789012",
      "--reason", "Investigating S3 access issues"
    ],
    "scriptName": "p0"
  }'
```

The response confirms that P0 created the request and includes its request ID. Capture the ID for the next steps:

```bash
REQUEST_ID=$(curl -s -X POST "${P0_BASE_URL}/command" \
  -H "Authorization: Bearer ${P0_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "argv": ["request", "aws", "role", "MyReadOnlyRole", "--account", "123456789012", "--reason", "Automated deploy access"],
    "scriptName": "p0"
  }' | jq -r '.requestId')

echo "Created request ${REQUEST_ID}"
```

{% hint style="info" %}
To find the right `argv` for any resource, run the equivalent CLI command with `--help` — for example `p0 request gcloud --help`. See [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request) for the full list of providers and subcommands. For the complete request and response schema, see the [Command API reference](/access-management/just-in-time-access/just-in-time-api/command-api).
{% endhint %}

## Check the request status

To read the current state of a request from a script, send a `GET` request to `/o/{orgId}/permission-requests/{requestId}`. It returns the full request document as plain JSON:

```bash
curl -s "${P0_BASE_URL}/permission-requests/${REQUEST_ID}" \
  -H "Authorization: Bearer ${P0_API_KEY}" | jq
```

Poll this endpoint to wait for a decision — for example, until the status moves from pending to approved and provisioned.

{% hint style="info" %}
The `/command/{requestId}/poll` endpoint streams live updates over Server-Sent Events for interactive clients such as the CLI and web app. For one-shot status checks in automation, use the `GET /permission-requests/{requestId}` endpoint shown above.
{% endhint %}

## Approve, deny, or revoke the request

The Access Requests API acts on an existing request by ID. Each action is a `POST` to `/o/{orgId}/permission-requests/{requestId}/{action}`, where `{action}` is `approve`, `deny`, or `revoke`.

Approve a request:

```bash
curl -s -X POST "${P0_BASE_URL}/permission-requests/${REQUEST_ID}/approve" \
  -H "Authorization: Bearer ${P0_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Each action returns a success confirmation:

```json
{ "message": "Success" }
```

When you approve a request, you can override the grant duration with an optional body. Set `expirationLength` to a P0 duration such as `30m`, `2h`, or `1d`, and set `isCustomExpiry` to `true`:

```bash
curl -s -X POST "${P0_BASE_URL}/permission-requests/${REQUEST_ID}/approve" \
  -H "Authorization: Bearer ${P0_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{ "expirationLength": "2h", "isCustomExpiry": true }'
```

Deny a pending request, or revoke an active grant before it expires, by changing the action:

```bash
# Deny a pending request
curl -s -X POST "${P0_BASE_URL}/permission-requests/${REQUEST_ID}/deny" \
  -H "Authorization: Bearer ${P0_API_KEY}" -H "Content-Type: application/json" -d '{}'

# Revoke an active grant
curl -s -X POST "${P0_BASE_URL}/permission-requests/${REQUEST_ID}/revoke" \
  -H "Authorization: Bearer ${P0_API_KEY}" -H "Content-Type: application/json" -d '{}'
```

{% hint style="warning" %}
P0 auto-revokes access at expiry, so you only need `revoke` to end a grant early. Denying or revoking a request cannot be undone — submit a new request to restore access.
{% endhint %}

## Verify it worked

Confirm the full lifecycle end to end:

1. **Check the status.** Send a `GET` to `/permission-requests/{requestId}` and confirm the state reflects your action (approved, denied, or revoked).
2. **Confirm provisioning.** For an approved request, verify the underlying grant exists — for example, assume the AWS role with [`p0 aws role assume`](/p0-cli/p0-commands-and-usage/p0-aws-role-assume), or check the resource directly.
3. **Review the audit trail.** Each action writes an audit event (`api.jit.permission-requests.approved`, `.denied`, or `.revoked`). Find it in the P0 dashboard or in your [SIEM integration](/integrations/siem-integrations).

## Troubleshooting

| Symptom                           | Cause                                                         | Fix                                                                                                                                      |
| --------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized`                | Missing or invalid API key                                    | Confirm the `Authorization: Bearer` header is set and the key has not been deleted. Generate a new key if needed.                        |
| `403 Forbidden`                   | The key's user lacks permission for the action                | Use a key belonging to a user with the **Owner** role. See [Role-based access control](/p0-management/role-based-access-control).        |
| `404 Not Found` on an action      | Wrong `requestId` or `orgId`, or the request no longer exists | Recheck the ID returned when you created the request and confirm `P0_ORG` matches your organization slug.                                |
| `argv is not an array of strings` | The `argv` field is missing or malformed                      | Send `argv` as a JSON array of strings, and put each flag and its value as separate elements.                                            |
| Request stays pending             | An approval policy requires a human approver                  | Approve it with the Access Requests API, or adjust the matching [access policy](/access-management/just-in-time-access/request-routing). |

## Related

* [Command API](/access-management/just-in-time-access/just-in-time-api/command-api) — create access requests programmatically.
* [Access Requests API](/access-management/just-in-time-access/just-in-time-api/access-requests-api) — approve, deny, and revoke requests.
* [Generating an API key](/p0-management/generating-an-api-key) — create a key to authenticate these requests.
* [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request) — the CLI command whose arguments the `argv` array mirrors.
* [Management API](/p0-management/management-api) — programmatically configure roles and JIT settings.


# Deploying the P0 AI Gateway

Architecture and deployment of the self-hosted P0 AI Gateway and OAuth server using the batteries-included Helm chart or the Terraform module.

The P0 AI Gateway is the self-hosted runtime enforcement layer for the [P0 AuthZ Control Plane for Agents](/readme/agentic-control-plane). You deploy it into your own Kubernetes cluster, where it sits in the data path between your AI agents and your MCP servers. Because it runs in your environment, your sensitive data and upstream credentials never leave your perimeter.

This guide covers the architecture of the self-hosted components and how to install them.

## Architecture

Agentic authorization spans three runtime planes: two you self-host, and the P0 AuthZ Control Plane™ for Agents, which P0 delivers as SaaS.

```mermaid
flowchart LR
  A["AI agent<br/>(MCP client)"]

  subgraph self["Your environment (self-hosted)"]
    direction TB
    GW["P0 AI Gateway"]
    OS["P0 OAuth Server"]
    UP["Upstream MCP servers"]
  end

  subgraph saas["P0 SaaS"]
    CTRL["AuthZ Control Plane"]
  end

  IDP["Your IdP<br/>(Okta, Entra ID, Google)"]
  RES["Apps & cloud resources"]
  SIEM["Logging sink / SIEM<br/>(Splunk, Elastic, Grafana, …)"]

  A -->|"OAuth token (user + agent)"| GW
  A -.->|"authenticate"| OS
  OS <-->|"federate"| IDP
  GW <-->|"policy sync, approvals"| CTRL
  GW -->|"token exchange, WIF credentials"| OS
  GW -->|"proxied tool calls"| UP
  GW -->|"audit"| SIEM
  UP -->|"access"| RES
  CTRL -->|"session identity and access provisioning"| RES
```

**P0 AI Gateway** (self-hosted). The runtime enforcement point for agent traffic. It proxies MCP tool calls to your upstream MCP servers, verifies the identity token on every call, evaluates policy, and ships audit activity to your logging sink or SIEM. For upstream servers that require just-in-time credentials, it launches an isolated, per-session container for each grant and injects short-lived credentials into it. The gateway periodically syncs MCP server definitions and tool catalogs from the AuthZ Control Plane, and calls the AuthZ Control Plane to drive the access request → approval → grant → revoke lifecycle.

**P0 OAuth Server** (self-hosted). The authorization server and credential broker. It federates with your existing IdP to authenticate the user, issues signed tokens that bind the user and agent identities together, and brokers downstream cloud credentials. When the gateway needs to reach a cloud resource, the OAuth Server mints short-lived Workload Identity Federation (WIF) credentials for that session (for example, exchanging a signed OIDC token with GCP STS or AWS `AssumeRoleWithWebIdentity`), so cloud credentials are minted per session rather than stored.

**P0 AuthZ Control Plane™ for Agents** (SaaS). The authorization and policy layer. It holds your MCP roles and policies, pushes server definitions to the gateway, decides whether each tool call is allowed, coordinates approvals, and provisions session identity and access in your upstream apps and cloud resources for deeper enforcement. The AuthZ Control Plane is not deployed by these charts. The self-hosted components reach it over HTTPS at your tenant URL.

## Prerequisites

* A Kubernetes cluster (EKS, GKE, or AKS).
* A block-storage `StorageClass` for the bundled PostgreSQL. For example, `gp2` on EKS (requires the EBS CSI driver add-on), `standard-rwo` on GKE, or `managed-premium` on AKS.
* A Google OAuth 2.0 client (client ID and client secret) for user sign-in. The self-hosted OAuth server authenticates end users through Google today.
* A P0 SaaS tenant: you need your tenant's P0 URL and audience.
* Control over a public DNS record for the gateway's hostname (required for TLS certificate issuance).
* `helm` (v3, with OCI support) and `kubectl` configured against your cluster.

## Deployment options

P0 publishes three artifacts. Most deployments should use the **batteries-included Helm chart**.

| Option                                                                                                                         | What it is                                                                                                                                                                         | When to use it                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Batteries-included Helm chart**: [`p0security/p0-helm-oauthed-mcp`](https://hub.docker.com/r/p0security/p0-helm-oauthed-mcp) | An umbrella chart that deploys the gateway and OAuth server **plus** everything they depend on: Envoy Gateway, cert-manager (with Let's Encrypt), PostgreSQL, and Valkey.          | Standard installs, and any cluster that doesn't already provide these dependencies. **Recommended.**          |
| **Basic Helm chart**: [`p0security/oauthed-mcp`](https://hub.docker.com/r/p0security/oauthed-mcp)                              | Deploys only the gateway and OAuth server and their wiring. It does **not** include the Gateway API controller, cert-manager/TLS, PostgreSQL, or Valkey. You bring those yourself. | Clusters that already manage those dependencies (for example, a platform team's shared Postgres and ingress). |
| **Terraform module**                                                                                                           | A thin wrapper that installs the batteries-included chart via a `helm_release`.                                                                                                    | Teams that manage infrastructure as code with Terraform.                                                      |

The rest of this guide uses the batteries-included chart.

## Install with the batteries-included Helm chart

### 1. Create the `app-secrets` secret

The chart doesn't create secrets for you. The `app-secrets` Secret must exist in the target namespace before you install. It holds the signing keys and credentials the services need:

| Key                                  | Description                                               |
| ------------------------------------ | --------------------------------------------------------- |
| `JWT_PRIVATE_KEY` / `JWT_PUBLIC_KEY` | Key pair the OAuth server uses to sign and verify tokens. |
| `KMS_LOCAL_ENCRYPTION_KEY`           | 32-byte (64 hex character) key for local encryption.      |
| `REFRESH_TOKEN_SECRET`               | Base64-encoded secret (≥32 bytes) for refresh tokens.     |
| `OIDC_CLIENT_SECRET`                 | The client secret for your Google OAuth client.           |
| `POSTGRESQL_PASSWORD`                | Password for the bundled PostgreSQL.                      |

Generate the signing key pair and random secrets, then create the Secret in your namespace:

```bash
# Create the namespace (the Secret must exist before you install)
kubectl create namespace oauthed-mcp

# RSA signing key pair for the OAuth server
openssl genrsa -out jwt-private.pem 2048
openssl rsa -in jwt-private.pem -pubout -out jwt-public.pem

# Create app-secrets with the generated keys, random secrets, and your OIDC client secret
kubectl -n oauthed-mcp create secret generic app-secrets \
  --from-file=JWT_PRIVATE_KEY=jwt-private.pem \
  --from-file=JWT_PUBLIC_KEY=jwt-public.pem \
  --from-literal=KMS_LOCAL_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
  --from-literal=REFRESH_TOKEN_SECRET="$(openssl rand -base64 32)" \
  --from-literal=OIDC_CLIENT_SECRET="<your-oidc-client-secret>" \
  --from-literal=POSTGRESQL_PASSWORD="$(openssl rand -base64 24)"
```

### 2. Create your values file

{% hint style="info" %}
Google Workspace is currently the only supported identity provider for user sign-in. The `oidcClientId` in the following example is a Google OAuth 2.0 client ID.
{% endhint %}

Create a `my-values.yaml` with the values required for your environment:

```yaml
letsEncrypt:
  email: platform@example.com   # for TLS certificate registration
  env: staging                  # switch to "prod" once staging certs succeed

postgresql:
  storageClass: gp2             # your cluster's block-storage class

oauthed-mcp:
  imageRegistry: p0security     # override only if self-building images

  gateway:
    className: oauthed-mcp      # unique per release; use the release name from the `helm install` command in step 3
    host: gateway.example.com   # public hostname for the gateway
    tlsSecretName: gateway-tls

  oauthServer:
    oidcClientId: <your-client-id>.apps.googleusercontent.com   # Google OAuth 2.0 client ID; user sign-in goes through Google
    p0Url: https://api.p0.app/o/<tenant>
    p0Audience: https://api.p0.app/o/<tenant>
    gatewayIss: https://gateway.example.com

  mcpServer:
    oauthServer: http://oauth-server:52701                 # in-cluster URL
    p0Url: https://api.p0.app/o/<tenant>
    p0Audience: https://api.p0.app/o/<tenant>              # equal to p0Url
    gatewayIss: https://gateway.example.com
    managementAudience: https://gateway.example.com/manage # gateway address + "/manage" path
    manageGcpIssuers: https://accounts.google.com          # accept Google-issued identity tokens on /manage; required for the P0 AuthZ Control Plane to reach the gateway
    manageAllowedEmails: customer-p0-gcp-sa@p0-prod.iam.gserviceaccount.com # P0 service account allowed to call the gateway's /manage endpoint
```

If your cluster already provides any of the bundled dependencies, disable the corresponding subchart (`cert-manager.enabled`, `envoy-gateway.enabled`, `postgresql.enabled`, `valkey.enabled`) and point the services at your managed services instead.

### 3. Install the chart

```bash
helm install oauthed-mcp \
  oci://registry-1.docker.io/p0security/p0-helm-oauthed-mcp \
  --version <chart-version> \
  --namespace oauthed-mcp \
  -f my-values.yaml
```

{% hint style="warning" %}
Don't pass `--wait`. cert-manager can't issue the TLS certificate until you add the DNS record in the next step, so `--wait` would block and eventually time out.
{% endhint %}

### 4. Add the DNS record

Find the load balancer address assigned to the gateway, then create a public DNS record for your gateway host that points at it:

```bash
kubectl -n oauthed-mcp get gateway oauthed-mcp \
  -o jsonpath='{.status.addresses[0].value}'
```

cert-manager retries certificate issuance automatically; the certificate becomes `Ready` once DNS resolves.

### 5. Verify

Confirm the pods are running:

```bash
kubectl -n oauthed-mcp get pods
```

Confirm DNS resolves and the certificate is `Ready` (this may take several minutes):

```bash
kubectl -n oauthed-mcp get certificate
```

Desired output:

```
NAME          READY   SECRET        AGE
gateway-tls   True    gateway-tls   15m
```

Once staging certificates issue successfully, promote to production certificates:

```bash
helm upgrade oauthed-mcp \
  oci://registry-1.docker.io/p0security/p0-helm-oauthed-mcp \
  --namespace oauthed-mcp --reuse-values \
  --set letsEncrypt.env=prod
```

The `prod` certificate is required for testing the backends. The `gateway-tls` certificate is reissued by cert-manager. Wait for it to be `Ready` again.

Confirm both backends respond through the gateway host over public DNS. Replace `<gateway-host>` with your gateway's public hostname:

```bash
# OAuth server (exact-match route) - expect 200
curl -sS -o /dev/null -w '%{http_code}\n' https://<gateway-host>/.well-known/oauth-authorization-server

# Gateway (catch-all route) - expect 200
curl -sS -o /dev/null -w '%{http_code}\n' https://<gateway-host>/health

# HTTP is redirected to HTTPS - expect 301
curl -sS -o /dev/null -w '%{http_code}\n' http://<gateway-host>/health
```

## Install with the Terraform module

The Terraform module wraps the batteries-included chart in a single `helm_release`. It requires Terraform ≥ 1.7 and the `hashicorp/helm` provider ≥ 3.0.

```hcl
module "oauthed_mcp" {
  source  = "p0-security/p0-oauthed-mcp/kubernetes"
  version = "<module-version>"

  release_name     = "oauthed-mcp"
  namespace        = "oauthed-mcp"
  create_namespace = true

  # Same YAML as my-values.yaml above, passed through to the chart.
  values = [file("${path.module}/my-values.yaml")]
}
```

The module passes your values straight through to the chart, so the prerequisites are the same: you still create the `app-secrets` Secret and add the DNS record yourself. Each module version pins a specific chart version. Check the module's compatibility matrix.

## Next steps

Once you deploy the gateway, register it with P0 and configure the MCP servers it fronts:

* [Agentic Gateway integration](/integrations/resource-integrations/agentic-gateway): register the gateway and configure upstream MCP servers.


# Share P0 With Your Team

Use the P0 slackbot to help your users learn how to create access requests through P0.

If you've installed the slack integration, you can use the Slack bot to instruct users on requesting access through P0.

Type `/p0 share` in any channel or DM, and the P0 bot will respond with a message that explains how to use P0 for access requests and includes a button to immediately begin an access request.

<figure><img src="/files/OcEKC8tF9qt88alhT6kg" alt="Slack message from P0 Security bot explaining how to use /p0 request for access requests, with a Request Access button"><figcaption></figcaption></figure>

`/p0 share` also accepts an optional user argument: use the command `/p0 share USER_EMAIL` or `/p0 share @USER_MENTION` to have the bot directly DM the specified user.

This can help your organization transition towards using P0 as the only system for access requests: if somebody makes a request through another means, use `/p0 share` to inform them of P0, and they can quickly get started with their first request.


# Configure Access Policies

Set up access policies in Policy Studio to control who can request access, what they can request, and who approves it. A step-by-step guide for security administrators.

Access policies give you fine-grained control over your organization's just-in-time access workflow. With access policies, you define who can request access to specific resources, and who approves those requests.

This guide walks you through creating your first access policies in Policy Studio, covering three common scenarios:

1. [Route requests by team to the correct approver](#scenario-1-route-requests-by-team)
2. [Restrict access to production resources](#scenario-2-restrict-access-to-production-resources)
3. [Auto-approve requests for on-call engineers](#scenario-3-auto-approve-on-call-engineers)

{% hint style="info" %}
Access policies require a Pro-tier P0 subscription. If you are on the free tier, your organization uses [default approvals](/access-management/just-in-time-access/approving-access#configuring-approvals) instead.
{% endhint %}

## Prerequisites

Before you begin, confirm the following:

* You have a P0 account with the **Owner** or **Security Reviewer** role.
* You have completed the [Getting Started with Just-in-Time Access](/getting-started/getting-started-with-just-in-time-access) guide, including installing at least one resource integration.
* You have a [directory integration](/integrations/directory-integrations) connected (Google Workspace, Okta, or Microsoft Entra ID) if you plan to route by group.
* *(Optional)* You have a [PagerDuty](/integrations/approval-integrations/pagerduty) or [Incident.io](/integrations/approval-integrations/incidentio) integration installed if you plan to use on-call auto-approvals.

## Open Policy Studio

1. Sign in to [p0.app](https://p0.app).
2. Navigate to **Policy Studio** in the left sidebar, or go directly to `https://p0.app/o/<your-organization>/policies`.

Policy Studio displays your current access policies as a YAML workflow. If this is your first time, the editor is empty. Your organization is using default approvals.

{% hint style="info" %}
Saving any policy configuration in Policy Studio switches your organization from default approvals to policy-based approvals. All access requests are then evaluated against your access policies.
{% endhint %}

## Scenario 1: Route requests by team

Route your engineering team's requests to the SRE team for approval, and your data team's requests to the Data Ops team.

1. In Policy Studio, enter the following access policies:

```yaml
- requestor:
    type: group
    id: engineering@yourcompany.com
    label: Engineering
    directory: workspace
  resource:
    type: any
  approval:
    - type: group
      id: sre@yourcompany.com
      label: SRE Team
      directory: workspace
      options: {allowOneParty: false}
- requestor:
    type: group
    id: data-team@yourcompany.com
    label: Data Team
    directory: workspace
  resource:
    type: integration
    service: snowflake
  approval:
    - type: group
      id: data-ops@yourcompany.com
      label: Data Ops
      directory: workspace
      options: {allowOneParty: false}
```

2. Replace the group email addresses with your organization's actual directory groups.
3. Click **Save** to activate the access policies.

**What this does:**

* Any engineer who requests access to any resource gets routed to the SRE team for approval.
* Any data team member who requests Snowflake access gets routed to Data Ops for approval.
* `allowOneParty: false` prevents requestors from approving their own requests.

{% hint style="warning" %}
If a request does not match any access policy, P0 rejects it with the message: "This resource doesn't exist, or your organization doesn't allow this principal to access this resource." Add a catch-all policy at the end of your workflow if you want unmatched requests to fall through to default approvers.
{% endhint %}

### Add a catch-all policy

To ensure unmatched requests still reach your security reviewers, add this policy at the end of your workflow:

```yaml
- requestor:
    type: any
  resource:
    type: any
  approval:
    - type: p0
```

The `type: p0` approval routes requests to the approvers configured on your Settings page.

## Scenario 2: Restrict access to production resources

Block requests to production AWS accounts while allowing development and staging access with different approval requirements.

1. In Policy Studio, add the following policies. Replace the AWS account IDs and Okta group IDs with your own values:

```yaml
# Development - one-party approval (engineers can self-approve)
- requestor:
    type: group
    id: 00g5j4jojlGZMzfhM69
    label: Engineers
    directory: okta
  resource:
    type: integration
    service: aws
    filters:
      policy: {effect: keep, key: arn, pattern: "^arn:aws:iam::111111111111:policy/"}
  approval:
    - type: group
      id: 00g5j4jojlGZMzfhM69
      label: Engineers
      directory: okta
      options: {allowOneParty: true}

# Staging - peer approval required, reason mandatory
- requestor:
    type: group
    id: 00g5j4jojlGZMzfhM69
    label: Engineers
    directory: okta
  resource:
    type: integration
    service: aws
    filters:
      policy: {effect: keep, key: arn, pattern: "^arn:aws:iam::222222222222:policy/"}
  approval:
    - type: group
      id: 00g5j4jojlGZMzfhM69
      label: Engineers
      directory: okta
      options: {allowOneParty: false, requireReason: true}

# Production - deny all access
- requestor:
    type: any
  resource:
    type: integration
    service: aws
    filters:
      policy: {effect: keep, key: arn, pattern: "^arn:aws:iam::333333333333:policy/"}
  approval:
    - type: deny
```

2. Click **Save**.

**What this does:**

* **Development** (account `111111111111`): Engineers can self-approve their own requests.
* **Staging** (account `222222222222`): Engineers need a peer to approve, and must provide a reason.
* **Production** (account `333333333333`): P0 denies all requests. No one can request access through P0.

{% hint style="info" %}
Deny policies always take precedence. If any matching policy specifies `type: deny`, the request is denied immediately, regardless of other matching policies.
{% endhint %}

### Exclude dangerous permissions

To further restrict which AWS permissions engineers can request, add filters that remove overly broad policies:

```yaml
resource:
  type: integration
  service: aws
  accessType: policy
  filters:
    policy: {effect: remove, key: arn, pattern: FullAccess}
    tag: {effect: keep, key: P0Grantable, pattern: "^true$"}
```

This removes any policy containing "FullAccess" in its ARN, and only keeps policies tagged with `P0Grantable: true`.

## Scenario 3: Auto-approve on-call engineers

Automatically approve requests from engineers who are currently on-call in PagerDuty or Incident.io, while routing all other requests to the SRE team.

1. Confirm that your [PagerDuty](/integrations/approval-integrations/pagerduty) or [Incident.io](/integrations/approval-integrations/incidentio) integration is installed.
2. In Policy Studio, add the following policies:

{% tabs %}
{% tab title="PagerDuty" %}

```yaml
# On-call engineers get auto-approved
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: pagerduty
      options: {requireReason: true}
    - type: group
      id: sre@yourcompany.com
      label: SRE Team
      directory: workspace
      options: {allowOneParty: false}
```

{% endtab %}

{% tab title="Incident.io" %}

```yaml
# On-call engineers get auto-approved
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: incidentio
      options: {requireReason: true}
    - type: group
      id: sre@yourcompany.com
      label: SRE Team
      directory: workspace
      options: {allowOneParty: false}
```

{% endtab %}
{% endtabs %}

3. Click **Save**.

**What this does:**

* If the requestor is currently on-call (as determined by PagerDuty escalation policies or Incident.io schedules), P0 automatically approves their request for one hour.
* If the requestor is not on-call, P0 routes the request to the SRE team for manual approval.
* `requireReason: true` ensures all requests include a justification in the audit log, even auto-approved ones.

### Add escalation for urgent requests

You can also configure on-call users as escalation approvers. When a request is pending, the requestor can escalate it to the on-call engineer:

```yaml
approval:
  - type: p0
    options: {requireReason: true, allowOneParty: false}
  - type: escalation
    integration: pagerduty
    options: {requireReason: true, allowOneParty: false}
    services: [PSJXXXG]
```

Replace `PSJXXXG` with your PagerDuty service ID. When the requestor escalates, PagerDuty creates an incident against the specified service, and the on-call engineer receives both a PagerDuty alert and a P0 approval notification.

## Verify your access policies

After saving your access policies, verify that they work as expected:

1. Open Slack and use `/p0 request` (or the [web request modal](/access-management/just-in-time-access/requesting-access/web-request-modal)) to create a test access request that matches one of your policies.
2. Confirm that the correct approver receives the approval notification.
3. If you configured deny policies, submit a request that matches a denied resource and confirm that P0 blocks it.
4. Check the **Activity** page at `https://p0.app/o/<your-organization>/jit/activity` to view the request and verify the policy decision.

{% hint style="info" %}
When multiple policies with different manual approvers match the same request, P0 notifies all matching approvers. Approval from any one of them is sufficient.
{% endhint %}

## Troubleshooting

| Symptom                                                | Cause                                                                                    | Solution                                                                                                                                                                                  |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Request rejected with "This resource doesn't exist..." | No access policy matches the request.                                                    | Add a catch-all policy or verify that your requestor and resource filters match the request.                                                                                              |
| Wrong approver notified                                | A broader policy matches before the specific one.                                        | Reorder policies so more specific policies come first. Deny policies always take precedence regardless of order.                                                                          |
| Auto-approval not working                              | The requestor is not on-call, or the PagerDuty/Incident.io integration is not installed. | Verify the requestor's on-call status in your incident management tool, and confirm the integration is active in **Integrations**.                                                        |
| Filter not matching                                    | Regex pattern mismatch.                                                                  | Patterns are unanchored by default. Use `^` and `$` to anchor. P0 uses the [JavaScript regex dialect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions). |

## What's next

Now that you have access policies configured, you can:

* Set up [pre-approvals](/access-management/just-in-time-access/approving-access/pre-approving-access) for standing access during projects or maintenance windows.
* Add [resource filters](/access-management/just-in-time-access/request-routing) for fine-grained control over which resources are requestable per service.
* Connect a [SIEM integration](/integrations/siem-integrations) to send access request audit logs to Datadog or Splunk.
* Review the full [request routing reference](/access-management/just-in-time-access/request-routing) for all available requestor, resource, and approval types.


# Access Inventory

Browse and query your entire IAM configuration. Combine data from identity providers, IAM policies, access logs, and P0's IAM Privilege Catalog.

The inventory page lets you browse and query your entire IAM configuration, combining data from your identity provider, IAM policies, your access logs, and P0's [IAM Privilege Catalog](https://catalog.p0.dev).

<figure><img src="/files/YZ8d0Xt93rPI8TvMbrYq" alt="Access inventory graph visualization showing identities, entitlements, and resources connected by lateral movement paths" width="563"><figcaption></figcaption></figure>

### Search interface

When you land on the **Inventory** page, you'll be presented with a search interface. At the top of this view you'll see a query control, and, below, all items that match your query. By default results are returned in a asset table. Everything in your IAM configuration matches an empty search, so you'll see everything listed at first.

#### Asset list

To search for something specific, type any text included in that IAM datum into the "where" bar:

<figure><img src="/files/aMZy4hPz53kDXquFyZjU" alt="Inventory search results table showing entitlements for bucket resources with columns for Principal, Privilege set, Resource, and Risks" width="563"><figcaption></figcaption></figure>

If you're new to querying, [Query Language Basics](/inventory/query-search/query-language-basics) walks you through the core search terms and operators from scratch. For detailed information on how to query your data, see [Query Search](/inventory/query-search). You can also have P0 help you construct queries by hovering over items:

<figure><img src="/files/A60v3E2uovGWioDR6TBE" alt="Inventory item hover menu showing options to show or hide identities of this type for query refinement" width="563"><figcaption></figcaption></figure>

Clicking "show" or "hide" will update your query to show or hide the selected items.

You can display credentials, entitlements, identities, or resources by selecting these in the "show" selection:

<figure><img src="/files/EnKwErLzMDeqd5Y0bDGb" alt="Inventory Show dropdown menu with Credentials, Entitlements, Identities, and Resources options for filtering results" width="563"><figcaption></figcaption></figure>

For each item, you can see detailed information by selecting "view," which will take you to the relevant [Result Details](/inventory/result-details) page.

#### Graph visualization

Results can also be viewed as a graph visualization. You will see all items that can reach your search terms, as well as the access paths that connect them.

<figure><img src="/files/JHULnwQh64nTDKP1MdvJ" alt="Access inventory graph visualization showing identities connected to GCP role bindings, Cloud Storage service, and a storage bucket" width="563"><figcaption></figcaption></figure>

You can get more information on any node in your access graph by clicking on it, which will open a view of all that graph node's properties.

<figure><img src="/files/plNu367bLSyKGxbVqzfS" alt="Graph node detail panel showing GCP Role Binding properties including principal, role, parent project, and cross-resource access status" width="563"><figcaption></figcaption></figure>

### Creating custom monitors

You create custom monitors from the Inventory page. Results from these monitors will appear in [Monitor Results](/posture/monitor-results) on every scan of your environment. To create a custom monitor:

* Select a "show" option and enter a "where" query
* After ensuring that the displayed results match your expectations, click **Save Search**
* Enable the "Create a monitor for this search?" toggle, then follow the prompts to add a title, description, and severity for your monitor

<figure><img src="/files/PXVZWdTrq9RNo5bsF7z0" alt="Create New Monitor dialog with query, label, description, and priority fields for a custom BigQuery grants monitor" width="375"><figcaption></figcaption></figure>


# Result Details

Clicking on a query result will open a drawer with that result's details. Details looks like this:

<figure><img src="/files/w9o2ejsicLXhltU43sIu" alt="" width="563"><figcaption></figcaption></figure>

### Query path

At the top of the details you see a graph visualization of why this result matches your query. For instance, if you select an identity with `risk:exfiltration` as your search, you see the entitlements and privileges that lead to data-exfiltration risks. To understand how queries like `risk:exfiltration` work, see [Query Language Basics](/inventory/query-search/query-language-basics).

### Result information

The top of the page shows detailed information for the result. The information displayed depends on the result type.

<table data-header-hidden><thead><tr><th width="123.33333333333331">Result type</th><th width="173">Field</th><th>Description</th></tr></thead><tbody><tr><td><strong>Credential</strong></td><td>Identity</td><td>The identity accessed via this credential</td></tr><tr><td></td><td>Last used</td><td>The most recent date that this credential was used</td></tr><tr><td></td><td>Last rotated</td><td>When this credential was created</td></tr><tr><td></td><td>Entitlements</td><td>All entitlements that can be used for access via this credential</td></tr><tr><td></td><td>Risks</td><td>Access risks reachable from this credentiall, and the privileges that expose those risks</td></tr><tr><td><strong>Entitlement</strong></td><td>Principal</td><td>The principal identity that is assigned this entitlement</td></tr><tr><td></td><td>Role | Policy</td><td>The name of the granted role (for non-AWS systems) or policy (for AWS)</td></tr><tr><td></td><td>Condition</td><td>(GCP role bindings only) this role binding's access condition</td></tr><tr><td></td><td>Resource</td><td>The resource(s) to which this entitlement grants direct access</td></tr><tr><td></td><td>Risks</td><td>Reachable IAM risks for this entitlement, broken down by whether the privilege(s) that yield the risk are used or not within the previous 90 days</td></tr><tr><td></td><td>Accessible by</td><td>The identities that can use this entitlement, including via federation, group membership, or lateral movement</td></tr><tr><td><strong>Identity</strong></td><td>Parent</td><td>The resource in which the identity is defined (e.g. AWS account, Azure subscription, GCP project, etc.)</td></tr><tr><td></td><td>Last Used</td><td>The last time this identity authenticated with its identity provider</td></tr><tr><td></td><td>Accessible by</td><td>(Federation identities only) the identities that can gain access to your system via this federation identity</td></tr><tr><td></td><td>Members</td><td>(Groups only) this group's direct and indirect members</td></tr><tr><td></td><td>MFA</td><td>(Users only) whether two-factor authentication is required for this user</td></tr><tr><td></td><td>Entitlements</td><td>A link to view all of the identity's entitlements</td></tr><tr><td></td><td>Risks</td><td>Access risks reachable from this identity, and the privileges that expose those risks</td></tr><tr><td><strong>Resource</strong></td><td>Parent</td><td>This resource's parent resource in the system's resource hierarchy (e.g. a database table's parent resource will be its enclosing database schema); top-level resources have the service as their parent</td></tr><tr><td></td><td>Children</td><td>A list of all this resource's child resources (e.g. a database schema will have all its tables, indices, views, etc. as children)</td></tr><tr><td></td><td>Accessible by</td><td>All identities that have direct access to this resource</td></tr></tbody></table>


# Inventory export API

List your P0 environments and export their access inventory as JSON. Pull credentials, identities, grants, and resources programmatically for custom integrations.

The Inventory export API lets you pull your cloud [access inventory](/inventory/access-inventory) programmatically instead of using the in-app **Export as JSON** button. Use it to feed inventory into custom integrations, data warehouses, or compliance workflows.

The API has two read-only endpoints:

* **List environments** returns every environment in your organization and its assessment scopes.
* **Export inventory** returns the latest completed assessment for an environment as a single JSON document, grouped by entity type.

Environments are backed by IAM assessments, so an environment's `id` is also its assessment ID. Use the `id` from the list endpoint as the `assessmentId` path parameter when you export.

Authenticate each request with an API key or user token in the `Authorization` header:

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.p0.app/o/{orgId}/assessment
```

Both endpoints require the `assessment.read` permission. API keys carry the **Owner** role, which includes this permission. To create a key, see [Generating an API key](/p0-management/generating-an-api-key).

{% file src="/files/1hQJXIe7jnIweH7Ypuof" %}

## List environments

> Returns every environment in the organization, along with the assessment scopes each environment covers and when each last completed an assessment.

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"servers":[{"url":"https://api.p0.app/o/{orgId}","variables":{"orgId":{"default":"demo-org","description":"The organization ID"}}}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"schemas":{"EnvironmentList":{"type":"object","required":["environments"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/Environment"}}}},"Environment":{"type":"object","description":"An environment in the organization. Environments are backed by IAM assessments.","required":["id","name","targets","lastCompletedAt"],"properties":{"id":{"type":"string","description":"The environment ID. Pass this as the `assessmentId` path parameter to export the environment's inventory."},"name":{"type":"string","description":"The display name of the environment."},"targets":{"type":"array","description":"The assessment scopes the environment covers.","items":{"$ref":"#/components/schemas/AssessmentScope"}},"lastCompletedAt":{"type":"string","format":"date-time","nullable":true,"description":"When this environment's most recently completed assessment finished (ISO 8601), or null if it has never completed one. Lets a client that syncs many environments spot a stale one — a scan that's stuck or hasn't run in a while — without paying for a full export first."}}},"AssessmentScope":{"description":"A single scope covered by an environment's assessment. The shape depends on `type`: item/project scopes carry an `id`, group scopes carry `key`/`value`, and organization scopes carry neither.","oneOf":[{"$ref":"#/components/schemas/ProjectScope"},{"$ref":"#/components/schemas/GroupScope"},{"$ref":"#/components/schemas/OrganizationScope"}],"discriminator":{"propertyName":"type","mapping":{"project":"#/components/schemas/ProjectScope","group":"#/components/schemas/GroupScope","organization":"#/components/schemas/OrganizationScope"}}},"ProjectScope":{"type":"object","description":"A scope covering a single item, such as a GCP project, AWS account, or Azure subscription. (`project` is a legacy name for \"item\".)","required":["id","integration","type"],"properties":{"id":{"type":"string","description":"The identifier of the scoped target, such as a project, account, or subscription ID."},"integration":{"type":"string","description":"The cloud integration the scope belongs to."},"type":{"type":"string","enum":["project"]},"label":{"type":"string","description":"Optional display label for the scope."}}},"GroupScope":{"type":"object","description":"A scope covering a group of items, such as all projects in a GCP folder or all accounts carrying a given AWS tag.","required":["key","value","integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["group"]},"key":{"type":"string","description":"The grouping dimension (e.g. `folder` for GCP)."},"value":{"type":"string","description":"The value of the grouping dimension."},"label":{"type":"string","description":"Optional display label for the scope."}}},"OrganizationScope":{"type":"object","description":"A scope covering an entire cloud organization.","required":["integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["organization"]}}}},"responses":{"UnauthorizedError":{"description":"The caller could not be authenticated."},"ForbiddenError":{"description":"The caller is authenticated but lacks the required `assessment.read` permission."}}},"paths":{"/assessment":{"get":{"summary":"List environments","description":"Returns every environment in the organization, along with the assessment scopes each environment covers and when each last completed an assessment.","responses":{"200":{"description":"The environments in the organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentList"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Export inventory

> Exports the inventory of an environment's latest completed assessment as a single JSON document, grouped by entity type. The response is streamed, so it scales to large environments. The \`X-P0-Assessment-Job-Id\` and \`X-P0-Assessment-Completed-At\` response headers identify the assessment job the inventory came from and when it finished.

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"servers":[{"url":"https://api.p0.app/o/{orgId}","variables":{"orgId":{"default":"demo-org","description":"The organization ID"}}}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key"}},"parameters":{"assessmentId":{"name":"assessmentId","in":"path","required":true,"description":"The environment ID returned by the list endpoint. An environment ID is also its assessment ID.","schema":{"type":"string"}}},"schemas":{"InventoryExport":{"type":"object","description":"The environment's inventory, grouped by entity type. Each entity appears once per group; entities that span multiple assessment scopes are de-duplicated by key.","required":["completedAt","credentials","identities","grants","resources"],"properties":{"completedAt":{"type":"string","format":"date-time","description":"When the assessment job behind this export (X-P0-Assessment-Job-Id) finished, in ISO 8601. The authoritative \"as-of\" timestamp for every entity below — a client syncing several environments should use this instead of its own fetch time when reporting per-environment data freshness. Also returned as the `X-P0-Assessment-Completed-At` response header."},"credentials":{"type":"array","description":"Keys, tokens, and other credentials discovered in the environment.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"identities":{"type":"array","description":"Users, service accounts, and groups.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"grants":{"type":"array","description":"Access grants that bind a principal to a privilege set on one or more resources. These appear as entitlements in the inventory UI.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"resources":{"type":"array","description":"Cloud resources such as buckets, databases, and compute instances. Resources do not carry a risk roll-up.","items":{"$ref":"#/components/schemas/InventoryEntity"}}}},"RiskBearingEntity":{"description":"An inventory entity that carries a per-entity risk roll-up. Identities, grants, and credentials are risk-bearing; resources are not.","allOf":[{"$ref":"#/components/schemas/InventoryEntity"},{"type":"object","required":["risk"],"properties":{"risk":{"type":"array","description":"The distinct risks reachable from this entity, aggregated from the privileges it grants or holds. Always present; an empty array means no risk was found.","items":{"$ref":"#/components/schemas/Risk"}}}}]},"InventoryEntity":{"type":"object","description":"A single inventory entity. Every entity carries a stable `key` alongside its own fields. The remaining fields vary by entity type and by cloud provider.","required":["key"],"properties":{"key":{"type":"string","description":"The entity's stable identifier in the inventory graph."}},"additionalProperties":true},"Risk":{"type":"object","description":"A single risk finding attached to an inventory entity, mapped from the privileges reachable from that entity.","required":["id","name","score"],"properties":{"id":{"type":"string","description":"Risk identifier in `tactic:subtype` form, where the tactic follows a MITRE-style attacker taxonomy."},"name":{"type":"string","description":"Human-readable risk name."},"score":{"type":"string","description":"The severity/classification of the risk.","enum":["CRITICAL","HIGH","MEDIUM","LOW","BOOST","EVASION"]}}}},"responses":{"UnauthorizedError":{"description":"The caller could not be authenticated."},"ForbiddenError":{"description":"The caller is authenticated but lacks the required `assessment.read` permission."},"NotFoundError":{"description":"No environment matches the given ID."},"NoCompletedAssessmentError":{"description":"The environment has no completed assessment to export."},"TooManyRequestsError":{"description":"Too many inventory exports are in progress. Back off and retry shortly."}}},"paths":{"/assessment/{assessmentId}/export":{"get":{"summary":"Export inventory","description":"Exports the inventory of an environment's latest completed assessment as a single JSON document, grouped by entity type. The response is streamed, so it scales to large environments. The `X-P0-Assessment-Job-Id` and `X-P0-Assessment-Completed-At` response headers identify the assessment job the inventory came from and when it finished.","parameters":[{"$ref":"#/components/parameters/assessmentId"}],"responses":{"200":{"description":"The environment's inventory, grouped by entity type.","headers":{"X-P0-Assessment-Job-Id":{"description":"The ID of the assessment job the inventory came from.","schema":{"type":"string"}},"X-P0-Assessment-Completed-At":{"description":"When the assessment job behind this export finished (ISO 8601). Mirrors the body's `completedAt`.","schema":{"type":"string","format":"date-time"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryExport"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"422":{"$ref":"#/components/responses/NoCompletedAssessmentError"},"429":{"$ref":"#/components/responses/TooManyRequestsError"}}}}}}
```

## The AssessmentScope object

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"components":{"schemas":{"AssessmentScope":{"description":"A single scope covered by an environment's assessment. The shape depends on `type`: item/project scopes carry an `id`, group scopes carry `key`/`value`, and organization scopes carry neither.","oneOf":[{"$ref":"#/components/schemas/ProjectScope"},{"$ref":"#/components/schemas/GroupScope"},{"$ref":"#/components/schemas/OrganizationScope"}],"discriminator":{"propertyName":"type","mapping":{"project":"#/components/schemas/ProjectScope","group":"#/components/schemas/GroupScope","organization":"#/components/schemas/OrganizationScope"}}},"ProjectScope":{"type":"object","description":"A scope covering a single item, such as a GCP project, AWS account, or Azure subscription. (`project` is a legacy name for \"item\".)","required":["id","integration","type"],"properties":{"id":{"type":"string","description":"The identifier of the scoped target, such as a project, account, or subscription ID."},"integration":{"type":"string","description":"The cloud integration the scope belongs to."},"type":{"type":"string","enum":["project"]},"label":{"type":"string","description":"Optional display label for the scope."}}},"GroupScope":{"type":"object","description":"A scope covering a group of items, such as all projects in a GCP folder or all accounts carrying a given AWS tag.","required":["key","value","integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["group"]},"key":{"type":"string","description":"The grouping dimension (e.g. `folder` for GCP)."},"value":{"type":"string","description":"The value of the grouping dimension."},"label":{"type":"string","description":"Optional display label for the scope."}}},"OrganizationScope":{"type":"object","description":"A scope covering an entire cloud organization.","required":["integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["organization"]}}}}}}
```

## The Environment object

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"components":{"schemas":{"Environment":{"type":"object","description":"An environment in the organization. Environments are backed by IAM assessments.","required":["id","name","targets","lastCompletedAt"],"properties":{"id":{"type":"string","description":"The environment ID. Pass this as the `assessmentId` path parameter to export the environment's inventory."},"name":{"type":"string","description":"The display name of the environment."},"targets":{"type":"array","description":"The assessment scopes the environment covers.","items":{"$ref":"#/components/schemas/AssessmentScope"}},"lastCompletedAt":{"type":"string","format":"date-time","nullable":true,"description":"When this environment's most recently completed assessment finished (ISO 8601), or null if it has never completed one. Lets a client that syncs many environments spot a stale one — a scan that's stuck or hasn't run in a while — without paying for a full export first."}}},"AssessmentScope":{"description":"A single scope covered by an environment's assessment. The shape depends on `type`: item/project scopes carry an `id`, group scopes carry `key`/`value`, and organization scopes carry neither.","oneOf":[{"$ref":"#/components/schemas/ProjectScope"},{"$ref":"#/components/schemas/GroupScope"},{"$ref":"#/components/schemas/OrganizationScope"}],"discriminator":{"propertyName":"type","mapping":{"project":"#/components/schemas/ProjectScope","group":"#/components/schemas/GroupScope","organization":"#/components/schemas/OrganizationScope"}}},"ProjectScope":{"type":"object","description":"A scope covering a single item, such as a GCP project, AWS account, or Azure subscription. (`project` is a legacy name for \"item\".)","required":["id","integration","type"],"properties":{"id":{"type":"string","description":"The identifier of the scoped target, such as a project, account, or subscription ID."},"integration":{"type":"string","description":"The cloud integration the scope belongs to."},"type":{"type":"string","enum":["project"]},"label":{"type":"string","description":"Optional display label for the scope."}}},"GroupScope":{"type":"object","description":"A scope covering a group of items, such as all projects in a GCP folder or all accounts carrying a given AWS tag.","required":["key","value","integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["group"]},"key":{"type":"string","description":"The grouping dimension (e.g. `folder` for GCP)."},"value":{"type":"string","description":"The value of the grouping dimension."},"label":{"type":"string","description":"Optional display label for the scope."}}},"OrganizationScope":{"type":"object","description":"A scope covering an entire cloud organization.","required":["integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["organization"]}}}}}}
```

## The EnvironmentList object

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"components":{"schemas":{"EnvironmentList":{"type":"object","required":["environments"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/Environment"}}}},"Environment":{"type":"object","description":"An environment in the organization. Environments are backed by IAM assessments.","required":["id","name","targets","lastCompletedAt"],"properties":{"id":{"type":"string","description":"The environment ID. Pass this as the `assessmentId` path parameter to export the environment's inventory."},"name":{"type":"string","description":"The display name of the environment."},"targets":{"type":"array","description":"The assessment scopes the environment covers.","items":{"$ref":"#/components/schemas/AssessmentScope"}},"lastCompletedAt":{"type":"string","format":"date-time","nullable":true,"description":"When this environment's most recently completed assessment finished (ISO 8601), or null if it has never completed one. Lets a client that syncs many environments spot a stale one — a scan that's stuck or hasn't run in a while — without paying for a full export first."}}},"AssessmentScope":{"description":"A single scope covered by an environment's assessment. The shape depends on `type`: item/project scopes carry an `id`, group scopes carry `key`/`value`, and organization scopes carry neither.","oneOf":[{"$ref":"#/components/schemas/ProjectScope"},{"$ref":"#/components/schemas/GroupScope"},{"$ref":"#/components/schemas/OrganizationScope"}],"discriminator":{"propertyName":"type","mapping":{"project":"#/components/schemas/ProjectScope","group":"#/components/schemas/GroupScope","organization":"#/components/schemas/OrganizationScope"}}},"ProjectScope":{"type":"object","description":"A scope covering a single item, such as a GCP project, AWS account, or Azure subscription. (`project` is a legacy name for \"item\".)","required":["id","integration","type"],"properties":{"id":{"type":"string","description":"The identifier of the scoped target, such as a project, account, or subscription ID."},"integration":{"type":"string","description":"The cloud integration the scope belongs to."},"type":{"type":"string","enum":["project"]},"label":{"type":"string","description":"Optional display label for the scope."}}},"GroupScope":{"type":"object","description":"A scope covering a group of items, such as all projects in a GCP folder or all accounts carrying a given AWS tag.","required":["key","value","integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["group"]},"key":{"type":"string","description":"The grouping dimension (e.g. `folder` for GCP)."},"value":{"type":"string","description":"The value of the grouping dimension."},"label":{"type":"string","description":"Optional display label for the scope."}}},"OrganizationScope":{"type":"object","description":"A scope covering an entire cloud organization.","required":["integration","type"],"properties":{"integration":{"type":"string"},"type":{"type":"string","enum":["organization"]}}}}}}
```

## The InventoryEntity object

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"components":{"schemas":{"InventoryEntity":{"type":"object","description":"A single inventory entity. Every entity carries a stable `key` alongside its own fields. The remaining fields vary by entity type and by cloud provider.","required":["key"],"properties":{"key":{"type":"string","description":"The entity's stable identifier in the inventory graph."}},"additionalProperties":true}}}}
```

## The InventoryExport object

```json
{"openapi":"3.0.4","info":{"title":"P0 Inventory Export API","version":"1.1.0"},"components":{"schemas":{"InventoryExport":{"type":"object","description":"The environment's inventory, grouped by entity type. Each entity appears once per group; entities that span multiple assessment scopes are de-duplicated by key.","required":["completedAt","credentials","identities","grants","resources"],"properties":{"completedAt":{"type":"string","format":"date-time","description":"When the assessment job behind this export (X-P0-Assessment-Job-Id) finished, in ISO 8601. The authoritative \"as-of\" timestamp for every entity below — a client syncing several environments should use this instead of its own fetch time when reporting per-environment data freshness. Also returned as the `X-P0-Assessment-Completed-At` response header."},"credentials":{"type":"array","description":"Keys, tokens, and other credentials discovered in the environment.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"identities":{"type":"array","description":"Users, service accounts, and groups.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"grants":{"type":"array","description":"Access grants that bind a principal to a privilege set on one or more resources. These appear as entitlements in the inventory UI.","items":{"$ref":"#/components/schemas/RiskBearingEntity"}},"resources":{"type":"array","description":"Cloud resources such as buckets, databases, and compute instances. Resources do not carry a risk roll-up.","items":{"$ref":"#/components/schemas/InventoryEntity"}}}},"RiskBearingEntity":{"description":"An inventory entity that carries a per-entity risk roll-up. Identities, grants, and credentials are risk-bearing; resources are not.","allOf":[{"$ref":"#/components/schemas/InventoryEntity"},{"type":"object","required":["risk"],"properties":{"risk":{"type":"array","description":"The distinct risks reachable from this entity, aggregated from the privileges it grants or holds. Always present; an empty array means no risk was found.","items":{"$ref":"#/components/schemas/Risk"}}}}]},"InventoryEntity":{"type":"object","description":"A single inventory entity. Every entity carries a stable `key` alongside its own fields. The remaining fields vary by entity type and by cloud provider.","required":["key"],"properties":{"key":{"type":"string","description":"The entity's stable identifier in the inventory graph."}},"additionalProperties":true},"Risk":{"type":"object","description":"A single risk finding attached to an inventory entity, mapped from the privileges reachable from that entity.","required":["id","name","score"],"properties":{"id":{"type":"string","description":"Risk identifier in `tactic:subtype` form, where the tactic follows a MITRE-style attacker taxonomy."},"name":{"type":"string","description":"Human-readable risk name."},"score":{"type":"string","description":"The severity/classification of the risk.","enum":["CRITICAL","HIGH","MEDIUM","LOW","BOOST","EVASION"]}}}}}}
```

## Response notes

* **Export** groups entities into `credentials`, `identities`, `grants`, and `resources`. Grants appear as **entitlements** in the inventory UI.
* Every entity carries a `key`, its stable identifier in the inventory graph, alongside the entity's own fields. Fields vary by entity type and by cloud provider.
* The export unions every scope of the assessment and de-duplicates entities by `key`, so each entity appears once even when it spans multiple scopes.
* The export contains the raw inventory entities. Aggregated roll-ups that the inventory UI layers on top, such as risk summaries and connected-node references, aren't included.
* The `X-P0-Assessment-Job-Id` response header identifies the assessment job the inventory came from. Use it to correlate an export with a specific assessment run.

### Example export request

```bash
curl -sD - "https://api.p0.app/o/{orgId}/assessment/{assessmentId}/export" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o inventory.json
```

The response is streamed and gzip-compressed, so it scales to large environments. The `-o` flag writes the body to `inventory.json`, and `-D -` prints the response headers so you can read the job ID.

## Related

* [Access Inventory](/inventory/access-inventory): browse and query your inventory in the P0 dashboard.
* [Generating an API key](/p0-management/generating-an-api-key): create a key to authenticate these requests.
* [Management API](/p0-management/management-api): other programmatic P0 APIs.


# Query Search

P0's environment query searches let you find specific IAM data across your cloud inventory.

Query searches are controlled using two parts:

<figure><img src="/files/mKRu0Tm9XL7pZcO0OhNd" alt="Inventory query search bar with Show dropdown set to Grants and a Where field for entering search terms" width="563"><figcaption></figcaption></figure>

* **show** - controls which kind of data are displayed
* **where** - controls which data to show

### Show control

Currently, you can choose to "show" credentials (access keys or short-term authentication), identities (users, groups, machine identities, and so forth), entitlements (in Google Cloud, a role binding; in AWS, a policy attachment), or resources (projects, accounts, services, and individual resources such as storage buckets).

### Where control

The "where" control is a free-form search box. You can enter any term here, and P0 will find the principals or grants that relate to your search term.

*Example*:

Searching for a permission (in this case `compute.instances.create` in a Google Cloud assessment) will show you all grants that provide that permission:

<figure><img src="/files/ZZUtoUBw9HdiIhqTLgVK" alt="Query results for compute.instances.create showing grants with principals, roles, resources, risk counts, and permission usage" width="563"><figcaption></figcaption></figure>

To see *why* a search result matches your query, you can click on that result's "view" link. The details page will show an "Explanation" section at the bottom, describing how that result satisfies your query:

<figure><img src="/files/Ms91LSv5o6PkESNVbpEr" alt="" width="563"><figcaption></figcaption></figure>

### Learn the query language

A free-form term gets you started, but you can be far more specific by writing query expressions. Two pages cover the full query language:

* [Query Language Basics](/inventory/query-search/query-language-basics): a beginner-friendly walkthrough of the core search terms (`identity`, `credential`, `entitlement`, `risk`) and the operators that connect them. Start here if you're new to querying.
* [Search Reference](/inventory/query-search/search-reference): the complete reference for every operator, search type, and attribute, with Cypher equivalents. Use it to look up specifics.

### Query examples

One of the best resources for constructing queries is to view the search queries for P0's built-in assessment monitors.

For instance, here's the query for detecting unused service account keys:

`show = credential`

```
credential=enabledKey:"true"
credential=last40:"unused"
principal=type:"service-account"
principal=status:"active"
```

This returns all service-account keys that have not been used in the last 40 days. For the syntax behind each term, see the [Search Reference](/inventory/query-search/search-reference).

### Query links

You can also construct queries using tooltips in the displayed data. To do this, hover over an item you want to either include or exclude from your search:

<figure><img src="/files/iaSvAiBwTFlj7vV907o6" alt="" width="563"><figcaption></figcaption></figure>

Select the corresponding "show" or "hide" link to either include or exclude that item in your search results.


# Query Language Basics

A beginner's guide to querying P0's Access Inventory. Learn the core search terms (identity, credential, entitlement, risk), the colon, arrow, and reverse-arrow operators, the type argument, and how t

This guide introduces the query language you use to search the Access Inventory. It assumes no prior experience. By the end, you can read and write queries like `identity:->identity:->entitlement:->risk:` and understand exactly what they return.

If you want the complete reference (every operator, search term, and attribute), see the [Search Reference](/inventory/query-search/search-reference). For an overview of the search interface itself, see [Query Search](/inventory/query-search).

## Your inventory is a graph

P0 models your cloud IAM configuration as a *graph*: a set of items (called **nodes**) connected by relationships (called **edges**).

Each node is one piece of your access setup, such as a user, an access key, or a permission grant. Each edge records how two nodes relate, such as "this identity holds this entitlement."

You query the inventory by describing a pattern of nodes and the connections between them. P0 finds every part of your graph that matches the pattern and shows you the results.

{% hint style="info" %}
You don't need to know graph theory to write queries. Think of each query as a sentence that describes the access you're looking for, reading from left to right.
{% endhint %}

## The core search terms

The most common nodes you search for are the four that follow. Type one of these words to limit your search to that kind of node.

| Search term   | What it represents                                                            | Example                                          |
| ------------- | ----------------------------------------------------------------------------- | ------------------------------------------------ |
| `identity`    | A user, group, machine identity, or role that can authenticate.               | An employee, a service account, an AWS IAM role. |
| `credential`  | A single way to authenticate, such as an access key or a federated SSO login. | An AWS access key, a short-lived token.          |
| `entitlement` | A grant that gives an identity privileges over one or more resources.         | An AWS policy attachment, a GCP role binding.    |
| `risk`        | A security risk that a privilege carries.                                     | A privilege that allows data exfiltration.       |

These four are the terms you use most often, but they aren't the only ones. The inventory also models `resource`, `privilege`, `usage`, and more. For the complete list, see [Search types](/inventory/query-search/search-reference#search-types).

## The colon operator: `:`

The colon turns a word into a **node-type filter**. On its own, a term followed by a colon matches every node of that type:

```
identity:
```

This query matches every identity in your inventory.

To narrow the search, add a keyword after the colon. P0 then matches nodes of that type whose name contains the keyword:

```
identity:alice
```

This query matches identities whose name contains `alice`.

Read the colon as "that is a." So `identity:alice` reads as "a node *that is an* identity, named `alice`."

{% hint style="info" %}
A colon with nothing after it (`risk:`) is a presence search: it finds every node of that type. Use it to answer questions like "which entitlements carry any risk at all?" with `entitlement:->risk:`.
{% endhint %}

## The type argument

Many node types come in several varieties. An identity might be a user, a group, or a machine role. A credential might be a static key or a short-lived token. To filter by variety, use the `type` argument.

The `type` argument is an *attribute* of a node, so you write it as a second colon-separated value:

```
identity:type:user
```

This reads as "an identity whose `type` is `user`." The pattern is always:

```
<search term>:type:<value>
```

Here are some common examples:

| Query                           | Matches                                          |
| ------------------------------- | ------------------------------------------------ |
| `identity:type:user`            | Human user identities.                           |
| `identity:type:aws-iam-role`    | AWS IAM roles.                                   |
| `identity:type:service-account` | Machine identities (service accounts).           |
| `credential:type:key`           | Static secret credentials, such as access keys.  |
| `credential:type:short-lived`   | Ephemeral credentials, such as temporary tokens. |
| `usage:type:unused`             | Privileges that have gone unused.                |

{% hint style="info" %}
`type` is one of several attributes you can filter on. Each search term supports its own attributes, such as `identity:status` or `credential:last90`. See [Search attributes](/inventory/query-search/search-reference#search-attributes) for the full set and their allowed values.
{% endhint %}

## The inverted operator: `!`

Put a `!` immediately before a keyword to match nodes whose value *does not* contain it. This is the **inverted** (or "NOT") operator.

```
identity:status:!disabled
```

This reads as "an identity whose `status` is *not* `disabled`." It returns every identity that is enabled or whose status is unknown.

The `!` goes after the type and attribute, directly in front of the keyword it inverts. The pattern is:

```
<search term>:<attribute>:!<keyword>
```

{% hint style="info" %}
On its own, an inverted keyword does little, because each identity and grant connects to many values and some won't match anyway. Inverted matches work best combined with a type or attribute, as in `credential:type:!key` (credentials that aren't static keys).
{% endhint %}

The inverted operator (`!`) flips a single keyword. A related operator, the **exclusion** operator (`^`), removes whole results that match a term. For both, see [Inverted matches](/inventory/query-search/search-reference#inverted-matches) and [Exclusion matches](/inventory/query-search/search-reference#exclusion-matches) in the reference.

## Matching with a regular expression: `/.../`

A plain keyword matches any value that *contains* it. When you need more control (a value that *starts* with something, or matches one of several patterns), wrap a **regular expression** in forward slashes.

```
identity:/^svc-/
```

This reads as "an identity whose name matches the pattern `^svc-`," which finds identities whose name *starts with* `svc-`. The `^` anchors the match to the beginning of the value.

You can use the full standard regular expression syntax, including anchors (`^`, `$`), character classes, and alternation:

```
identity:/prod|staging/
```

This matches identities whose name contains either `prod` or `staging`.

Regex works wherever a keyword does, including after an attribute (`identity:status:/^en/`) and combined with the inverted operator (`identity:type:!/role/`).

{% hint style="info" %}
Regex matches are **case sensitive**, unlike plain keyword matches. To match either case, build it into the pattern, for example, `/[Pp]rod/` rather than `/prod/i`.
{% endhint %}

For escaping rules, limitations, and the equivalent Cypher, see [Regex matches](/inventory/query-search/search-reference#regex-matches) in the reference.

## The path operators: `->` and `<-`

A single term finds nodes in isolation. To describe how nodes *connect*, join terms with an arrow. We call this a **path**.

The arrow points along the direction of the graph's edges:

| Operator | Name        | Meaning                                                                  |
| -------- | ----------- | ------------------------------------------------------------------------ |
| `->`     | Child path  | Follow the connection forward, from the left term toward the right term. |
| `<-`     | Parent path | Follow the connection backward, from the left term toward its parent.    |

For example, to find identities that hold an entitlement, follow the connection forward:

```
identity:->entitlement:
```

This reads as "an identity that connects forward to an entitlement." The same relationship viewed from the other side uses the reverse arrow:

```
entitlement:<-identity:
```

Both describe the same connection. You pick the direction that matches how you want to read the query and which nodes you want to start from.

You can chain as many terms as you need, adding one arrow between each pair:

```
identity:->entitlement:->risk:
```

This reads as "an identity that holds an entitlement that carries a risk."

Switch to the graph view to see the matching paths. Each row traces an identity (left) through the entitlement it holds to the risk that entitlement carries (right), with the nodes that match your query highlighted in yellow:

<figure><img src="/files/QUMwzINaCyiXCEXajAbD" alt="Graph view of the query identity arrow entitlement arrow risk, showing identities such as Okta users and AWS IAM roles connected through AWS policy assignments and privileges to critical data-exfiltration risks, with matching nodes highlighted in yellow"><figcaption><p>The graph view for <code>identity:->entitlement:->risk:</code></p></figcaption></figure>

{% hint style="warning" %}
A single path must use one direction throughout. Mixed paths like `a:->b:<-c:` are not supported. Use all `->` or all `<-` within one path.
{% endhint %}

{% hint style="info" %}
Arrows follow the real connections in the graph, so not every combination is valid. For example, `identity:->entitlement:->risk:` works, but `resource:->risk:` doesn't, because resources don't connect directly to risks. The [IAM graph diagram](/inventory/query-search/search-reference#iam-graph) shows which connections exist.
{% endhint %}

## Reading a worked example

Now you can read the example query from the top of this guide:

```
identity:->identity:->entitlement:->risk:
```

Walk through it one hop at a time, left to right:

1. `identity:` - Start from an identity.
2. `->identity:` - Follow the connection forward to another identity that the first one is linked to. For example, a user and a group or role that user can act through.
3. `->entitlement:` - Follow the connection forward to an entitlement that this second ("right") identity holds.
4. `->risk:` - Follow the connection forward to a risk that the entitlement carries.

Put together, the query finds **identities that are linked to other identities, the entitlements those linked identities hold, and the risks those entitlements carry**. It's a way to surface indirect risk: access that one identity gains through another, and the danger that access brings.

The graph view makes each hop visible. Here, Okta users reach groups, which hold AWS policy assignments, whose privileges carry critical exfiltration risks, each matching node highlighted in yellow:

<figure><img src="/files/0i56CvmCJV91MkaMpyCC" alt="Graph view of the query identity arrow identity arrow entitlement arrow risk, showing Okta users connected to Okta groups, then to AWS roles and policy assignments, then to privileges that carry critical data-exfiltration and cryptographic-exfiltration risks, with matching nodes highlighted in yellow"><figcaption><p>The graph view for <code>identity:->identity:->entitlement:->risk:</code></p></figcaption></figure>

## More example queries

| Query                                                | What it finds                                     |
| ---------------------------------------------------- | ------------------------------------------------- |
| `identity:`                                          | Every identity in your inventory.                 |
| `identity:type:service-account`                      | Every service account.                            |
| `credential:type:key`                                | Every static access key.                          |
| `identity:->entitlement:`                            | Identities and the entitlements they hold.        |
| `entitlement:->risk:`                                | Entitlements that carry any risk.                 |
| `entitlement:->risk:CRITICAL`                        | Entitlements that carry a critical risk.          |
| `identity:type:service-account->entitlement:->risk:` | Service accounts whose entitlements carry a risk. |

## Build queries visually with the Query builder

If you'd rather not type the syntax by hand, use the **Query builder**. Click the **+** button next to the **where** box, above the table or graph, to open it.

The Query builder is a form that assembles one search term and inserts it into the **where** box for you. In it, you:

1. Choose a connection: **are** (match the displayed node itself) or **can reach** (match a node it connects to).
2. Select a search type, such as **identities** or **entitlements**, and an attribute to filter on.
3. Pick **containing** (substring) or **equal to** (exact), then enter a keyword.
4. Optionally turn on **Invert match?** to apply the `!` operator, **Remove match?** to apply the exclusion operator (`^`), or **Only first node?** to match just the first node in a chain.

A live preview shows the term as you build it. Click **Add term** to drop it into the **where** box, where you can edit it or chain it with other terms.

{% hint style="info" %}
The Query builder produces ordinary query text, the same syntax this guide describes. It's a quick way to discover operators and exact attribute values; once you know the syntax, typing is often faster.
{% endhint %}

## Next steps

* Try a query: open the **Inventory** page, choose what to display in the **show** control, and type a query in the **where** box. See [Access Inventory](/inventory/access-inventory) for a tour of the search interface.
* Look up the rest of the operators (exact matches, inverted matches, exclusions, and more) with every search term and attribute in the [Search Reference](/inventory/query-search/search-reference).


# Search Reference

This page is the complete reference for inventory queries: every query operator, search term, attribute, and allowed value. If you're new to the query language, read [Query Language Basics](/inventory/query-search/query-language-basics) first for a guided introduction. This page is for looking up specifics.

## Query operators

Query expressions let you be more specific in your searches. Here's a summary of every operator:

<table><thead><tr><th width="272.3333333333333">Expression</th><th width="218">See</th><th></th></tr></thead><tbody><tr><td>Key terms</td><td></td><td></td></tr><tr><td><code>keyword</code></td><td><a data-mention href="#contains-matches">#contains-matches</a></td><td>Match data substring</td></tr><tr><td><code>"keyword"</code></td><td><a data-mention href="#exact-matches">#exact-matches</a></td><td>Match data exactly</td></tr><tr><td><code>/keyword/</code></td><td><a data-mention href="#regex-matches">#regex-matches</a></td><td>Match data by regular expression</td></tr><tr><td><code>!keyword</code></td><td><a data-mention href="#inverted-matches">#inverted-matches</a></td><td>Invert keyword matches</td></tr><tr><td>Node terms</td><td></td><td></td></tr><tr><td><code>type:keyterm</code></td><td><a data-mention href="#type-matches">#type-matches</a></td><td>Match data types</td></tr><tr><td><code>type=keyterm</code></td><td><a data-mention href="#first-matches">#first-matches</a></td><td>Match first datum only</td></tr><tr><td><code>type:attribute:keyterm</code> or <code>type:{attribute1:keyterm1 attribute2:keyterm2 ...}</code></td><td><a data-mention href="#attribute-matches">#attribute-matches</a></td><td>Match data attributes</td></tr><tr><td>Path terms</td><td></td><td></td></tr><tr><td><code>keyterm->childpath</code></td><td>Child paths</td><td>Match a directed path in child direction</td></tr><tr><td><code>keyterm&#x3C;-parentpath</code></td><td>Parent paths</td><td>Match a directed path in parent direction</td></tr><tr><td><code>keyterm&#x3C;>eitherpath</code></td><td>Either paths</td><td>Match a directed path in either parent or child direction</td></tr><tr><td><code>childpath</code> | <code>parentpath</code> | <code>eitherpath</code></td><td><a data-mention href="#via-matches">#via-matches</a></td><td>Place multiple conditions on a data connection</td></tr><tr><td>Exclusion term</td><td></td><td></td></tr><tr><td><code>^pathterm</code></td><td><a data-mention href="#exclusion-matches">#exclusion-matches</a></td><td>Remove matches from results</td></tr><tr><td>Compound expression</td><td></td><td></td></tr><tr><td><code>expression term</code></td><td><a data-mention href="#multiple-matches">#multiple-matches</a></td><td>Require multiple data connections</td></tr></tbody></table>

*Cypher equivalents*

Each detailed explanation below also describes the equivalent statement in the Cypher query language (replace `{show}` with the corresponding label of the "show" control).

When displaying data as a table, the displayed data are the nodes matching the "show" type (represented by `s` in the equivalent queries); when displaying data as a graph visualization, the displayed data are the returned paths (represented by `p` in the equivalent queries).

### "Contains" matches

In its simplest usage, P0 matches IAM data if it includes your search keyword. For example, searching for `compute` shows you grants that allow access to any compute resource, give any privileges with "compute" in their name, grant a permission set with "compute" in its name, or grant access to compute service principals.

"Contains" matches are case insensitive; use [#exact-matches](#exact-matches "mention") to find data with exact casing.

*Cypher equivalent*:

```cypher
CALL () {
    MATCH p=(s:{show})-[*]->(r)
    RETURN p, r, s
    UNION
    MATCH p=(r)-[*]->(s:{show})
    RETURN p, r, s
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
```

### Exact matches

To match data exactly, enclose your keyword in double quotes. For example, searching for `compute.instances.get` in GCP matches extra permissions, such as `compute.instances.getEffectiveFirewalls`. Searching for `"compute.instances.get"` limits results to only those grants that have that specific permission.

{% hint style="info" %}
When using exact matches with type and attribute matches, the quotes surround the keyword only: `type:attribute:"keyword"`.

You can also use quotes to search for data where the data includes a colon without triggering a type or attribute match. For example, `risk:"exfiltration:data"` returns all results that yield a data exfiltration risk.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] = '{keyword}')
RETURN p, s
```

### Regex matches

To match data against a regular expression, enclose your pattern in forward slashes. For example, `/^arn:aws:iam::\d+:role\//` matches values that start with an AWS IAM role ARN prefix, and `/prod|staging/` matches values containing either `prod` or `staging`.

P0 evaluates the pattern with the standard JavaScript regular expression engine, so anchors (`^`, `$`), character classes, quantifiers, and alternation (`|`) all work as you'd expect.

Regex matches combine with type and attribute matches the same way other keywords do. The slashes surround the pattern only: `type:/pattern/` or `type:attribute:/pattern/`. To invert a regex match, place the `!` before the pattern: `type:attribute:!/pattern/`. See [#inverted-matches](#inverted-matches "mention").

{% hint style="warning" %}
Regex matches are **case sensitive**, unlike [#contains-matches](#contains-matches "mention"), which are case insensitive. JavaScript inline flags such as `/pattern/i` aren't supported, so express case insensitivity inside the pattern, for example, `/[Pp]rod/`.
{% endhint %}

{% hint style="info" %}
To match a literal forward slash inside the pattern, escape it as `\/`, for example, `/role\/Admin/`. An empty pattern (`//`), an unclosed pattern (`/abc`), or a syntactically invalid pattern is rejected. P0 also rejects patterns that are vulnerable to [ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) (catastrophic backtracking), such as `/(a+)+$/`; simplify the pattern if you hit this.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE r[k] =~ '{keyword}')
RETURN p, s
```

### Inverted matches

You can search for grants and principals that are connected to data that *don't* match a keyword by typing a `!` in front of your search keyword.

Note that using an inverted match on its own usually doesn't do much, as grants and principals connect to *many* data, and some of these data are likely to not match your keyword. Instead, inverted matches are usually best when combined with type or attribute matches, or with exclusion matches. For example, `principal:mfa:!enabled` shows you all users that have either disabled or unknown MFA status.

{% hint style="info" %}
When using inverted matches with type and attribute matches, the `!` comes *after* the type and attribute: `type:attribute:!keyword`.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE ANY(k IN KEYS(r) WHERE NOT ({keyterm condition}))
RETURN p, s
```

### Exclusion matches

You can search for items that aren't connected to data that match a term by typing a `^` in front of your entire search term.

For example, searching for `^usage:type:"unused"` shows all grants that have only used or unknown permission usage. Searching for `^usage:type:!"unused"` shows all grants where *all* permissions are unused.

{% hint style="info" %}
When using exclusion matches, the `^` comes *before* the type and attribute: `^type:attribute:keyterm`.
{% endhint %}

*Cypher equivalent*:

```cypher
MATCH (s1:{show})
WHERE (COUNT {
    // pathterm query w/out "RETURN"
    AND s=s1
}) = 0
RETURN s1
```

### Type matches

Limit your search to a specific type of IAM data using a type prefix. For example, adding `risk:CRITICAL` in front of your search limits your search to only showing grants that allow a critical IAM risk (as defined by the [IAM Privilege Catalog](https://catalog.p0.dev/scores)). See [#search-types](#search-types "mention") for a list of all possible types.

{% hint style="info" %}
You can use a type match without a keyword to search for the presence of data.

For example, `condition:` shows you all conditional grants.
{% endhint %}

*Cypher equivalent*:

<pre class="language-cypher"><code class="lang-cypher"><strong>CALL () {
</strong>    // per "contains" CALL statement
}
WITH p, r, s
WHERE r:{type} AND ANY(k IN keys(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
</code></pre>

### "First" matches

Data may connect to a chain of items of the same type. For instance, a grant on a resource gives access to all that resource's children, and all those child resources' children, and so forth. Or, grants may target directory groups with nested group membership.

To restrict your search to only the first item in such a chain, use a first match. For example, `principal=alice@my.co` shows only the `alice@my.co` user, and not the groups to which that user belongs.

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE NOT (p)-[*]->(:{type})-[*]->(r)
  AND NOT (r)-[*]->(:{type})-[*]->(p)
  AND ANY(k IN keys(r) WHERE r[k] =~ '(?i).*{keyword}.*')
RETURN p, s
```

### Attribute matches

Attribute expressions allow you to make even more specific searches. For example, searching for `credential:last90:unused` limits displayed principals to those with at least one credential that hasn't been used in the previous 90 days. See [#search-attributes](#search-attributes "mention") for a list of all possible attributes.

{% hint style="info" %}
You can combine first and attribute matches using the syntax `{type}={attribute}:{keyterm}`.
{% endhint %}

*Cypher equivalent*:

```cypher
CALL () {
    // per "contains" CALL statement
}
WITH p, r, s
WHERE r:{type} AND r.{attribute} =~ '(?i).*{keyword}.*'
RETURN p, s
```

### Multiple matches

Return items that connect to multiple data by separating search terms using whitespace.

For instance, `resource:one resource:two` shows you grants that give access to both resources "one" and "two".

*Cypher equivalent*:

```cypher
CALL () {
    // Result of first query
    RETURN p AS p1, s AS s1
}
WITH p1, s1
CALL () {
    // Result of second query
    RETURN p AS p2, s AS s2
}
WITH p2, s2
WHERE s1 = s2
RETURN s1, p1, p2
```

### Via matches

Your IAM data are modeled as a directed graph. You can require data to connect to your search results according to multiple search terms using a via match.

To use a via match, connect two or more terms using `->` (for child relationships), `<-` (for parent relationships), or `<>` (for either child or parent relationships).

For example, to find all entitlements that have unused permissions that create a data exfiltration risk, you can search for `usage:type:"unused"->risk:"exfiltration:data"`.

You can chain multiple terms together using more `->`. For example `usage:type:"unused"->privilege:s3->risk:"exfiltration:data"`.

{% hint style="warning" %}
Paths must consistently use child, parent, or "either" relationship syntax. Mixed paths like `a->b<-c` are not currently supported.
{% endhint %}

You can reference how data are connected in this graph using [#iam-graph](#iam-graph "mention").

{% hint style="info" %}
Exclusion matches combined with via matches return results where one or more of the via conditions don't match.
{% endhint %}

*Cypher equivalent for* `s<>r`:

```cypher
CALL () {
    MATCH p=(s:{show})-[*]->(q)-[*]->(r)
    RETURN p, q, r, s
    UNION
    MATCH p=(r)-[*]->(q)-[*]->(s:{show})
    RETURN p, q, r, s
}
WITH p, q, r, s
WHERE
    // constraints on q
    AND
    // constraints on r
RETURN p, s
```

## Search types

These are all the possible search types, and their meaning:

* **awsPolicy** - an AWS policy
* **condition** - a grant condition
* **consumer** - the entity that authenticates using a credential; this is typically an IP address
* **credential** - a single authentication credential; search matches the name of the credential (e.g. ID of an API key); will be "federated" if the principal authenticates using SSO
* **entitlement** - a set of privileges to use one or more resources, granted to an identity (an entitlement may be an AWS policy assignment, GCP role binding, or Azure / Kubernetes / Okta / Workspace role assignment)
* **identity** - an IAM identity; search matches the name of the identity (e.g. email; group name, AWS role name, etc.)
* **lateral** - represents potential machine-identity impersonation; each path is represented by two graph nodes, one attached to the grant that allows impersonation, the other attached to the principal that can be impersonated (see `lateral:flow` below)
* **permissionSet** - an AWS permission set
* **privilege** - a grantable privilege (this can be an AWS action, or Azure, Google Cloud, Okta, or Workspace permission)
* **resource** - an IAM resource
* **risk** - a security risk associated with holding a privilege; possible risks are listed in the [IAM Privilege Catalog](https://catalog.p0.dev/risks); you can also search for risk severity scores (e.g. `CRITICAL`)
* **role** - an Azure, Google Cloud, Kubernetes, Microsoft Entra ID (directory role, such as Global Administrator), Okta, or Workspace role (note that this is *not* an AWS role; use `identity:type:aws-iam-role` to search AWS roles)
* **usage** - represents privilege usage (in the last 90 days):
  * `used` - the privilege was used in the last 90 days
  * `unused` - the privilege has been unused for all of the previous 90 days
  * `unknown` - P0 lacks evidence to determine if the privilege is used or unused

## Search attributes

Search attributes allow more specific type searches. Allowable attributes are:

{% hint style="info" %}
Microsoft Entra data uses two provider values: `entra-id` for the current Microsoft Entra ID integration and `azure-ad` for the legacy Azure AD integration. Search the value that matches your installed integration. Azure cloud resources (subscriptions, role assignments) use the separate `azure` provider.
{% endhint %}

* **condition:expression** - a grant condition's expression
* **credential:stale90** - represents whether this credential is stale: created more than 90 days ago (`true`) or more recently (`false`)
* **credential:last40** & **credential:last90** - represents if this authentication method has been used in the previous 40 or 90 days (respectively); values are `used` or `unused`
* **credential:type** - the type of the authentication credential; may be one of
  * `federated` - a credential from an external IAM system
  * `key` - a static secret credential
  * `password` - a user password credential (for example, a Microsoft Entra ID user password)
  * `short-lived` - represents all ephemeral credentials, including JWTs, temporary keys, account impersonation, and the like
* **entitlement:cross** - true if access is granted to an identity managed outside of the IAM resource (e.g. a GCP role assigned to an Okta user)
* **entitlement:parent** - the scope (AWS account, Azure subscription, GCP project, etc.) in which this entitlement is defined
* **entitlement:principal** - the principal identity granted access by this entitlement
* **entitlement:principalType** - the identity type of this entitlement's principal identity (see `identity:type` below for possible values)
* **entitlement:provider** - the service in which this entitlement is defined; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **entitlement:resource** - the resource(s) to which this entitlement grants access
* **entitlement:role** - the role granted by this entitlement
* **identity:accessAdd** - who can add users to this group (only available for Workspace groups):
  * `admin` - only group administrators can add users
  * `group` - anyone in the group can add users
  * `owner` - only the group owners can add users
  * If not present, no one can directly add users
* **identity:accessApprove** - who can approve group join requests (only available for Workspace groups):
  * `admin` - only group administrators can approve requests
  * `group` - anyone in the group can approve requests
  * `owner` - only the group owners can approve requests
  * If not present, no one can approve requests
* **identity:accessJoin** - who can join this group without approval (only available for Workspace groups):
  * `public` - anyone on the Internet can join
  * `domain` - anyone in the Workspace domain can join
  * `invited` - users can join if they've received an invite
  * If not present, users can only be directly added to the group
* **identity:accessView** - who can view this group's content (only available for Workspace groups; content is the group's messages):
  * `public` - anyone on the Internet can view
  * `domain` - anyone in the Workspace domain can view
  * `group` - anyone in the group can view
  * `admin` - only group administrators can view
* **identity:external** - true if the identity is managed outside the assessed environment
* **identity:parent** - the scope (AWS account, Azure subscription, GCP project, etc.) that manages this identity
* **identity:provider** - the service that manages this identity; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **identity:status** - one of:
  * `enabled` - the principal can authenticate
  * `disabled` - the principal's authentication is disabled
* **identity:type** - the type of the IAM principal; may be one of
  * `aws-iam-role` - an AWS IAM role
  * `aws-permission-set-role` - an AWS IAM role automatically generated by AWS when assigning an AWS permission set to an account
  * `entra-app-registration` - a Microsoft Entra ID application registration (the application object that defines an app and its permissions)
  * `federated` - an identity used to provide access to identities from another provider (e.g. an AWS IAM role with `Principal.Federated` in its trust relationship); the identity's parents will be the federated identities
  * `group` - a directory group
  * `public` - any identity
  * `service-agent` - a provider-managed account
  * `service-account` - a machine identity (in AWS this is usually an AWS role)
  * `service-principal` - a Microsoft Entra ID service principal (the local instance of an application or managed identity within a tenant)
  * `user` - a user identity
* **lateral:type** - the mechanism via which lateral escalation can be achieved:
  * `grant` - lateral movement via a granted privilege (e.g. GCP `iam.serviceAccounts.actAs` or AWS `sts:assumeRole`)
  * `resource` - lateral movement via usage of a service-linked resource (e.g. lateral movement to a compute service identity via shell access)
  * Note: federated access is represented as a direct principal-to-principal relationship, and is not modeled via lateral-movement
* **privilegeSet:provider** - the service that manages this role or AWS policy; possible values are `aws`, `azure`, `azure-ad`, `entra-id`, `gcp`, `k8s`, `okta`, or `workspace`
* **resource:service** - the resource's parent cloud service; use the API path of the service (e.g. `sso` instead of `Identity Center`)
* **resource:type** - the resource's type (e.g. `bucket`)
* **risk:score** - the access risk score from the [IAM Privilege Catalog](https://catalog.p0.dev/risks); one of `CRITICAL`, `HIGH`, `MEDIUM`, `BOOST`, `EVASION`, or `LOW`

## IAM graph

Your IAM data are connected in a directed graph, as shown, with each node label indicating the datum's respective type:

<div data-full-width="true"><figure><img src="/files/eaDEI372kpVB57bLgdPt" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
Via queries should only be used for types matching along a directed path in this graph. E.g., `principal:->used:->risk:` will produce matches, but `resource:->risk:` will not.
{% endhint %}

## Query builder

You can assemble a single search term with the **Query builder** instead of typing it. Click the **+** button beside the **where** box, above the table or graph, to open the builder form. As you set each control, the builder shows a live preview of the term, and clicking **Add term** inserts it into the **where** box.

Each control maps to an operator described above:

| Builder control                                   | Effect on the term                                                                   |
| ------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Show … that are** vs **can reach**              | Matches the displayed node itself (`=`) or a node it reaches (`:`).                  |
| Search type (**identities**, **entitlements**, …) | Adds the [type prefix](#type-matches), such as `identity:`.                          |
| **with** *(attribute)*                            | Adds an [attribute filter](#attribute-matches).                                      |
| **containing** vs **equal to**                    | [Substring match](#contains-matches) or [exact match](#exact-matches) (`"keyword"`). |
| **Invert match?**                                 | Applies the `!` [inverted](#inverted-matches) operator to the keyword.               |
| **Remove match?**                                 | Applies the `^` [exclusion](#exclusion-matches) operator to the term.                |
| **Only first node?**                              | Uses `=` instead of `:` to match only the [first node](#first-matches) in a chain.   |

The builder constructs one term at a time and produces ordinary query text, the same as what you would type by hand. To require several conditions, add multiple terms (see [Multiple matches](#multiple-matches)).


# Posture Overview

Detect access vulnerabilities with automated monitors. View scan results, define custom policies, and enforce organization-specific access controls with P0.

When P0 scans your environment, it automatically runs P0-provided monitors against your data to detect access vulnerability issues. You can also define custom monitors to enforce your organization-specific access policies.

When you select **Posture** in the P0 app sidebar, you see the results of each monitor:

<figure><img src="/files/En5gA1PKFJUuR8KQeqoO" alt="Posture overview page showing findings summary with urgent, new, and average age metrics, filter controls, and a list of monitors with severity and count"><figcaption></figcaption></figure>

#### Filtering results

You can narrow results to a specific target scope (e.g. AWS account, Azure subscription, or GCP project) or monitor.

By default, this display shows you all open findings. Select the filter icon to reveal the filter controls.

Use the **Status** dropdown to filter by finding status:

* `Open`: show open findings (issues appearing in the latest run that are not manually ignored)
* `Ignored`: show only ignored findings (see [Finding Details](/posture/finding-details#ignoring-findings) to learn how)
* `Resolved`: show findings that have been resolved

Enable the **Unassigned** checkbox to show only findings that haven't been assigned. Clear it to show all findings.

Fixed findings are resolved automatically by P0 when they are no longer detected in your latest assessment run.

#### Results export

Select "Export" to download these results as a TSV or JSON file.

#### Result details

Selecting a monitor takes you to that monitor's [Monitor Results](/posture/monitor-results) page.

#### Custom monitors

To create a custom monitor, run a query search in [Access Inventory](/inventory/access-inventory), then follow the instructions in [Access Inventory](/inventory/access-inventory#creating-custom-monitors).


# Create a custom monitor

Build a custom posture monitor in P0 to continuously detect a specific access vulnerability, such as unused privileged grants, across every environment scan.

P0 runs its built-in monitors against your environment on every scan to surface common access vulnerabilities. When you need to enforce a policy that's specific to your organization (for example, flagging unused privileged grants or credentials that violate your rotation policy), you create a custom monitor.

A custom monitor turns an [inventory query](/inventory/query-search) into a recurring check. P0 re-runs the query on every scan and reports matches as findings in [Monitor Results](/posture/monitor-results), alongside your built-in monitors.

## Prerequisites

Before you start, make sure you have:

* A P0 account with the **Owner** or **Admin** role. See [Role-Based Access Control](/p0-management/role-based-access-control).
* At least one [resource integration](/integrations/resource-integrations) connected to an [environment](/environments/creating-an-environment).
* A completed access scan. If you haven't run one yet, follow [Getting Started with Inventory & Posture](https://github.com/p0-security/p0-docs/blob/main/user-guides/getting-started-with-inventory-and-posture.md).
* Familiarity with P0 [query expressions](/inventory/query-search). This guide uses them to define what the monitor detects.

## Build and save the monitor

You create custom monitors from the **Inventory** page, where you can write and test a query before promoting it to a monitor.

1. Select **Inventory** in the P0 app sidebar.
2. Select what the monitor evaluates from the **show** control: `credentials`, `identities`, `entitlements`, or `resources`. For example, select `entitlements` to monitor grants.
3. Enter a query in the **where** field that isolates the vulnerability you want to detect. To find entitlements that grant critical-risk privileges that no one has used, enter:

   ```
   usage:type:"unused"->risk:CRITICAL
   ```

   This matches entitlements connected to an unused privilege that carries a `CRITICAL` risk in the [IAM Privilege Catalog](https://catalog.p0.dev/risks).
4. Review the results. Adjust the query until only the grants you want to flag appear. Select **view** on any result to see an **Explanation** of why it matched.
5. Select **Save Search**.
6. Enable the **Create a monitor for this search?** toggle.
7. Enter a **title**, **description**, and **severity** for the monitor. Write the description so a finding's assignee understands the risk and how to resolve it.
8. Save the monitor.

{% hint style="info" %}
To model a new monitor on an existing one, open a built-in monitor in [Monitor Results](/posture/monitor-results) and reuse its query as a starting point. For example, the built-in unused service-account key monitor uses `show = credential` with:

```
credential=enabledKey:"true"
credential=last40:"unused"
principal=type:"service-account"
principal=status:"active"
```

{% endhint %}

## Verify the monitor

Confirm the monitor is active and reporting:

1. Select **Posture** in the sidebar.
2. Find your monitor by its title in the monitor list. It appears with the severity you assigned.
3. Select the monitor to open its [Monitor Results](/posture/monitor-results) page and review the findings from the most recent scan.

P0 re-evaluates the monitor on every scan. New matches appear as open findings, and P0 resolves findings automatically once a grant no longer matches the query.

From the results, you can [assign, ignore, or review fixes](/posture/finding-details) for findings, and route them to your [ticketing system](/integrations/tracker-integrations).

## Troubleshooting

| Problem                                    | Cause                                               | Fix                                                                                                                                                |
| ------------------------------------------ | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| The monitor returns no findings            | The query is too narrow, or no current data matches | Re-run the query on the Inventory page and confirm it returns the expected results before saving                                                   |
| The monitor returns too many findings      | The query is too broad                              | Add [type, attribute, or via matches](/inventory/query-search) to narrow scope, for example, scope to one provider with `entitlement:provider:aws` |
| The monitor isn't in the Posture list      | Findings appear after the next scan completes       | Wait for the next scan, or trigger a scan from the [environment settings](/environments/settings)                                                  |
| Results changed unexpectedly between scans | The underlying access data changed                  | Open a finding and review its **Explanation** to see why it now matches                                                                            |

## What's next

* Tune detection with the full [query expression reference](/inventory/query-search/search-reference).
* [Analyze and resolve findings](/posture/finding-details) the monitor produces.
* Connect a [tracker integration](/integrations/tracker-integrations) to assign findings automatically.


# Monitor Results

Each monitor results page shows details of the monitor itself at the top of the page:

* The monitor name
* The monitor severity
* A detailed description of the monitor
* The history of new and resolved findings for this monitor

<figure><img src="/files/141CrIKrrpMMcQ0LnEQA" alt="Monitor results page for AWS Policies With Unused Privileged Access showing severity, findings history chart, and a table of policy findings" width="563"><figcaption></figcaption></figure>

Below is a list of findings for the monitor, filterable by finding status and target scope (AWS account, Azure subscription, GCP project, etc.).

#### Finding details

Click "view" next to a finding to get its detailed view. See [Finding Details](/posture/finding-details) for documentation on this display.

#### Bulk actions

You can [assign](/posture/finding-details#assigning-findings), [ignore](/posture/finding-details#ignoring-findings), or review fixes for multiple findings at once. If no findings are selected, operations apply to all findings.


# Finding Details

To view extended information for a single finding, click "view" next to a monitor result. This opens that finding's details:

<figure><img src="/files/2zdfyiAEzfqElwIxNG8P" alt="Finding details page showing attack path visualization, actions for Assign, Ignore, and Review fix, and risk details for an AWS IAM policy" width="563"><figcaption></figcaption></figure>

### Actions

#### Assign

If you've integrated P0 with Jira, you can assign findings for resolution. By default, you manually assign the assignee. If you've configured P0 for automatic assignment, the configured resource owner for the target scope in which the finding was discovered determines the assignee.

The created Jira ticket contains the finding description, finding context, and, if available, the resolution commands.

#### Ignore

To ignore a finding, click the "Ignore" button on that finding's details. The finding no longer appears in your results, unless you select "Ignored" in the results views.

#### Review fix

For P0-provided monitors, P0 provides cloud shell commands that resolve the finding. For example, for the "Unused Privileged Access" finding, P0 provides commands to replace the vulnerable entitlement with a least-privilege entitlement.

<figure><img src="/files/RjndgWnpG66UvxOQCynO" alt="Remediation commands showing a least-privilege IAM policy replacement for an overly permissive AmazonEC2FullAccess policy" width="375"><figcaption></figcaption></figure>

#### Add notes

Add notes, including business justifications, to findings by typing on the finding's details page.

### Attack path

P0 displays a graphical representation of the finding's attack path: how an actor holding the identity can gain risky access to your system.

The attack path view has the same capabilities as the [Access Inventory](/inventory/access-inventory#graph-visualization) in the Access Inventory.

### Detailed information

The remainder of this page shows detailed information for the finding, and explains why this finding matched the monitor's search. For an explanation of this information, see [Result Details](/inventory/result-details).


# Just-in-time access

Set up ephemeral, on-demand access to production resources. Requests are approved, provisioned, and automatically revoked within minutes using P0 Security.

Just-in-time (JIT) access allows your organization's users to gain ephemeral access to individual production resources on demand, replacing standing access. Access is requested, approved, provisioned, and automatically revoked, all within minutes.

{% hint style="info" %}
**New to P0?**

* **Developers requesting access:** Start with the [request access quickstart](/getting-started/request-access-quickstart) to submit your first request in minutes.
* **Administrators setting up P0:** Start with the [Getting started with just-in-time access](/getting-started/getting-started-with-just-in-time-access) guide to configure integrations and approval workflows.
  {% endhint %}

## How it works

1. A user **requests** access to a specific resource (via Slack, the P0 web app, or the [P0 CLI](/p0-cli/p0-commands-and-usage/p0-request)).
2. P0 **routes** the request to the appropriate approver based on your organization's policies.
3. An approver **reviews and approves** (or denies) the request.
4. P0 **provisions** access automatically and notifies the requestor.
5. Access **expires** after the approved duration, or the requestor relinquishes it early.

## Request access

Learn how to create, track, and manage access requests:

* [Requesting access](/access-management/just-in-time-access/requesting-access): Create access requests via Slack or the P0 web app, discuss with approvers, and manage active sessions.
* [Request on behalf of another user](/access-management/just-in-time-access/requesting-access/for-another-party): Submit access requests for a colleague or service account.
* [Web request modal](/access-management/just-in-time-access/requesting-access/web-request-modal): Use the P0 web app to request access directly from your browser.

You can also request access using the P0 CLI. See [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request), [`p0 aws role assume`](/p0-cli/p0-commands-and-usage/p0-aws-role-assume), and [`p0 ssh`](/p0-cli/p0-commands-and-usage/p0-ssh) for command-line workflows.

## Approve access

Configure approval policies and review incoming requests:

* [Approving access](/access-management/just-in-time-access/approving-access): Configure approvers, review requests, and manage approval workflows.
* [Pre-approving access](/access-management/just-in-time-access/approving-access/pre-approving-access): Set up standing approvals so that specific users or groups receive access automatically.
* [P0 Allow modal, CLI, and UI](/access-management/just-in-time-access/approving-access/p0-allow-workflows): Grant pre-approved access through the web app or CLI.

## Configure access policies

Control who can request what, and who approves:

* [Access policies](/access-management/just-in-time-access/request-routing): Define policies that route requests to specific approvers based on the requestor, resource, and access type.
  * [Google Cloud filtering](/access-management/just-in-time-access/request-routing/google-cloud-filtering)
  * [AWS filtering](/access-management/just-in-time-access/request-routing/aws-filtering)
  * [Microsoft Azure filtering](/access-management/just-in-time-access/request-routing/microsoft-azure-filtering)
  * [SSH filtering](/access-management/just-in-time-access/request-routing/ssh-filtering)

## Monitor and audit

* [Session recording](/access-management/just-in-time-access/session-recording): View detailed activity logs for privileged sessions to answer questions about what happened during access.

## Automate with the API

* [Just-in-time API](/access-management/just-in-time-access/just-in-time-api): Programmatically manage access workflows, including the [Command API](/access-management/just-in-time-access/just-in-time-api/command-api), [Access Requests API](/access-management/just-in-time-access/just-in-time-api/access-requests-api), and [Access Policies API](/access-management/just-in-time-access/just-in-time-api/access-policies-api).


# Requesting Access

Request just-in-time access to cloud resources using P0.

Need temporary access to a cloud resource? P0 lets you request time-limited access that's automatically provisioned after approval and revoked when it expires.

You can request access through any of these methods:

| Method              | Best for                                      | Details                                                     |
| ------------------- | --------------------------------------------- | ----------------------------------------------------------- |
| **Slack**           | Quick requests when you already use Slack     | [Request via Slack](#request-via-slack)                     |
| **Microsoft Teams** | Quick requests when you already use Teams     | [Request via Microsoft Teams](#request-via-microsoft-teams) |
| **Web app**         | Browser-based requests without Slack or Teams | [Request via the web app](#request-via-the-web-app)         |
| **CLI**             | Terminal workflows and automation             | [Request via the CLI](#request-via-the-cli)                 |

## How access requests work

1. You **request** access to a specific resource, role, or permission.
2. P0 **routes** the request to the appropriate approver based on your organization's policies.
3. An approver **reviews and approves** (or denies) the request.
4. P0 **provisions** access automatically and notifies you.
5. Access **expires** after the approved duration, or you relinquish it early.

{% hint style="info" %}
Most IAM systems have a propagation delay of 10-60 seconds after access is provisioned before you can use it.
{% endhint %}

## Request via Slack

If your organization has installed the [Slack integration](/integrations/notifier-integrations/slack), you can request access directly from Slack.

### Using the Slack request modal

Open the interactive modal to discover available resources and access modes:

* Type `/p0 request` in any Slack channel
* Or click the **Run Shortcut** icon in the message draft bar, then search for and select **Request access**

<figure><img src="/files/DTQwubIk7vMN7kPCnTWG" alt="" width="375"><figcaption></figcaption></figure>

Select a resource and access type, then fill out the remaining fields. You may skip optional fields.

<figure><img src="/files/uTk7OYw7KVCRjhHHE1My" alt="" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
The "reason" field is optional, but highly recommended. Filling this out helps your request get approved more quickly.
{% endhint %}

Once you've filled out all required fields, click **Request**. P0 then sends you a DM with details of your request.

<figure><img src="/files/1pmITc1dqKrCdLkE1j63" alt="" width="375"><figcaption></figcaption></figure>

### Using Slack slash commands

If you already know what you need, use slash commands for faster requests:

```
/p0 request gcloud role my-project viewer --reason "investigating production issue"
```

Add `--help` to any command to see available options. You can also type an incomplete command (for example, `/p0 request aws policy`) to open a filled modal.

## Request via Microsoft Teams

If your organization has installed the [Microsoft Teams integration](/integrations/notifier-integrations/microsoft-teams), you can request access by messaging the P0 Security bot directly in Teams.

### Sending a request message

Open a direct message with the **P0 Security** bot and type your request. For example:

```
request gcloud role my-project viewer --reason "investigating production issue"
```

The bot presents an interactive card where you can fill in resource details, select an access type, and submit your request.

### Supported commands

You can use the following commands when messaging the P0 Security bot:

| Command   | Purpose                              |
| --------- | ------------------------------------ |
| `request` | Request access to a resource         |
| `ls`      | List available resources             |
| `help`    | Display available commands and usage |

Type `help` to see the full list of available commands and options.

## Request via the web app

1. Open the [P0 app](https://p0.app) and navigate to **Access Management**.
2. Click **Request Access** in the header.
3. Fill in the resource, role, duration, and reason.
4. Submit for approval.

You can also repeat an earlier request without re-entering its details: open the request from the **Access Management** page and click **Request again** to open the modal prefilled with that request's values.

For a detailed walkthrough, see [Web request modal](/access-management/just-in-time-access/requesting-access/web-request-modal).

## Request via the CLI

The [P0 CLI](/p0-cli/installing-p0-cli) provides command-line access requests that integrate with your terminal workflow.

After [installing](/p0-cli/installing-p0-cli) and [logging in](/p0-cli/p0-commands-and-usage/p0-login), use these commands:

| Command                                                                                      | Purpose                                                  |
| -------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| [`p0 request`](/p0-cli/p0-commands-and-usage/p0-request)                                     | Request access to any supported resource                 |
| [`p0 aws role assume`](/p0-cli/p0-commands-and-usage/p0-aws-role-assume)                     | Request and assume an AWS IAM role                       |
| [`p0 aws permission-set assume`](/p0-cli/p0-commands-and-usage/p0-aws-permission-set-assume) | Request and assume an AWS Identity Center permission set |
| [`p0 ssh`](/p0-cli/p0-commands-and-usage/p0-ssh)                                             | Request and establish an SSH session                     |
| [`p0 kubeconfig`](/p0-cli/p0-commands-and-usage/p0-kubeconfig)                               | Request Kubernetes access and configure kubeconfig       |

Use `--wait` with any request command to block until the system provisions access, then automatically execute the underlying tool command.

## Request access to specific resources

The methods described earlier in this topic work for every resource type. For request syntax, access levels, and details specific to a resource, see its integration guide:

| Resource            | Guide                                                                                                             |
| ------------------- | ----------------------------------------------------------------------------------------------------------------- |
| AWS                 | [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access)                                |
| Google Cloud        | [Requesting Google Cloud access](/integrations/resource-integrations/google-cloud/requesting-access)              |
| Microsoft Azure     | [Requesting Microsoft Azure access](/integrations/resource-integrations/microsoft-azure/requesting-access)        |
| Kubernetes          | [Requesting Kubernetes access](/integrations/resource-integrations/kubernetes/requesting-access)                  |
| SSH                 | [SSH](/integrations/resource-integrations/ssh)                                                                    |
| PostgreSQL          | [Requesting PostgreSQL access](/integrations/resource-integrations/postgresql-new/requesting-postgresql-access)   |
| MySQL               | [Requesting MySQL access](/integrations/resource-integrations/mysql/requesting-access)                            |
| Snowflake           | [Snowflake](/integrations/resource-integrations/snowflake)                                                        |
| GitHub              | [Requesting GitHub access](/integrations/resource-integrations/github/requesting-access)                          |
| Salesforce          | [Requesting Salesforce access](/integrations/resource-integrations/salesforce/requesting-access)                  |
| Cloudflare          | [Requesting Cloudflare access](/integrations/resource-integrations/cloudflare/requesting-access)                  |
| Grafana Cloud       | [Requesting Grafana Cloud access](/integrations/resource-integrations/grafana-cloud/requesting-access)            |
| Oracle Cloud        | [Requesting Oracle Cloud access](/integrations/resource-integrations/oracle-cloud/requesting-access)              |
| Tailscale           | [Requesting Tailscale access](/integrations/resource-integrations/tailscale/requesting-access)                    |
| Cisco Secure Access | [Requesting Cisco Secure Access](/integrations/resource-integrations/cisco-secure-access/requesting-access)       |
| Microsoft Entra ID  | [Requesting Microsoft Entra ID access](/integrations/directory-integrations/microsoft-entra-id/requesting-access) |

For the full list of supported resources, see [Resource integrations](/integrations/resource-integrations).

## Discussing your request with approvers

After you submit a request, a message appears in your organization's P0 approval channel (in Slack or Microsoft Teams) asking for approval. Your approver may:

* Approve or deny the request immediately
* Respond in a thread to ask for more information

{% hint style="info" %}
You can't approve your own requests unless you are a configured approver *and* your organization allows one-party approvals.
{% endhint %}

If your organization has configured automatic approvals and you meet the approval conditions (for example, you are on-call on a specified PagerDuty escalation policy), access is granted automatically.

## Gaining access

After approval, P0 provisions access and notifies you. Propagation times vary by system:

| System                                  | Time to use                      |
| --------------------------------------- | -------------------------------- |
| AWS                                     | 10-15 seconds                    |
| Directories (Okta, Entra ID, Workspace) | Depends on SCIM propagation time |
| Google Cloud                            | 30 seconds - 1 minute            |
| PostgreSQL                              | Immediate                        |
| Snowflake                               | Immediate                        |

## Relinquishing access

Access expires automatically after the approved duration. If you finish early, click the **Relinquish** button in your P0 notification (in Slack or Microsoft Teams) or on the **Access Management** page in the P0 app to give up access. This helps avoid unintentional use of elevated permissions.

## Request on behalf of someone else

You can submit access requests for a colleague or service account. See [Request for another party](/access-management/just-in-time-access/requesting-access/for-another-party).

## Related

* [Approving access](/access-management/just-in-time-access/approving-access) -- How approvers review and manage requests
* [Request routing](/access-management/just-in-time-access/request-routing) -- How your organization controls who can request what
* [Pre-approving access](/access-management/just-in-time-access/approving-access/pre-approving-access) -- Set up automatic approvals for specific scenarios


# For Another Party

In addition to using P0 to request just-in-time access for yourself, you can use P0 to request access for another account.

For instance, if you use Terraform to deploy infrastructure, you may need to temporarily escalate the privileges of Terraform's service account during deploy.

## :pray: Creating a 2nd-party request

To make a 2nd-party access request, use the `/p0 grant` slash command in Slack.

The arguments for this command are exactly the same as `/p0 request` (see [Requesting Access](/access-management/just-in-time-access/requesting-access#using-slack-slash-commands)), with a couple changes:

* You must add a `--to <email>` option to your request, using the email identifier of the principal to which you want to grant access
* When requesting access to Google Cloud, use `--principal-type group` or `--principal-type service-account` to grant access to users groups or service accounts, respectively

The principal issuing the `grant` command does not have to be a valid approver. The principal in the `--to` argument must be a valid requestor based on [access policies](/access-management/just-in-time-access/request-routing).

## :speech\_balloon: Discussing your request

After you make your request, an approval message will be sent to your approvals channel. This approval message is exactly the same as for a first-party access request, except that the approval message indicates that you are making the request on behalf of the email you specified:

<figure><img src="/files/rTiTPCxK9zXKBM3lFiyv" alt="Slack approval message showing an on-call approver notified that one user requests access to a storage role on behalf of another user" width="563"><figcaption></figcaption></figure>


# Web Request Modal

## Overview

The **Web Request Modal** in **P0 Security** allows engineers to request **just-in-time** (JIT) and **short-lived** access to cloud resources. You can launch the modal directly from the **P0 App**. This process automates approvals, reduces wait times, and ensures access is provisioned and revoked according to the specified duration, thereby strengthening security by granting permissions only when needed.

## Requesting Access

1. Open the **P0 App**.
2. Click **Access Management**. Click **Request Access**.

<figure><img src="/files/7FIOpdfPOHrpCQMMSrEt" alt="P0 app Access Management page with Activity, Pre Approvals, History, and Shell tabs and the Request Access button highlighted" width="439"><figcaption></figcaption></figure>

3. Fill in the form with resource, role, duration, and reason.
4. Submit for approval.

### Typical Workflow

Request → Approval → Automatic Provisioning → Automatic Revocation

Access expires automatically after the requested duration.

## Request again

To repeat a previous request, reuse it instead of filling out the modal from scratch:

1. On the **Access Management** page, open a request to view its details.

<figure><img src="/files/mfhxbLAJjnd6J9CGao04" alt="P0 Request Details panel with the Request again button highlighted, showing its tooltip explaining it creates a new access request prefilled with this request&#x27;s details"><figcaption></figcaption></figure>

2. Click **Request again**. The **Request Access** modal opens, prefilled with the original request's resource, access type, access arguments, reason, and duration.
3. Edit any field as needed.

<figure><img src="/files/Vb8IcAbI6LHERfgErbx6" alt="Request Access modal prefilled with the Secure Shell (SSH) resource, single-instance access type, and destination miguel-node-2, ready for editing" width="259"><figcaption></figcaption></figure>

4. Submit for approval.

You can start from any request, including one submitted by another user. P0 doesn't carry over the requestor or principal, so submitting always creates a request for you and routes it through normal policy evaluation.

{% hint style="info" %}
If a prefilled value is no longer valid (for example, a deleted role), the field shows the stored value so you can select a new one. If the resource is no longer requestable, P0 shows an error instead of a partial form.
{% endhint %}

**Request again** isn't shown for a request whose access you currently hold—relinquish that access instead, or start from a different request.

If you run into any issues, please reach out to <support@p0.dev> for assistance. We're here to help!


# Approving Access

This page describes how to review and approve just-in-time access requests

This page walks you through the lifecycle of an access request and review.

* :gear: [Configuring approvals](#configuring-approvals)
* :bell: [Request notifications](#request-notifications)
* :white\_check\_mark: [Approving (and denying) access](#approving-and-denying-requests)
* :thinking: [Reviewing requests](#reviewing-requests)

## :gear: Configuring approvals

There are two ways to configure approvals with P0:

* Default approvals
* Access policies

### Default approvals

To use the default approvals, you must configure who can approve and revoke access requests. Do this on [p0.app](https://p0.app)'s "P0 Management" page, under "Access control".

<figure><img src="/files/zeTDW3y3F4f2LurpLh0B" alt="" width="563"><figcaption></figcaption></figure>

Configure *who* can approve access requests by entering approvers' emails in the "Security Reviewers" section. Approvers must have accounts in Slack using the same email addresses.

{% hint style="info" %}
Approvers' email addresses may be from outside your domain.
{% endhint %}

#### Two-party and one-party approvals

By default, a requestor cannot approve their own access requests. If you want to allow requestors to approve their own requests, allow one-party approvals.

#### Auto approvals

In addition to approvals by humans, P0 also allows you to automatically approve requests if the requestor is currently on-call on an escalation policy. See [Approval Integrations](/integrations/approval-integrations) for more details.

#### Escalated approvals

In addition to normal approval flow, P0 allows the requestor to escalate the request using PagerDuty or Incident.io and notify on-call users to approve pending requests. See [Approval Integrations](/integrations/approval-integrations) for setup details.

### Access policies

If you need more fine-grained control over approvals based on who is requesting access, and to what, use access policies. See the [Access Policies](/access-management/just-in-time-access/request-routing) reference for more details.

The remainder of this guide assumes your organization is using default approvals.

## :bell: Request notifications

When an access request is made, P0 creates an approval message in your Slack integration's configured channel.

<figure><img src="/files/nMdyGqFgjO8UE1fFVE8H" alt="" width="375"><figcaption></figcaption></figure>

With default approvals, P0 mentions the `@p0approvers` Slack group, which contains all configured approvers.

If you use access policies with directory group approvers, P0 instead DMs each approver with a link to the approval message.

## :white\_check\_mark: Approving (and denying) requests

To **Approve** this request, first choose an access duration from the "Select expiry" dropdown, then click "Approve".

{% hint style="warning" %}
If you are not in the P0 approvers group, you will receive an error when attempting to approve or deny access.
{% endhint %}

To **Deny** this request, click "Deny".

#### Requesting further justification

If the requestor's justification for requesting access is incomplete or needs follow-up, reply to the request message *in a thread*. The request conversation thread is linked to the access request, and this discussion will be available in future access reviews.

## :thinking: Reviewing requests

You can review all requests made via P0, whether approved or denied, by visiting p0.app and navigating to "Access Management". You see a dashboard of all requests:

<figure><img src="/files/o74EuHdS9z2e7S3mZa4M" alt="" width="563"><figcaption></figcaption></figure>

Clicking the Slack icon in the request description will take you to the approval-message conversation, where you can view any conversation around justification.

You can also get more details on the lifecycle of an individual grant by clicking on a request row to open the "Request Details" drawer:

<figure><img src="/files/OvoYGLmKVBoREExGjAJT" alt="" width="563"><figcaption></figcaption></figure>

Finally, you can export all requests as a tab-separated values list (`.tsv`) by clicking "Export requests".


# Auto-approve access for on-call engineers

Configure P0 to automatically grant just-in-time access to engineers who are on-call, using your PagerDuty or Incident.io schedule. Give responders fast, time-boxed access during incidents without man

This guide shows you how to grant just-in-time access automatically to engineers who are currently on-call, using your PagerDuty escalation policies or Incident.io schedules. When an on-call responder requests a covered resource, P0 approves the request without waiting for a human approver, then expires the access after one hour.

Use this pattern for break-glass and incident-response workflows. Responders need fast access during an incident, but you still want every grant to be time-boxed, logged, and tied to an active on-call shift.

## Prerequisites

Before you begin, confirm the following:

* **P0 organization owner role**: You configure integrations and access policies as an organization owner.
* **An on-call provider**: Either a PagerDuty account where you are an admin, or an Incident.io account where you are an administrator with API key access.
* **A resource integration**: At least one resource integration (AWS, Google Cloud, Azure, SSH, Kubernetes, or another) installed, so there is something to grant access to. See [Resource integrations](/integrations/resource-integrations).
* **Matching identities**: The email addresses your engineers use in PagerDuty or Incident.io match the identities they use to sign in to P0.

{% hint style="warning" %}
Anyone who can place themselves on-call for an enabled schedule can grant themselves access without further approval. Restrict who can edit your on-call schedules and overrides accordingly.
{% endhint %}

## Step 1: Connect your on-call provider

Install the approval integration for the provider you use.

{% tabs %}
{% tab title="PagerDuty" %}

1. Navigate to **Integrations** on [p0.app](https://p0.app), then select **PagerDuty**.
2. Click **Install integration**. P0 redirects you to PagerDuty's consent screen.
3. Approve the installation to return to P0.

For full details, see [PagerDuty](/integrations/approval-integrations/pagerduty).
{% endtab %}

{% tab title="Incident.io" %}

1. Navigate to **Integrations** on [p0.app](https://p0.app), then select **Incident.io**.
2. Create an API key in your Incident.io account with permissions to view data, create and edit incidents, manage organization settings, view catalog types and entries, and read schedules. See the [Incident.io API documentation](https://docs.incident.io/integrations/api-overview#where-can-i-find-the-api-keys).
3. Enter the API key in P0 and click **Install integration**. P0 validates the key and creates a custom field in your Incident.io account.

For full details, see [Incident.io](/integrations/approval-integrations/incidentio).
{% endtab %}
{% endtabs %}

## Step 2: Select the schedules that grant access

Tell P0 which on-call rotations qualify a requestor for automatic approval.

{% tabs %}
{% tab title="PagerDuty" %}

1. On the **PagerDuty** integration page, find the escalation policy selector.
2. Select one or more escalation policies whose active on-call members receive automatic approval.
3. Save your changes.

P0 approves a request when the requestor is currently on-call for one of the selected escalation policies.
{% endtab %}

{% tab title="Incident.io" %}

1. On the **Incident.io** integration page, open the auto-approval settings.
2. Select one or more schedules from the dropdown. P0 fetches available schedules from your Incident.io account.
3. Save your changes.

P0 approves a request when the requestor is currently on-call for one of the selected schedules.
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
For Incident.io, you must select at least one schedule. If you select none, auto-approval denies every request.
{% endhint %}

## Step 3: Add an auto-approval rule to your access policy

The integration tells P0 *who* is on-call. An access policy tells P0 *which requests* to auto-approve. Add an `auto` approval rule to your policy configuration.

1. Navigate to **Policy Studio** on [p0.app](https://p0.app).
2. Add a rule with the requestor, resource, and approval sections shown in the following example.
3. Save the policy configuration.

The following policy auto-approves any AWS request from an on-call engineer and requires a reason on every request:

{% tabs %}
{% tab title="PagerDuty" %}

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: pagerduty
      options: { requireReason: true }
```

{% endtab %}

{% tab title="Incident.io" %}

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: incidentio
      options: { requireReason: true }
```

{% endtab %}
{% endtabs %}

The system automatically approves a matching request for one hour when the requester is on-call. The `requireReason` option records why each grant was necessary, useful for incident review. Set it to `false` to skip the reason prompt.

{% hint style="info" %}
Change `service: aws` to the integration you want to cover (`gcloud`, `azure`, `ssh`, `k8s`, and others), or use `resource: { type: any }` to cover every resource. To narrow the rule to specific resources, add [filters](/access-management/just-in-time-access/request-routing#integration). For the full policy format, see [Access Policies](/access-management/just-in-time-access/request-routing).
{% endhint %}

## Step 4 (optional): Fall back to manual approval

On-call auto-approval pairs well with a manual approver for everyone else. List both approval types in the same rule. P0 combines them so that an on-call requestor is auto-approved, while anyone off-call routes to your security reviewers.

{% tabs %}
{% tab title="PagerDuty" %}

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: pagerduty
      options: { requireReason: true }
    - type: p0
```

{% endtab %}

{% tab title="Incident.io" %}

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: auto
      integration: incidentio
      options: { requireReason: true }
    - type: p0
```

{% endtab %}
{% endtabs %}

The `p0` approval type routes to the security reviewers configured on your **Access control** settings. See [Approving access](/access-management/just-in-time-access/approving-access#configuring-approvals).

## Verify it worked

Confirm the rule before you rely on it during an incident:

1. Make sure a test user is on-call for one of the selected schedules (add a temporary override in PagerDuty or Incident.io if needed).
2. As that user, request a covered resource, for example, run `p0 request aws role MyReadOnlyRole --account 123456789012 --reason "Testing on-call auto-approval"`.
3. Confirm the request is approved automatically, without a human approver acting on it.
4. Open **Access management > History** at `https://p0.app/o/<your-org>/access-management/history` and confirm the request shows automatic approval and the reason you supplied.
5. As a user who isn't on-call, request the same resource and confirm the request routes to manual approval (if you added the Step 4 fallback) or the system denies it (if you didn't).

## Troubleshooting

| Symptom                                                     | Cause                                                                   | Fix                                                                                                                                                                                         |
| ----------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| On-call user's request is denied                            | The user's P0 email doesn't match their PagerDuty or Incident.io email  | Align the email addresses across both systems                                                                                                                                               |
| Every request is denied (Incident.io)                       | No schedules selected in auto-approval settings                         | Select at least one schedule on the Incident.io integration page                                                                                                                            |
| Request routes to manual approval instead of auto-approving | The requestor isn't currently on-call, or their schedule isn't selected | Confirm the user's active on-call shift and select their escalation policy or schedule in Step 2                                                                                            |
| Rule has no effect                                          | The resource or requestor in the policy doesn't match the request       | Check the `service` value and requestor type against the request; see [Evaluation of access policies](/access-management/just-in-time-access/request-routing#evaluation-of-access-policies) |
| Access expires too soon                                     | Auto-approval grants last one hour by design                            | For longer standing access, use [pre-approvals](/access-management/just-in-time-access/approving-access/pre-approving-access) instead                                                       |

## What's next

* [Escalate stuck requests to on-call approvers](/access-management/just-in-time-access/request-routing#escalation) with the `escalation` approval type, so on-call users can approve *others'* requests during an incident.
* [Pre-approve access](/access-management/just-in-time-access/approving-access/pre-approving-access) for planned work that's not tied to an on-call shift.
* [Configure access policies](/access-management/just-in-time-access/request-routing) to route different resources to different approvers.
* [PagerDuty](/integrations/approval-integrations/pagerduty) and [Incident.io](/integrations/approval-integrations/incidentio) integration reference.


# Pre-approving Access

Approvers can pre-approve access before the requestor creates an access request.

For instance, the approver may want to allow certain users to elevate their permissions automatically for the duration of a project, without having to wait for the approver to approve manually every time.

## 🕒 Allowing access ahead of time

To allow access requests for the future, use the `/p0 allow` slash command in Slack.

The arguments for this command are similar to `/p0 request` (see [Requesting Access](/access-management/just-in-time-access/requesting-access#using-slack-slash-commands)), with a few additional required options:

* `--to <email>`\
  Use the email identifier of the principal to which you want to grant access
* `--length <duration>`\
  Duration for auto-approved access. The requestor will be automatically approved between the `start` time of the `allow` command up to this duration. Format like `'10 minutes'`, `'2 hours'`, `'5 days'`, or `'1 week'`.
* `--request-duration <duration>`\
  Access duration for individual requests. Once the requestor submits an access request, it will be automatically approved for this duration. Format like the `--length` option.

Optionally you can specify the `--start` option, which is the start time for auto-approved access. Defaults to now if not specified. Use ISO 8601 format, like `'2021-01-01T00:00:00Z'` or `2021-01-01`.

The principal issuing the `allow` command must be a valid approver for the principal in the `--to` argument, and for the resources specified, based on [access policies](/access-management/just-in-time-access/request-routing).


# P0 allow modal, CLI, and UI

Configure P0 allow pre-approvals from Slack, the CLI, or the P0 web app.

## Overview

`p0 allow` creates **standing pre-approvals** so specific principals can receive access automatically when they request it. Team members can configure these allows from three entry points:

* **Slack allow modal** for guided form-based setup
* **`p0 allow` CLI** for scripted or bulk automation
* **P0 App UI** for point-and-click management across environments

Every allow captures the same core fields: the target resource, the principal (`--to`), how long the auto-approval window remains active with `--start` and `--length`.

> You must be an approver for the target resource according to your [access policies](/access-management/just-in-time-access/request-routing) before you can create or edit an allow.

## Slack Allow Modal

Slack provides an interactive modal when you launch `/p0 allow` without full arguments. Use it when you prefer a visual form but want to stay in Slack.

### Launching the modal

* Type `/p0 allow` in any direct message or channel where the P0 bot is installed.
* (Optional) Include a partial command like `/p0 allow aws` to pre-populate the provider and resource fields.
* Press **Enter**. Slack opens the **Allow access** modal.

### Completing the form

The modal walks you through:

1. **Principal**: Email or directory identifier for the user, group, or service account.
2. **Provider & target**: Choose the cloud/platform and specify the resource (for example, IAM role, project, permission set).
3. **Auto-approval window**: Select start/end or a duration (maps to `--start` and `--length`). The modal defaults to the current time plus one week.
4. **Per-request duration**: How long each automatically approved request lasts (`--requested-duration`).
5. **Reason (optional)**: Appears in audit logs and request history when requestors receive access.

Submit the modal to create the allow. P0 confirms in DM and posts to the approval channel if configured. The modal’s interactive blocks provide inline validation (including date/time pickers), so you see errors such as missing `--to` or malformed durations before submission.

## CLI `p0 allow`

Use the CLI when you need automation, version-controlled workflows, or provider-specific flags. The command accepts the same data as the modal but allows you to script or template it.

```bash
p0 allow <provider> <subcommand> [resource args…] \
  --to <principal> \
  --length <duration> \
  [--start <timestamp>] \
  [--reason <text>] \
  [--wait]
```

Key tips:

* Run `p0 allow <provider> --help` for resource-specific arguments (for example, `--project`, `--account`).
* Durations accept natural language strings such as `"4 hours"`, `"10 days"`, or `"1 month"`.
* Combine with `p0 ls` to discover requestable resources before issuing the allow.
* Use `--wait` when you want the CLI to block until backend provisioning completes.

See `p0-cli/p0-commands-and-usage/p0-allow.md` for full examples covering AWS, GCP, SSH, and other providers, plus troubleshooting guidance in `p0-cli/troubleshooting/p0-allow.md`.

## Operational Best Practices

* **Align access policies first.** Ensure the allow creator appears as an approver for the resource; otherwise the modal and UI block creation.
* **Default to shorter windows.** Use the smallest `--length` that satisfies the project needs and rely on renewals when necessary.
* **Capture justification.** Require reasons via access policy options (`requireReason: true`) so audit logs show why the standing access exists.
* **Review regularly.** Schedule periodic reviews of the **Pre Approvals** tab in Access Management or use the CLI to script an inventory (`p0 allow list --json`).

## Related Resources

* [Pre-approving Access](/access-management/just-in-time-access/approving-access/pre-approving-access)
* [p0 allow CLI reference](/p0-cli/p0-commands-and-usage/p0-allow)
* [Access Policies](/access-management/just-in-time-access/request-routing)


# Access Policies

Access policies allow you to limit and direct just-in-time access requests, based on *who* is making the request and *which* resource is requested.

Use this page to configure and manage access policies.

* [Configuring access policies](#configuring-access-policies)
* [Access policy format](#access-policy-format)
* [Examples](#examples)
* [Evaluation of access policies](#evaluation-of-access-policies)

## Configuring access policies

To use access policies, go to p0.app and navigate to **Policy Studio**. Saving a policy configuration here configures your organization to use policy-based approvals, rather than default approvals.

<figure><img src="/files/AalhKnpEIkq5zVIooJ4h" alt="" width="563"><figcaption></figcaption></figure>

## Access policy format

When working with access policies directly, use this reference page for specific definitions of how to format your request. This feature of P0 is powerful and customizable, and is accessible via a full API.

### Structure of a policy configuration

A policy configuration is a collection of access policies. To change how P0 routes your requests (such as sending engineers' requests to their managers or restricting access to a particular prod resource to a small group), submit a new policy configuration.

You only have one policy configuration active at any given time, but that one configuration can have as many individual access policies as you want. You don't need to separate out different rule types or anything like that.

Here's an example policy configuration that you can copy into your app as a starting point:

```yaml
- requestor:
    type: group
    id: engineering@yourorg.com
    label: Engineering
    directory: workspace
  resource:
    type: integration
    service: snowflake
  approval:
    - type: group
      id: dataops@yourorg.com
      label: Data Ops Team
      directory: workspace
      options: {allowOneParty: false}
```

### Structure of a "Rule"

The core of policy configurations 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 three types of requestors you can choose from:

#### "Any"

```yaml
requestor:
  type: any
```

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

#### "Group"

```yaml
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 supports Google Workspace, Microsoft Entra ID, and Okta.

**id**: For Google Workspace, this is the group email address (ie, <engineering@yourco.com>). For Entra, this is the Entra ID 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](https://support.okta.com/help/s/article/how-to-find-group-ids-through-the-okta-user-interface?language=en_US).

**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 Entra ID, this is "azure-ad".

#### "User"

```yaml
requestor:
  type: user
  uid: <user's email address>
```

This rule will match only a specific user, as identified by their email address.

#### "Agentic"

```yaml
requestor:
  type: agentic
  agent: <agent rule>
  user: <user rule>
```

This rule matches requests made by AI agents through the [P0 AI Gateway](/readme/agentic-control-plane), based on the agent and user combination. See [Agentic Access Policies](/access-management/just-in-time-access/request-routing/agentic-access-policies) for the agent rule types and examples.

### Resource

The second part of an access policy is the resource this rule should apply to.

#### "Any"

```yaml
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.

#### "Integration"

```yaml
resource:
  type: integration
  service: <target service>
  accessType: <target access type>
```

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", for Microsoft Azure "azure", for Snowflake, "snowflake", and for SSH, "ssh".

**accessType** (Optional): The access type within the service that the rule should apply to, or "any" meaning the rule will match requests of any access type. Defaults to "any" if omitted.

**filters** (Optional):\
Filters allow you to apply the rule only to the service components that match the filtering condition.

```yaml
resource:
  type: integration
  service: aws|azure|azure-ad|gcloud|k8s|okta|snowflake|ssh
  filters:
    <access-type>:
      effect: keep|remove|removeAll
      key: <property>
      pattern: <regex pattern>
```

Each filter has a `filter-name` that refers to the type of the requested object. For instance, when "service" is "aws", the filter with the name "policy" will only allow requesting policies whose ARNs match the `pattern`.

Filters are independent when the access type is omitted or set to "any." For example, if you specify a `filter-name=permission` filter for `service=gcloud` requests, but omit a `filter-name=role` filter, then roles are unaffected by the filter, and all roles 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"

{% hint style="info" %}
Patterns are unanchored. Use line-start (`^`) and line-end (`$`) markers to anchor patterns.

P0 uses the [JavaScript regex dialect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions).
{% endhint %}

*Filter behavior*

The behavior of filters depends on the requested access type.

For example, the "role" filter in the Gcloud integration has a slightly different meaning depending on which access type is used in the request:

* When making a GCP request with "role" as the access type (e.g. `p0 request gcloud role`), the filter limits the roles the user can request access to
* When making a GCP request with "resource" as the access type (e.g. `p0 request gcloud resource`), the filter limits the roles that the user can request on the resource they are requesting

By setting the rule's access type to either "role" or "resource", you can explicitly specify which of these requests is allowable.

{% hint style="warning" %}
To ensure predictable filtering behavior, P0 recommends setting an `accessType` constraint when using filters.
{% endhint %}

Valid filter filter-name / key combinations are summarized in the following table. For more detailed information on the filters, see the documentation for [AWS](/access-management/just-in-time-access/request-routing/aws-filtering), [Microsoft Azure](/access-management/just-in-time-access/request-routing/microsoft-azure-filtering), [Google Cloud](/access-management/just-in-time-access/request-routing/google-cloud-filtering), and [SSH](/access-management/just-in-time-access/request-routing/ssh-filtering).

<table><thead><tr><th width="155">service</th><th width="147">access-type</th><th width="136">key</th><th>Notes</th></tr></thead><tbody><tr><td>aws</td><td>tag</td><td>&#x3C;tag key></td><td>Only filters policies and permission sets. AWS managed policies can't be tagged.</td></tr><tr><td></td><td>group</td><td>name</td><td>Filters IAM group names</td></tr><tr><td></td><td>permission-set</td><td>arn | name</td><td>Filters Identity Center permission sets</td></tr><tr><td></td><td>policy</td><td>arn</td><td>Filters policies with matching ARNs</td></tr><tr><td></td><td>resource</td><td>arn | name | service</td><td>Filters resource requests based on the resource ARN, the resource name, or the service the resource belongs to.</td></tr><tr><td>azure</td><td>subscription</td><td>id</td><td>Filters requests at a subscription level</td></tr><tr><td></td><td>resource</td><td>id | name</td><td>Filters requests based on what resource is requested</td></tr><tr><td></td><td>role</td><td>id | name</td><td>Filters requests based on the role requested</td></tr><tr><td>azure-ad|okta</td><td>group</td><td>id | label</td><td>Filters directory groups</td></tr><tr><td>gcloud</td><td>permission</td><td>id</td><td>Filters IAM permissions</td></tr><tr><td></td><td>role</td><td>id</td><td>Filters IAM roles based on full ID (for example, the ID for "Owner" is <code>roles/owner</code>)</td></tr><tr><td></td><td>resource</td><td>name | type | full-resource-name</td><td>Filters resource requests based on the resource name, resource type, or the full resource name.</td></tr><tr><td>snowflake</td><td>role</td><td>name</td><td>Filters roles</td></tr><tr><td>k8s</td><td>resource</td><td>kind | name | namespace</td><td>Filters resources</td></tr><tr><td></td><td>role</td><td>name</td><td>Filters roles and cluster roles</td></tr><tr><td></td><td>cluster</td><td>name</td><td>Filters clusters based on the cluster name specified when installed in P0</td></tr><tr><td>ssh</td><td>provider</td><td>id</td><td>Filters by cloud provider (<code>aws</code>, <code>gcloud</code>, <code>azure</code>, or <code>self-hosted</code>)</td></tr><tr><td></td><td>destination</td><td>arn | name | full-resource-name</td><td>Filters by instance identifier</td></tr><tr><td></td><td>group</td><td>name</td><td>Filters by SSH group name</td></tr><tr><td></td><td>parent</td><td>id</td><td>Filters by parent resource ID (AWS account ID, GCP project ID, or Azure subscription ID)</td></tr><tr><td></td><td>region</td><td>id</td><td>Filters by AWS region, GCP zone, or Azure region</td></tr><tr><td></td><td>sudo</td><td><em>(boolean)</em></td><td>Filters by whether sudo privileges are requested</td></tr></tbody></table>

Filters are not currently available for AWS or GCP resource-level grants, nor for Snowflake SQL grants.

*Example that covers each possible access type in the AWS service:*

1. Exclude all permission sets and policies containing "FullAccess"
2. Only allow AWS policies and permission sets where the tag "P0Grantable" is equal to the string "true"
3. Do not allow requesting any AWS groups

<pre><code><strong>- resource:
</strong>    type: integration
    service: aws
    accessType: permission-set
    filters:
      permission-set:
        effect: remove
        key: name
        pattern: FullAccess
      tag:
        effect: keep
        key: P0Grantable
        pattern: ^true$
  requestor:
    type: any
  approval:
    - type: any

- resource:
    type: integration
    service: aws
    accessType: policy
    filters:
      policy:
        effect: remove
        key: name
        pattern: FullAccess
      tag:
        effect: keep
        key: P0Grantable
        pattern: ^true$
  requestor:
    type: any
  approval:
    - type: any
    
- resource:
    type: integration
    service: aws
    accessType: group
  requestor:
    type: any
  approval:
    - type: deny
</code></pre>

### Approval

The final part of an access policy 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"

```json
approval:
  - type: p0
    options: { allowOneParty: true|false, requireReason: true|false, breakGlassApprover: true|false }
```

This approval type is analogous to the default approval behavior. This rule routes approvals to the people designated as "Security Reviewers" 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`.
* designate this approver as a break glass approver for SSH "all" access requests with the `breakGlassApprover: true` setting. Defaults to `false`. See [SSH Filtering](/access-management/just-in-time-access/request-routing/ssh-filtering#break-glass-access) for details.

#### "Group"

```yaml
approval:
  - type: group
    id: <group identifier>
    label: <human readable name>
    directory: azure-ad|okta|workspace
    options: { allowOneParty: true|false,  requireReason: true|false, breakGlassApprover: true|false }
```

This rule will match any requestor who is a member of a group in your Identity Provider. Currently, P0 supports Google Workspace, Microsoft Entra ID, and Okta.

**id**: For Google Workspace, this is the group email address (ie, <engineering@yourco.com>). For Entra ID, this is the Entra ID 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](https://support.okta.com/help/s/article/how-to-find-group-ids-through-the-okta-user-interface?language=en_US).

**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 Entra ID this is "azure-ad".

**options**: See ["p0" section](#p0)

#### "Auto"

<pre class="language-yaml"><code class="lang-yaml"><strong>approval:
</strong>  - type: auto
    integration: pagerduty|incidentio
    options: { requireReason: true|false }
</code></pre>

This rule automatically approves matching access requests for one hour.

**integration**: `"pagerduty"` or `"incidentio"`. P0 automatically approves the request if the requestor is on-call. For PagerDuty, P0 checks the escalation policies configured on the integration page. For Incident.io, P0 checks the schedules selected on the [Incident.io integration settings page](/integrations/approval-integrations/incidentio#selecting-schedules).

**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`.

#### "Escalation"

<pre><code><strong>approval:
</strong>  - type: escalation
    integration: pagerduty|incidentio
    options: { allowOneParty: true|false,  requireReason: true|false, breakGlassApprover: true|false }
    services: [&#x3C;Service or Schedule ID>]
</code></pre>

This rule routes approval to users who are currently on-call for the specified services or schedules. When combined with other approval rules, it enables on-call users to approve requests that have been escalated.

**integration**: `"pagerduty"` or `"incidentio"`.

* For PagerDuty, on-call status is determined by the escalation policies of the configured services. An incident is created against the specified services when the request is escalated.
* For Incident.io, on-call status is determined by the specified schedule IDs. Users who are on-call for any of the listed schedules can approve the request.

**options**: See ["p0" section](#p0).

**services**: List of PagerDuty service IDs or Incident.io schedule IDs, depending on the configured integration.

#### "Always allowed"

```yaml
approval:
  - type: persistent
```

Access is always granted automatically.

**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"

```yaml
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

Access policies can support a variety of use cases.

#### Different access depending on organizational role

Configure different approvers and different resources for developers and customer-success engineers:

```yaml
- requestor:
    type: group
    id: devs@you.co
    label: Developers
    directory: workspace
  resource:
    type: any
  approval:
    - type: group
      id: sre@you.co
      label: SREs
      directory: workspace
      options: { allowOneParty: true }
- requestor:
    type: group
    id: customer-success@you.co
    label: Customer Success
    directory: workspace
  resource:
    type: integration
    service: snowflake
  approval:
    - type: group
      id: data-ops@you.co
      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.

<pre class="language-yaml"><code class="lang-yaml"><strong>- requestor:
</strong>    type: group
    id: 00g5j4jojlGZMzfhM69
    label: Engineers
    directory: okta
  resource:
    type: integration
    service: aws
    accessType: resource
    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
    accessType: resource
    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
    accessType: resource
    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 }
</code></pre>

#### Filter access to AWS policies and permission sets by tag

Restrict which AWS policies and permission sets can be requested to those for which a tag matches a specific value:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: aws
    accessType: policy
    filters:
      tag: { effect: keep, key: P0Grantable, pattern: ^true$ }
  approval:
    - type: p0
- requestor:
    type: any
  resource:
    type: integration
    service: aws
    accessType: permission-set
    filters:
      tag: { 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
    id: devs@you.co
    directory: workspace
  resource:
    type: any
  approval:
    - type: group
      id: eng-managers@you.co
      label: Eng managers
      directory: workspace
- requestor:
    type: group
    id: devs@you.co
    directory: workspace
  resource:
    type: integration
    service: gcloud
  approval:
    - type: group
      id: gcloud-owners@you.co
      label: GCloud owners
      directory: workspace
```

#### Mandatory reason for a specific resource type

Make reason mandatory for AWS requests

<pre class="language-yaml"><code class="lang-yaml"><strong>- resource:
</strong>    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
</code></pre>

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

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

#### Escalate request using PagerDuty for priority approval when requesting google cloud requests

```
- resource:
    service: gcloud
    type: integration
  approval:
    - type: p0
      options: {requireReason: true, allowOneParty: false}  
    - type: escalation
      integration: pagerduty
      options: {requireReason: true, allowOneParty: false}
      services: [PSJXXXG]
  requestor:
    type: any
```

#### Allow users to request access to Google Cloud roles, but not permissions

```
- resource:
    service: gcloud
    type: integration
    accessType: role
  approval:
    - type: p0
  requestor:
    type: any
- resource:
    service: gcloud
    type: integration
    accessType: permission
  approval:
    - type: deny
  requestor:
    type: any
```

#### Deny access to specific roles, but allow users to request others

```
- resource:
    service: gcloud
    type: integration
    accessType: role
    filters:
      role:
        effect: keep
        key: name
        pattern: roles/owner
  approval:
    - type: deny
  requestor:
    type: any
- resource:
    service: gcloud
    type: integration
    accessType: role
  approval:
    - type: p0
  requestor:
    type: any
```

## Evaluation of access policies

1. Match Rules to the Request

   Identify rules that match the request. A rule matches if both the requestor and the resource criteria in the rule align with the request details.
2. Handle Missing Matches

   If no rules match, the access request is not created, and further evaluation stops. The requestor will see the following message:

   *This resource doesn't exist, or your organization doesn't allow this principal to access this resource*
3. Evaluate Access Control of Matching Rules

   For matching rules, review the Access Control field in the following order:

   * Deny all access\
     If *any* matching rule specifies "Deny all access", the request is denied immediately, and further evaluation stops.
   * Always allowed\
     If any rule specifies "Always allowed," the request is automatically approved and provisioned, and further evaluation stops.
   * Third-party auto-approval\
     If a rule specifies a third-party auto-approval, such as a PagerDuty or Incident.io on-call rule, the request is evaluated for automatic approval. If it cannot be auto-approved, proceed to the next step.
   * Manual approval\
     For all other Access Control values, the request requires manual approval by a designated person or group. When multiple rules with different manual approvers match, approval from any one approver is sufficient to provision the request. All approvers are notified.

### Key points to remember

* **Deny all access:** Always takes precedence and stops further evaluation immediately.
* **Always allowed:** Overrides other Access Control values and is prioritized in the evaluation process.
* **Multiple matching rules:** When multiple rules match the requestor and resource, approvers are combined using an **ANY** relationship, meaning approval from any one approver is sufficient.

### Examples

1. **Always allowed rule takes precedence over other allow rules**

Consider a scenario where two rules apply to the same resource, **`node1`** in the **devstack** group:

* An "Always allow" rule grants access to **`node1`**.
* Another "Allow" rule requires approval before granting access.

In this case, the **"Always allow" rule** takes precedence. As a result:

* The user is immediately granted access to **`node1`** without requiring additional approval.

2. **Deny Rules are evaluated first, before ANY allow rules**

Using the same example as before, if there is an additional rule that **denies access** to any instance containing **`node`** in its name, the system will evaluate the "Deny" rule first.

In this case:

* The "Deny" rule matches because **`node1`** contains the string **`node`** in its name.
* The user's request is immediately denied, and is not evaluated further.

This highlights the priority of "Deny" rules, ensuring they are enforced before any other rules are considered.


# Configure your first access policy

Create and manage access policies in P0 Security's Policy Studio to control who can request access to which resources and how requests are approved.

Access policies give you fine-grained control over who can request access, which resources they can request, and how those requests are approved. This guide walks you through creating your first policy in Policy Studio.

{% hint style="info" %}
Access policies require a **Pro-tier** P0 subscription.
{% endhint %}

## Prerequisites

Before you begin, confirm the following:

* A P0 account with a **Pro-tier** subscription.
* **Owner** or **Security Reviewer** role in your P0 organization.
* At least one [resource integration](/integrations/resource-integrations) installed (AWS, Google Cloud, Azure, Kubernetes, or another supported resource).
* A [directory integration](/integrations/directory-integrations) configured (Google Workspace, Okta, or Microsoft Entra ID) if you plan to use group-based policies.

## Open Policy Studio

1. Sign in to [p0.app](https://p0.app).
2. Navigate to **Policy Studio** in the sidebar, or go to `https://p0.app/o/<your-organization>/policies`.

You see a list of existing policies. If this is your first time, the list may be empty or contain a default policy.

{% hint style="info" %}
Toggle between **Table View** and **YAML View** using the segmented control at the top of the list to see your policies in different formats.
{% endhint %}

## Create a new policy

1. Click **Add New Policy**.

   The policy editor opens in **Guided editor**, which provides a visual form for building your policy. To edit raw YAML instead, select **YAML editor** from the dropdown menu in the header.
2. Enter a descriptive name for your policy in the name field at the top (for example, "Engineering - AWS read-only").

The editor has three sections: **Identity**, **Resource(s)**, and **Actions**. Configure each one in order.

## Define the identity (who can request)

The **Identity** section specifies which users can make requests that match this policy.

1. In the **Identity** section, select one of the following:
   * **Any**: Matches all users in your organization.
   * **User**: Matches a specific user or directory group.
2. If you selected **User**, choose either:
   * **Specific user**: Enter the user's email address.
   * **Directory group**: Select your directory provider and enter the group identifier.

{% hint style="info" %}
**Finding your group identifier:**

* **Google Workspace:** The group email address (for example, `engineering@yourcompany.com`).
* **Okta:** The group ID from the admin console URL. See the [Okta documentation](https://support.okta.com/help/s/article/how-to-find-group-ids-through-the-okta-user-interface?language=en_US) for details.
* **Microsoft Entra ID:** The group's UUID from the Entra admin center.
  {% endhint %}

### Example

To create a policy for your engineering team using Google Workspace:

* Select **User** then **Directory group**.
* Directory: **Google Workspace**
* Group ID: `engineering@yourcompany.com`
* Label: `Engineering`

## Define the resource (what they can request)

The **Resource** section specifies which resources this policy applies to.

1. In the **Resource** section, select one of the following:
   * **Any resource**: Matches all integrated resources.
   * A specific integration (for example, **AWS**, **Google Cloud**, **Kubernetes**).
2. If you selected a specific integration, optionally configure:
   * **Access type**: Restrict to a specific type (for example, `role`, `permission-set`, or `resource` for AWS).
   * **Filters**: Narrow the scope further by matching resource properties.

### Add a resource filter

Filters let you control which specific resources within an integration can be requested.

1. Click **Add New Resource Filter** in the resource section.
2. Select the **filter type** (for example, `policy`, `role`, `resource`).
3. Choose the **effect**:
   * **Include only**: Allow requests for resources that match the pattern.
   * **Exclude only**: Block requests for resources that match the pattern.
   * **Exclude all**: Disable this resource type entirely.
4. Enter the **pattern** (a regular expression) to match against.

{% hint style="info" %}
Patterns are unanchored by default. Use `^` and `$` to anchor patterns. For example, `^true$` matches the exact string "true", while `FullAccess` matches any resource containing "FullAccess" in its name.
{% endhint %}

### Example

To restrict AWS access to non-admin permission sets:

* Integration: **AWS**
* Access type: **permission-set**
* Filter: `permission-set`, Effect: **Exclude only**, Pattern: `FullAccess|Admin`

## Define the actions (how requests are approved)

The **Actions** section specifies how matching requests are handled.

1. Select an approval type:

| Approval type  | Behavior                                                                                                                                                                                  |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **P0**         | Routes to your configured Security Reviewers                                                                                                                                              |
| **Group**      | Routes to members of a specific directory group                                                                                                                                           |
| **Persistent** | Automatically grants access (standing access)                                                                                                                                             |
| **Deny**       | Denies all matching requests                                                                                                                                                              |
| **Auto**       | Automatically approves if the requestor is on-call (requires [PagerDuty](/integrations/approval-integrations/pagerduty) or [Incident.io](/integrations/approval-integrations/incidentio)) |
| **Escalation** | Routes to on-call users for priority approval                                                                                                                                             |

2. Configure approval options as needed:
   * **Require reason with request**: Requestors must give a justification.
   * **Allow self-approvals**: Requestors can approve their own requests.
3. To add multiple approvers, click **Add** to create additional approval rules. When multiple approvers are configured, approval from any one approver is sufficient.

### Example

To route engineering AWS requests to the SRE team with mandatory justification:

* Approval type: **Group**
* Directory: **Google Workspace**
* Group ID: `sre-team@yourcompany.com`
* Label: `SRE Team`
* Enable **Require reason with request**

## Save and enable the policy

1. Review your policy configuration across all three sections.
2. Click **Save Policy**.
3. Confirm the policy appears in the policies list with the **Enabled** toggle turned on.

{% hint style="warning" %}
Policies take effect immediately after saving. When you save a new policy, it becomes part of your active workflow and applies to all later access requests.
{% endhint %}

## Verify the policy

1. Have a user who matches the identity criteria make a test access request via Slack (`/p0 request`), the [P0 CLI](/p0-cli/p0-commands-and-usage/p0-request), or the [web request modal](/access-management/just-in-time-access/requesting-access/web-request-modal).
2. Confirm the following:
   * The request is created (not blocked by a missing match).
   * The correct approvers receive the approval notification.
   * Resources outside the policy's filters are not available for request.

{% hint style="info" %}
If the requestor sees *"This resource doesn't exist, or your organization doesn't allow this principal to access this resource"*, no policy matches their request. Review the identity and resource criteria in your policy.
{% endhint %}

## Common policy patterns

### Separate approvers by environment

Route development requests to peer engineers with self-approval, and production requests to managers without self-approval:

```yaml
# Development - peer approval with self-approve
- requestor:
    type: group
    id: engineering@yourcompany.com
    label: Engineering
    directory: workspace
  resource:
    type: integration
    service: aws
    filters:
      policy:
        effect: keep
        key: arn
        pattern: "^arn:aws:iam::111111111111:policy/"
  approval:
    - type: group
      id: engineering@yourcompany.com
      label: Engineering
      directory: workspace
      options: { allowOneParty: true }

# Production - manager approval, no self-approve
- requestor:
    type: group
    id: engineering@yourcompany.com
    label: Engineering
    directory: workspace
  resource:
    type: integration
    service: aws
    filters:
      policy:
        effect: keep
        key: arn
        pattern: "^arn:aws:iam::222222222222:policy/"
  approval:
    - type: group
      id: eng-managers@yourcompany.com
      label: Engineering Managers
      directory: workspace
      options: { allowOneParty: false, requireReason: true }
```

### Auto-approve on-call engineers

Automatically approve requests from engineers who are currently on-call in PagerDuty:

```yaml
- requestor:
    type: group
    id: engineering@yourcompany.com
    label: Engineering
    directory: workspace
  resource:
    type: any
  approval:
    - type: auto
      integration: pagerduty
      options: { requireReason: true }
```

### Block sensitive roles

Deny all requests for the Google Cloud Owner role:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: gcloud
    accessType: role
    filters:
      role:
        effect: keep
        key: id
        pattern: roles/owner
  approval:
    - type: deny
```

## Understand policy evaluation order

When a request matches multiple policies, P0 evaluates them in this order:

1. **Deny**: If any matching policy specifies **Deny**, the request is denied immediately.
2. **Persistent**: If any matching policy specifies **Persistent** (always allowed), the request is automatically approved.
3. **Auto**: If a matching policy specifies auto-approval, P0 checks the requestor's on-call status.
4. **Manual approval**: For all other matches, P0 notifies the combined set of approvers. Approval from any one approver is sufficient.

{% hint style="info" %}
For a complete reference of policy syntax, filter options, and evaluation logic, see the [Access Policies](/access-management/just-in-time-access/request-routing) reference.
{% endhint %}

## Next steps

* Add [resource-specific filters](/access-management/just-in-time-access/request-routing/aws-filtering) to fine-tune which AWS, [Google Cloud](/access-management/just-in-time-access/request-routing/google-cloud-filtering), [Azure](/access-management/just-in-time-access/request-routing/microsoft-azure-filtering), or [SSH](/access-management/just-in-time-access/request-routing/ssh-filtering) resources users can request.
* Configure [PagerDuty](/integrations/approval-integrations/pagerduty) or [Incident.io](/integrations/approval-integrations/incidentio) for on-call auto-approvals.
* Use the [Access Policies API](/access-management/just-in-time-access/just-in-time-api/access-policies-api) to manage policies programmatically.


# Google Cloud Filtering

We'll go through all the available access-types for Google Cloud request filtering.

### Filtering permission requests

To filter on permission requests, we can use the `permission` access-type. There is a single available key, `id`, which refers to the permission ID (list available in Google's docs [here](https://cloud.google.com/iam/docs/permissions-reference))

#### Rule structure:

```
resource:
  type: integration
  service: gcloud
  filters:
    permission:
      effect: keep|remove|removeAll
      key: id
      pattern: <regex pattern>
```

#### Allow requesting only bigquery permissions:

```
resource:
  type: integration
  service: gcloud
  filters:
    permission:
      effect: keep
      key: id
      pattern: ^bigquery.
```

#### Allow requesting any permissions except compute.instances.delete

```
resource:
  type: integration
  service: gcloud
  filters:
    permission:
      effect: remove
      key: id
      pattern: ^compute.instances.delete$
```

### Filtering role requests

To filter on permission requests, we can use the `role` access-type. There is a single available key, `id`, which refers to the role ID (list available in Google's docs [here](https://cloud.google.com/iam/docs/understanding-roles)). Note that this is the ID that is prefixed with `roles/`

#### Rule structure:

```
resource:
  type: integration
  service: gcloud
  filters:
    role:
      effect: keep|remove|removeAll
      key: id
      pattern: <regex pattern>
```

#### Allow requesting only compute roles

```
resource:
  type: integration
  service: gcloud
  filters:
    role:
      effect: keep
      key: id
      pattern: ^roles/compute.
```

#### Allow requesting any roles except the basic roles (viewer, editor, owner)

```
resource:
  type: integration
  service: gcloud
  filters:
    role:
      effect: remove
      key: id
      pattern: ^roles/editor$|^roles/viewer$|^roles/owner$
```

### Filtering resource requests

To filter on permission requests, we can use the `resource` access-type. There are 3 available keys:

* `name`: This is the name of the resource.
* `type`: This is the type of the resource. The available values for `type` are below:

| Resource type        | "type" value     |
| -------------------- | ---------------- |
| BigQuery Dataset     | `dataset`        |
| BigQuery Table       | `table`          |
| Compute Zone         | `zone`           |
| Compute Instance     | `instance`       |
| IAM Service Account  | `serviceaccount` |
| Cloud Storage Bucket | `bucket`         |
| Cloud Storage Object | `object`         |

* `full-resource-name`: This is the Google API full resource name, including the service, type, and name. Available formats for the `full-resource-name` are below.

| Resource type        | "type" value                                                                            |
| -------------------- | --------------------------------------------------------------------------------------- |
| BigQuery Dataset     | `//bigquery.googleapis.com/projects/PROJECT_ID/datasets/DATASET_NAME`                   |
| BigQuery Table       | `//bigquery.googleapis.com/projects/PROJECT_ID/datasets/DATASET_NAME/tables/TABLE_NAME` |
| Compute Zone         | `//compute.googleapis.com/zones/ZONE_NAME`                                              |
| Compute Instance     | `//compute.googleapis.com/projects/PROJECT_ID/zones/ZONE_NAME/instances/INSTANCE_NAME`  |
| IAM Service Account  | `//iam.googleapis.com/projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL`        |
| Cloud Storage Bucket | `//storage.googleapis.com/BUCKET_NAME`                                                  |
| Cloud Storage Object | `//storage.googleapis.com/BUCKET_NAME/objects/OBJECT_PATH`                              |

#### Rule structure:

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: keep|remove|removeAll
      key: name|type|full-resource-name
      pattern: <regex pattern>
```

#### Allow requesting only the Bigquery Dataset "customer-data" in project "test"

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: keep
      key: full-resource-name
      pattern: ^//bigquery.googleapis.com/projects/test/datasets/customer-data$
```

#### Allow requesting any Cloud Storage bucket:

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: keep
      key: type
      pattern: ^bucket$
```

#### Allow requesting any resource with "application-1" in the name

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: keep
      key: name
      pattern: application-1
```

#### Allow requesting any resource except compute instances with names starting with "prod" in project "test" and zone "us-west1-a"

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: remove
      key: full-resource-name
      pattern: ^//compute.googleapis.com/projects/test/zones/us-west1-a/instances/prod 
```

#### Allow requesting only Cloud Storage buckets with names starting with dev

```
resource:
  type: integration
  service: gcloud
  filters:
    resource:
      effect: keep
      key: full-resource-name
      pattern: ^//storage.googleapis.com/dev
```


# AWS Filtering

This page covers all the available access-types for AWS request filtering.

### Filtering on tags

Policies and permission sets can be filtered based on their tags in AWS. To do this, use the `tag` access-type. The key is the tag key, and the pattern matches on the tag value.

#### Rule structure:

```
resource:
  type: integration
  service: aws
  filters:
    tag:
      effect: keep|remove|removeAll
      key: <tag key>
      pattern: <regex pattern>
```

#### Allow requesting only policies and permission sets with the tag "environment" set to "dev" :

```
resource:
  type: integration
  service: aws
  filters:
    tag:
      effect: keep
      key: environment
      pattern: ^dev$
```

### Filtering on IAM groups

To filter on IAM group requests, use the `group` access-type. There is a single available key, `name`, which refers to the name of the IAM group.

#### Rule structure:

```
resource:
  type: integration
  service: aws
  filters:
    group:
      effect: keep|remove|removeAll
      key: name
      pattern: <regex pattern>
```

#### Allow requesting any IAM groups except for "Admin" :

```
resource:
  type: integration
  service: aws
  filters:
    group:
      effect: remove
      key: name
      pattern: ^Admin$
```

### Filtering on permission sets

To filter on Identity Center permission set requests, use the `permission-set` access-type. There are two available keys, `name` (the name of the permission set) and `arn` (the ARN of the permission set).

#### Rule structure:

```
resource:
  type: integration
  service: aws
  filters:
    permission-set:
      effect: keep|remove|removeAll
      key: name | arn
      pattern: <regex pattern>
```

#### Allow requesting only permission sets with "project-1" in the name:

```
resource:
  type: integration
  service: aws
  filters:
    permission-set:
      effect: keep
      key: name
      pattern: project-1
```

### Filtering on policies

To filter on IAM policy requests, use the `policy` access-type. There is a single available key, `arn`, which refers to the ARN of the IAM policy.

#### Rule structure:

```
resource:
  type: integration
  service: aws
  filters:
    policy:
      effect: keep|remove|removeAll
      key: arn
      pattern: <regex pattern>
```

#### Allow requesting only AmazonS3 predefined policies

```
resource:
  type: integration
  service: aws
  filters:
    policy:
      effect: keep
      key: arn
      pattern: ^arn:aws:iam::aws:policy/AmazonS3
```

### Filtering on resources

To filter on permission requests, use the `resource` access-type. There are 3 available keys:

* `name`: This is the name of the resource.
* `service`: This is the AWS service that the resource belongs to: for example, `s3`, or `sagemaker`. It will found in the resource ARN, after `arn:aws:`. For example, if the ARN is `arn:aws:iam::391052057035:role/AmazonEKSNodeRole` the service is `iam`.
* `arn`: This is the ARN of the resource.

#### Rule structure:

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: keep|remove|removeAll
      key: name|service|arn
      pattern: <regex pattern>
```

#### Allow requesting only S3 resources

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: keep
      key: service
      pattern: ^s3$
```

#### Allow requesting any resource except for IAM resources

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: remove
      key: service
      pattern: ^iam$
```

#### Allow requesting any resource containing "project-1" in the name

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: keep
      key: name
      pattern: project-1
```

#### Allow requesting only S3 buckets with names starting with "dev"

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: keep
      key: arn
      pattern: ^arn:aws:s3:::dev
```

#### Allow requesting any resource except for the S3 bucket named "top-secret-bucket"

```
resource:
  type: integration
  service: aws
  filters:
    resource:
      effect: remove
      key: arn
      pattern: ^arn:aws:s3:::top-secret-bucket$
```


# Microsoft Azure Filtering

This document covers the various ways fine-grained just-in-time access for Microsoft Azure can be configured by using P0's access policies.

### Filtering on subscription

Requests can be filtered at the level of an entire subscription by adding a filter based on the subscription's `id`

#### Rule structure:

```
resource:
  type: integration
  service: azure
  filters:
    subscription: {
      effect: keep|remove|removeAll
      key: id
      pattern: <regex pattern>
    }
```

Deny all requests to the subscription with id \<subscription id>

```
resource:
  type: integration
  service: azure
  accessType: any
  filters:
    subscription: {effect: keep, key: id, pattern: <subscription id>}
approval:
  - type: deny
```

### Filtering on resource

Requests can be filtered by details pertaining to the `resource` being requested. There are two available keys for `resource` filters, `name` and `id` .

#### Rule structure:

```
resource:
  type: integration
  service: azure
  filters:
    resource: {
      effect: keep|remove|removeAll
      key: name
      pattern: <regex pattern>
    }
```

#### Examples:

Auto-approve any requests for the resource with an `id` of `/subscriptions/<subscription number>/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/NetworkWatcher_eastus`

```
resource:
  type: integration
  service: azure
  filters:
    resource: {
      effect: keep, 
      key: id, 
      pattern: /subscriptions/<subscription number>/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/NetworkWatcher_eastus
    }
approval:
  - type: persistent
    
```

Auto-approve on-call requests for any resource except for the one named "sensitive-virtual-network"

<pre><code><strong>resource:
</strong>  type: integration
  service: azure
  accessType: any
  filters:
    resource: {effect: remove, key: name, pattern: sensitive-virtual-network}
approval:
  - type: auto
    integration: pagerduty
    options: {}
</code></pre>

### Filtering on roles

Requests can be filtered by details pertaining to the `role` being requested. There are two available keys for `role` filters, `name` and `id` .

#### Rule structure:

```
resource:
  type: integration
  service: azure
  filters:
    role: {
      effect: keep|remove|removeAll
      key: id | name
      pattern: <regex pattern>
    }
```

#### Examples:

Allow approvals of requests to the `role` named "P0 Developer Role" to be approved by users with the DevOpsManager profile property in Okta

```
resource:
  type: integration
  service: azure
  accessType: any
  filters:
    role: {effect: keep, key: name, pattern: P0 Developer Role}
approval:
  - type: requestor-profile
    directory: okta
    options: {}
    profileProperty: DevOpsManager
```

Allow requests to the role with `id` of `/subscriptions/<subscription id>/providers/Microsoft.Authorization/roleDefinitions/5bc02df6-6cd5-43fe-ad3d-4c93cf56cc16` to be approved by users defined in P0

```
resource:
  type: integration
  service: azure
  accessType: any
  filters:
    role: {
      effect: keep, 
      key: id, 
      pattern: /subscriptions/<subscription id>/providers/Microsoft.Authorization/roleDefinitions/5bc02df6-6cd5-43fe-ad3d-4c93cf56cc16
    }
approval:
  - type: p0
    options: {}
```


# SSH Filtering

SSH access policies allow you to control access to SSH resources based on provider, destination, group, region, parent resource, and sudo privileges. You can also configure **break glass** access, which grants unrestricted SSH access to all resources for emergency scenarios.

{% hint style="info" %}
Before configuring SSH access policies, ensure you have installed the SSH integration. See [SSH integration setup](/integrations/resource-integrations/ssh) for details.
{% endhint %}

## SSH access types

The SSH integration supports four access types. Each access type represents a different scope of resources you can grant access to:

| Access type | Description                                                                                                  |
| ----------- | ------------------------------------------------------------------------------------------------------------ |
| `session`   | Access to an individual compute instance. This is the most granular level of SSH access.                     |
| `group`     | Access to a tagged collection of instances within a service provider. A group may contain one or more nodes. |
| `parent`    | Access to all instances within a hierarchical unit, an AWS account, GCP project, or Azure subscription.      |
| `all`       | A global access request that grants access to all SSH resources. This is **break glass** access.             |

Outside of `session`, the other access types control access to collections of instances, which may include one or more nodes at a time.

You can scope an access policy to a specific access type using the `accessType` field:

```yaml
resource:
  type: integration
  service: ssh
  accessType: session
```

If you omit `accessType` or set it to `any`, the rule applies to all SSH access types.

## Available filters

SSH access policies support six filter types:

| Filter        | Key                                    | Description                                                                                                                                                                                                    |
| ------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`    | `id`                                   | Cloud provider managing the instance. Must be `aws`, `azure`, `gcloud`, or `self-hosted`.                                                                                                                      |
| `destination` | `arn`, `name`, or `full-resource-name` | Instance identifier. Use `arn` for AWS instances, `full-resource-name` for GCP instances, or `name` for instance name across providers. To list available instance names, run `p0 ls ssh session destination`. |
| `group`       | `name`                                 | SSH group name, the tagged collection of instances within a provider.                                                                                                                                          |
| `parent`      | `id`                                   | Parent resource identifier. Use a GCP project name, AWS account ID, or Azure subscription ID.                                                                                                                  |
| `region`      | `id`                                   | AWS region, GCP zone, or Azure region.                                                                                                                                                                         |
| `sudo`        | *(boolean filter)*                     | Whether the request includes sudo privileges. When set, you can control who can approve or deny sudo access.                                                                                                   |

### Filter rule structure

```yaml
resource:
  type: integration
  service: ssh
  filters:
    <filter-name>:
      effect: keep|remove|removeAll
      key: <property>
      pattern: <regex pattern>
```

Each filter has three properties:

* **effect**: How the filter is applied:
  * `keep`: Retain resources that match the pattern
  * `remove`: Retain resources that do *not* match the pattern
  * `removeAll`: Disable this filter type entirely
* **key**: The property to match against
* **pattern**: A regex pattern to match (uses the [JavaScript regex dialect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions))

{% hint style="info" %}
Patterns are unanchored. Use line-start (`^`) and line-end (`$`) markers to anchor patterns.
{% endhint %}

### Sudo filter

The `sudo` filter uses a boolean format rather than a regex pattern:

```yaml
resource:
  type: integration
  service: ssh
  filters:
    sudo:
      effect: keep
      value: true
```

## Filter examples

### Restrict SSH access to a specific cloud provider

Allow SSH requests only for AWS-managed instances:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    filters:
      provider:
        effect: keep
        key: id
        pattern: ^aws$
  approval:
    - type: p0
```

### Restrict SSH access to a specific group

Allow SSH access only to instances in the "web-servers" group:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    accessType: group
    filters:
      group:
        effect: keep
        key: name
        pattern: ^web-servers$
  approval:
    - type: p0
```

### Restrict SSH access by AWS account

Allow SSH access only to instances in a specific AWS account:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    filters:
      parent:
        effect: keep
        key: id
        pattern: ^123456789012$
  approval:
    - type: group
      id: sre-team@yourco.com
      label: SRE Team
      directory: workspace
```

### Deny sudo access

Deny all SSH requests that include sudo privileges:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    filters:
      sudo:
        effect: keep
        value: true
  approval:
    - type: deny
```

### Restrict SSH to a specific region

Allow SSH access only to instances in `us-east-1`:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    filters:
      region:
        effect: keep
        key: id
        pattern: ^us-east-1$
  approval:
    - type: p0
```

## Break glass access

Break glass provides emergency SSH access to **all** resources covered by your access policies. It's designed for incident response, when there is an outage and an engineer needs broad access to production systems to troubleshoot. Instead of requesting access to each instance individually and waiting for approval, they can use break glass access.

### How break glass works

1. A user requests SSH break glass access (access type `all`) via the CLI: `p0 request ssh all`
2. P0 identifies all access policies where the user is a matching requestor **and** the policy has a `breakGlassApprover` configured
3. P0 creates a **separate request for each matching access policy**. If you are a requestor in five different access policies, P0 creates five requests, and each must be individually approved.
4. Each request is routed to the break glass approver(s) configured on that policy
5. Once a break glass request for an access policy is approved, individual session requests to instances covered by that policy are **auto-approved**. You still make the individual session requests, but they no longer require manual approval
6. If no access policies with `breakGlassApprover` match the user, the request is rejected with: *"No access policy allows break-glass access"*

{% hint style="warning" %}
Break glass access grants broad SSH access. Restrict the `breakGlassApprover` option to a small, trusted group of approvers, for example, a network operations center (NOC) staffed 24/7.
{% endhint %}

{% hint style="info" %}
Break glass doesn't provision access to all instances at once. Instead, it pre-approves later individual session requests. You request specific instances as needed, and those requests are automatically approved based on the break glass grant.
{% endhint %}

### Configuring break glass

Break glass requires **two** types of access policies working together:

1. A **regular rule** with a standard approver, this handles day-to-day access to individual instances
2. A **break glass rule** with a `breakGlassApprover`, this handles the emergency `all` access request

Both rules must exist. The regular rule defines which resources are accessible and who approves normal requests. The break glass rule defines who can approve the emergency override.

{% hint style="warning" %}
If an access policy uses `accessType: session` filters, break glass requests (`accessType: all`) do not match that policy. Ensure your break glass policy either omits `accessType` or explicitly sets `accessType: all`.
{% endhint %}

#### Example: complete break glass configuration

```yaml
# Rule 1: Regular SSH access to customer stack
# Day-to-day access, approved by engineering managers
- requestor:
    type: group
    id: engineers@yourco.com
    label: Engineers
    directory: workspace
  resource:
    type: integration
    service: ssh
    accessType: session
    filters:
      destination:
        effect: keep
        key: name
        pattern: ^customer-node
  approval:
    - type: group
      id: eng-managers@yourco.com
      label: Engineering Managers
      directory: workspace

# Rule 2: Break glass access to customer stack
# Emergency access, approved by NOC team
- requestor:
    type: group
    id: engineers@yourco.com
    label: Engineers
    directory: workspace
  resource:
    type: integration
    service: ssh
    accessType: all
  approval:
    - type: group
      id: noc-team@yourco.com
      label: NOC Team
      directory: workspace
      options: { breakGlassApprover: true }
```

In this example:

* **Rule 1** grants engineers access to specific instances matching `customer-node*`, approved by engineering managers
* **Rule 2** grants engineers break glass access to all SSH resources, approved by the NOC team (staffed 24/7)
* When an engineer runs `p0 request ssh all`, P0 creates a break glass request routed to the NOC team
* Once the NOC team approves, the engineer can request individual sessions (for example, `customer-node-1`) and those requests are auto-approved

### Break glass with PagerDuty escalation

You can combine break glass with PagerDuty escalation for incident-driven emergency access:

```yaml
- requestor:
    type: any
  resource:
    type: integration
    service: ssh
    accessType: all
  approval:
    - type: escalation
      integration: pagerduty
      options: { breakGlassApprover: true, requireReason: true }
      services: [PSJXXXG]
```

In this example:

* Any user can request break glass SSH access
* The request requires a reason
* PagerDuty routes the request through the configured escalation policy
* Only the on-call responder from the configured PagerDuty service can approve

### Multiple access policies and break glass

When you are a requestor in multiple access policies, a break glass request creates a **separate request for each matching policy**. Each request:

* Routes the request to the break glass approver configured on that specific rule
* Must be individually approved
* Grants auto-approval for instances covered by that rule only

This means you can have different break glass approvers for different sets of resources. For example, the NOC team approves break glass for production systems, while the SRE team approves break glass for staging systems.

### Separating break glass from regular approvals

P0 routes requests to the correct approvers based on whether `breakGlassApprover` is set:

* Regular SSH requests (`session`, `group`, `parent`) are routed to approvers on rules **without** `breakGlassApprover`
* Break glass SSH requests (`all`) are routed to approvers on rules **with** `breakGlassApprover: true`

This separation ensures that break glass approvals require explicit authorization from designated approvers, while regular access follows the standard approval flow.

### Supported approval types for break glass

The `breakGlassApprover` option is available on the following approval types:

| Approval type       | Description                                        |
| ------------------- | -------------------------------------------------- |
| `p0`                | P0 security reviewers                              |
| `group`             | Members of a directory group                       |
| `escalation`        | PagerDuty escalation                               |
| `requestor-profile` | The requestor's manager from the directory profile |

{% hint style="info" %}
The `auto`, `persistent`, and `deny` approval types do not support the `breakGlassApprover` option.
{% endhint %}


# Agentic Access Policies

When an AI agent requests access through the [P0 AI Gateway](/readme/agentic-control-plane), the request is evaluated against your access policies just like a human request, but you can match it with a dedicated **agentic** requestor type. An agentic rule matches on the *agent and user combination*: which agent is acting, and which human it is acting for.

Configure these rules in **Policy Studio**, alongside your other access policies. See [Access Policies](/access-management/just-in-time-access/request-routing) for the general policy format.

## The agentic requestor

```yaml
requestor:
  type: agentic
  agent: <agent rule>
  user: <user rule>
```

Both halves must match: the `agent` rule matches the agent identity bound to the session, and the `user` rule matches the human on whose behalf the agent acts.

{% hint style="info" %}
Agent-driven requests only match policies whose requestor type is `agentic` or `any`. Policies with a `user` or `group` requestor never match agent-driven requests, so your existing human-only rules don't accidentally apply to agents. Conversely, an `agentic` rule never matches a request a human makes directly.
{% endhint %}

### Agent rules

#### "Any agent"

```yaml
agent:
  type: any
```

Matches any agent. Use this for blanket rules such as "all agent requests require human approval."

#### "MCP client"

```yaml
agent:
  type: mcp-client
  clientId: <client id>
```

Matches an agent using a specific MCP client, identified by the `client_id` issued when the agent registered with P0.

#### "User owned"

```yaml
agent:
  type: agent-owner
  owner: <owner's email address>
```

Matches any agent owned by a specific user.

#### "Group owned"

```yaml
agent:
  type: owner-group
  groups:
    type: group
    effect: keep|remove
    groups:
      - id: <group identifier>
        label: <human-readable name>
        directory: azure-ad|okta|workspace
```

Matches agents whose owner is (`keep`) or isn't (`remove`) a member of one of the listed IdP groups. The group `id`, `label`, and `directory` fields work the same way as in [group requestor rules](/access-management/just-in-time-access/request-routing#group).

#### "Federated"

{% hint style="info" %}
The Federated agent rule is in preview.
{% endhint %}

```yaml
agent:
  type: provider
  providerId: <identity provider id>
  subjectPattern: <regular expression>   # optional
```

Matches agents that authenticate to the gateway by federating a token from an external identity provider, rather than registering as a P0 MCP client. Use this rule to define policy for federated agents by *provider* instead of per agent.

* `providerId` is the identifier of an identity provider enrolled with your P0 AI Gateway (for example, `okta` or `azure-ad`). The rule matches only when every agent in the session was federated by this provider.
* `subjectPattern` is an optional regular expression matched against each agent's token subject. Set it to narrow the match to specific agents; omit it to match every agent from the provider.

Federated agents act without a bound human user, so a Federated rule always pairs with `user: { type: none }`. In Policy Studio, selecting the **Federated** agent type fixes the **User** selector to **No user**.

### User rules

The `user` half accepts the same rule types as a top-level requestor:

* `type: any` matches any user
* `type: user` with `uid: <email>` matches a specific user
* `type: group` with `id`, `label`, and `directory` matches members of an IdP group

See [Access Policies](/access-management/just-in-time-access/request-routing#requestor) for field definitions.

## Headless agents

Autonomous agents that don't act on a specific person's behalf (for example, a scheduled reporting job or a CI pipeline) make requests without a bound user identity. Their requests appear in P0 attributed to the agent itself ("Agent *\<client id>* requests…").

Constrain the **agent** side to match these sessions: use `mcp-client`, `agent-owner`, `owner-group`, or `provider` and pair it with `user: { type: any }`. The `provider` rule instead pairs with `user: { type: none }`, which matches only sessions that have no human user. A `user` or `group` user rule never matches a headless session, since there is no human identity to match.

Headless agents run unattended, so their policies typically pair [automatic approval](/access-management/just-in-time-access/request-routing#always-allowed) with a narrowly scoped resource: the agent gets exactly the access its job needs, without waking a human. For example, auto-approve a nightly reporting agent's AWS requests, but only for a single reports bucket:

```yaml
- requestor:
    type: agentic
    agent:
      type: mcp-client
      clientId: nightly-reporting-agent
    user:
      type: any
  resource:
    type: integration
    service: aws
    accessType: resource
    filters:
      resource:
        effect: keep
        key: arn
        pattern: ^arn:aws:s3:::nightly-reports$
  approval:
    - type: persistent
```

Any request the agent makes outside this scope (a different bucket, a different service) doesn't match this rule and falls through to your other policies.

{% hint style="warning" %}
`user: { type: any }` matches both headless and user-driven sessions. To govern a headless agent distinctly, give it its own MCP client registration and match on its `clientId`.
{% endhint %}

## Resource and approval

The `resource` and `approval` parts of an agentic policy stay the same. The resource is the underlying service the agent is requesting (for example, `aws` when an agent requests AWS access through the [AWS MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/aws)). The same [resource filters](/access-management/just-in-time-access/request-routing#resource) you use for human requests apply to agent requests too.

Any [approval rule](/access-management/just-in-time-access/request-routing#approval) can be attached: route agent requests to human approvers (`p0`, `group`), deny them outright (`deny`), or approve them automatically based on on-call status (`auto`, `escalation`).

## Examples

Require Security Reviewer approval for everything any agent requests:

```yaml
- requestor:
    type: agentic
    agent:
      type: any
    user:
      type: any
  resource:
    type: any
  approval:
    - type: p0
```

Block a specific MCP client from requesting any AWS access:

```yaml
- requestor:
    type: agentic
    agent:
      type: mcp-client
      clientId: my-ci-agent
    user:
      type: any
  resource:
    type: integration
    service: aws
  approval:
    - type: deny
```

Let engineers' agents (provided the Platform team owns the agent) request S3 access, with approval routed to Platform:

```yaml
- requestor:
    type: agentic
    agent:
      type: owner-group
      groups:
        type: group
        effect: keep
        groups:
          - id: platform@yourorg.com
            label: Platform
            directory: workspace
    user:
      type: group
      id: engineering@yourorg.com
      label: Engineering
      directory: workspace
  resource:
    type: integration
    service: aws
    filters:
      resource:
        effect: keep
        key: service
        pattern: ^s3$
  approval:
    - type: group
      id: platform@yourorg.com
      label: Platform
      directory: workspace
```

Auto-approve AWS access for agents federated by Okta whose subject starts with `ci-`, and only for a single S3 bucket:

```yaml
- requestor:
    type: agentic
    agent:
      type: provider
      providerId: okta
      subjectPattern: ^ci-
    user:
      type: none
  resource:
    type: integration
    service: aws
    accessType: resource
    filters:
      resource:
        effect: keep
        key: arn
        pattern: ^arn:aws:s3:::ci-artifacts$
  approval:
    - type: persistent
```

## Related documentation

* [Access Policies](/access-management/just-in-time-access/request-routing): the general policy format, resource filters, and approval options
* [Requesting access through the Agentic Gateway](/integrations/resource-integrations/agentic-gateway/requesting-access): how agents submit and use the requests these policies govern


# Access Bundles

Group several resource accesses into a single requestable Access Bundle in P0 Security, so users request everything they need for a task in one step.

An Access Bundle groups multiple resource accesses into a single requestable item. Instead of filing separate requests for an AWS role, a Google Cloud role, and a Kubernetes namespace, a user requests one bundle and P0 provisions every resource in it after approval.

Bundles are useful when a task consistently requires the same set of permissions across integrations, for example onboarding an engineer to a service or granting a standard "incident responder" access set.

{% hint style="info" %}
Access Bundles are in **beta**. The feature and its interface may change.
{% endhint %}

## How Access Bundles work

1. An **Owner** creates a bundle in Policy Studio and adds 2-15 resources from your installed integrations.
2. A user **requests** the bundle from the web app or Slack.
3. P0 **routes** the request to the approvers configured on the bundle.
4. After approval, P0 **provisions** every resource in the bundle through its own integration.
5. Access **expires** after the requested duration, the same as any other just-in-time request.

Each item in a bundle keeps the access behavior of its underlying integration. A bundle is a way to request several accesses together, not a new kind of grant.

## Prerequisites

Before you begin, confirm the following:

* The **Owner** role in your P0 organization (required to create and manage bundles).
* At least two [resource integrations](/integrations/resource-integrations) installed and configured, so the bundle has resources to include.

## Create an Access Bundle

### Open the Access Bundles view

1. Sign in to [p0.app](https://p0.app).
2. Navigate to **Policy Studio** in the sidebar.
3. Select **Access Bundles** in the category control at the top of the page.

<figure><img src="/files/CyEB7Fwof9G1I0VLfKTe" alt="" width="563"><figcaption></figcaption></figure>

You see a list of existing bundles. The list is empty the first time you open it.

### Start a new bundle

1. Click **Create Bundle**.

   The bundle editor opens with three sections: **Identity**, **Resource(s)**, and **Actions**. Configure each one in order.
2. Enter a name for the bundle in the name field at the top (for example, "Incident responder").

<figure><img src="/files/s2xeGYvfWaSeb1jJauJI" alt="" width="435"><figcaption></figcaption></figure>

{% hint style="info" %}
Access Bundles are edited only in the visual editor. Unlike access policies, they can't be edited as YAML.
{% endhint %}

### Define who can request the bundle

The **Identity** section specifies which users can request this bundle.

<figure><img src="/files/1CNDDiamWn9pZYzYReSY" alt="" width="388"><figcaption></figcaption></figure>

1. In the **Identity** section, select one of the following:
   * **Any**: Any user in your organization can request the bundle.
   * **User**: A specific user or directory group can request the bundle.
2. If you selected **User**, choose a specific user's email address or a directory group.

### Add resources to the bundle

The **Resource(s)** section defines what the bundle grants. A bundle must contain at least 1 and at most 15 resources.

<figure><img src="/files/aTivjciSYTLB16SsF1cL" alt=""><figcaption></figcaption></figure>

1. Click **Add to Access Bundle**.
2. Select the integration for the resource (for example, **AWS**, **Google Cloud**, or **Kubernetes**).
3. Select the access type and the specific resource for that integration.
4. Repeat for each resource you want to include. Resources are grouped by integration in the editor.

{% hint style="info" %}
If you add the same resource and access type twice, the editor flags the duplicate and excludes it from the saved bundle.
{% endhint %}

### Define how requests are approved

<figure><img src="/files/IAeG675Zag8QKLDt9Ylw" alt="" width="240"><figcaption></figcaption></figure>

The **Actions** section specifies how P0 handles requests for the bundle. This works the same way as approvals on an [access policy](/access-management/just-in-time-access/request-routing/configure-your-first-access-policy#define-the-actions-how-requests-are-approved).

1. Select an approval type (for example, **P0**, **Group**, or **Auto**).
2. Configure approval options as needed, such as **Require reason with request**.

If you don't configure an approval, P0 routes bundle requests to your configured Security Reviewers by default.

### Save the bundle

1. Review the bundle across all three sections.
2. Click **Create Access Bundle**.

The bundle appears in the Access Bundles list with the **Enabled** toggle turned on. It is now available for users who match the identity you configured.

## Request an Access Bundle

Users request a bundle the same way they request any other resource, by selecting **Access Bundle** as the resource type. Bundles can be requested from the web app and from Slack.

### Request from the web app

<figure><img src="/files/ZMQ6X9hPY04gJOTHBWI0" alt="" width="388"><figcaption></figcaption></figure>

1. Open the [P0 app](https://p0.app) and navigate to **Access Management**.
2. Click **Request Access**.
3. Select **Access Bundle** as the resource, then select the specific bundle.
4. Set the duration and, optionally, a reason.
5. Submit the request for approval.

### Request from Slack

If your organization has installed the [Slack integration](/integrations/notifier-integrations/slack), type `/p0 request` and select **Access Bundle** in the request modal, then choose the bundle to request.

For more ways to request access, see [Requesting Access](/access-management/just-in-time-access/requesting-access).

## Manage bundles

From the **Access Bundles** list, an Owner can:

* **Edit a bundle**: Click a bundle row to open the editor and change its identity, resources, or approval.
* **Disable a bundle**: Turn off the **Enabled** toggle. Disabled bundles aren't available for requests.
* **Delete a bundle**: Click the delete icon on the bundle row. This action can't be undone.

## Related

* [Configure your first access policy](/access-management/just-in-time-access/request-routing/configure-your-first-access-policy): Control who can request individual resources and how those requests are approved.
* [Requesting Access](/access-management/just-in-time-access/requesting-access): All the ways users can request access in P0.
* [Approving Access](/access-management/just-in-time-access/approving-access): How approvers review and manage requests.


# Session Recording

Session Recording in P0 allows you to view detailed activity that occurs within a privileged session.

You can see what actions users took, when they took them, who took them, and from where, empowering you to answer questions like:

* *What did a user do after gaining access?*
* *Were any sensitive operations performed?*
* *Did anything unexpected happen during a session?*

{% hint style="info" %}
Access logging is not generally available at the moment.

Please contact P0 support to learn more about this feature.
{% endhint %}

{% content-ref url="/pages/VVT1O9x1aG5hisaTgRIz" %}
[AWS](/access-management/just-in-time-access/session-recording/aws)
{% endcontent-ref %}


# AWS

View CloudTrail activity taken within a privileged session.

### **Step 1: Create a CloudTrail and CloudLake Data Store**

> Note: AWS CloudTrail is enabled by default for all AWS accounts, capturing management events in the Event history. However, to [retain logs beyond 90 days](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html#event-history-limitations) and to integrate with services like P0, you need to create a trail that delivers queryable logs to an Amazon S3 bucket.

<figure><img src="/files/sT0VRtbMy0NyFTUd9KT0" alt=""><figcaption><p>Enabling a CloudTrail trail allows more flexibility than the default logging settings.</p></figcaption></figure>

<figure><img src="/files/VaQ5GbGQpgoUJtgG6vfm" alt=""><figcaption><p>CloudTrail Lake allows you to run SQL-based queries on events.</p></figcaption></figure>

1. **Sign in** to the AWS Management Console and open the [CloudTrail console](https://console.aws.amazon.com/cloudtrail/).
2. Refer to [AWS's official documentation](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html) for up-to-date instructions on creating a trail and the accompanying CloudLake Data Store.
3. After creation, **copy the ARN** of the event data store for integration with P0.

### **Step 2: Integrate CloudTrail with P0** <a href="#id-6e974fe1-e164-4738-b8c2-a8c14de22e9b" id="id-6e974fe1-e164-4738-b8c2-a8c14de22e9b"></a>

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2F8jp4v6x8B1cMMNd5050e%2Fsession-recording-install-demo.mp4?alt=media&token=22f54e0f-c6b4-4081-ba2d-fcdaf5855263>" %}
Add AWS Access Logging Installation
{% endembed %}

#### **A. Adding a New AWS Account in P0** <a href="#f48495ec-2a34-482f-ada8-ca929eb8ba0a" id="f48495ec-2a34-482f-ada8-ca929eb8ba0a"></a>

1. In P0, navigate to **Integrations** > **AWS** > **Access Logging**.
2. Click **Add account**.
3. Select your AWS account identifier (Account must have previously been set up with IAM Management).
4. Paste the **CloudTrail Lake Event Data Store ARN** copied earlier.
5. Click **Next**. P0 will provide setup instructions, including Shell and Terraform options.

#### **B. Apply the IAM Role Policy** <a href="#id-7583ea12-5b5a-4904-92ff-645495f0625b" id="id-7583ea12-5b5a-4904-92ff-645495f0625b"></a>

1. Use the AWS CLI or CloudShell to run the `aws iam put-role-policy` command provided by P0.
   * This command grants the P0 Service Account permissions to query the specified CloudTrail Lake event data store.
   * This feature requires `StartQuery` and `GetQueryResults` within CloudLake, in addition to `GetRole` and `GetRolePolicy` from IAM.

### **Step 3: Viewing Sessions in P0** <a href="#a443529c-e368-488e-99db-02764834784f" id="a443529c-e368-488e-99db-02764834784f"></a>

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2F2Vz9DiceJTYVcMZPjIir%2Fsession-recording-search-demo.mp4?alt=media&token=02edbc17-ce53-44ea-b179-ab404fe56e4f>" %}
Search Logs
{% endembed %}

{% embed url="<https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2FYWZ4F4pVKm4pxss2Jhjv%2Fsession-recording-usage-demo.mp4?alt=media&token=14811433-97c2-4b71-9143-722a9c69c1ab>" %}
Export Logs
{% endembed %}

After integrating CloudTrail with P0:

1. **Access Requests**: When a user requests access (e.g., to assume a role), and it’s approved, the session is initiated.
2. **Session History**:
   * Navigate to Access Management > Activity or Access Management > History in P0.
   * Click ‘view’ for specified request
   * Click on ‘View Session History’
   * Here, you can see:
     * **Event names**: e.g., `GetCallerIdentity`, `DescribeAccessEntry`.
     * **Source**: e.g., `sts.amazonaws.com`, `eks.amazonaws.com`.
     * **User Identity**: Who performed the action.
     * **User Agent**: The tool or service used.
     * **Event Timestamps**: When the action occurred.
     * **Error Indicators**: Toggle off to only show successful events.
3. **Raw Logs**:
   * Click on individual entries to view raw CloudTrail logs.
   * Details include IP addresses, request IDs, session context, etc.
4. **Search:**
   * Search by event name, source, user agent, error, IP address, or resource ARN.
5. **Export:**
   * Export as either CSV or JSON
6. **Pagination:**
   * Adjust the number of rows requested (10/20/50/100).
   * Navigate through pages to view older logs.

> **Note**: CloudTrail logs may take up to **5 minutes** to appear after an event occurs.

### **Additional Considerations** <a href="#f00739ea-41b0-4da7-8bb8-0d20710ed35a" id="f00739ea-41b0-4da7-8bb8-0d20710ed35a"></a>

* **Data Events**: Enable only if necessary, as they can significantly increase log volume and costs.
* **Multi-Region Trails**: Recommended to capture events across all regions.


# Just-in-time API

P0’s Just-In-Time APIs enable secure, automated access provisioning with fine-grained control. These APIs are purpose-built for modern DevOps and security teams who need to grant ephemeral access based on intent, not static policies.

**Key API Groups:**

* [**Command API**](/access-management/just-in-time-access/just-in-time-api/command-api): Submit actionable commands that trigger access workflows, such as requesting temporary AWS roles or starting pre-approved tasks. Ideal for CLI or bot-driven automation.
* [**Access Requests API**](/access-management/just-in-time-access/just-in-time-api/access-requests-api): Programmatically approve, deny, or revoke access requests with full context. These APIs allow security teams and automated systems to control access lifecycles in real time.
* [**Access Policies API**](/access-management/just-in-time-access/just-in-time-api/access-policies-api): Define dynamic access policies that map incoming requests to specific approval paths. This enables custom access control based on user, group, environment, or resource context.

All endpoints are protected with bearer tokens and designed for high-trust, auditable interactions.

For a step-by-step walkthrough of creating, checking, approving, and revoking a request in code, see [Automate access requests with the API](/getting-started/automate-access-requests-with-the-api).

## JIT Settings in P0 Management

P0 Management provides a user-friendly interface to configure key Just-in-time (JIT) access settings: **custom expiry**, **approvable duration**, **max access duration**, and **persistent access duration**. These settings define the lifetime and conditions of temporary access for users. Admins can configure these parameters directly within the app, allowing for granular control over access privileges in line with least-privilege principles and audit requirements. By tailoring these durations in the UI, organizations can automate and standardize just-in-time access workflows without leaving the P0 platform.

### Impact on User Access and Permissions

When set on the P0 Management page, these settings directly influence how users request and receive access within the app:

* **Custom Expiry**
  * Admins can define multiple custom expiry presets (e.g., 30 minutes, 2 hours, 1 day).
  * When users request access, these presets appear as selectable options in the access request UI, allowing requestors or approvers to choose the most appropriate duration for the use case.
  * This streamlines access requests, promotes consistency, and reduces the risk of over-permissioning.
* **Approvable Duration**
  * Defines the window of time within which an access request must be approved. Requests that remain pending beyond this duration are automatically timed out.
  * Admins can configure this setting directly from the P0 Management page. The default is 14 days.
  * This prevents stale requests from lingering indefinitely, ensuring that unapproved requests are cleaned up automatically.
* **Max Access Duration**
  * Sets the upper limit for how long any single access grant can last, regardless of the preset or custom request.
  * The UI enforces this limit, preventing users or approvers from granting access that exceeds the configured maximum.
  * This ensures no temporary access persists longer than governance policies allow.
* **Persistent Access Duration**
  * Defines the standard (default) duration for recurring or standing access (such as scheduled access windows).
  * Admins can configure these durations directly from the P0 Management page, supporting dynamic permissioning and minimizing standing privileges.
  * The UI will apply this default when users or automation processes request standing access, reducing manual errors.

<figure><img src="/files/PxAYIDOdluvMhOqXFwmd" alt="P0 Management Just-in-time settings page showing expiry duration options, maximum access duration, and standing access duration configuration" width="560"><figcaption></figcaption></figure>

These controls allow admins to tailor access durations directly in the app, streamlining workflows and supporting least-privilege principles. For more details, see the [JIT Settings API](/p0-management/management-api/just-in-time-settings-api).

You can also configure these settings as code with the [P0 Terraform provider](https://registry.terraform.io/providers/p0-security/p0/latest/docs) (version `0.50.0` or later):

* Use [`p0_access_durations`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/access_durations) to set the approvable, max access, and standing access durations.
* Use [`p0_expiry_options`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/expiry_options) to define the custom expiry presets requestors can select.


# Command API

Enable external systems to programmatically initiate access requests, enabling automation and integration with internal tools, bots, and security workflows.

The Command API enables programmatic creation of access requests within the P0 platform. It is designed to support custom workflows and automation. Integrate with external systems and services to initiate access grants without using the P0 user interface.

This is particularly useful for integrating P0 into your internal tooling, bots, or security workflows that require automatic access escalation based on alerts, CI/CD pipelines, or external approvals.

## Submit a command to P0

> Submits a command to P0. This endpoint allows automation of access requests or other operations.<br>

```json
{"openapi":"3.0.3","info":{"title":"P0 Command API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/o/{orgId}/command":{"post":{"summary":"Submit a command to P0","operationId":"submitCommand","description":"Submits a command to P0. This endpoint allows automation of access requests or other operations.\n","parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization identifier"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["argv","scriptName"],"properties":{"argv":{"type":"array","items":{"type":"string"},"description":"Command-line arguments"},"scriptName":{"type":"string","description":"The script or command name to execute"}}}}}},"responses":{"200":{"description":"Command accepted and processed","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"},"message":{"type":"string"},"id":{"type":"string","description":"Request ID"},"isPreexisting":{"type":"boolean"},"isPersistent":{"type":"boolean"}}}}}},"400":{"description":"Bad request – malformed payload"},"401":{"description":"Unauthorized – missing or invalid token"}}}}}}
```


# Access requests API

Enable programmatic approval, denial, and revocation of access, enabling seamless integration with internal tools, bots, and security workflows for automated access escalation.

The Access Request API enables programmatic approval, denial, and revocation of access requests within the P0 platform. It is designed to support custom workflows and automation. Integrate with external systems and services to process access grants without using the P0 user interface.

This is particularly useful for integrating P0 into your internal tooling, bots, or security workflows that require automatic access escalation based on alerts, CI/CD pipelines, or external approvals.

## Approve a permission request

> Approve an access request by request ID.

```json
{"openapi":"3.0.4","info":{"title":"P0 Permission Request API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/approve":{"post":{"summary":"Approve a permission request","operationId":"approveRequest","description":"Approve an access request by request ID.","parameters":[{"name":"orgId","in":"path","description":"Organization identifier","required":true,"schema":{"type":"string"}},{"name":"requestId","in":"path","description":"Unique identifier for the permission request","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expirationLength"],"properties":{"expirationLength":{"type":"string","description":"Duration for which access should be granted (e.g. \"2h\", \"30m\")"}}}}}},"responses":{"200":{"description":"Request approved"},"400":{"description":"Invalid or expired request"},"401":{"description":"Unauthorized"}}}}}}
```

## Deny a permission request

> Deny an access request by request ID.

```json
{"openapi":"3.0.4","info":{"title":"P0 Permission Request API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/deny":{"post":{"summary":"Deny a permission request","operationId":"denyRequest","description":"Deny an access request by request ID.","parameters":[{"name":"orgId","in":"path","description":"Organization identifier","required":true,"schema":{"type":"string"}},{"name":"requestId","in":"path","description":"Unique identifier for the permission request","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Request denied"},"400":{"description":"Invalid or expired request"},"401":{"description":"Unauthorized"}}}}}}
```

## Revoke a granted permission

> Revoke access previously granted by request ID.

```json
{"openapi":"3.0.4","info":{"title":"P0 Permission Request API","version":"1.0.0"},"servers":[{"url":"https://api.p0.app"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"paths":{"/o/{orgId}/permission-requests/{requestId}/revoke":{"post":{"summary":"Revoke a granted permission","operationId":"revokeRequest","description":"Revoke access previously granted by request ID.","parameters":[{"name":"orgId","in":"path","description":"Organization identifier","required":true,"schema":{"type":"string"}},{"name":"requestId","in":"path","description":"Unique identifier for the permission request","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Access revoked"},"400":{"description":"Invalid or expired request"},"401":{"description":"Unauthorized"}}}}}}
```


# Access policies API

Enable fine-grained control over how just-in-time access requests are evaluated, approved, and enforced, ensuring secure, compliant, and context-aware access policies.

The Access Policies API gives you fine-grained control over how just-in-time access requests are evaluated and approved. By defining policy rules based on both the **requestor** (who is making the request) and the **resource** (what they’re trying to access), you can enforce consistent, auditable, and dynamic access controls across your infrastructure.

**Access policies** allow you to direct access requests through different approval paths based on context. For example, you can require manual approval for sensitive production systems, while allowing auto-approved access to staging environments. You can also limit request scope using filters or directory-based rules, ensuring access is only available to the right people at the right time.


# Creating an Environment

Follow this guide to install P0 for data collection in your cloud provider, and to run your first posture and inventory scans.

## Install for IAM data collection

First, connect P0 to your cloud service provider by installing the **IAM assessment** integration.

{% hint style="warning" %}
You must install the **IAM assessment** integration to use **Access Inventory** or **Posture**. P0 collects the IAM data for both products through this integration. Install it on each cloud provider you want to assess before creating an environment.
{% endhint %}

{% hint style="warning" %}
If you have P0 installed for just-in-time access, you'll still need to follow this step, as data collection requires different permissions in your cloud provider.
{% endhint %}

Follow the cloud-specific guide for each provider you want to assess:

* [Install IAM assessment on Google Cloud](/environments/creating-an-environment/install-iam-assessment-google-cloud)
* [Install IAM assessment on AWS](/environments/creating-an-environment/install-iam-assessment-aws)
* [Install IAM assessment on Microsoft Azure](/environments/creating-an-environment/install-iam-assessment-azure)

Each guide walks you through navigating to your provider's integration page on the P0 app. After logging in to [p0.app](https://p0.app), select "Integrations," then your cloud provider. Choose "IAM assessment" and follow the steps to install P0.

<figure><img src="/files/NZ54NhyUiZ81NuhYUABv" alt="Google Cloud integration page in P0 showing available components including Access logging, Cloud Run invocation, Domain-restricted sharing, and IAM assessment" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
Make sure you have the ability to create custom roles and assign privileges in your cloud provider before beginning.
{% endhint %}

{% hint style="info" %}
To augment the usage data available to P0, you may also install "Access logging"
{% endhint %}

## Running your first scan

Navigate to "Dashboard", then select "Create" under "Create an environment to get started":

<figure><img src="/files/Cg4DQmTHm2oOnOZcFaqq" alt="P0 dashboard prompt showing Create an environment to get started with a Create button"><figcaption></figcaption></figure>

Choose a useful name, an assessment frequency, and the targets to assess (this will be the resources you installed in the previous step), then select "Create Environment".

<figure><img src="/files/FN0QIOBSOZdIHbuhylT4" alt="Create New Environment dialog with fields for environment name, assessment frequency, integration selection, and an option to start scheduling immediately" width="375"><figcaption></figcaption></figure>

{% hint style="info" %}
If you select "Start scheduling assessments immediately", the first scan runs as soon as the environment is created. If you would rather trigger the scan manually, you can uncheck this setting and navigate to "Settings" to run a scan once the environment is created.
{% endhint %}

Within a few moments P0 will start collecting data from your project:

<figure><img src="/files/QXKfCqNvQBdXHavmE8Fo" alt="Environment status page showing data collection progress with steps for Data Sources Prepared, Collecting Data, Constructing IAM Graph, and Evaluating Monitors" width="563"><figcaption></figcaption></figure>

Once the data-collection job completes, click "Dashboard" to see your results.

<figure><img src="/files/fFIhzxqmlrTyizWNCm43" alt="P0 dashboard showing posture findings chart, inventory identity breakdown, and just-in-time access metrics including approval time and request frequency" width="563"><figcaption></figcaption></figure>

Congratulations, you've run your first environment scan with P0!

For information on how to view and use the results, see [Access Inventory](/inventory/access-inventory) and [Posture Overview](/posture/posture-overview).


# Install IAM assessment on Google Cloud

Install the P0 IAM assessment integration on Google Cloud to collect IAM data. Required to use Access Inventory and Posture for your GCP projects.

Install the **IAM assessment** integration to let P0 collect and analyze the IAM configuration of your Google Cloud projects.

{% hint style="warning" %}
You must install the **IAM assessment** integration to use **Access Inventory** or **Posture**. P0 builds the identity graph and evaluates posture findings from the data this integration collects. Without it, Inventory and Posture have no data to display.
{% endhint %}

## What data P0 collects

The IAM assessment grants P0 a read-only custom role and uses it to collect the IAM configuration of your projects. P0 reads metadata and configuration only. It doesn't read the contents of your storage buckets, databases, or other application data.

P0 collects the following datasets:

| Dataset                          | What it includes                                                                                        | Google Cloud API                  |
| -------------------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------- |
| IAM policy bindings              | Role grants on organizations, folders, projects, and resources, including inherited (ancestor) bindings | Cloud Asset API                   |
| Resource inventory               | Resources in scope, such as Compute instances, storage buckets, service accounts, and BigQuery datasets | Cloud Asset API                   |
| Roles                            | Predefined and custom role definitions and their permissions                                            | IAM API                           |
| Service accounts                 | Service accounts and their metadata                                                                     | IAM API                           |
| Service account keys             | Key metadata, such as creation date and key type (P0 does not read private key material)                | IAM API                           |
| Service account activity         | Authentication-event counts used to detect unused identities and keys                                   | Cloud Monitoring API              |
| IAM recommendations              | Google's IAM policy insights, such as over-privileged or unused grants                                  | Recommender API                   |
| Policy analysis                  | Effective access derived from `analyzeIamPolicy`                                                        | Cloud Asset API                   |
| Compute and Cloud Run identities | Service identities attached to Compute instances and Cloud Run services and jobs                        | Compute Engine API, Cloud Run API |
| Essential contacts               | Project technical contacts                                                                              | Essential Contacts API            |

P0 collects this data when you first install the integration and refreshes it on each scan.

## Required Google Cloud APIs

Enable the following APIs on each project you assess. The custom role's permissions depend on these services, so the assessment fails to read data if an API is disabled.

| API                                      | Service name                          | Used for                                                    |
| ---------------------------------------- | ------------------------------------- | ----------------------------------------------------------- |
| Cloud Asset API                          | `cloudasset.googleapis.com`           | IAM policy bindings, resource inventory, policy analysis    |
| Cloud Resource Manager API               | `cloudresourcemanager.googleapis.com` | Project, folder, and organization metadata and IAM policies |
| Identity and Access Management (IAM) API | `iam.googleapis.com`                  | Roles, service accounts, and key metadata                   |
| Cloud Monitoring API                     | `monitoring.googleapis.com`           | Service account and key activity                            |
| Recommender API                          | `recommender.googleapis.com`          | IAM policy insights and recommendations                     |
| Compute Engine API                       | `compute.googleapis.com`              | Compute instance and service-identity data                  |
| Cloud Run Admin API                      | `run.googleapis.com`                  | Cloud Run service and job identities                        |
| Essential Contacts API                   | `essentialcontacts.googleapis.com`    | Project technical contacts                                  |

{% hint style="info" %}
The commands P0 generates during installation enable the required APIs and create the custom role for you. Enable the APIs manually only if your organization restricts API enablement or uses a separate provisioning process.
{% endhint %}

## Project-level vs organization-level configuration

You can install the IAM assessment on individual projects or across an entire organization. The data P0 collects is the same; the scope of the role binding and the permissions differ.

### Project-level install

Install on one or more specific projects. For each project, P0:

* Creates the **P0 IAM Auditor** (`p0IamAuditor`) custom role at the project level.
* Grants the role to the P0 service account on that project.
* Enables the [required APIs](#required-google-cloud-apis) on that project.

A project-level install assesses only the projects you add.

### Organization-level install

Install once at the organization to assess every project in the hierarchy. P0:

* Creates the custom role at the organization level and grants it to the P0 service account on the organization. The grant is inherited by all folders and projects, so you don't bind the role to each project individually.
* Adds the following organization- and folder-level permissions to the role, on top of the project-level permissions, so P0 can read the resource hierarchy and enumerate projects:
  * `resourcemanager.organizations.get`
  * `resourcemanager.organizations.getIamPolicy`
  * `resourcemanager.folders.get`
  * `resourcemanager.folders.list`
  * `resourcemanager.folders.getIamPolicy`
  * `resourcemanager.projects.list`

{% hint style="info" %}
Enable the [required APIs](#required-google-cloud-apis) on each project you want to assess, even with an organization-level install. The custom role binding is inherited across the hierarchy, but API enablement is per project.
{% endhint %}

The permissions the custom role grants at the project level are:

* `cloudasset.assets.analyzeIamPolicy`
* `cloudasset.assets.searchAllIamPolicies`
* `cloudasset.assets.searchAllResources`
* `compute.instances.list`
* `compute.projects.get`
* `compute.zones.list`
* `essentialcontacts.contacts.list`
* `iam.roles.get`
* `iam.roles.list`
* `iam.serviceAccountKeys.list`
* `iam.serviceAccounts.get`
* `monitoring.timeSeries.list`
* `recommender.iamPolicyInsights.list`
* `resourcemanager.projects.get`
* `resourcemanager.projects.getIamPolicy`
* `run.jobs.list`
* `run.revisions.list`

## Prerequisites

* Existing P0 account at [p0.app](https://p0.app/).
* Existing Google project(s) where you want to install P0.
* Permissions to create GCP roles and add IAM bindings to your Google project(s):
  * `iam.roleAdmin` (Role Admin)
  * `iam.securityAdmin` (Security Admin)

{% hint style="info" %}
You may need to work with your organization's administrator to obtain these permissions.
{% endhint %}

## Install the integration

1. Go to [p0.app](https://p0.app/), navigate to **Integrations**, and select **Google Cloud**.
2. If you have not connected an organization yet, enter your organization ID and click **Next**. To find your organization ID, run `gcloud organizations list` in the [Google Cloud Console Shell](https://console.cloud.google.com), or go to **IAM & Admin** > **Manage Resources**.
3. Choose the **IAM assessment** component.
4. Click **Add project**, enter the **Project identifier** of the GCP project you want to assess, and click **Next**.
5. Review the generated commands. P0 creates a custom role named **P0 IAM Auditor** (`p0IamAuditor`) with the read-only permissions required to collect IAM data, then grants it to the P0 service account.

## Provision access

Provision access using the [Google Cloud Console Shell](https://console.cloud.google.com) or Terraform. To use the Cloud Shell:

1. Go to your [Google Cloud project](https://console.cloud.google.com/) and select the project you entered in the previous step.
2. Open **Cloud Shell Editor**, then click **Open Terminal**.
3. If you use multiple Google accounts, run `gcloud config set account email@email.com` and replace the email with your account email.
4. Copy the **Shell** commands from the P0 configuration page, paste them into the terminal, and press `Return`. If an authorization window appears, click **Authorize**.
5. Return to the P0 configuration page and click **Next** to begin installation.

## Verify the installation

When the commands finish, click **Next** on the P0 configuration page. P0 validates that it can read your IAM data. When validation succeeds, the project appears as installed under the **IAM assessment** component.

## Next steps

* Create an environment and run your first scan. See [Creating an environment](/environments/creating-an-environment).
* View your results in [Access Inventory](/inventory/access-inventory) and [Posture](/posture/posture-overview).


# Install IAM assessment on AWS

Install the P0 IAM assessment integration on AWS to collect IAM data. Required to use Access Inventory and Posture for your AWS accounts.

Install the **IAM assessment** integration to let P0 collect and analyze the IAM configuration of your AWS accounts.

{% hint style="warning" %}
You must install the **IAM assessment** integration to use **Access Inventory** or **Posture**. P0 builds the identity graph and evaluates posture findings from the data this integration collects. Without it, Inventory and Posture have no data to display.
{% endhint %}

## Prerequisites

* Existing P0 account at [p0.app](https://p0.app/).
* At least one AWS account on which to install P0.
* The ability to create roles, add trust relationships, and create and assign role policies. You have this if the [IAMFullAccess managed policy](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/IAMFullAccess.html) is attached to your user.

## Install the integration

1. Navigate to **Integrations** on [p0.app](https://p0.app), then select **AWS**.
2. Choose the **IAM assessment** component.
3. Click **Add account**, enter your numeric AWS account ID, then click **Next**.
4. Review the generated commands. P0 sets up an [AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html) for unused access and creates a read-only IAM role that P0 assumes to collect IAM data.

## Provision access

Provision access using the AWS CLI or Terraform. To use the AWS CLI:

1. Copy the commands from the P0 configuration page.
2. Run the commands with the AWS CLI or in [AWS CloudShell](https://docs.aws.amazon.com/cloudshell/latest/userguide/welcome.html), or apply the Terraform configuration instead.

## Verify the installation

Return to the P0 configuration page and click **Next** to verify the installation. When verification succeeds, P0 takes you to the integration configuration page and the account appears as installed under the **IAM assessment** component.

## Next steps

* Create an environment and run your first scan. See [Creating an environment](/environments/creating-an-environment).
* View your results in [Access Inventory](/inventory/access-inventory) and [Posture](/posture/posture-overview).


# Install IAM assessment on Microsoft Azure

Install the P0 IAM assessment integration on Microsoft Azure to collect IAM data. Required to use Access Inventory and Posture for your Azure subscriptions.

Install the **IAM assessment** integration to let P0 collect and analyze Azure role assignments, permissions, and resource access for your subscriptions. The assessment also inventories the key and password credentials of service principals that hold role assignments, so Posture can flag stale, expiring, and overprivileged service principal access.

P0 also collects usage signals: the last sign-in activity of users and service principals, and the control-plane actions recorded in the [Azure Activity Log](https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/activity-log). P0 uses these signals to populate **Last Used** in Access Inventory and to flag unused identities and privileges in Posture.

{% hint style="warning" %}
You must install the **IAM assessment** integration to use **Access Inventory** or **Posture**. P0 builds the identity graph and evaluates posture findings from the data this integration collects. Without it, Inventory and Posture have no data to display.
{% endhint %}

{% hint style="info" %}
IAM assessment on Azure is available in beta.
{% endhint %}

## Prerequisites

* Existing P0 account at [p0.app](https://p0.app/).
* One Entra ID directory and at least one subscription on which to install P0.
* A completed [Azure app registration](/integrations/resource-integrations/microsoft-azure/azure-app-registration). IAM assessment uses the service identity created during app registration.
* The ability to create role assignments. You have this if the [Owner](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/privileged#owner) role is assigned to your user.
* The ability to grant admin consent for Microsoft Graph application permissions. You have this if the [Privileged Role Administrator](https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#privileged-role-administrator) or [Global Administrator](https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#global-administrator) role is assigned to your user.

{% hint style="info" %}
P0 derives the **Last Used** time for users and service principals from Microsoft Entra sign-in activity, which requires your tenant to hold a [Microsoft Entra ID P1 or P2](https://learn.microsoft.com/en-us/entra/fundamentals/licensing) license. Without a P1 or P2 license, P0 records only the usage it can observe from the Azure Activity Log, so some identities may show **Last Used** as *Unknown*.
{% endhint %}

## Install the integration

1. Navigate to **Integrations** on [p0.app](https://p0.app), then select **Azure**.
2. If prompted, enter the ID of the Entra tenant you want to install P0 on.
3. Choose the **IAM assessment** component.
4. Enter the **subscription ID** of the subscription you want to assess, then click **Next**.
5. Review the generated commands. To assess your subscription, P0 needs the built-in **Reader** role on the subscription, so P0 can collect IAM data, and the following read-only Microsoft Graph permissions, so P0 can inventory directory identities and the app credentials of service principals that hold role assignments:

   | Permission                | Description                                           |
   | ------------------------- | ----------------------------------------------------- |
   | `Group.Read.All`          | Read all groups                                       |
   | `GroupMember.Read.All`    | Read group memberships                                |
   | `User.Read.All`           | Read all users' full profiles                         |
   | `RoleManagement.Read.All` | Read role management resources                        |
   | `Reports.Read.All`        | Read all usage reports                                |
   | `AuditLog.Read.All`       | Read all audit log data                               |
   | `Application.Read.All`    | Read all application and service principal properties |

   Granting the Microsoft Graph permissions requires admin consent.

{% hint style="info" %}
The IAM assessment integration grants the same Microsoft Graph permissions as the [Entra ID directory integration](/integrations/resource-integrations/microsoft-azure). This lets you install IAM assessment on its own, without first installing the Entra ID integration.
{% endhint %}

## Provision access

The P0 configuration page provides the provisioning commands in two formats. Choose the tab that matches how you manage Azure access:

{% tabs %}
{% tab title="Shell" %}

1. Copy the commands from the **Shell** tab on the P0 configuration page. P0 generates a command that adds and admin-consents the Microsoft Graph permissions and a command that assigns the **Reader** role.
2. Run the commands with the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/) or in [Azure Cloud Shell](https://learn.microsoft.com/en-us/azure/cloud-shell/overview).

{% hint style="info" %}
The `az ad app permission admin-consent` command grants tenant-wide admin consent for the Graph permissions. Run it with an account that holds the Privileged Role Administrator or Global Administrator role.
{% endhint %}
{% endtab %}

{% tab title="Terraform" %}

1. Copy the configuration from the **Terraform** tab on the P0 configuration page. P0 generates:
   * An `azuread_application_api_access` resource that grants the Microsoft Graph permissions to the P0 app registration.
   * An `azuread_app_role_assignment` resource that grants admin consent for each permission.
   * An `azurerm_role_assignment` resource that assigns the **Reader** role on the subscription.
2. Add the configuration to your Terraform project, then run `terraform apply`.

{% hint style="info" %}
Applying the `azuread_app_role_assignment` resources grants tenant-wide admin consent for the Graph permissions. Run `terraform apply` with credentials that hold the Privileged Role Administrator or Global Administrator role.
{% endhint %}
{% endtab %}
{% endtabs %}

## Verify the installation

Return to the P0 configuration page and click **Next** to verify the installation. When verification succeeds, the subscription appears as installed under the **IAM assessment** component.

## Next steps

* Create an environment and run your first scan. See [Creating an environment](/environments/creating-an-environment).
* View your results in [Access Inventory](/inventory/access-inventory) and [Posture](/posture/posture-overview).


# Environment Terminology

This page is a guide to the terminology P0 uses for environment scans.

* **Environment** - The systems that P0 will analyze; consists of a name, scan frequency, and the targets from which P0 will collect data
* **Detection** - A match for a monitor query on a single scan
* **Finding** - An evolving history of detections for a single query match, across multiple scans; findings also have a status and you may attach notes to a finding; statuses are:
  * **Open** - The finding has been detected in the latest scan
  * **Ignored** - The finding has been manually ignored by an assessment owner
  * **Resolved** - The finding was not detected in the latest scan
* **Monitor** - A query that will run automatically on every scan; it also includes a description, severity, and any suggested remediation actions
* **Scan** - A single data collection and analysis run for an environment
* **Target** - A single system to be scanned; this is the integration and specification of what to scan; e.g. AWS accounts, Azure subscriptions, Google Cloud organizations, projects, or folders, Kubernetes clusters, or Okta or Workspace domains
* **Query** - A search of a scan's data for a specific set of terms; a query is composed of a "show" part (describing what element of the IAM configuration to return) and a "where" part (describing conditions that the shown elements must match)
* **Query Result** - A single match for a query; a query may return 0 or more results


# Settings

The settings page lets you control how your environment is scanned and edit your monitors. It's organized into three tabs: **Status**, **Configuration**, and **Monitors**.

### Status

The **Status** tab shows the current state of your environment.

### Configuration

The **Configuration** tab has the following sections:

#### Scheduling

You can edit the frequency at which your assessment runs, or disable scheduled runs altogether in this section.

<figure><img src="/files/weaojqzzNhDalvbLnHuN" alt="Scheduling configuration panel with frequency input set to 1 day, and Update Scheduling and Disable Scheduled Runs buttons" width="375"><figcaption></figcaption></figure>

### Monitors

The **Monitors** tab lets you edit or archive your monitors:

<figure><img src="/files/ouUsUxCXH7e3mPbMNggl" alt="Monitors tab showing an active monitor named Critical GCS risks with HIGH severity, and Edit and Archive options" width="563"><figcaption></figcaption></figure>

Edit monitors to change their severity, description, or search query. Archive monitors to prevent them from running on future assessment jobs. Archived monitors will also be removed from your default findings view.


# Integrations

Connect P0 with AWS, Google Cloud, Azure, Kubernetes, Okta, Slack, and other systems. Configure cloud, directory, notifier, and SIEM integrations.

Integrations allow you to connect your **P0 platform** with external systems, such as cloud environments (AWS, GCP, Azure, Kubernetes), SIEM tools, notification channels (Email, Slack), and custom applications.

Many resource integrations broker access through a [P0 connector](/readme/connectors), a small runtime you deploy in your own cloud account so that no standing credentials sit on laptops or in P0's SaaS.

## Prerequisites

* Existing P0 account at [p0.app](https://p0.app/).
* Sufficient privileged access to configure the target integration to connect with P0 app.

## Installation steps

To install an integration:

1. Login to you P0 account at [p0.app](https://p0.app/).
2. Click on Integrations.
3. Follow the specific guide for the integration.

## Available Integrations

Currently, P0 security has the following integrations:

* [📞 Notifier integrations](/integrations/notifier-integrations)
  * [💬 Slack](/integrations/notifier-integrations/slack)
  * [👬 Microsoft Teams](/integrations/notifier-integrations/microsoft-teams)
  * [✉️ Email](/integrations/notifier-integrations/email)
  * [📣 Custom Notifiers](/integrations/notifier-integrations/custom-notifiers)
    * [AWS Lambda Notifier](/integrations/notifier-integrations/custom-notifiers/aws-lambda-notifier)
* [🔑 Resource integrations](/integrations/resource-integrations)
  * [☁️ Google Cloud](/integrations/resource-integrations/google-cloud)
    * [Security perimeter](/integrations/resource-integrations/google-cloud/security-perimeter)
    * [Requesting Access](/integrations/resource-integrations/google-cloud/requesting-access)
    * [Permissions Reference](/integrations/resource-integrations/google-cloud/permissions-reference)
      * [Cloud Storage](/integrations/resource-integrations/google-cloud/permissions-reference/cloud-storage)
      * [Compute Engine](/integrations/resource-integrations/google-cloud/permissions-reference/compute-engine)
    * [Function Caller](https://github.com/p0-security/p0-docs/tree/main/integrations/resource-integrations/google-cloud/function-caller.md)
  * [📦 AWS](/integrations/resource-integrations/aws)
    * [Requesting Access](/integrations/resource-integrations/aws/requesting-access)
    * [AWS Integration API](/integrations/resource-integrations/aws/aws-integration-api)
    * [Function Caller](https://github.com/p0-security/p0-docs/tree/main/integrations/resource-integrations/aws/function-caller.md)
  * [🔷 Microsoft Azure](/integrations/resource-integrations/microsoft-azure)
    * [Requesting Access](/integrations/resource-integrations/microsoft-azure/requesting-access)
    * [Bastion host](https://github.com/p0-security/p0-docs/tree/main/integrations/broken-reference/README.md)
  * [☸️ Kubernetes](/integrations/resource-integrations/kubernetes)
    * [Requesting Access](/integrations/resource-integrations/kubernetes/requesting-access)
    * [Advanced Requests](/integrations/resource-integrations/kubernetes/advanced-requests)
  * [🔋 PostgreSQL](https://github.com/p0-security/p0-docs/tree/main/integrations/resource-integrations/postgresql/README.md)
    * [Installing an RDS Database](https://github.com/p0-security/p0-docs/tree/main/integrations/resource-integrations/postgresql/installing-an-rds-database.md)
    * [Requesting Access](https://github.com/p0-security/p0-docs/tree/main/integrations/resource-integrations/postgresql/requesting-access.md)
  * [❄️ Snowflake](/integrations/resource-integrations/snowflake)
  * [🌀 Tailscale](/integrations/resource-integrations/tailscale)
    * [Requesting Access](/integrations/resource-integrations/tailscale/requesting-access)
  * [🖥️ SSH](/integrations/resource-integrations/ssh)
  * [GitHub](/integrations/resource-integrations/github)
    * [Requesting Access](/integrations/resource-integrations/github/requesting-access)
  * [🛠️ Custom Resource](/integrations/resource-integrations/custom-resource)
    * [Installing a Custom Resource Integration](/integrations/resource-integrations/custom-resource/installing-a-custom-resource-integration)
* [👥 Directory integrations](/integrations/directory-integrations)
  * [Microsoft Entra ID](/integrations/directory-integrations/microsoft-entra-id)
    * [Requesting Access](/integrations/directory-integrations/microsoft-entra-id/requesting-access)
  * [Google Workspace](/integrations/directory-integrations/google-workspace)
  * [Okta](/integrations/directory-integrations/okta)
* [📝 Tracker integrations](/integrations/tracker-integrations)
  * [🎫 Jira](/integrations/tracker-integrations/jira)
* [✔️ Approval integrations](/integrations/approval-integrations)
  * [🔔 PagerDuty](/integrations/approval-integrations/pagerduty)
* [⚡ SIEM Integrations](/integrations/siem-integrations)
  * [Datadog Setup](/integrations/siem-integrations/datadog-setup)
  * [Splunk HEC Setup](/integrations/siem-integrations/splunk-hec-setup)


# Notifier integrations

Notifiers are where access requests are broadcasted and approvers may allow or deny requests.


# Slack

{% hint style="info" %}
Installing P0 on Slack takes about 2 minutes.
{% endhint %}

### Before you begin

Make sure you are either "Workspace Admin" or "Workspace Owner" for your workspace, or ask a user with one of these roles to install the P0 Slack integration.

### Adding Slack

1. On [p0.app](https://p0.app), navigate to "Integrations", then select Slack:

<figure><img src="/files/7cz0YrumcJsBs27SLAx3" alt="" width="563"><figcaption></figcaption></figure>

2. Click "Install integration". You'll be redirected to Slack's OAuth install page:

<figure><img src="/files/Esvii9rVqhAGuiYTVfqp" alt="" width="408"><figcaption></figcaption></figure>

3. Choose the workspace where you want P0 installed, and select a channel where you want P0 to post.

{% hint style="warning" %}
The Slack channel you specify must be a public channel.
{% endhint %}

After you finish adding the Slack bot, your integration should look like this (just with your own information of course):

<figure><img src="/files/NVUcQV2q954ziLclbwox" alt="" width="563"><figcaption></figcaption></figure>

And that's it. You're ready to use p0 to grant least-privileged, just-in-time access to members of your organization!

### Slack Settings

{% hint style="info" %}
P0 can create and manage a <mark style="color:blue;">@P0Approvers</mark> Slack group to automatically notify approvers when access requests are made.

If you want P0 to manage this group, you will need to configure Slack (in your Slack's admin settings page) so that anyone except guests can create and modify user groups.
{% endhint %}

<figure><img src="/files/fDAIX05r1ycUmYCHxKWB" alt="" width="563"><figcaption></figcaption></figure>


# Microsoft Teams

{% hint style="info" %}
Installing P0 on Microsoft Teams takes about 5 minutes.
{% endhint %}

### Before you begin

Make sure you are either "Privileged Role Administrator" or "Global Administrator" for your Microsoft Entra ID directory, or ask a user with one of these roles to install the P0 Microsoft Teams integration.

### Adding Microsoft Teams

1. On [p0.app](https://p0.app), navigate to "Integrations", then select **Microsoft Teams**.

<figure><img src="/files/JA1cp0KzZV1ORoQksHNU" alt=""><figcaption></figcaption></figure>

2. Complete the prerequisite steps outlined before clicking the "Install integration" button
   * Make the app available to users in your organization ([Teams docs](https://learn.microsoft.com/en-us/microsoftteams/teams-custom-app-policies-and-settings#upload-a-custom-app-using-teams-admin-center))
     * Access app management in the [Admin Center](https://admin.teams.microsoft.com/policies/manage-apps)
     * Navigate to Manage apps and search for P0 Security
     * Edit availability to all users of your organization

<figure><img src="/files/LyHdmhdIXv3LxBAZBj2y" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="warning" %}
While typically it takes a few minutes, sometimes it may take hours before the P0 Security app becomes fully available in your Teams instance.\
If you encounter errors during the installation process, try again later.
{% endhint %}

3. Click the "Install integration" button. You will be redirected to login to Entra ID. Authorize the P0 Security Bot by clicking "Accept".

<figure><img src="/files/JHuD96i7oTpAlU8Tyhdl" alt="" width="338"><figcaption></figcaption></figure>

4. Choose a Team and a public Channel where the P0 Security Bot will send approval messages. Click "Connect" to complete the installation.

{% hint style="info" %}
The Microsoft Teams integration supports standard channels only
{% endhint %}

<figure><img src="/files/k4irkBzUiLr6G3B3kSx6" alt="" width="563"><figcaption></figcaption></figure>

You should see the following screen when the integration is successful:

<figure><img src="/files/I4pBaAvsRfj6wCeBs3Ao" alt="" width="563"><figcaption></figcaption></figure>

You can pick a new channel from the drop-down and click "Switch channel" any time to route approval messages to a different channel. To use a different team, uninstall first by clicking the trash icon and re-install in a different team.

And that's it. You're ready to use p0 to grant least-privileged, just-in-time access to members of your organization!


# Email

The **Email Notifier** for P0 Security keeps your team informed of critical access-related events in real-time. It ensures that both access **requestors (principals)** and **approvers** are immediately notified of important lifecycle changes in access permissions.

The Email Notifier automatically sends email alerts for key access events, including:

* **New Access Request**: Notifies approvers when a user submits a request for access.
* **Approval Granted**: Notifies the requestor and approvers when their access is approved.
* **Access Revoked**: Notifies both the requestor and approvers when access is explicitly revoked.
* **Access Expired**: Sends alerts when an access grant naturally expires.
* **Pre-approval Granted**: Notifies the requestor and approver when pre-approved access has been granted.
* **Pre-approval Expiration Reminder**: Notifies approver 2 weeks before their pre-approval expires.

#### Who Gets Notified

| Event                            | Notified Parties      |
| -------------------------------- | --------------------- |
| Access Request Created           | Approvers             |
| Access Approved                  | Approvers & Requestor |
| Access Revoked                   | Requestor             |
| Access Expired                   | Requestor             |
| Pre-approval Created             | Approver & Requestor  |
| Pre-approval Expiration Reminder | Requestor             |

## Installing your Email Notifier

1. Go to p0.app in your browser, navigate to **Integrations**, and select **Email** in the **Notifiers** section.

<figure><img src="/files/Y41endxJymB0jQLDyD8R" alt="" width="563"><figcaption></figcaption></figure>

2. Within the integration, click the **"Install integration"** button.

<figure><img src="/files/TTPeKpd0CW3uzx4rHqbp" alt="" width="563"><figcaption></figcaption></figure>

2. You're ready to go! No additional configuration is needed.

<figure><img src="/files/yWutS8oU4iffonzBxfys" alt="" width="563"><figcaption></figcaption></figure>


# Custom Notifiers

Integrate P0 with any internal notification system you own, or with systems that do not have a built-in notification service yet.

Implement your own API endpoints that P0 can send notifications to.

## Set up Custom Notifier Integration

### Configuration Parameters

These parameters are configured by you during setup.

The examples use a custom notifier that sends notifications to an internal application for custom processing. Each custom notifier integration supports different trigger types. To reduce notification noise, you can choose only the specific triggers you want to be notified about.

<table><thead><tr><th width="179.36224365234375">Parameter</th><th>Description</th><th>Example Value</th></tr></thead><tbody><tr><td>Notifier ID</td><td>The identifier of the system you are integrating*</td><td>my-notifier-service</td></tr><tr><td>Notifier Name</td><td>The name of the custom notifier integration</td><td>Internal Customer Admin App</td></tr><tr><td>Webhook URL</td><td>Your https URL that P0 uses to call your endpoints.</td><td>https://p0-api.example.com/notifications</td></tr></tbody></table>

<sup>\* Identifiers in P0 do not allow whitespace and by convention use CamelCasing. Not visible to users.</sup>

## OpenAPI Specification

This specification describes the API endpoint you must implement to create a custom notifier integration in P0.

{% file src="/files/6GWcgg2VuYj1plYfB7Ts" %}

## Receive notifications about requests and preapprovals

> This endpoint receives access-related notifications from P0, including user access requests and preapproval notifications. Implement this endpoint to handle custom notifiers that are not natively supported by P0. Once implemented, register the endpoint using a custom notifier in the P0 console to start receiving events.<br>

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"tags":[{"name":"notifications"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"P0 generates a keypair during integration setup. Each http request sent by P0 to your endpoints contains a JWT signed with the private key in the Authorization header. Your endpoints must use the public key retrieved during integration setup, to decode the JWT   and verify its claims. The claims are: sub (Subject) iss (Issuer), aud (Audience), iat (Issued At), exp (Expiry)"}},"schemas":{"NotificationEvent":{"oneOf":[{"$ref":"#/components/schemas/PreapprovalCreatedEvent"},{"$ref":"#/components/schemas/PreapprovalExpiredEvent"}],"discriminator":{"propertyName":"type"}},"PreapprovalCreatedEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-created"]},"data":{"$ref":"#/components/schemas/Preapproval"}}},"Preapproval":{"type":"object","required":["id","type","access","startsAt","endsAt","principal","permission"],"properties":{"id":{"type":"string","description":"Random identifier for the preapproval generated by P0"},"type":{"type":"string","description":"The integration type the preapproval is for."},"access":{"type":"string","description":"The access type the preapproval is for."},"permission":{"$ref":"#/components/schemas/Permission"},"startsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval becomes active."},"endsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval expires."},"createdAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval was created."},"principal":{"type":"string","description":"The principal this preapproval grants access to"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"reason":{"type":"string","description":"The justification for the creation of this preapproval."}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}},"PreapprovalExpiredEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-expired"]},"data":{"$ref":"#/components/schemas/Preapproval"}}},"Error":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["public","internal"]},"message":{"type":"string"},"errorId":{"type":"string"}}}},"responses":{"EmptySuccessResponse":{"description":"Success"},"ErrorResponse":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/":{"post":{"tags":["notifications"],"summary":"Receive notifications about requests and preapprovals","description":"This endpoint receives access-related notifications from P0, including user access requests and preapproval notifications. Implement this endpoint to handle custom notifiers that are not natively supported by P0. Once implemented, register the endpoint using a custom notifier in the P0 console to start receiving events.\n","operationId":"handleAccessEvent","requestBody":{"description":"Grant a user access to a resource","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationEvent"}}},"required":true},"responses":{"200":{"$ref":"#/components/responses/EmptySuccessResponse"},"default":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## The NotificationEvent object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"NotificationEvent":{"oneOf":[{"$ref":"#/components/schemas/PreapprovalCreatedEvent"},{"$ref":"#/components/schemas/PreapprovalExpiredEvent"}],"discriminator":{"propertyName":"type"}},"PreapprovalCreatedEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-created"]},"data":{"$ref":"#/components/schemas/Preapproval"}}},"Preapproval":{"type":"object","required":["id","type","access","startsAt","endsAt","principal","permission"],"properties":{"id":{"type":"string","description":"Random identifier for the preapproval generated by P0"},"type":{"type":"string","description":"The integration type the preapproval is for."},"access":{"type":"string","description":"The access type the preapproval is for."},"permission":{"$ref":"#/components/schemas/Permission"},"startsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval becomes active."},"endsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval expires."},"createdAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval was created."},"principal":{"type":"string","description":"The principal this preapproval grants access to"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"reason":{"type":"string","description":"The justification for the creation of this preapproval."}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}},"PreapprovalExpiredEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-expired"]},"data":{"$ref":"#/components/schemas/Preapproval"}}}}}}
```

## The PreapprovalCreatedEvent object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"PreapprovalCreatedEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-created"]},"data":{"$ref":"#/components/schemas/Preapproval"}}},"Preapproval":{"type":"object","required":["id","type","access","startsAt","endsAt","principal","permission"],"properties":{"id":{"type":"string","description":"Random identifier for the preapproval generated by P0"},"type":{"type":"string","description":"The integration type the preapproval is for."},"access":{"type":"string","description":"The access type the preapproval is for."},"permission":{"$ref":"#/components/schemas/Permission"},"startsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval becomes active."},"endsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval expires."},"createdAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval was created."},"principal":{"type":"string","description":"The principal this preapproval grants access to"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"reason":{"type":"string","description":"The justification for the creation of this preapproval."}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}}}}}
```

## The PreapprovalExpiredEvent object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"PreapprovalExpiredEvent":{"required":["id","name","eventType","data"],"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of your custom notifier. The id is configured during setup of the custom notifier in P0."},"name":{"type":"string","description":"The user friendly name of your custom notifier. The name is configured during setup of the custom notifier in P0."},"eventType":{"type":"string","enum":["preapproval-expired"]},"data":{"$ref":"#/components/schemas/Preapproval"}}},"Preapproval":{"type":"object","required":["id","type","access","startsAt","endsAt","principal","permission"],"properties":{"id":{"type":"string","description":"Random identifier for the preapproval generated by P0"},"type":{"type":"string","description":"The integration type the preapproval is for."},"access":{"type":"string","description":"The access type the preapproval is for."},"permission":{"$ref":"#/components/schemas/Permission"},"startsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval becomes active."},"endsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval expires."},"createdAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval was created."},"principal":{"type":"string","description":"The principal this preapproval grants access to"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"reason":{"type":"string","description":"The justification for the creation of this preapproval."}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}}}}}
```

## The PermissionRequest object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"PermissionRequest":{"type":"object","properties":{"requestId":{"type":"string","description":"Random identifier for the request generated by P0"},"type":{"type":"string","description":"The integration type that this request was created for"},"access":{"type":"string","description":"The access type requested"},"status":{"type":"string","enum":["APPROVED","CLEANED_UP","DENIED","DONE","DRAFT","ERRORED","EXPIRED","NEW","EXPIRY_SUBMITTED","PENDING_APPROVAL","REVOKE_SUBMITTED","REVOKED","STAGED"]},"principal":{"type":"string","description":"The principal access will be granted to"},"requestor":{"type":"string","description":"The user requesting access. This payload might be different if requesting on behalf of another user."},"reason":{"type":"string","description":"The requestor's justification for this access request."},"requestedTimestamp":{"type":"number","description":"The epoch timestamp in milliseconds of when this request was created."},"permission":{"$ref":"#/components/schemas/Permission"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"error":{"$ref":"#/components/schemas/Error"}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}},"Error":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["public","internal"]},"message":{"type":"string"},"errorId":{"type":"string"}}}}}}
```

## The Preapproval object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"Preapproval":{"type":"object","required":["id","type","access","startsAt","endsAt","principal","permission"],"properties":{"id":{"type":"string","description":"Random identifier for the preapproval generated by P0"},"type":{"type":"string","description":"The integration type the preapproval is for."},"access":{"type":"string","description":"The access type the preapproval is for."},"permission":{"$ref":"#/components/schemas/Permission"},"startsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval becomes active."},"endsAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval expires."},"createdAt":{"type":"number","description":"The epoch timestamp in milliseconds for when this preapproval was created."},"principal":{"type":"string","description":"The principal this preapproval grants access to"},"approver":{"$ref":"#/components/schemas/ApprovalDetails"},"reason":{"type":"string","description":"The justification for the creation of this preapproval."}}},"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}},"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}}}}}
```

## The Permission object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"Permission":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"A short label or name for the requested permission."},"description":{"type":"string","description":"A full friendly description of the requested permission."}}}}}}
```

## The ApprovalDetails object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"ApprovalDetails":{"type":"object","required":["id"],"properties":{"id":{"type":"string","description":"A unique identifier of the entity that approved the request, this may be an email."},"name":{"type":"string","description":"A user friendly name of the entity that approved the request"},"email":{"type":"string","description":"The email of the entity that approved the request."}}}}}}
```

## The Error object

```json
{"openapi":"3.0.4","info":{"title":"Custom Notifier API","version":"0.0.1"},"components":{"schemas":{"Error":{"type":"object","required":["type","message"],"properties":{"type":{"type":"string","enum":["public","internal"]},"message":{"type":"string"},"errorId":{"type":"string"}}}}}}
```


# AWS Lambda Notifier

The **P0 AWS Lambda Notifier** lets you route notification events directly to your own AWS Lambda function. Built using the [Custom Notifier API](/integrations/notifier-integrations/custom-notifiers), it enables you to trigger custom workflows, integrate with internal systems, or run arbitrary logic in response to notification events from your existing AWS infrastructure.

Use it to:

* Trigger automation pipelines
* Forward events to internal alerting systems
* Apply custom filtering or enrichment
* Connect with services beyond email or Slack

## Before you begin

This guide walks you through setting up your **AWS Lambda Notifier.** Before diving into the steps, make sure you have installed an AWS function caller component in P0

[How to install the AWS function caller component](https://github.com/p0-security/p0-docs/blob/main/integrations/resource-integrations/aws/function-caller.md)

## Installing your AWS Lambda Notifier

1. Go to p0.app in your browser, navigate to **Integrations**, and select **AWS Lambda** in the **Notifiers** section.

<figure><img src="/files/CaXfkx4ugvT5H9nkhzRJ" alt="" width="563"><figcaption></figcaption></figure>

2. Within the integration, click the **"Add Notifier"** button.

<figure><img src="/files/28y4luKfLzlJWM1EUSlq" alt="" width="563"><figcaption></figcaption></figure>

3. Give your AWS Lambda notifier name. This is a user-friendly label that helps you recognize the purpose of the notifier at a glance.

<figure><img src="/files/zU1Clc8wqI3wUegodp86" alt="" width="563"><figcaption></figcaption></figure>

4. Choose the Lambda function you registered previously via the function-caller.

<figure><img src="/files/fHL80FV4ew49Bav6j3vs" alt="" width="563"><figcaption></figcaption></figure>

5. Complete the setup by clicking **"Finish"**. Your notifier is now active!

<figure><img src="/files/URN20Al9bSHL4rNpLBVR" alt="" width="563"><figcaption></figcaption></figure>

## Related Links

[Review the Custom Notifier OpenAPI specification](/integrations/notifier-integrations/custom-notifiers)


# Resource integrations

Configure just-in-time access for AWS, Google Cloud, Azure, Kubernetes, SSH, and more. Install P0 Security resource integrations to manage privileged cloud access.

Resource integrations allow you to request and grant access to resources in your systems.


# Agentic Gateway

Configure the P0 AI Gateway and the upstream MCP servers it fronts, so P0-managed AI agents can access them under runtime authorization policy.

The Agentic Gateway integration puts runtime authorization in front of the MCP servers in your environment, so agents don't operate on loose delegation or standing privilege and every action stays attributable. The [P0 AI Gateway](/readme/agentic-control-plane) sits in the data path between your agents and your MCP servers, verifies the identity of the originator and the agent on every tool call, and evaluates each action against the authorization policy defined in the [P0 AuthZ Control Plane™ for Agents](/readme/agentic-control-plane) before it reaches its target.

{% hint style="info" %}
The Agentic Gateway integration is a preview feature.
{% endhint %}

This integration has three components:

| Component                                                                                      | Use                                                                                                                                        |
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| [**Gateway**](/integrations/resource-integrations/agentic-gateway/gateway)                     | Registers your self-hosted P0 AI Gateway deployment with P0 so it can enforce policy and report activity.                                  |
| [**Identity provider**](/integrations/resource-integrations/agentic-gateway/identity-provider) | Enrolls an external identity provider so its JWT-authenticated agents are trusted at the gateway.                                          |
| [**MCP server**](/integrations/resource-integrations/agentic-gateway/mcp-server)               | Configures an upstream MCP server behind the gateway. Once configured, it becomes available to P0-managed agents across your organization. |

## Prerequisites

* An existing P0 account at [p0.app](https://p0.app/).
* A deployed P0 AI Gateway. See [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway). This is a prerequisite for the [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component.

## How it works

1. [**Register the gateway**](/integrations/resource-integrations/agentic-gateway/gateway). After deploying the gateway into your environment, register it with P0 so the AuthZ Control Plane can supply policy and collect audit activity.
2. [**Enroll an identity provider**](/integrations/resource-integrations/agentic-gateway/identity-provider). Tell the gateway which token issuer to trust so its JWT-authenticated agents are accepted.
3. [**Configure upstream MCP servers**](/integrations/resource-integrations/agentic-gateway/mcp-server). Declare each MCP server you want to expose behind the gateway. P0 supports two kinds:
   * **Predefined**: P0-authored server definitions
   * **Custom**: servers you define yourself

## Next steps

* Connect your agents. Each developer points their own agent at the configured server through the gateway. For Claude Code, see [Use MCP servers with Claude Code](/integrations/resource-integrations/agentic-gateway/using-mcp-servers).

Once an agent connects, the gateway authenticates every tool call, authorizes it against policy, and logs it. See [Requesting access](/integrations/resource-integrations/agentic-gateway/requesting-access) for how agents request and use just-in-time access, and [Agentic Access Policies](/access-management/just-in-time-access/request-routing/agentic-access-policies) for governing those requests.


# Gateway

Register your self-hosted P0 AI Gateway with P0 so it can enforce policy on agent tool calls and receive its MCP server definitions.

The **Gateway** component registers a deployed [P0 AI Gateway](/readme/agentic-control-plane) with P0. Once registered, P0 recognizes the gateway's identity, pushes it the definitions of the [MCP servers](/integrations/resource-integrations/agentic-gateway/mcp-server) it should host, and enforces policy at runtime. The gateway ships access logs directly to the system of your choice. You register one Gateway component per gateway deployment.

## Prerequisites

* An existing P0 account at [p0.app](https://p0.app/).
* A deployed P0 AI Gateway. See [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway). You need the gateway's public URL and its OAuth server endpoint from that deployment.

## Register the gateway

1. Navigate to **Integrations** on [p0.app](https://p0.app) and select **Agentic gateway**, then choose the **Gateway** component.

<figure><img src="/files/HLyvdsJfzfSLTE0JoBx0" alt="Agentic gateway integration page listing the Gateway and MCP server components, not installed"><figcaption></figcaption></figure>

2. Click **Add gateway**.

<figure><img src="/files/KJx3RGpNtWSfLYg68odJ" alt="Gateway component page with an empty list of installed gateways and an Add gateway button"><figcaption></figcaption></figure>

3. Enter the gateway details, then click **Next**:

<figure><img src="/files/OfV0jbMgUMelYtcNnRQC" alt="Form for installing a new gateway with fields for gateway identifier and agentic gateway URL"><figcaption></figcaption></figure>

* **Gateway identifier**: a name for this gateway within P0.
* **Agentic gateway URL**: the public URL where your gateway runs. The gateway exposes your MCP servers under this URL. This is the gateway host you configured during deployment.

4. Enter the **OAuth server endpoint** then click **Finish**:

<figure><img src="/files/otvIucpmE8iaCGwkY8ZI" alt="Second step of gateway configuration showing the read-only gateway URL and the OAuth server endpoint field"><figcaption></figcaption></figure>

* **OAuth server endpoint**: the public URL of your gateway's OAuth server, typically the same as the **Agentic gateway URL**. It must be publicly accessible and serve `.well-known/jwks.json`. P0 uses this endpoint as the gateway's token issuer to verify the requests it receives, so it must exactly match the issuer your deployed OAuth server presents.

5. The gateway now appears with the state **Installed**.

<figure><img src="/files/pUFUd6ZkJqJPoYkt1scJ" alt="Installed gateways list showing the new gateway with state Installed"><figcaption></figcaption></figure>

## How it works

After registration, the gateway periodically calls P0 to sync its configuration. P0 returns the set of [MCP servers](/integrations/resource-integrations/agentic-gateway/mcp-server) configured for this gateway, and the gateway reconciles them, adding newly configured servers and removing ones that are no longer configured. No servers are exposed until you configure them.

## Next steps

* Configure the [MCP servers](/integrations/resource-integrations/agentic-gateway/mcp-server) this gateway should front.


# Identity provider

Enroll an identity provider with the P0 AI Gateway so its JWT-authenticated agents are trusted to access the gateway.

The **Identity provider** component enrolls an external identity provider (IdP) with the [P0 AI Gateway](/readme/agentic-control-plane). Once enrolled, agents that present a JWT issued by that provider are trusted at the gateway, provided the token's claims match the patterns you configure. Use this component to federate the gateway with the issuer that mints your agents' tokens, so those agents can reach the [MCP servers](/integrations/resource-integrations/agentic-gateway/mcp-server) behind the gateway.

{% hint style="info" %}
The Agentic Gateway integration is a preview feature.
{% endhint %}

Enrolling an identity provider establishes **issuer trust**: it tells the gateway which token issuers to accept and which audience and subject claims those tokens must carry. When a matching token arrives, P0 resolves it to an individual agent client, either by registering the client automatically or by matching one you pre-registered, depending on the provider's **Dynamic registration** setting. Enrolling a provider does not, on its own, grant access to any resource. Every accepted request is still authorized against the [policies](/access-management/just-in-time-access/request-routing/agentic-access-policies) you define in P0.

## Prerequisites

* An existing P0 account at [p0.app](https://p0.app/).
* A registered [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component, and the gateway deployed in your environment. See [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway).
* The details of the issuer whose tokens you want to trust: its issuer URL (the `iss` claim), and the audience (`aud`) and subject (`sub`) claim values its agent tokens carry.

## Enroll an identity provider

1. Navigate to **Integrations** on [p0.app](https://p0.app) and select **Agentic gateway**, then choose the **Identity provider** component.
2. Click **Add identity provider**.
3. Enter the identity provider details, then finish the configuration:
   * **Issuer**: the issuer URL of the identity provider, matching the `iss` claim in the tokens it issues. Enter it as a full URL, such as `https://your-idp.example.com/`. P0 matches this value against the token's `iss` claim exactly, so it must match the issuer your provider presents character for character.
   * **Audience pattern**: a pattern that a token's audience (the `aud` claim) must match to be accepted. A token is accepted when at least one of its audience values matches this pattern.
   * **Subject pattern**: a pattern that a token's subject (the `sub` claim) must match to be accepted.
   * **Dynamic registration**: whether P0 automatically registers agents whose tokens match this provider. Enable it to let P0 register each matching agent as a client the first time it validates the agent's token. Leave it disabled to require that each agent client be pre-registered before P0 accepts its tokens.
4. The identity provider now appears in the component's list of enrolled providers.

{% hint style="info" %}
**Audience pattern** and **Subject pattern** are regular expressions, not literal strings. To match an exact value, anchor the expression, for example `^my-agent$`. To accept any value, use `.*`.
{% endhint %}

You can enroll more than one identity provider. A token is trusted if it matches **any** enrolled provider.

## Fields

| Field                    | Claim | Matching           | Description                                                                                                                                                            |
| ------------------------ | ----- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Issuer**               | `iss` | Exact match        | The issuer URL of the identity provider. Must be a valid URL and match the token's `iss` claim exactly.                                                                |
| **Audience pattern**     | `aud` | Regular expression | A token is accepted when at least one of its `aud` values matches this pattern.                                                                                        |
| **Subject pattern**      | `sub` | Regular expression | The token's `sub` claim must match this pattern.                                                                                                                       |
| **Dynamic registration** | —     | Toggle             | When enabled, P0 registers a matching agent as a client automatically on first validation. When disabled, the agent client must be pre-registered or validation fails. |

## How it works

When an agent presents a JWT to the gateway, the gateway asks P0 to validate it against the enrolled identity providers. P0 first rejects the token outright if it carries no audience or has a missing, malformed, or expired `exp` claim. It then looks for an enrolled provider that satisfies all of the following:

* The provider's **Issuer** equals the token's `iss` claim.
* At least one of the token's `aud` values matches the provider's **Audience pattern**.
* The token's `sub` claim matches the provider's **Subject pattern**.

If no enrolled provider matches, the token is rejected. Matching a provider establishes that the token comes from a trusted issuer and carries the expected audience and subject. It is a trust decision about the issuer, not an authorization decision about a specific resource.

Once a token matches a provider, P0 resolves it to an individual agent client, identified by the token's verified email when it carries one, or by its subject otherwise:

* If the client is already registered, P0 accepts the token, unless that client has been disabled.
* If the client is not yet registered, the provider's **Dynamic registration** setting decides the outcome. With dynamic registration enabled, P0 registers the client automatically and accepts the token. With it disabled, P0 rejects the token until you pre-register the client.

After the token is accepted, the gateway authorizes each tool call against your P0 policies and logs it.

## Next steps

* Configure the [MCP servers](/integrations/resource-integrations/agentic-gateway/mcp-server) you want to expose behind the gateway.
* Define the [Agentic Access Policies](/access-management/just-in-time-access/request-routing/agentic-access-policies) that govern what trusted agents can do.


# MCP server

Configure upstream MCP servers behind the P0 AI Gateway to make them available to P0-managed agents under policy.

The **MCP server** component configures an upstream MCP server behind the [P0 AI Gateway](/readme/agentic-control-plane). Once an MCP server is configured, it is available to P0-managed agents across your organization: agents connect to it through the gateway's URL, and every tool call is authenticated and checked against policy before it reaches the upstream server.

## Prerequisites

* A registered [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component, and the gateway deployed in your environment. See [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway).

## Types of MCP server

When you add a server, you set its **Definition**: a server predefined by P0, or a custom server you define yourself.

| Server                                                                              | Type       | Description                                                                                                                                                                                      |
| ----------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [**AWS**](/integrations/resource-integrations/agentic-gateway/mcp-server/aws)       | Predefined | Exposes the AWS CLI to agents. Requires the [AWS OIDC](/integrations/resource-integrations/aws/aws-oidc) component.                                                                              |
| [**GCP**](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp)       | Predefined | Exposes Google Cloud APIs to agents, with one server per Google Cloud service. Requires a [GCP Workload Identity Federation](/integrations/resource-integrations/google-cloud/gcp-wif) provider. |
| [**Custom**](/integrations/resource-integrations/agentic-gateway/mcp-server/custom) | Custom     | A server you define yourself, for any MCP server P0 does not ship a predefined definition for.                                                                                                   |

## Add an MCP server

Every MCP server starts with the same steps. The final configuration screen differs by server. Continue to the [AWS](/integrations/resource-integrations/agentic-gateway/mcp-server/aws), [GCP](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp), or [Custom](/integrations/resource-integrations/agentic-gateway/mcp-server/custom) page once you reach it.

1. Navigate to **Integrations** on [p0.app](https://p0.app) and select **Agentic gateway**, then choose the **MCP server** component.

<figure><img src="/files/naXhaQAraCRmOqMmG2QA" alt="Agentic gateway integration page listing the Gateway and MCP server components, not installed"><figcaption></figcaption></figure>

2. Click **Add server**.

<figure><img src="/files/1lDp6Mn8SDC8m94CH7du" alt="MCP server component page with an empty list of installed servers and an Add server button"><figcaption></figcaption></figure>

3. Enter the server details, then click **Next**:

<figure><img src="/files/WZ7IBREUXtefxhOMCnFp" alt="Form for installing a new server with fields for server identifier, gateway, and path"><figcaption></figcaption></figure>

* **Server identifier**: a name for this server within P0.
* **Gateway**: the [registered gateway](/integrations/resource-integrations/agentic-gateway/gateway) that hosts this server.
* **Path**: the path, relative to the gateway URL, where agents reach this server.

4. Set the **Definition** to the kind of server you are adding:
   * **P0**: a predefined server. Continue to its page, [AWS MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/aws) or [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp).
   * **Custom**: a server you define yourself. See [Custom MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/custom).

## Next steps

Once a server is configured behind the gateway, each developer connects their own agent to it. See [Use MCP servers with Claude Code](/integrations/resource-integrations/agentic-gateway/using-mcp-servers).


# AWS MCP server

Install the predefined AWS MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the AWS CLI.

The **AWS** MCP server is a predefined server that runs the official [AWS API MCP server](https://github.com/awslabs/mcp/blob/main/src/aws-api-mcp-server/README.md) (`awslabs.aws-api-mcp-server`) behind the [P0 AI Gateway](/readme/agentic-control-plane), wired up with P0's access controls. Agents can run AWS API calls (via `call_aws`, with `suggest_aws_commands` for help) without ever holding AWS credentials: the gateway obtains short-lived, policy-scoped access for each session using Workload Identity Federation, backed by the [AWS OIDC](/integrations/resource-integrations/aws/aws-oidc) component.

## Prerequisites

* A registered [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component, with the gateway deployed in your environment.
* The [AWS OIDC](/integrations/resource-integrations/aws/aws-oidc) component installed on the AWS account you want agents to reach. This provides the federated identity the AWS MCP server uses as its credential provider, and it requires the base [AWS integration](/integrations/resource-integrations/aws) with IAM management on the same account.

## Configure the AWS MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:

<figure><img src="/files/FDqeLDx4a8aqJjgIjHbc" alt="AWS MCP server configuration showing AWS IAM federation as the credential source and the P0 AWS CLI predefined definition"><figcaption></figcaption></figure>

* **Credential source**: choose **AWS IAM federation**, then select the **Federation provider**: the [AWS OIDC](/integrations/resource-integrations/aws/aws-oidc) identity you installed. The gateway uses this identity's audience when it federates to AWS, and your account's IAM trust policy authorizes it.
* **Definition**: choose **P0**, then select **AWS CLI** as the pre-defined server identifier.

{% hint style="info" %}
A Federation provider maps one-to-one to a single AWS account. To give agents access to multiple AWS accounts, configure a separate AWS MCP server for each account, using that account's [AWS OIDC](/integrations/resource-integrations/aws/aws-oidc) identity as its Federation provider.
{% endhint %}

2. The server now appears with the state **Installed**.

<figure><img src="/files/8bfVVjWtgHJBRpN8Fa6U" alt="Installed servers list showing the new AWS server with state Installed"><figcaption></figcaption></figure>

Once saved, P0 pushes the server definition to the gateway on its next sync, and the AWS MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived AWS credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the AWS MCP server, and what they may do in AWS.


# GCP MCP server

Install the predefined GCP MCP servers behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to Google Cloud APIs.

The **GCP** MCP servers are predefined servers that expose Google Cloud APIs to P0-managed agents behind the [P0 AI Gateway](/readme/agentic-control-plane), each wired up with P0's access controls. P0 ships one server per Google Cloud service, so you install only the services your agents need.

Agents call these services without ever holding Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation, backed by a [GCP Workload Identity Federation](/integrations/resource-integrations/google-cloud/gcp-wif) provider. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

{% hint style="info" %}
The GCP MCP servers are a preview feature. Contact P0 to enable them for your organization.
{% endhint %}

## Available servers

| Server                                                                                                       | Exposes                                                               |
| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
| [Compute Engine MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/compute)      | Compute Engine resources such as VM instances, disks, and networks.   |
| [Cloud Storage MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/storage)       | Cloud Storage buckets and objects.                                    |
| [BigQuery MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/bigquery)           | BigQuery datasets, tables, and jobs.                                  |
| [Cloud Monitoring MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/monitoring) | Cloud Monitoring metrics, alerting policies, and dashboards.          |
| [IAM MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/iam)                     | Identity and Access Management service accounts, roles, and policies. |

## Prerequisites

Every GCP MCP server shares the same prerequisites:

* A registered [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component, with the gateway deployed in your environment.
* A [GCP Workload Identity Federation](/integrations/resource-integrations/google-cloud/gcp-wif) provider installed on the Google Cloud project you want agents to reach. This provides the federated identity each GCP MCP server uses as its credential provider. It requires the base [Google Cloud integration](/integrations/resource-integrations/google-cloud) with IAM management installed on the same project.

## Configure a GCP MCP server

Every GCP MCP server follows the shared [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) flow. On the configuration screen you choose **GCP WIF federation** as the credential source and select the predefined definition for the service you want.

{% hint style="info" %}
A Federation provider maps one-to-one to a single Google Cloud project. To give agents access to more than one project, configure a separate MCP server for each project, using that project's GCP Workload Identity Federation provider as its Federation provider.
{% endhint %}

The service-specific configuration and the roles agents can request differ by server. Continue to the page for the server you are installing:

* [Compute Engine MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/compute)
* [Cloud Storage MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/storage)
* [BigQuery MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/bigquery)
* [Cloud Monitoring MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/monitoring)
* [IAM MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp/iam)

## Next steps

* Define the MCP roles and policies that determine which agents and users may call each GCP MCP server, and what they may do in Google Cloud.


# Compute Engine MCP server

Install the predefined Compute Engine MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the Google Cloud Compute Engine API.

The **Compute Engine** MCP server is a predefined [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp) that exposes the Google Cloud Compute Engine API to agents, so they can inspect and manage Compute Engine resources such as VM instances, disks, and networks. It runs P0's Google Cloud MCP image behind the [P0 AI Gateway](/readme/agentic-control-plane) and bridges to Google's hosted Compute Engine MCP endpoint.

Agents can request Compute Engine access two ways, and they never hold Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation.

* **Resource-scoped** access to a single VM instance, with a role such as `compute.instanceAdmin.v1`. This is preferred, since it grants the least access.
* **Project-wide** access across every resource in the project, with a role such as `compute.viewer`. Use this only when the calling tools must span multiple resources.

{% hint style="info" %}
The Compute Engine MCP server is a preview feature. Contact P0 to enable it for your organization.
{% endhint %}

Before you start, complete the [GCP MCP server prerequisites](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp#prerequisites).

## Configure the Compute Engine MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:
   * **Credential source**: choose **GCP WIF federation**, then select the **Federation provider**: the GCP Workload Identity Federation identity you installed. The gateway uses this identity's audience when it federates to Google Cloud, and the provider's trust configuration authorizes it.
   * **Definition**: choose **P0**, then select **Google Cloud Compute** as the predefined server identifier.
2. The server now appears with the state **Installed**.

Once saved, P0 pushes the server definition to the gateway on its next sync, and the Compute Engine MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the Compute Engine MCP server, and what they may do in Compute Engine.


# Cloud Storage MCP server

Install the predefined Cloud Storage MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the Google Cloud Storage API.

The **Cloud Storage** MCP server is a predefined [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp) that exposes the Google Cloud Storage API to agents, so they can work with buckets and objects. It runs P0's Google Cloud MCP image behind the [P0 AI Gateway](/readme/agentic-control-plane) and bridges to Google's hosted Cloud Storage MCP endpoint.

Agents can request Cloud Storage access two ways, and they never hold Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation.

* **Resource-scoped** access to a single bucket, with a role such as `storage.objectViewer` for read-only access or `storage.objectUser` for read/write access. Prefer this, since it grants the least access.
* **Project-wide** access across every resource in the project, with a role such as `storage.objectViewer`. Use this only when the calling tools must span multiple resources.

{% hint style="info" %}
The Cloud Storage MCP server is a preview feature. Contact P0 to enable it for your organization.
{% endhint %}

Before you start, complete the [GCP MCP server prerequisites](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp#prerequisites).

## Configure the Cloud Storage MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:
   * **Credential source**: choose **GCP WIF federation**, then select the **Federation provider**: the GCP Workload Identity Federation identity you installed. The gateway uses this identity's audience when it federates to Google Cloud, and the provider's trust configuration authorizes it.
   * **Definition**: choose **P0**, then select **Google Cloud Storage** as the predefined server identifier.
2. The server now appears with the state **Installed**.

Once saved, P0 pushes the server definition to the gateway on its next sync, and the Cloud Storage MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the Cloud Storage MCP server, and what they may do in Cloud Storage.


# BigQuery MCP server

Install the predefined BigQuery MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the Google Cloud BigQuery API.

The **BigQuery** MCP server is a predefined [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp) that exposes the Google Cloud BigQuery API to agents, so they can work with datasets, tables, and query jobs. It runs P0's Google Cloud MCP image behind the [P0 AI Gateway](/readme/agentic-control-plane) and bridges to Google's hosted BigQuery MCP endpoint.

Agents can request BigQuery access two ways, and they never hold Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation.

* **Resource-scoped** access to a single dataset or table, with a role such as `bigquery.dataViewer`. Prefer this, since it grants the least access.
* **Project-wide** access across every resource in the project, with a role such as `bigquery.dataEditor`. Use this only when the calling tools must span multiple resources.

{% hint style="info" %}
The BigQuery MCP server is a preview feature. Contact P0 to enable it for your organization.
{% endhint %}

Before you start, complete the [GCP MCP server prerequisites](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp#prerequisites).

## Configure the BigQuery MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:
   * **Credential source**: choose **GCP WIF federation**, then select the **Federation provider**: the GCP Workload Identity Federation identity you installed. The gateway uses this identity's audience when it federates to Google Cloud, and the provider's trust configuration authorizes it.
   * **Definition**: choose **P0**, then select **Google Cloud BigQuery** as the predefined server identifier.
2. The server now appears with the state **Installed**.

Once saved, P0 pushes the server definition to the gateway on its next sync, and the BigQuery MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the BigQuery MCP server, and what they may do in BigQuery.


# Cloud Monitoring MCP server

Install the predefined Cloud Monitoring MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the Google Cloud Monitoring API.

The **Cloud Monitoring** MCP server is a predefined [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp) that exposes the Google Cloud Monitoring API to agents, so they can query metrics and time series and inspect alerting policies and dashboards. It runs P0's Google Cloud MCP image behind the [P0 AI Gateway](/readme/agentic-control-plane) and bridges to Google's hosted Cloud Monitoring MCP endpoint.

Agents request access by Cloud Monitoring IAM role (for example, `monitoring.viewer`), scoped to a project and a business justification. They never hold Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation.

{% hint style="info" %}
The Cloud Monitoring MCP server is a preview feature. Contact P0 to enable it for your organization.
{% endhint %}

Before you start, complete the [GCP MCP server prerequisites](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp#prerequisites).

## Configure the Cloud Monitoring MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:
   * **Credential source**: choose **GCP WIF federation**, then select the **Federation provider**: the GCP Workload Identity Federation identity you installed. The gateway uses this identity's audience when it federates to Google Cloud, and the provider's trust configuration authorizes it.
   * **Definition**: choose **P0**, then select **Google Cloud Monitoring** as the predefined server identifier.
2. The server now appears with the state **Installed**.

Once saved, P0 pushes the server definition to the gateway on its next sync, and the Cloud Monitoring MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the Cloud Monitoring MCP server, and what they may do in Cloud Monitoring.


# IAM MCP server

Install the predefined IAM MCP server behind the P0 AI Gateway, giving agents policy-scoped, credential-free access to the Google Cloud IAM API.

The **IAM** MCP server is a predefined [GCP MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp) that exposes the Google Cloud Identity and Access Management (IAM) API to agents, so they can inspect service accounts, roles, and policies. Because Google does not host an MCP server for IAM, this is a P0-built server that implements its tools directly against the IAM API behind the [P0 AI Gateway](/readme/agentic-control-plane).

Agents request access by IAM role (for example, `iam.serviceAccountViewer`), scoped to a project and a business justification. They never hold Google Cloud credentials: the gateway obtains a short-lived, policy-scoped token for each session using Workload Identity Federation.

{% hint style="info" %}
The IAM MCP server is a preview feature. Contact P0 to enable it for your organization.
{% endhint %}

Before you start, complete the [GCP MCP server prerequisites](/integrations/resource-integrations/agentic-gateway/mcp-server/gcp#prerequisites).

## Configure the IAM MCP server

1. Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set the following fields, then click **Finish**:
   * **Credential source**: choose **GCP WIF federation**, then select the **Federation provider**: the GCP Workload Identity Federation identity you installed. The gateway uses this identity's audience when it federates to Google Cloud, and the provider's trust configuration authorizes it.
   * **Definition**: choose **P0**, then select **Google Cloud IAM** as the predefined server identifier.
2. The server now appears with the state **Installed**.

Once saved, P0 pushes the server definition to the gateway on its next sync, and the IAM MCP server becomes available to agents through the gateway URL. Access is granted per session and governed by your P0 policy; no long-lived Google Cloud credentials are issued.

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the IAM MCP server, and what they may do in Google Cloud IAM.


# Custom MCP server

Define and configure a custom MCP server behind the P0 AI Gateway when P0 does not ship a predefined server for it.

A **custom** MCP server is one you define yourself, for any MCP server P0 does not ship a [predefined](/integrations/resource-integrations/agentic-gateway/mcp-server) definition for. The gateway either proxies to a server hosted outside it or runs a Docker container to host the server's tools. Once configured, it behaves like any other server behind the [P0 AI Gateway](/readme/agentic-control-plane): agents reach it through the gateway URL, and every tool call is authenticated and checked against policy.

## Prerequisites

* A registered [Gateway](/integrations/resource-integrations/agentic-gateway/gateway) component, with the gateway deployed in your environment.

## Configure the custom MCP server

Follow the shared steps in [Add an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server#add-an-mcp-server) to name the server, choose its gateway, and set its path. On the configuration screen, set **Definition** to **Custom**, then choose a **Server type**.

<figure><img src="/files/rENk3fFyGiomqBhYCHZK" alt="Custom server definition form with Server type set to External, showing Server URL, Label, Logo URL, and Agent prompt fields"><figcaption></figcaption></figure>

### Server type

The **Server type** determines how the gateway reaches the server.

**External** proxies requests to an MCP server hosted outside the gateway, reachable at a fixed URL:

| Field          | Description                              | Required |
| -------------- | ---------------------------------------- | -------- |
| **Server URL** | URL of the externally hosted MCP server. | Yes      |
| **Label**      | Human-friendly label for this server.    | Yes      |

**Container** runs a Docker container behind the gateway to host the server's tools:

| Field                 | Description                                                                                        | Required |
| --------------------- | -------------------------------------------------------------------------------------------------- | -------- |
| **Docker image**      | Image that hosts the MCP server.                                                                   | Yes      |
| **Docker entrypoint** | Container run entrypoint. Supports Jinja2 templating to inject request parameters and credentials. | Yes      |

### Server details

These fields apply to both server types:

| Field            | Description                                | Required |
| ---------------- | ------------------------------------------ | -------- |
| **Logo URL**     | Address of a logo image for the server.    | No       |
| **Agent prompt** | Text that describes this server to agents. | Yes      |

## Next steps

* Define the MCP roles and policies that determine which agents and users may call the custom MCP server, and what they may do.


# Requesting access

How an AI agent requests, checks, uses, and relinquishes just-in-time access to MCP servers behind the P0 AI Gateway.

Once an agent [connects to a server behind the gateway](/p0-cli/p0-commands-and-usage/p0-claude-mcp-add), it doesn't hold standing access to the underlying resource. Instead, the gateway wraps the server's tools with **access meta-tools**, and the agent requests just-in-time access through the same P0 workflow that governs human requests, including your [access policies](/access-management/just-in-time-access/request-routing), approvals, and audit trail.

## The access meta-tools

Alongside the server's own tools, the gateway exposes four meta-tools to the agent:

| Tool         | What it does                                                                                                                                                                                                        |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list`       | Lists possible values for access-request fields (for example, available AWS accounts or resources), so the agent can fill in the request correctly. The agent only calls it when it doesn't already know the value. |
| `access`     | Submits an access request to P0 on the user's behalf. Returns a request ID and a link to the request.                                                                                                               |
| `check`      | Polls whether a submitted request has been granted.                                                                                                                                                                 |
| `relinquish` | Revokes an active grant and tears down the session.                                                                                                                                                                 |

The server's own tools are always visible to the agent, but calling them requires the request ID of a granted access request. Without one, the call fails and directs the agent to use `access` and `check` first. This means a prompt-injected or misbehaving agent can't bypass the request flow: the tools don't work without a live grant.

## The request loop

A typical session looks like this:

1. **The agent discovers what to request.** If it doesn't already know the right values (for example, which project or account hosts a resource), it calls `list` to enumerate valid options for each request field.
2. **The agent requests access.** It calls `access` with the arguments describing the resource, role, and reason. The gateway submits a P0 access request as the authenticated user, and returns the request ID together with a link to the request in P0.
3. **P0 evaluates the request.** Your [agentic access policies](/access-management/just-in-time-access/request-routing/agentic-access-policies) decide what happens next: the request can be auto-approved, denied, or routed to approvers in Slack or the P0 web app, exactly like a human-initiated request.
4. **The agent polls for the outcome.** It calls `check` with the request ID. While the request is pending approval, `check` tells the agent to keep polling (the gateway instructs it to back off exponentially, for up to 30 minutes). When the request is granted, `check` confirms the agent can start calling the server's tools; if it's denied or errors, the agent is told to stop.
5. **The agent uses the tools.** Each tool call carries the request ID. The gateway verifies the grant is still live, obtains the short-lived credential for the session, and runs the tool in an isolated, per-session environment. The credential is never exposed to the agent.
6. **The agent relinquishes access.** When the work is done (for example, when the user tells the agent they're finished), the agent calls `relinquish`. The gateway revokes the P0 grant and tears down the session.

## Session isolation and expiry

* **Per-session isolation.** Each grant runs in its own isolated environment, keyed to the user, the agent session, and the request. Sessions are never shared across users or grants.
* **Continuous verification.** The gateway re-verifies the grant with P0 during use. If access is revoked in P0 (by the user, an admin, or expiry), the agent's tool calls stop working as soon as the access revocation propagates in the target system (typically under 30 seconds).
* **Idle teardown.** The gateway tears down session environments after 10 minutes of inactivity; the agent's next granted call transparently starts a fresh one.

## Related documentation

* [Agentic access policies](/access-management/just-in-time-access/request-routing/agentic-access-policies): route, auto-approve, or deny agent requests
* [Just-in-time access overview](/access-management/just-in-time-access): the approval workflow agents participate in
* [p0 claude mcp add](/p0-cli/p0-commands-and-usage/p0-claude-mcp-add): connect Claude Code to a gated server


# Use MCP servers with Claude Code

Connect your Claude Code client to the MCP servers behind the P0 AI Gateway, so your agent's tool calls are authenticated and governed by policy.

After an admin [configures an MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server) behind the [P0 AI Gateway](/readme/agentic-control-plane), each developer connects their own [Claude Code](https://docs.claude.com/en/docs/claude-code) client to it with the P0 CLI. Connecting registers a per-user OAuth client and signs you in through P0, so your agent reaches the server through the gateway and every tool call is authenticated and checked against policy.

{% hint style="info" %}
Connecting is per user and per machine. Everyone who wants to use a server must run these steps on their own machine. Configuring a server behind the gateway is an admin task. It doesn't connect anyone's client.
{% endhint %}

## Prerequisites

* The [P0 CLI installed](/p0-cli/installing-p0-cli) and logged in (`p0 login`).
* [Claude Code](https://docs.claude.com/en/docs/claude-code) installed, with the `claude` binary on your `PATH`.
* At least one [MCP server configured](/integrations/resource-integrations/agentic-gateway/mcp-server) behind the gateway.

## List the available servers

List the MCP servers configured behind the gateway and available to you, and note the key of each one you want:

```bash
p0 claude mcp list
```

The output shows each server's key and gateway URL. See [`p0 claude mcp list`](/p0-cli/p0-commands-and-usage/p0-claude-mcp-list) for details.

## Add each server

Connect Claude Code to a server by its key. Run the command once per server you want to use:

```bash
p0 claude mcp add aws
p0 claude mcp add gcs
```

See [`p0 claude mcp add`](/p0-cli/p0-commands-and-usage/p0-claude-mcp-add) for all flags and options.

### Choose a scope

The `--scope` flag maps to Claude Code's own configuration scopes, which control **which of your projects** can see the server. When you omit `--scope`, Claude Code applies its default, `local`.

| Scope             | Where the server is available                                                                                                                    |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `local` (default) | Only in the current project directory, and only to you.                                                                                          |
| `user`            | Across all your projects on this machine, and only to you.                                                                                       |
| `project`         | To everyone who works in this project, through a `.mcp.json` committed to the repository. Each user still authenticates through P0 individually. |

To make a server available in every project on your machine, add it with `--scope user`:

```bash
p0 claude mcp add aws --scope user
```

## Connect and authenticate

1. Open Claude Code.
2. Run `/mcp`.
3. Connect and authenticate to the server. You sign in through P0.

From then on, your agent's tool calls are enforced and audited by the gateway.

## Verify

Run `/mcp` in Claude Code and confirm the server shows as connected. Your agent can now call the server's tools; the gateway authenticates and checks each call against policy before it reaches the upstream server.

## Switch to a different P0 user

The P0 CLI stores all your local state under `~/.p0`: your identity and config, the credential cache, and the OAuth client it registered for MCP (`~/.p0/claude/mcp-client.json`). To operate as a different P0 user, delete this directory, then sign in and reconnect:

```bash
rm -rf ~/.p0
p0 login
p0 claude mcp add <server> --scope user
```

{% hint style="info" %}
`p0 logout` clears your credentials but keeps the cached MCP OAuth client, so the next `p0 claude mcp add` reuses the previous client. Delete `~/.p0` to force the CLI to register a fresh client for the new user.
{% endhint %}

## Related

* [`p0 claude mcp list`](/p0-cli/p0-commands-and-usage/p0-claude-mcp-list): list the servers available to you.
* [`p0 claude mcp add`](/p0-cli/p0-commands-and-usage/p0-claude-mcp-add): connect Claude Code to a server.
* [MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server): configure a server behind the gateway (admin).


# AWS

Install P0 IAM management on AWS in about 10 minutes. Configure just-in-time access, identity governance, and privilege management for your AWS environment.

The AWS integration lets P0 grant just-in-time, least-privileged access to your AWS accounts. It has two components:

* **IAM management** provisions and revokes access for your users. Installing it takes about 10 minutes.
* **Resource inventory** extends IAM management with fine-grained, resource-level access.

### Setting up AWS IAM management

To install the IAM management component and choose how P0 provisions your users, see [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods). You choose one of these login types during setup:

* [IAM](/integrations/resource-integrations/aws/installation-methods/iam) — provision users defined in the account's IAM service.
* [Identity Center](/integrations/resource-integrations/aws/installation-methods/identity-center) — provision users through AWS Identity Center.
* [Federated](/integrations/resource-integrations/aws/installation-methods/federated) — provision users through an Okta SAML federation.

To provision access through a single shared Identity Center permission set instead, use the [Identity Center (merged)](/integrations/resource-integrations/aws/identity-center-merged) integration (beta).

### Setting up AWS resource inventory

Installing P0 resource inventory on AWS takes about 10 minutes.

The resource inventory component extends the IAM management integration and allows requesting [fine-grained resource-level](/integrations/resource-integrations/aws/requesting-access#fine-grained-resource-level-access) access in AWS.

{% hint style="info" %}
An installed AWS IAM management integration is required
{% endhint %}

1. Navigate to "Integrations" on [p0.app](https://p0.app), then select "Amazon Web Services". Choose the "Resource inventory" component:

<figure><img src="/files/oquAhMb0mBYOJ09LP6wn" alt="" width="563"><figcaption></figcaption></figure>

2. Click "Add account"

<figure><img src="/files/wOjhtUBgqT8olp6ze1bc" alt="" width="563"><figcaption></figcaption></figure>

3. Choose one of the AWS accounts already installed for IAM management:

<figure><img src="/files/7UXfgMD0eYoBfbrHoPEW" alt="" width="563"><figcaption></figcaption></figure>

4. Run the AWS CLI commands to configure Resource Explorer

<figure><img src="/files/mloqJw1rQrEjneavX6In" alt="" width="563"><figcaption></figcaption></figure>

5. Click "Next" to validate your setup. You will land on the resource inventory configuration page. Clicking "Next" again takes you back to the Resource inventory overview page.

<figure><img src="/files/XCWuYwPfvV5G0nKepE6P" alt="" width="563"><figcaption></figcaption></figure>

And that's it. You're all set to start granting just-in-time, least-privileged access to AWS with P0.


# Setting up AWS IAM management

Install the P0 AWS IAM management integration and choose how P0 provisions and identifies your users — as IAM users, through AWS Identity Center, or through a federated identity provider.

Installing P0 IAM management on AWS takes about 10 minutes. You install the IAM management component on an account, then choose how P0 provisions and identifies your users — the integration's **login type**.

## Before you begin

* Choose at least one account on which to install P0.
* Make sure you can create roles, add trust relationships, and create and assign role polices. You can do this if you have the [IAMFullAccess managed policy](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/IAMFullAccess.html) attached to your user.

## Install the IAM management component

{% hint style="info" %}
For fine-grained Kubernetes access in EKS use the [P0 Kubernetes integration](/integrations/resource-integrations/kubernetes).
{% endhint %}

1. Navigate to "Integrations" on [p0.app](https://p0.app), then select "Amazon Web Services". Choose the "IAM management" component:

<figure><img src="/files/oquAhMb0mBYOJ09LP6wn" alt="" width="563"><figcaption></figcaption></figure>

2. Click the "Add account" button to begin the installation

<figure><img src="/files/z4gQZ03LnBvoPUrcLSjg" alt="" width="563"><figcaption></figcaption></figure>

3. Enter an AWS numeric account ID, then click "Next".

<figure><img src="/files/z5wK5Io1jQJKkDVbrUjT" alt="" width="563"><figcaption></figcaption></figure>

4. The next page displays commands you can run using the AWS CLI to provision P0. You can also run these commands using AWS Cloud Shell.

<figure><img src="/files/GEXzt4K8bsrybnZOTW1p" alt="" width="563"><figcaption></figcaption></figure>

5. Copy and run these commands or use the Terraform configuration to deploy the changes. Click "Next" to verify the installation. If verification is successful you will be taken to the integration configuration page.

<figure><img src="/files/W7bGF1OVzFzIA6xAO4a4" alt="" width="563"><figcaption></figcaption></figure>

## Troubleshooting

### "The web identity token provided could not be validated"

When you click "Next" to verify the installation, the verification fails with an error like this:

```
Error configuring Amazon Web Services
Failed to verify permissions for account 171433610395: The web identity token provided could not be validated. See the AssumeRoleWithWebIdentity documentation for requirements. (account=171433610395 region=undefined)
```

This happens when the account already has an IAM identity provider for `accounts.google.com` whose audience list doesn't include P0's audience. P0 assumes the `P0RoleIamManager` role by calling `sts:AssumeRoleWithWebIdentity` with a Google-signed token. When a Google identity provider exists, AWS validates the token's audience against that provider's configured audiences, and the assume-role call fails if P0's audience is missing.

To fix this, either remove the existing Google identity provider so AWS validates the token against Google's built-in federation, or add P0's audience to the provider. If other workloads depend on the existing provider, add the audience instead of removing it.

To add P0's audience to the existing Google identity provider:

1. In the AWS console, open **IAM** > **Roles** and open the `P0RoleIamManager` role.
2. Select the **Trust relationships** tab and copy the value of the `accounts.google.com:aud` condition. This is P0's audience.

<figure><img src="/files/qhhk82RqbIfBVTaS7M22" alt="Trust relationships tab of the P0RoleIamManager role, with the accounts.google.com:aud condition value highlighted"><figcaption></figcaption></figure>

3. Open **IAM** > **Identity providers** and select your `accounts.google.com` provider.
4. On the **Audiences** tab, select **Actions** > **Add audience**, then paste the value you copied and save.

<figure><img src="/files/1DbQ0nxpT5pCBC5ckh29" alt="Audiences tab of the accounts.google.com identity provider with the Actions menu open and Add audience selected"><figcaption></figcaption></figure>

5. Return to the P0 installation and click "Next" to verify again.

## Choose a login type

On the configuration page, you define how P0 provisions and identifies your users in AWS. This choice is the integration's login type:

| Login type                                                                                      | How P0 identifies and provisions users                                                   | Best for                                                           |
| ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [IAM](/integrations/resource-integrations/aws/installation-methods/iam)                         | Matches users to IAM users in the account, by user name or by a tag.                     | Accounts whose users are defined directly in IAM.                  |
| [Identity Center](/integrations/resource-integrations/aws/installation-methods/identity-center) | Matches users to AWS Identity Center identities and grants a per-request permission set. | Organizations that provision access through AWS Identity Center.   |
| [Federated](/integrations/resource-integrations/aws/installation-methods/federated)             | Matches users through an Okta SAML federation and grants IAM roles.                      | Accounts that sign in through an Okta federated identity provider. |

Federated is a legacy sign-in method — AWS recommends Identity Center for new deployments.

The access types each login type supports differ:

| Access type      | IAM | Identity Center | Federated |
| ---------------- | :-: | :-------------: | :-------: |
| `group`          |  ✅  |                 |           |
| `permission-set` |     |        ✅        |           |
| `policy`         |  ✅  |        ✅        |           |
| `resource`       |  ✅  |        ✅        |     ✅     |
| `role`           |     |                 |     ✅     |

{% hint style="info" %}
To avoid Identity Center permission-set sprawl, you can provision access through a single shared permission set with the [Identity Center (merged)](/integrations/resource-integrations/aws/identity-center-merged) method. That method is in beta and requires a separately installed AWS Identity Center (merged) integration.
{% endhint %}

## Next steps

* [Set up AWS resource inventory](/integrations/resource-integrations/aws#setting-up-aws-resource-inventory) to request fine-grained, resource-level access.
* [Request AWS access](/integrations/resource-integrations/aws/requesting-access).


# IAM

Configure the P0 AWS IAM management integration to provision users defined in the account's IAM service, matching them by user name or by an email tag.

Choose the **IAM** login type when your users are defined directly in the account's IAM service. P0 matches each requestor to an IAM user and grants access to that user. This is the default login type.

## Prerequisites

* An [AWS IAM management integration](/integrations/resource-integrations/aws/installation-methods) installed on the target account.

## Configure IAM provisioning

On the AWS IAM management configuration page, select **As AWS IAM users**, then choose how P0 identifies your users:

* **User name is user email**: Select this option if each user's IAM user name equals their email address. P0 matches users by user name.
* **User email in a tag**: Select this option if user names don't equal email addresses. P0 reads the email from a tag you specify.

### Match users by an email tag

If your IAM user names don't equal email addresses, add a tag to each user you want to allow access through P0, then give P0 the tag name. For example, with a tag named `Email`:

<figure><img src="/files/OVE6o1Qxn6PaAhd30jm1" alt="AWS IAM user with an Email tag whose value is the user&#x27;s email address" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/KhgU3e8n9oIejaIQZVAq" alt="P0 AWS configuration set to provision users as AWS IAM users with an email tag" width="459"><figcaption></figcaption></figure>

## Related

* [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access)
* [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods)


# Identity Center

Configure the P0 AWS IAM management integration to provision users through AWS Identity Center, matching them by user name or by their Identity Center email.

Choose the **Identity Center** login type when you provision access through AWS Identity Center — for example, when you provision users via SSO. P0 matches each requestor to an Identity Center identity and grants a per-request permission set.

## Prerequisites

* An [AWS IAM management integration](/integrations/resource-integrations/aws/installation-methods) installed on the management account where the Identity Center instance resides. You must install P0 on that account.

## Configure Identity Center provisioning

On the AWS IAM management configuration page, select **Via AWS Identity Center**, then use the **How are users identified in AWS Identity Center?** dropdown to tell P0 which Identity Center attribute holds the user's email address:

* **Username is user's email** (default): Select this option if each user's Identity Center user name equals their email address. P0 matches users by user name.
* **User's IDC email is user's email**: Select this option if user names don't equal email addresses and the email appears in the Identity Center email attribute instead. P0 matches users by email address.

To finish the configuration, select the management account in which the Identity Center instance resides, choose how to identify users, and click **Next**.

<figure><img src="/files/OGhwC1ArOSI6FpfmIKhb" alt="P0 AWS configuration set to provision users via AWS Identity Center" width="422"><figcaption></figcaption></figure>

## Related

* [Identity Center — merged permission set](/integrations/resource-integrations/aws/identity-center-merged)
* [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access)
* [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods)


# Federated

Configure the P0 AWS IAM management integration to provision users through an Okta SAML federation, granting IAM roles assigned to your AWS Account Federation app.

Choose the **Federated** login type when you use an IAM identity provider to sign in users to your AWS account. P0 matches each requestor through the federation and grants IAM roles. This is a legacy sign-in method — AWS recommends using [Identity Center](/integrations/resource-integrations/aws/installation-methods/identity-center).

{% hint style="info" %}
Only Okta SAML federation is supported, via an AWS Account Federation.

An installed [Okta directory integration](/integrations/directory-integrations/okta) is required. Your AWS Account Federation Okta app must be in the same Okta organization as the one installed as the directory integration.
{% endhint %}

## Prerequisites

* An [AWS IAM management integration](/integrations/resource-integrations/aws/installation-methods) installed on the target account.
* An installed [Okta directory integration](/integrations/directory-integrations/okta) in the same Okta organization as your AWS Account Federation app.

## Configure federated provisioning

On the AWS IAM management configuration page, select **Via a federated identity provider**. Saving the configuration by clicking **Next** automatically applies the following changes to your AWS Account Federation app:

* Adds a custom attribute `managedByP0` to your Okta app's user profile. This lets P0 clean up dynamically assigned users from your AWS SSO Okta app.
* Enables the [`Join all roles`](https://help.okta.com/en-us/content/topics/deploymentguides/aws/aws-configure-aws-app.htm) flag. This lets users assume AWS roles that P0 assigns directly to their Okta user.

<figure><img src="/files/H2KmylvLc4GtEbVzzwTX" alt="P0 AWS configuration set to provision users via a federated identity provider" width="499"><figcaption></figcaption></figure>

{% hint style="warning" %}
When you edit or make changes to your role pool, always refresh your application data. Find this action by navigating to your Okta environment as a super admin.

<img src="/files/I721z9NSHFqmslCNR5nx" alt="Okta admin action to refresh application data" data-size="original">

See Okta's [Refresh application data](https://support.okta.com/help/s/article/Refresh-Application-Data-Functionality-and-Usage?language=en_US) guidance for details.
{% endhint %}

## Related

* [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access)
* [p0 aws role assume](/p0-cli/p0-commands-and-usage/p0-aws-role-assume)
* [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods)


# Identity Center (merged)

Install the AWS Identity Center (merged) integration and configure the merged login type so P0 provisions access through a single shared permission set per user, avoiding Identity Center permission-se

{% hint style="info" %}
This login type is in beta.
{% endhint %}

Choose the **Identity Center (merged permission set)** login type to provision access through a single shared Identity Center permission set per user, rather than creating a new permission set for each access request. Each request attaches its own customer-managed policy to the shared permission set, which avoids Identity Center permission-set sprawl.

This method requires a separately installed AWS Identity Center (merged) integration on the account that hosts the Identity Center instance. Install it first, then select the merged login type on your AWS IAM management integration.

## Prerequisites

* An [AWS IAM management integration](/integrations/resource-integrations/aws/installation-methods) installed on the account that hosts the Identity Center instance.
* The AWS Identity Center (merged) integration installed on the same account. See [Install the AWS Identity Center (merged) integration](#install-the-aws-identity-center-merged-integration).

## Install the AWS Identity Center (merged) integration

Install the AWS Identity Center (merged) integration on the AWS account that hosts your Identity Center instance, typically your management or delegated administrator account. With this integration, P0 manages a single shared permission set per user and attaches a per-request customer-managed policy to it, instead of creating a separate permission set for every request.

1. Navigate to **Integrations** on [p0.app](https://p0.app), then select the **AWS MIDC** integration.
2. Enter the AWS account ID of the account that hosts the Identity Center instance.
3. Enter the AWS region where Identity Center is installed (for example, `us-east-1`). This region must match the region where your Identity Center instance resides.
4. Select the AWS partition: `aws` for commercial regions or `aws-us-gov` for GovCloud.
5. Run the displayed AWS CLI commands to provision P0's access. You can also run these commands using AWS Cloud Shell. These commands create the `P0RoleMergedIdc` role, which grants P0 permission to manage Identity Center permission sets and account assignments.
6. Click **Next** to verify the installation.
7. After verification, choose how P0 identifies users in Identity Center:
   * **Username is user's email** (default): P0 matches users by their Identity Center user name.
   * **User's IDC email is user's email**: P0 matches users by the email attribute on their Identity Center profile.

### Install with Terraform

You can install the AWS Identity Center (merged) integration with the [P0 Terraform provider](https://registry.terraform.io/providers/p0-security/p0/latest/docs) instead of the P0 app. Use the [`p0_aws_midc_staged`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/aws_midc_staged) resource to generate the role's trust and inline policies, create the `P0RoleMergedIdc` role from them, then use the [`p0_aws_midc`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/aws_midc) resource to complete the install.

```terraform
resource "p0_aws_midc_staged" "staged_account" {
  id         = "123456789012" # The account that hosts the Identity Center instance
  idc_region = "us-east-1"     # The region where Identity Center is installed
}

resource "aws_iam_role" "p0_midc_manager" {
  name               = p0_aws_midc_staged.staged_account.role.name
  assume_role_policy = p0_aws_midc_staged.staged_account.role.trust_policy
}

resource "aws_iam_role_policy" "p0_midc_manager" {
  name   = p0_aws_midc_staged.staged_account.role.inline_policy_name
  role   = aws_iam_role.p0_midc_manager.name
  policy = p0_aws_midc_staged.staged_account.role.inline_policy
}

resource "p0_aws_midc" "installed_account" {
  id         = p0_aws_midc_staged.staged_account.id
  idc_region = p0_aws_midc_staged.staged_account.idc_region
  partition  = p0_aws_midc_staged.staged_account.partition
  depends_on = [aws_iam_role_policy.p0_midc_manager]
}
```

Run `terraform init` and `terraform apply`.

## Configure the merged login type

After you install the AWS Identity Center (merged) integration, return to your AWS IAM management configuration, select **Via AWS Identity Center (merged permission set)**, choose the account that hosts the Identity Center instance, then click **Next**.

If you install with Terraform, configure the `merged-idc` login type on the AWS account's `aws_iam_write` resource to provision access through the merged permission set.

## Related

* [Identity Center](/integrations/resource-integrations/aws/installation-methods/identity-center)
* [Requesting AWS access](/integrations/resource-integrations/aws/requesting-access)
* [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods)


# Requesting AWS access

How to request just-in-time access to AWS IAM policies, groups, and roles through P0 via Slack, Teams, Webex, the P0 CLI, or the P0 dashboard.

## Requesting from Slack or through p0.app

Open up the p0 modal using `/p0 request` in Slack or with [the Request Access feature ](https://docs.p0.dev/integrations/resource-integrations/aws/pages/kn3Mg03ByLowqw155BWv#via-the-p0.app)in p0.app and select "Amazon Web Services" as the resource.

<figure><img src="/files/OsnHwVcVLGjYbYaRMm23" alt="" width="290"><figcaption></figcaption></figure>

You'll see an "Access type" field with 2 options, "Attach user policy", and "Add user to group".

<figure><img src="/files/oYukdoo59cUXQLdS5VjF" alt="" width="289"><figcaption></figcaption></figure>

* **"Attach user policy":** request a user policy to be attached to your AWS user. The policy can either be a customer-managed or AWS-managed policy.
* **"Add user to group":** request your AWS user to be added to a user group.

<figure><img src="/files/jb5nmEAqT1lnnorHJJWG" alt="" width="375"><figcaption></figcaption></figure>

P0 auto-completes as you start typing out the policy or group. Once you select the policy / group you need, you can optionally add a reason for p0 to supply to the approver(s), then submit the request. If an existing policy / group isn't shown in the auto-complete results, it may be [filtered out by access policies](/access-management/just-in-time-access/request-routing#resource).

### Fine-grained resource-level access

If you installed the [Resource inventory](/integrations/resource-integrations/aws#setting-up-aws-resource-inventory) integration you will be able to choose the "Resource in AWS" access type. You can specify the exact resource and a policy. P0 will generate a new policy that contains the actions from the selected policy filtered to the selected resource.

For example, request access to a specific S3 bucket called `p0-sensitive-data`:

<figure><img src="/files/efCHUAx9vTvmHR3vTWfp" alt="" width="432"><figcaption></figcaption></figure>

When requesting access to an AWS resource, each service offers multiple permission levels ranging from read-only to full access. For some services, P0 provides curated policies that grant least-privilege access when no suitable AWS-managed policy exists. For details on the specific permissions granted for each policy, see [AWS permission levels](/integrations/resource-integrations/aws/requesting-access/permission-levels).

### What happens next

Once you make the request, you should get a Slack message from the p0 bot showing your request. There will also be a message to the approvers in the Slack channel designated by your org admin, requesting access.

1. If your request is approved, when you get a message that it has been approved, that means you should already have access provisioned, as that happens all at the same time.
2. **If you are on-call (on a PagerDuty schedule), and your org admin has enabled PagerDuty routing, your access may be automatically approved for 1 hour.**
3. After your request is approved, there will be a “relinquish” button for you to let go of your permissions early if you finish what you wanted to do before the expiration date (so you can let go of unneeded permissions).
4. If you wait for the access to expire, you will get a message that it has expired once it does.
5. If your request is denied, you'll get a message letting you know.


# Permission levels

Permission levels available when requesting just-in-time access to AWS resources through P0, including P0 curated policies and scoped AWS-managed policies.

When you request access to an AWS resource through P0, you select a permission level. Some permissions map directly to AWS-managed policies, while others are curated policies that P0 generates to provide least-privilege access.

**AWS-managed policies** reference a standard AWS IAM policy. When requesting resource-level access, P0 scopes the policy actions to the specific resource (or sub-resource if applicable) you request.

**P0 curated policies** are custom policies that P0 generates when no AWS-managed policy provides the right level of access. The following sections document the specific actions for each curated policy.

## S3

| Permission                | Type                 | Description                     |
| ------------------------- | -------------------- | ------------------------------- |
| `AmazonS3ReadOnlyAccess`  | AWS-managed (scoped) | Read and list objects           |
| `AmazonS3ReadWriteAccess` | P0 curated           | Read, write, and delete objects |
| `AmazonS3FullAccess`      | AWS-managed (scoped) | All S3 actions                  |

`AmazonS3ReadOnlyAccess` and `AmazonS3FullAccess` use the corresponding AWS-managed policy, but P0 scopes the actions to the bucket and prefix you specify in your request.

All three permission levels support object-level scoping. When you specify an object prefix (for example, `data/reports`), P0 restricts access to only that path within the bucket.

### AmazonS3ReadWriteAccess

P0 generates this policy because no AWS-managed policy provides read/write access without also granting bucket management permissions like changing ACLs or retention policies.

| Action                        | Purpose                                                                  |
| ----------------------------- | ------------------------------------------------------------------------ |
| `s3:GetObject`                | Download objects                                                         |
| `s3:PutObject`                | Upload objects                                                           |
| `s3:DeleteObject`             | Delete objects                                                           |
| `s3:AbortMultipartUpload`     | Cancel incomplete uploads                                                |
| `s3:ListMultipartUploadParts` | List parts of incomplete uploads                                         |
| `s3:ListBucket`               | List objects (scoped to your prefix when requesting object-level access) |

## EC2

| Permission                | Type        | Description                       |
| ------------------------- | ----------- | --------------------------------- |
| `AmazonEC2ReadOnlyAccess` | AWS-managed | Read-only access to EC2 resources |
| `AmazonEC2FullAccess`     | AWS-managed | Full access to EC2 resources      |

## EKS

| Permission           | Type       | Actions               |
| -------------------- | ---------- | --------------------- |
| `EksDescribeCluster` | P0 curated | `eks:DescribeCluster` |

## RDS

| Permission             | Type       | Actions          |
| ---------------------- | ---------- | ---------------- |
| `AmazonRDSConnectUser` | P0 curated | `rds-db:connect` |

## SageMaker

| Permission                | Type        | Description                             |
| ------------------------- | ----------- | --------------------------------------- |
| `AmazonSageMakerReadOnly` | AWS-managed | Read-only access to SageMaker resources |
| `SageMakerAdmin`          | P0 curated  | Broad SageMaker administration          |

### SageMakerAdmin

P0 generates this policy as a curated alternative to `AmazonSageMakerFullAccess`. The policy grants the following categories of access:

| Category           | Actions                                                             | Scope                                                    |
| ------------------ | ------------------------------------------------------------------- | -------------------------------------------------------- |
| SageMaker          | All SageMaker and SageMaker Geospatial actions                      | All resources                                            |
| Storage            | All S3 and S3 Express actions                                       | All resources                                            |
| Container registry | All ECR actions                                                     | All resources                                            |
| Code services      | All CodeCommit and CodeBuild actions                                | All resources                                            |
| Data processing    | All Glue actions                                                    | All resources                                            |
| Notifications      | All SNS actions                                                     | All resources                                            |
| Monitoring         | Read-only CloudWatch, CloudWatch Logs, and CloudFormation           | All resources                                            |
| Compute            | `ec2:Describe*`, create/delete network interfaces and VPC endpoints | All resources                                            |
| IAM                | `iam:PassRole`                                                      | SageMaker-prefixed roles only                            |
| IAM                | `iam:CreateServiceLinkedRole`                                       | SageMaker and RoboMaker service roles only               |
| Lambda             | `lambda:InvokeFunction`                                             | Functions matching `*SageMaker*` or `*LabelingFunction*` |
| Step Functions     | Describe, start, stop, and update executions                        | State machines matching `*sagemaker*`                    |
| Secrets Manager    | Create, describe, and read secrets                                  | Secrets prefixed with `AmazonSageMaker-`                 |

> **Important**: This policy grants broad access including `iam:PassRole` and full S3 permissions. Review your access policies to restrict which users can request this permission level.

## SSM

| Permission                    | Type        | Description                                |
| ----------------------------- | ----------- | ------------------------------------------ |
| `AmazonSSMFullAccess`         | AWS-managed | Full access to Systems Manager             |
| `SessionManagerConnectAccess` | P0 curated  | Start a session on a specific EC2 instance |

### SessionManagerConnectAccess

P0 generates this policy to allow SSM session access scoped to a specific EC2 instance with time-limited sessions.

| Action                 | Purpose                                   | Scope                                        |
| ---------------------- | ----------------------------------------- | -------------------------------------------- |
| `ssm:StartSession`     | Start a session on the requested instance | Specific EC2 instance, with automatic expiry |
| `ssm:TerminateSession` | End a session                             | Your own sessions only                       |
| `ssm:ResumeSession`    | Reconnect to a session                    | Your own sessions only                       |


# AWS Integration API

Manage installable components of the P0 Amazon Web Services integration.

{% hint style="warning" %}
This API may change in a non-backward-compatible way. Please inform P0 Security support if you are planning to use it in production in order to receive notifications about changes.
{% endhint %}

## Overview

The **P0 AWS Integration API** allows you to programmatically manage installable components for integrating Amazon Web Services (AWS) within P0. Each component follows a consistent lifecycle (staging, verification, and configuration) and is typically identified by its AWS account ID.

This API is especially useful for automating cloud access, enabling just-in-time (JIT) permissions, and managing integrations across multiple AWS accounts at scale.

#### **Typical use cases include:**

* Set up secure, multi-account AWS access for users via P0.
* Automatically provision roles and permissions in AWS environments.
* Integrate AWS accounts with P0's monitoring or access tools.

{% hint style="info" %}
The P0 Terraform provider is recommended for configuring integrations programatically.

[Check the provider documentation here](https://registry.terraform.io/providers/p0-security/p0/latest/docs)!
{% endhint %}

## Key Concepts

* **Integration Root Object**: Represents the top-level configuration for an AWS integration within your organization.
* **Components**: Installable parts of the integration (e.g., IAM roles, logging, monitoring). Each component is scoped to an AWS account (via its 12-digit ID).
* **States**:
  * `stage`: Initial configuration before verification.
  * `configure`: Successfully verified and missing additional configuration options.
  * `installed`: Ready to be used.
* **Base Component**: Created automatically by P0. It includes the GCP service account used by P0 to interact with AWS. It will be automatically created by P0 as a side effect when the first component is created with the POST method. The base component contains the GCP service account assigned to the integration by P0.

## Integration Lifecycle

### 1. Create the root integration

Before adding components, you must initialize the integration:

```http
POST /o/{orgId}/integrations/aws/config
```

This sets up the foundation for all further AWS integrations within your organization.

### 2. Stage a component

Choose a component (e.g., `access`, `logging`, etc.) and stage it by specifying the AWS account ID:

```http
PUT /o/{orgId}/integrations/aws/config/{component}/{id}
```

* `{component}`: Type of component to install.
* `{id}`: an AWS account ID (12 digits).

⚠️ The `base` component is **automatically created** when you stage the first component.

#### Installation Components

* **Base:** Core platform layer for authentication, tenant isolation, and routing.
* **IAM Write:** Handles just-in-time access provisioning when requests are approved.
* **IAM assessment:** Continuously evaluates user permissions against least privilege principles.
* **Function Caller:** Executes user-defined functions or workflows during request processing.
* **Audit Logging:** Provides a tamper-evident trail for compliance and security investigations.
* **Resource Inventory:** Indexes all manageable resources across integrations in real time.

### 3. **Retrieve setup instructions**

To configure AWS correctly, retrieve the staged component metadata:

```http
GET /o/{orgId}/integrations/aws/config/{component}/{id}
```

The response includes a `metadata` field with the exact parameters (e.g., IAM role ARN, trust policy) needed for setup in AWS.

### 4. Verify AWS configuration

Once the AWS setup is complete, verify it with:

```
POST /o/{orgId}/integrations/aws/config/{component}/{id}/verify
```

* P0 will validate the setup by reaching out to AWS.
* On success, the component enters the `configure` state.

### 5. Review configuration

You can confirm the integration status:

```
GET /o/{orgId}/integrations/aws/config/{component}/{id}
```

* The response `item` field shows the current state and configurable fields.

### 6. Finalize configuration

You may change the integration configuration by passing the desired `item` field:

```
POST /o/{orgId}/integrations/aws/config/{component}/{id}/configure
```

* The `configure` endpoint MUST be called after `verify` when a new AWS account is installed.
* The `configure` endpoint may also be called to change the configuration of an existing AWS account without reinstalling it. In this case, a successful response indicates that P0 has both configured and verified the new configuration.

***

## Base Installation

Configures the foundational connection between P0 and Amazon Web Services. Each item in the configuration represents an AWS account, identified by a 12-digit numeric account ID. This component is automatically created when the first integration is added. It provisions the service account that P0 uses to securely interact with your AWS environment.

## Read configuration for all components

> Current configuration values for every available Amazon Web Services component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Global (no component)","description":"Manage global configuration parameters of the P0 Amazon Web Services integration."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"schemas":{"aws":{"type":"object","description":"Amazon Web Services integration configuration","properties":{"base":{"$ref":"#/components/schemas/base"},"iam-assessment":{"$ref":"#/components/schemas/iam-assessment"},"iam-write":{"$ref":"#/components/schemas/iam-write"},"function-caller":{"$ref":"#/components/schemas/function-caller"},"access-logs":{"$ref":"#/components/schemas/access-logs"},"inventory":{"$ref":"#/components/schemas/inventory"}}},"base":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/base-item"}},"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"},"iam-assessment":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-assessment-item"}},"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"},"iam-write":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-write-item"}},"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]},"function-caller":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/function-caller-item"}},"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}},"access-logs":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/access-logs-item"}},"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"},"inventory":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/inventory-item"}},"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}},"paths":{"/o/{orgId}/integrations/aws/config":{"get":{"tags":["Global (no component)"],"summary":"Read configuration for all components","description":"Current configuration values for every available Amazon Web Services component.","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/aws"}}}}}}}}}
```

## Create initial configuration

> Initialize installation of an AWS account in P0. Creates placeholders for every available Amazon Web Services component. Start with this method when installing an Amazon Web Services account integration for the first time.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Global (no component)","description":"Manage global configuration parameters of the P0 Amazon Web Services integration."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config":{"post":{"tags":["Global (no component)"],"summary":"Create initial configuration","description":"Initialize installation of an AWS account in P0. Creates placeholders for every available Amazon Web Services component. Start with this method when installing an Amazon Web Services account integration for the first time.","parameters":[],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Remove all items in all components

> Removes all items in all components of the Amazon Web Services integration from P0. Any configuration present in Amazon Web Services that grants access to P0 has to be removed separately.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Global (no component)","description":"Manage global configuration parameters of the P0 Amazon Web Services integration."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config":{"delete":{"tags":["Global (no component)"],"summary":"Remove all items in all components","description":"Removes all items in all components of the Amazon Web Services integration from P0. Any configuration present in Amazon Web Services that grants access to P0 has to be removed separately.","responses":{"204":{"description":"Removed all items in all components."}}}}}}
```

## Read install configuration of an Amazon Web Services account

> Current configuration values for base component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Base installation component","description":"Configures P0 integration with Amazon Web Services for Base installation component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"base":{"description":"base component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/base-item-with-metadata"}}}}},"schemas":{"base-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/base-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"}}},"paths":{"/o/{orgId}/integrations/aws/config/base/{id}":{"get":{"tags":["Base installation component"],"summary":"Read install configuration of an Amazon Web Services account","description":"Current configuration values for base component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Base installation","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/base"}}}}}}
```

***

## IAM assessment Component

Enables P0 to evaluate IAM roles, policies, and permissions within your AWS accounts. Each item represents an AWS account, identified by the 12-digit account ID. This component supports governance, policy posture analysis, and inventory visibility features on the P0 platform.

## Read install configuration of an IAM assessment component

> Current configuration values for iam-assessment component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM assessment component","description":"Configures P0 integration with Amazon Web Services for IAM assessment component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"iam-assessment":{"description":"iam-assessment component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/iam-assessment-item-with-metadata"}}}}},"schemas":{"iam-assessment-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/iam-assessment-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-assessment/{id}":{"get":{"tags":["IAM assessment component"],"summary":"Read install configuration of an IAM assessment component","description":"Current configuration values for iam-assessment component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM assessment","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/iam-assessment"}}}}}}
```

## Initialize installation of an IAM assessment component

> Execute this first to start the install of an account. Assembles an initial item in "stage" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM assessment component","description":"Configures P0 integration with Amazon Web Services for IAM assessment component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-assessment/{id}":{"put":{"tags":["IAM assessment component"],"summary":"Initialize installation of an IAM assessment component","description":"Execute this first to start the install of an account. Assembles an initial item in \"stage\" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM assessment","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## DELETE /o/{orgId}/integrations/aws/config/iam-assessment/{id}

> Remove installation of an IAM assessment component

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM assessment component","description":"Configures P0 integration with Amazon Web Services for IAM assessment component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-assessment/{id}":{"delete":{"tags":["IAM assessment component"],"summary":"Remove installation of an IAM assessment component","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM assessment","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"204":{"description":"Item successfully removed"}}}}}}
```

## Configure an IAM assessment component

> Transitions from "configure" to "installed" state, or reconfigures an item already in "installed" state. Verifies that Amazon Web Services is configured correctly.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM assessment component","description":"Configures P0 integration with Amazon Web Services for IAM assessment component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"schemas":{"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"},"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-assessment/{id}/configure":{"post":{"tags":["IAM assessment component"],"summary":"Configure an IAM assessment component","description":"Transitions from \"configure\" to \"installed\" state, or reconfigures an item already in \"installed\" state. Verifies that Amazon Web Services is configured correctly.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM assessment","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","login"],"properties":{"state":{"description":"The state must be \"configure\"","type":"string","enum":["configure"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Verify the configuration of an IAM assessment component

> Transitions the item from "stage" to "configure" state. Verification reads the target system and checks that the configuration is correctly applied.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM assessment component","description":"Configures P0 integration with Amazon Web Services for IAM assessment component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-assessment/{id}/verify":{"post":{"tags":["IAM assessment component"],"summary":"Verify the configuration of an IAM assessment component","description":"Transitions the item from \"stage\" to \"configure\" state. Verification reads the target system and checks that the configuration is correctly applied.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM assessment","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"description":"The state must be \"stage\"","type":"string","enum":["stage"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

***

## IAM Management

Allows P0 to manage IAM permissions in your AWS environment. Each item corresponds to an AWS account (12-digit account ID). This component is used for features like Just-in-Time access, where P0 can programmatically assign or revoke IAM policies based on user activity or approval workflows.

## Read install configuration of an IAM management component

> Current configuration values for iam-write component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM management component","description":"Configures P0 integration with Amazon Web Services for IAM management component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"iam-write":{"description":"iam-write component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/iam-write-item-with-metadata"}}}}},"schemas":{"iam-write-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/iam-write-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-write/{id}":{"get":{"tags":["IAM management component"],"summary":"Read install configuration of an IAM management component","description":"Current configuration values for iam-write component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM management","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/iam-write"}}}}}}
```

## Initialize installation of an IAM management component

> Execute this first to start the install of an account. Assembles an initial item in "stage" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM management component","description":"Configures P0 integration with Amazon Web Services for IAM management component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-write/{id}":{"put":{"tags":["IAM management component"],"summary":"Initialize installation of an IAM management component","description":"Execute this first to start the install of an account. Assembles an initial item in \"stage\" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM management","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## DELETE /o/{orgId}/integrations/aws/config/iam-write/{id}

> Remove installation of an IAM management component

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM management component","description":"Configures P0 integration with Amazon Web Services for IAM management component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-write/{id}":{"delete":{"tags":["IAM management component"],"summary":"Remove installation of an IAM management component","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM management","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"204":{"description":"Item successfully removed"}}}}}}
```

## Configure an IAM management component

> Transitions from "configure" to "installed" state, or reconfigures an item already in "installed" state. Verifies that Amazon Web Services is configured correctly.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM management component","description":"Configures P0 integration with Amazon Web Services for IAM management component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"schemas":{"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]},"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-write/{id}/configure":{"post":{"tags":["IAM management component"],"summary":"Configure an IAM management component","description":"Transitions from \"configure\" to \"installed\" state, or reconfigures an item already in \"installed\" state. Verifies that Amazon Web Services is configured correctly.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM management","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","login"],"properties":{"state":{"description":"The state must be \"configure\"","type":"string","enum":["configure"]},"login":{"$ref":"#/components/schemas/login"}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Verify the configuration of an IAM management component

> Transitions the item from "stage" to "configure" state. Verification reads the target system and checks that the configuration is correctly applied.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"IAM management component","description":"Configures P0 integration with Amazon Web Services for IAM management component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/iam-write/{id}/verify":{"post":{"tags":["IAM management component"],"summary":"Verify the configuration of an IAM management component","description":"Transitions the item from \"stage\" to \"configure\" state. Verification reads the target system and checks that the configuration is correctly applied.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for IAM management","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"description":"The state must be \"stage\"","type":"string","enum":["stage"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

***

## Function Caller

Allows P0 to invoke AWS Lambda functions on your behalf. Unlike other components, each item in this configuration represents a specific Lambda ARN. This is useful for custom integrations such as automated notifications, policy enforcement, or triggering cloud-native workflows.

## Read install configuration a function caller component

> Current configuration values for function-caller component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Function caller component","description":"Configures P0 integration with Amazon Web Services for Function caller component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"function-caller":{"description":"function-caller component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/function-caller-item-with-metadata"}}}}},"schemas":{"function-caller-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/function-caller-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/function-caller/{id}":{"get":{"tags":["Function caller component"],"summary":"Read install configuration a function caller component","description":"Current configuration values for function-caller component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Function caller","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/function-caller"}}}}}}
```

## Initialize installation of a function caller component

> Execute this first to start the install of an account. Assembles an initial item in "stage" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Function caller component","description":"Configures P0 integration with Amazon Web Services for Function caller component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/function-caller/{id}":{"put":{"tags":["Function caller component"],"summary":"Initialize installation of a function caller component","description":"Execute this first to start the install of an account. Assembles an initial item in \"stage\" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Function caller","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## DELETE /o/{orgId}/integrations/aws/config/function-caller/{id}

> Remove installation of a function caller component

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Function caller component","description":"Configures P0 integration with Amazon Web Services for Function caller component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config/function-caller/{id}":{"delete":{"tags":["Function caller component"],"summary":"Remove installation of a function caller component","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Function caller","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"204":{"description":"Item successfully removed"}}}}}}
```

## Configure a function caller component

> Transitions from "configure" to "installed" state, or reconfigures an item already in "installed" state. Verifies that Amazon Web Services is configured correctly.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Function caller component","description":"Configures P0 integration with Amazon Web Services for Function caller component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/function-caller/{id}/configure":{"post":{"tags":["Function caller component"],"summary":"Configure a function caller component","description":"Transitions from \"configure\" to \"installed\" state, or reconfigures an item already in \"installed\" state. Verifies that Amazon Web Services is configured correctly.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Function caller","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","login"],"properties":{"state":{"description":"The state must be \"configure\"","type":"string","enum":["configure"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Verify the configuration of a function caller component

> Transitions the item from "stage" to "configure" state. Verification reads the target system and checks that the configuration is correctly applied.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Function caller component","description":"Configures P0 integration with Amazon Web Services for Function caller component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/function-caller/{id}/verify":{"post":{"tags":["Function caller component"],"summary":"Verify the configuration of a function caller component","description":"Transitions the item from \"stage\" to \"configure\" state. Verification reads the target system and checks that the configuration is correctly applied.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Function caller","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"description":"The state must be \"stage\"","type":"string","enum":["stage"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

***

## Access Logs

Connects P0 to your AWS CloudTrail logs for audit and monitoring purposes. Each configuration item corresponds to an AWS account and allows P0 to read access logs. This enables audit trails and visibility into user actions across your cloud environment.

## Read install configuration of an access logging component

> Current configuration values for access-logs component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Access Logging component","description":"Configures P0 integration with Amazon Web Services for Access Logging component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"access-logs":{"description":"access-logs component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/access-logs-item-with-metadata"}}}}},"schemas":{"access-logs-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/access-logs-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"}}},"paths":{"/o/{orgId}/integrations/aws/config/access-logs/{id}":{"get":{"tags":["Access Logging component"],"summary":"Read install configuration of an access logging component","description":"Current configuration values for access-logs component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Access Logging","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/access-logs"}}}}}}
```

## Initialize installation of an access logging component

> Execute this first to start the install of an account. Assembles an initial item in "stage" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Access Logging component","description":"Configures P0 integration with Amazon Web Services for Access Logging component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/access-logs/{id}":{"put":{"tags":["Access Logging component"],"summary":"Initialize installation of an access logging component","description":"Execute this first to start the install of an account. Assembles an initial item in \"stage\" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Access Logging","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## DELETE /o/{orgId}/integrations/aws/config/access-logs/{id}

> Remove installation of an access logging component

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Access Logging component","description":"Configures P0 integration with Amazon Web Services for Access Logging component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config/access-logs/{id}":{"delete":{"tags":["Access Logging component"],"summary":"Remove installation of an access logging component","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Access Logging","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"204":{"description":"Item successfully removed"}}}}}}
```

## Configure an access logging component

> Transitions from "configure" to "installed" state, or reconfigures an item already in "installed" state. Verifies that Amazon Web Services is configured correctly.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Access Logging component","description":"Configures P0 integration with Amazon Web Services for Access Logging component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"schemas":{"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"},"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/o/{orgId}/integrations/aws/config/access-logs/{id}/configure":{"post":{"tags":["Access Logging component"],"summary":"Configure an access logging component","description":"Transitions from \"configure\" to \"installed\" state, or reconfigures an item already in \"installed\" state. Verifies that Amazon Web Services is configured correctly.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Access Logging","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","login"],"properties":{"state":{"description":"The state must be \"configure\"","type":"string","enum":["configure"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Verify the configuration of an access logging component

> Transitions the item from "stage" to "configure" state. Verification reads the target system and checks that the configuration is correctly applied.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Access Logging component","description":"Configures P0 integration with Amazon Web Services for Access Logging component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/access-logs/{id}/verify":{"post":{"tags":["Access Logging component"],"summary":"Verify the configuration of an access logging component","description":"Transitions the item from \"stage\" to \"configure\" state. Verification reads the target system and checks that the configuration is correctly applied.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Access Logging","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"description":"The state must be \"stage\"","type":"string","enum":["stage"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

***

## Resource Inventory

Provides P0 with visibility into AWS resources (e.g., S3 buckets, EC2 instances) for access control and automation. Each item in the configuration is tied to an AWS account. This component enables resource-based access governance within the P0 platform.

## Read install configuration of a resource inventory component

> Current configuration values for inventory component.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Resource inventory component","description":"Configures P0 integration with Amazon Web Services for Resource inventory component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"inventory":{"description":"inventory component","content":{"application/json":{"schema":{"$ref":"#/components/schemas/inventory-item-with-metadata"}}}}},"schemas":{"inventory-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/inventory-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/inventory/{id}":{"get":{"tags":["Resource inventory component"],"summary":"Read install configuration of a resource inventory component","description":"Current configuration values for inventory component.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Resource inventory","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/inventory"}}}}}}
```

## Initialize installation of a resource inventory component

> Execute this first to start the install of an account. Assembles an initial item in "stage" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Resource inventory component","description":"Configures P0 integration with Amazon Web Services for Resource inventory component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/inventory/{id}":{"put":{"tags":["Resource inventory component"],"summary":"Initialize installation of a resource inventory component","description":"Execute this first to start the install of an account. Assembles an initial item in \"stage\" state including generated metadata that is input for configuring the integration in Amazon Web Services. To inspect the contents of the assembled item, including metadata, use the GET method.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Resource inventory","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## DELETE /o/{orgId}/integrations/aws/config/inventory/{id}

> Remove installation of a resource inventory component

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Resource inventory component","description":"Configures P0 integration with Amazon Web Services for Resource inventory component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}}},"paths":{"/o/{orgId}/integrations/aws/config/inventory/{id}":{"delete":{"tags":["Resource inventory component"],"summary":"Remove installation of a resource inventory component","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Resource inventory","required":true,"schema":{"type":"string"},"in":"path"}],"responses":{"204":{"description":"Item successfully removed"}}}}}}
```

## Configure a resource inventory component

> Transitions from "configure" to "installed" state, or reconfigures an item already in "installed" state. Verifies that Amazon Web Services is configured correctly.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Resource inventory component","description":"Configures P0 integration with Amazon Web Services for Resource inventory component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/inventory/{id}/configure":{"post":{"tags":["Resource inventory component"],"summary":"Configure a resource inventory component","description":"Transitions from \"configure\" to \"installed\" state, or reconfigures an item already in \"installed\" state. Verifies that Amazon Web Services is configured correctly.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Resource inventory","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","login"],"properties":{"state":{"description":"The state must be \"configure\"","type":"string","enum":["configure"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Verify the configuration of a resource inventory component

> Transitions the item from "stage" to "configure" state. Verification reads the target system and checks that the configuration is correctly applied.

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"tags":[{"name":"Resource inventory component","description":"Configures P0 integration with Amazon Web Services for Resource inventory component.\nEach item in the configuration is an account within Amazon Web Services.\nThe {id} in the path refers to the ID of the item, the 12-digit numeric account ID."}],"security":[{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"APIKey","description":"Pass your API key in the Authorization header. Only owners can create API keys and configure integrations in P0."}},"responses":{"SuccessResponse":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"}}}},"ErrorResponse":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","enum":[false]}}}}},"paths":{"/o/{orgId}/integrations/aws/config/inventory/{id}/verify":{"post":{"tags":["Resource inventory component"],"summary":"Verify the configuration of a resource inventory component","description":"Transitions the item from \"stage\" to \"configure\" state. Verification reads the target system and checks that the configuration is correctly applied.","parameters":[{"name":"id","description":"The ID of an item that is configured in the Amazon Web Services resource for Resource inventory","required":true,"schema":{"type":"string"},"in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state"],"properties":{"state":{"description":"The state must be \"stage\"","type":"string","enum":["stage"]}}}}}},"responses":{"200":{"$ref":"#/components/responses/SuccessResponse"},"400":{"$ref":"#/components/responses/ErrorResponse"}}}}}}
```

## Schemas

## The Success object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"Success":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}}}}}}
```

## The base-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"base-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/base-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"}}}}
```

## The iam-write-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-write-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/iam-write-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]}}}}
```

## The iam-assessment-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-assessment-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/iam-assessment-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"}}}}
```

## The function-caller-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"function-caller-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/function-caller-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked.","properties":{"roleName":{"type":"string","description":"The name of the AWS IAM role to create for the P0 Amazon Web Services integration"},"inlinePolicy":{"type":"string","description":"The inline IAM policy to attach to the IAM role"},"inlinePolicyName":{"type":"string","description":"The name of the inline IAM policy"},"trustPolicy":{"type":"string","description":"The trust policy to attach to the IAM role for the P0 Amazon Web Services integration"},"serviceAccountId":{"type":"string","description":"The ID of the GCP service account that P0 uses to access your AWS account. This ID is already part of the trust policy."}}}}},"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The inventory-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"inventory-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/inventory-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The access-logs-item-with-metadata object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"access-logs-item-with-metadata":{"type":"object","description":"Component configuration of a specific Amazon Web Services account.","properties":{"ok":{"type":"boolean","enum":[true]},"item":{"$ref":"#/components/schemas/access-logs-item"},"metadata":{"type":"object","description":"Metadata of the item. Use contents to prepare Amazon Web Services before invoking the POST /verify method. This field is only populated after the PUT method was invoked."}}},"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"}}}}
```

## The serviceAccountEmail object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"}}}}
```

## The serviceAccountId object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"}}}}
```

## The base-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"}}}}
```

## The base object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"base":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/base-item"}},"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"}}}}
```

## The accessAnalyzerArn object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"}}}}
```

## The iam-assessment object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-assessment":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-assessment-item"}},"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"}}}}
```

## The iam-assessment-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"}}}}
```

## The login object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]}}}}
```

## The iam-write object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-write":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-write-item"}},"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]}}}}
```

## The iam-write-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]}}}}
```

## The function-caller object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"function-caller":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/function-caller-item"}},"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The function-caller-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The cloudLakeArn object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"}}}}
```

## The access-logs object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"access-logs":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/access-logs-item"}},"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"}}}}
```

## The access-logs-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"}}}}
```

## The inventory object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"inventory":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/inventory-item"}},"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The inventory-item object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```

## The aws object

```json
{"openapi":"3.0.4","info":{"title":"Amazon Web Services Integration API","version":"3.0.4"},"components":{"schemas":{"aws":{"type":"object","description":"Amazon Web Services integration configuration","properties":{"base":{"$ref":"#/components/schemas/base"},"iam-assessment":{"$ref":"#/components/schemas/iam-assessment"},"iam-write":{"$ref":"#/components/schemas/iam-write"},"function-caller":{"$ref":"#/components/schemas/function-caller"},"access-logs":{"$ref":"#/components/schemas/access-logs"},"inventory":{"$ref":"#/components/schemas/inventory"}}},"base":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/base-item"}},"base-item":{"type":"object","description":"Component configuration of a specific Base installation item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"serviceAccountEmail":{"$ref":"#/components/schemas/serviceAccountEmail"},"serviceAccountId":{"$ref":"#/components/schemas/serviceAccountId"}}},"serviceAccountEmail":{"type":"string","description":"P0 service account human-readable identifier"},"serviceAccountId":{"type":"string","description":"P0 service account machine identifier"},"iam-assessment":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-assessment-item"}},"iam-assessment-item":{"type":"object","description":"Component configuration of a specific IAM assessment item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"accessAnalyzerArn":{"$ref":"#/components/schemas/accessAnalyzerArn"}}},"accessAnalyzerArn":{"type":"string","description":"ARN of this account's IAM Access Analyzer"},"iam-write":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/iam-write-item"}},"iam-write-item":{"type":"object","description":"Component configuration of a specific IAM management item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"login":{"$ref":"#/components/schemas/login"}}},"login":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"As AWS IAM users","enum":["iam"]},"identity":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"User name is user email","enum":["email"]}}},{"type":"object","properties":{"type":{"type":"string","description":"User email in a tag","enum":["tag"]},"tagName":{"type":"string","description":"Tag name"}}}]}}},{"type":"object","properties":{"type":{"type":"string","description":"P0 must be installed in the account that contains the Identity Center instance.","enum":["idc"]},"parent":{"type":"string","description":"Account with Identity Center instance"}}},{"type":"object","properties":{"type":{"type":"string","description":"Via a federated identity provider","enum":["federated"]},"provider":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Okta","enum":["okta"]},"appId":{"type":"string","description":"Application ID of your AWS federation application, in Okta."},"identityProvider":{"type":"string","description":"Identity of your identity provider integration, in AWS."},"method":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"SAML","enum":["saml"]},"accountCount":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","description":"Single account","enum":["single"]}}},{"type":"object","properties":{"type":{"type":"string","description":"Choose if you have multiple \"Connected Accounts IDs\" on the Provisioning / Integration tab in your Federation app","enum":["multi"]},"parent":{"type":"string","description":"Parent AWS Account"}}}]}}}]}}}]}}}]},"function-caller":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/function-caller-item"}},"function-caller-item":{"type":"object","description":"Component configuration of a specific Function caller item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}},"access-logs":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/access-logs-item"}},"access-logs-item":{"type":"object","description":"Component configuration of a specific Access Logging item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]},"cloudLakeArn":{"$ref":"#/components/schemas/cloudLakeArn"}}},"cloudLakeArn":{"type":"string","description":"What is the ARN of your CloudLake Data Store?"},"inventory":{"type":"object","description":"All items of this component. Map of item identifier to the item configuration.","additionalProperties":{"$ref":"#/components/schemas/inventory-item"}},"inventory-item":{"type":"object","description":"Component configuration of a specific Resource inventory item.","properties":{"label":{"type":"string","description":"Friendly name of the item. (Optional)"},"state":{"type":"string","description":"The state of the item.","enum":["configure","error","installed","stage"]}}}}}}
```


# AWS OIDC

Install the AWS OIDC federation component so P0 can grant and revoke AWS access for OIDC-authenticated agents running through the P0 AI Gateway.

The **AWS OIDC** integration lets P0 grant and revoke AWS access for OIDC-authenticated agents. It registers an OIDC identity provider in your AWS account and provisions the IAM roles that P0 assumes on the agent's behalf, so an agent reaching AWS through the [P0 AI Gateway](/readme/agentic-control-plane) gets short-lived, policy-scoped access with no long-lived credentials.

This component exists specifically to enable **agentic access to AWS through the gateway**. The OIDC provider you register here is the gateway's own identity: the gateway signs a web-identity token, and AWS trusts it via the provider and role pool this component creates.

{% hint style="info" %}
This component supports only agentic access via the P0 AI Gateway. It's a prerequisite for the [AWS MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/aws).
{% endhint %}

## Prerequisites

* The base [AWS integration](/integrations/resource-integrations/aws) with **IAM management** installed on the same AWS account. AWS OIDC builds on that integration's IAM-write access, and the account picker only lists accounts where it's already installed.
* A deployed P0 AI Gateway. The **OIDC provider URL** and **Audience** you enter in the following fields come from your gateway deployment. See [Deploying the P0 AI Gateway](/getting-started/deploying-the-p0-mcp-gateway).
* Permission to apply Terraform (or run the equivalent `aws iam` commands) in the target AWS account, to create an OIDC provider and IAM roles.

## Install the OIDC federation component

1. Navigate to **Integrations** on [p0.app](https://p0.app), select **AWS OIDC**, and choose the **OIDC federation** component.

<figure><img src="/files/gr53G4USrDS1fyhTb2T4" alt="AWS OIDC integration page showing the OIDC federation component, not installed"><figcaption></figcaption></figure>

2. Click **Add identity provider**.

<figure><img src="/files/Rws69Ce9ls7zcaHnmO6d" alt="OIDC federation page with an empty list of installed identity providers and an Add identity provider button"><figcaption></figcaption></figure>

3. Fill in the identity provider details, then click **Next**:

<figure><img src="/files/K1TSZ68yQMtoU7wuhbJu" alt="Form for installing a new identity provider with fields for identifier, AWS account ID, OIDC provider URL, and audience"><figcaption></figcaption></figure>

* **Identity provider identifier**: a name for this identity provider within P0 (for example, the name of the gateway environment it serves).
* **AWS account ID**: the account to install into. The dropdown lists the accounts where the base AWS integration's IAM management is installed.
* **OIDC provider URL**: the issuer (`iss`) URL of your OIDC provider. For the P0 AI Gateway, this is the gateway's OIDC issuer URL.
* **Audience**: the `aud` claim the identity presents to AWS. For the P0 AI Gateway, this is the gateway's configured token audience.

{% hint style="info" %}
For the P0 AI Gateway, the **OIDC provider URL** and **Audience** are typically the same value: the public address of your deployed gateway.
{% endhint %}

4. P0 generates a Terraform configuration. Copy it into your Terraform project, `apply` it, then click **Next**.

<figure><img src="/files/xloAC4WIrzZ8xaYEp2NL" alt="Terraform tab showing generated configuration that registers an AWS IAM OpenID Connect provider"><figcaption></figcaption></figure>

The generated configuration registers the OIDC provider and provisions the IAM roles P0 uses to grant access.

5. Review the read-only summary and click **Finish**.

<figure><img src="/files/n3pybIdu5OtbaHRnFsdg" alt="Read-only confirmation of the AWS account ID, OIDC provider URL, and audience with a Finish button"><figcaption></figcaption></figure>

6. The identity provider now appears with the state **Installed**.

<figure><img src="/files/TGlPFAxjBZY4UjVyxzAo" alt="Installed identity providers list showing the new provider with state Installed"><figcaption></figcaption></figure>

## How it works

When an agent requests AWS access through the gateway, P0 attaches temporary, policy-scoped permissions to one of the pre-provisioned IAM roles and conditions them on the agent's identity (`sub`) and audience (`aud`). The gateway signs a web-identity token and calls `sts:AssumeRoleWithWebIdentity` to assume the role. P0 never issues long-lived AWS credentials to the agent, and removes the grant when the session ends or the agent relinquishes it.

## Next steps

* Configure the [AWS MCP server](/integrations/resource-integrations/agentic-gateway/mcp-server/aws) to expose AWS to agents behind the gateway, using this OIDC identity as its credential provider.


# Function invocation

The **function invocation** component is a secure, reusable building block in P0 that enables the platform to invoke AWS Lambda functions on your behalf. It acts as the bridge between P0 and your cloud environment, allowing notifications and events to trigger real-time execution of your custom logic inside AWS.

This component is important because it:

* **Establishes a trusted connection** between P0 and your AWS account
* **Ensures secure invocation** of your Lambda functions using least-privilege permissions
* **Allows you to reuse the same Lambda** across multiple integrations or event types without repeating setup steps
* **Provides flexibility**, enabling you to integrate deeply with your internal systems, automation flows, or alerting infrastructure

Setting up Function invocation is the first step toward enabling powerful serverless automation with your P0 events.

## Before you begin

This guide walks you through setting up an **AWS function invocation integration component**, but before diving into the steps, make sure you have an AWS Lambda function.

## Install the AWS function invocation component

First, you'll need to define an installer component in P0 that knows how to call your AWS Lambda function. This component will give P0 permission to invoke this specific AWS Lambda function

1. Go to p0.app in your browser, navigate to Integrations, and select AWS.
2. Select the function invocation component.

<figure><img src="/files/C4zbPkVjgPVeWnSrEBn2" alt="" width="563"><figcaption></figcaption></figure>

3. Enter the full **ARN** of your AWS Lambda function. This is required so P0 knows which function to invoke.

<figure><img src="/files/CA1gnzEqXLIP5ydz9IhY" alt="" width="563"><figcaption></figcaption></figure>

4. Follow the provided instructions to provision access using **AWS CloudShell** or **Terraform**. This step grants P0 permission to call your AWS Lambda securely.

<figure><img src="/files/kUDdUlhfqjYArAxLrqSh" alt="" width="563"><figcaption></figcaption></figure>

5. Once completed, P0 is now set up to call your AWS Lambda function.

<figure><img src="/files/LciYs7X0CTtK5Yj6nEkw" alt="" width="563"><figcaption></figcaption></figure>


# Managed services

P0 can also grant access to several managed services.

Navigate to the page for an individual service for more info.


# AWS RDS

Install AWS RDS to allow P0 to manage access to RDS-hosted databases.

## Installing AWS RDS

### Prerequisites

Before you begin, ensure you have:

* A configured VPC where you want to install the integration
* The ability to create IAM policy, and assign policy to roles, in the VPC's account
* A P0 [AWS](/integrations/resource-integrations/aws) integration installed on the VPC's account
  * The integration must be configured for either federated login or login via Identity Center

### Installation

Follow these steps to install P0 on a VPC for RDS:

#### Via the P0 app

* Navigate to **Integrations > AWS RDS** in the P0 app
* Select the **IAM management** component
* Click **Add VPC**
* Enter the AWS VPC ID
* Choose the P0-installed AWS account
* Choose the region in which this VPC resides
* Click **Next**
* Run the supplied Terraform commands to configure P0's access to RDS
* Click **Next**
* Click **Finish**

#### Via the P0 Terraform provider

1. Ensure you have configured the P0 Terraform provider (follow the provider docs at <https://registry.terraform.io/providers/p0-security/p0/latest/docs> to configure).
2. Use the example module definition at <https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/aws_rds> to configure P0's access to your environment.
3. Run `terraform init` and `terraform apply`.

## Requesting access

To request access, first install P0 on an individual database instance (or cluster), then follow the steps in that database integration's "Requesting access" section.

See: [Requesting MySQL access](/integrations/resource-integrations/mysql/requesting-access) in [MySQL](/integrations/resource-integrations/mysql)


# Cisco Secure Access

Installing P0 access management for Cisco Secure Access takes about 15 minutes.

The Cisco Secure Access integration allows P0 to securely manage and automate access to private network resources (such as servers, databases, or applications that are only reachable within a private network or cloud VPC) without requiring public IP exposure. When combined with **Just-in-Time (JIT) access policies**, this setup ensures that private infrastructure access is secure, traceable, and identity-aware.

{% hint style="info" %}
Installing P0 with Cisco Secure Access takes about 15 minutes.
{% endhint %}

## Integration components

The Cisco Secure Access integration has two components that you can install independently:

| Component             | Purpose                                                                      | CSA permissions required |
| --------------------- | ---------------------------------------------------------------------------- | ------------------------ |
| **Network access**    | Looks up the internally reachable addresses of private resources in CSA      | Read-only                |
| **Policy management** | Creates and removes Just-in-Time (JIT) access rules in the CSA access policy | Read and write           |

### Network access

The network access component allows P0 to discover your private resources in Cisco Secure Access and look up their internally reachable addresses. This component only requires read-only API permissions and doesn't modify any configuration in CSA.

### Policy management

The policy management component allows P0 to create JIT access rules in your Cisco Secure Access access policy. When a user requests access to a private resource through P0:

1. P0 looks up the user's identity in Cisco Secure Access.
2. P0 creates a time-limited Access Policy rule granting the user access to the requested private resource.
3. When the access expires or is revoked, P0 removes the access rule.

## How it works

1. **Private resource configuration**
   * A private resource (such as a VM or database) resides within a private network or virtual cloud (AWS VPC, Azure VNet, or GCP VPC).
   * The resource is defined as a **Private Resource** in **Cisco Secure Access** and connected via a **Secure Access Connector** instance.
   * Cisco Secure Access makes the private resource reachable through its internal IP address without exposing it to the public internet.
2. **Identity and access control**
   * Cisco Secure Access is configured with SSO (for example, Okta SAML SSO) for user authentication.
   * Access policy rules within Secure Access use user identities to grant or restrict access to specific users or groups.
3. **P0 integration**
   * P0 integrates with the **Secure Access API** to discover private resources and manage access rules.
   * The **network access** component reads private resource details from CSA.
   * The **policy management** component creates and removes JIT access rules when users request and release access through P0.
4. **Connection flow**
   * The user runs the Cisco Secure Access client locally.
   * The user logs in using their SSO credentials (for example, Okta).
   * Once authenticated, the user connects to the private resource directly through Secure Access using its private IP.
   * P0 validates compliance with policy, enforces approval workflows, and logs the event.

## Additional resources

* [Installation](/integrations/resource-integrations/cisco-secure-access/installation)
* [Requesting access](/integrations/resource-integrations/cisco-secure-access/requesting-access)
* [Cisco Secure Access documentation](https://docs.sse.cisco.com/sse-dns-guide/docs/get-started-secure-access)
* [Cisco Secure Access API reference](https://developer.cisco.com/docs/cloud-security/secure-access-api-reference-overview/)


# Installation

## Before you begin

### Prerequisites

To set up the Cisco Secure Access integration with P0, you need:

* **Cisco Secure Access account** with administrator privileges
* **Secure Access Connector** deployed and configured in your private network
* **Identity provider (IdP)** configured in Cisco Secure Access (for example, Okta, Microsoft Entra ID)
* **P0 account** with administrator access

### Required permissions

You must have the following permissions in Cisco Secure Access:

* **Administrator** or **API Admin** role
* Permission to create and manage API clients
* Permission to view and manage private resources
* Permission to configure access policies

## Setting up Cisco Secure Access

Each component requires its own API client in Cisco Secure Access with different permission scopes. You can either install only the Network access component or both, depending on your needs.

After you select **Cisco Secure Access** from the integrations list, P0 displays the available components:

<figure><img src="/files/NhGSgvUUAlNPUlLqEdBM" alt="Cisco Secure Access integration components"><figcaption><p>Select a component to install</p></figcaption></figure>

### Installing the network access component

This component allows P0 to look up the internally reachable addresses of your private resources in CSA. It only requires read-only permissions.

**Step 1: Create a read-only API client in CSA**

1. Log in to your **Cisco Secure Access Dashboard**.
2. Navigate to **Admin** > **API Keys**.
3. Click **Add**.
4. Configure the API key:
   * **Name**: `P0 Read-Only`
   * **Description**: `Read-only API key for P0 private resource discovery`
   * **Scope**: Select **Policies / Private Resources - Read-Only**
5. Click **Create** and save the generated API key and secret.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Both the API key and secret are 32-character hexadecimal strings. Store the secret securely. You can't view it again after closing the creation window.</p></div>

**Step 2: Configure the component in P0**

1. Log in to [p0.app](https://p0.app).
2. Navigate to **Integrations** and select **Cisco Secure Access** under **Resources**.
3. Select the **Cisco Secure Access network access** component and enter:

   | Field                 | Value                                                    |
   | --------------------- | -------------------------------------------------------- |
   | **Organization name** | A display name for your Cisco Secure Access organization |
   | **API key**           | The API key from Step 1                                  |
   | **Secret**            | The secret from Step 1                                   |

<figure><img src="/files/yPPHiGzh8bNFfqv8woc1" alt="Cisco Secure Access network access configuration" width="563"><figcaption><p>Network access component configuration</p></figcaption></figure>

4. Click **Update**.

{% hint style="success" %}
P0 can now discover and look up your private resources from Cisco Secure Access.
{% endhint %}

### Installing the policy management component

This component allows P0 to create and remove JIT access rules in your CSA access policy. It requires read and write permissions.

{% hint style="info" %}
You must install the network access component first. The policy management component links to an organization that you already configured in the network access component.
{% endhint %}

**Step 1: Create a read/write API client in CSA**

1. In the **Cisco Secure Access Dashboard**, navigate to **Admin** > **API Keys**.
2. Click **Add**.
3. Configure the API key:
   * **Name**: `P0 Policy Management`
   * **Description**: `Read/write API key for P0 JIT access policy management`
   * **Scopes**: Select both:
     * **Policies / Private Resources - Read-Only**
     * **Policies / Private Resources - Read / Write**
4. Click **Create** and save the generated API key and secret.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Both the API key and secret are 32-character hexadecimal strings. Store the secret securely. You cannot view it again after closing the creation window.</p></div>

**Step 2: Configure the component in P0**

1. Select the **Cisco Secure Access policy management** component.
2. Select the **Organization identifier** for the organization you want to configure, then click **Next**.

<figure><img src="/files/WJVpA6gLMNMxk3pfYaSU" alt="Select the organization to configure" width="563"><figcaption><p>Select the organization to configure</p></figcaption></figure>

3. Enter the following:

   | Field       | Value                   |
   | ----------- | ----------------------- |
   | **API key** | The API key from Step 1 |
   | **Secret**  | The secret from Step 1  |

<figure><img src="/files/4hkNVtARnWWt3HcYS2OS" alt="Cisco Secure Access policy management configuration" width="563"><figcaption><p>Policy management component configuration</p></figcaption></figure>

4. Click **Finish**.

{% hint style="success" %}
P0 can now create and remove JIT access rules in your Cisco Secure Access access policy.
{% endhint %}


# Requesting Cisco Secure Access

How to request just-in-time access to private network resources protected by Cisco Secure Access through P0 via Slack, Teams, Webex, the P0 CLI, or the P0 dashboard.

This guide explains how to request just-in-time access to private network resources protected by Cisco Secure Access through P0.

## Overview

When your organization uses P0 with Cisco Secure Access, you can request temporary access to private resources (servers, databases, applications) without permanent access rules. P0 creates a time-limited Access Policy rule in Cisco Secure Access and automatically removes it when access expires or is revoked.

## Prerequisites

Before requesting access, ensure you have:

* **P0 access**: Your P0 account is set up and you belong to the relevant access groups.
* **Cisco Secure Access client**: Install the Cisco Secure Access client application on your workstation.
* **SSO credentials**: Your identity provider credentials (for example, Okta, Microsoft Entra ID).

## Requesting from the P0 app

1. Open the P0 app and navigate to the **Access Management** page.
2. Click **Request Access**.
3. Click the dropdown for **Resource** and select **Cisco Secure Access**.
4. Select your **Organization** and enter the **Private Resource** name or ID.
5. Enter **Reason access is needed** and **Requested access duration**. Both fields are optional.

Once you submit the request, an approver can navigate to the **Access Management** page, select **Approve**, and approve the request for a specific time. If the system is configured for auto-approval, it grants access immediately.

To revoke access early, an approver can navigate to the **Access Management** page, select the **Prior Approval** tab, and click **Revoke**.

## After access is granted

1. Open the **Cisco Secure Access client** on your workstation.
2. Log in with your **SSO credentials**.
3. Connect to the private resource using its **private IP address**.

P0 automatically removes the access rule when the granted duration expires.

## Additional resources

* [Cisco Secure Access documentation](https://docs.sse.cisco.com/sse-dns-guide/docs/get-started-secure-access)
* [Cisco Secure Access API reference](https://developer.cisco.com/docs/cloud-security/secure-access-api-reference-overview/)


# Cloudflare

Managed just-in-time access to Cloudflare account roles

This page documents how to install P0 for a Cloudflare account so you can manage just-in-time access to Cloudflare account roles. Users request a role, and P0 assigns it to their Cloudflare user when access is approved and removes it when access expires.

{% hint style="warning" %}
The Cloudflare integration is in preview. Functionality and configuration may change.
{% endhint %}

P0 manages Cloudflare roles through Cloudflare's SCIM 2.0 API. P0 assigns a role when a request is approved and removes it when access expires.

### Before you begin

Cloudflare's SCIM API requires an Enterprise plan, and you need Super Administrator access to the Cloudflare account to complete these steps. Gather two values from Cloudflare:

* **Account ID**: the identifier of the Cloudflare account you want P0 to manage. Find it on the account's overview page in the Cloudflare dashboard, or follow Cloudflare's [Find your account and zone IDs](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/) guide.
* **SCIM API token**: a Cloudflare API token that grants P0 access to the account's SCIM API.

Create an [account-owned API token](https://developers.cloudflare.com/fundamentals/api/get-started/account-owned-tokens/) so the token stays tied to the account rather than an individual user:

1. In the Cloudflare dashboard, go to **Manage Account** > **Account API Tokens**.
2. Select **Create Token**, then create a custom token.
3. Add the **SCIM Provisioning** permission and set its access to **Edit**. P0 refers to this permission as **Account SCIM Provisioning**.
4. Under **Account Resources**, select the account you want P0 to manage.
5. Create the token, then copy its value. You provide it to P0 in the next section.

For the full procedure, see Cloudflare's [Set up SCIM provisioning](https://developers.cloudflare.com/fundamentals/account/account-security/scim-setup/) guide.

{% hint style="info" %}
P0 maps each requestor to a Cloudflare user by email address. Every user who requests Cloudflare access must already exist as a Cloudflare user in the account whose email matches their P0 identity. P0 assigns roles to existing users; it does not create Cloudflare users.
{% endhint %}

### Set up the Cloudflare integration

1. Open the P0 dashboard at [p0.app](https://p0.app) and log in to your organization.
2. In the sidebar, click **Integrations**. Under **Resources**, click **Cloudflare**.
3. Select the **Role management** component.
4. In the **Account** field, enter your Cloudflare account ID.
5. In the **SCIM API token** field, enter the Cloudflare API token you created.
6. Click **Next** to finish.

When you finish installation, P0 validates the credentials against the Cloudflare SCIM API. If validation fails, confirm that the account ID is correct and that the API token has the **SCIM Provisioning** permission set to **Edit**.

{% hint style="success" %}
You are ready to make just-in-time requests for Cloudflare roles with P0. See [Requesting Cloudflare access](/integrations/resource-integrations/cloudflare/requesting-access).
{% endhint %}

### What P0 grants

P0 grants Cloudflare **account roles**. A single request can include one or more roles. P0 lists the roles available in your Cloudflare account, so users select from your existing roles. Roles appear under their plain names, such as **Administrator** or **Read Only**.

To grant least-privileged access, make only the roles a user needs available through P0.

When access expires, or when a user relinquishes it early, P0 removes the granted role from the user but keeps the user in the Cloudflare account.

### Limitations

* The integration is in preview.
* P0 grants Cloudflare account roles only.
* Cloudflare's SCIM API requires an Enterprise plan.
* Each requestor must already exist as a Cloudflare user in the account whose email matches their P0 identity.


# Requesting Cloudflare access

How to request access to a Cloudflare account role via P0

Request just-in-time access to one or more Cloudflare account roles through Slack or the P0 web app. When your request is approved, P0 assigns the requested roles to your Cloudflare user and removes them when your access expires.

{% hint style="info" %}
You must already exist as a Cloudflare user in the account whose email matches your P0 identity. P0 assigns roles to your existing Cloudflare user.
{% endhint %}

### Requesting from Slack

1. Type `/p0 request` in any Slack channel to open the P0 request modal, then select **Cloudflare** as the resource.
2. If your organization connects more than one Cloudflare account, select the **Account** you want access to.
3. Under **Role**, start typing the name of a role. As you type, suggestions appear in a dropdown. Select one or more roles you need.
4. Optionally, enter a reason under **Reason access is needed**, and a duration under **Requested access duration**.
5. Click **Request**.

After you submit the request, the P0 bot confirms the request and notifies your approvers. If your request is approved, P0 assigns the selected roles to your Cloudflare user and tells you when access expires. When access expires, or if you relinquish it early, P0 removes the roles.

After your request is approved, you can use the **relinquish** button on the P0 bot message to release access early. Relinquishing revokes the roles, and you must make another request if you need them again.




---

[Next Page](/llms-full.txt/1)

