> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/integrations/resource-integrations/custom-application.md).

# Custom application

Grant just-in-time access to an internal application through a connector you deploy on AWS Lambda or Google Cloud Run. P0 invokes your connector to list, grant and revoke access, and never reads insid

{% hint style="info" %}
The custom application integration is in preview. Contact P0 if you'd like to build a connector for one of your internal applications.
{% endhint %}

The custom application integration lets you bring just-in-time access to an application that P0 Security has no built-in integration for. You deploy a small connector on AWS Lambda or Google Cloud Run, register it in P0, and P0 calls it to list the access a requestor can ask for and to grant or revoke that access.

P0 treats the access your connector exposes as opaque. Your connector decides which policies exist and how each one is provisioned and removed. P0 carries the requestor, the approval and the timing, then invokes your connector at the moment access is granted and again when it expires or is relinquished.

## How it works

* **You own the provisioning logic.** P0 sends your connector a grant or revoke call. Your code decides how to apply it inside your system.
* **P0 never reads your target system.** The integration has no read side, so P0 collects no inventory from your application. It only invokes the connector.
* **Requestors choose a policy.** Your connector's `list` primitive returns the policies available for an application. A requestor selects one or more of these when they request access.
* **No long-lived credentials to store.** P0 invokes AWS Lambda through your P0 AWS installation and Google Cloud Run through your P0 Google Cloud installation, so authorization uses IAM, not a stored secret.

This is a distinct integration from the [Custom resource](/integrations/resource-integrations/custom-resource.md) integration. Custom resource sends a standardized HTTP event to your endpoint on each grant and revoke. Custom application uses a connector that also lists the policies a requestor can select, which lets one connector expose several requestable policies.

## Before you begin

You need:

* A connector deployed as an **AWS Lambda function** or a **Google Cloud Run service** that implements the P0 custom application connector interface.
* The matching P0 installation for the cloud your connector runs in:
  * For AWS Lambda, an installed P0 AWS integration whose role can call `lambda:InvokeFunction` on the connector function.
  * For Google Cloud Run, an installed P0 Google Cloud integration whose service account can invoke the connector service.

When you install the integration, P0 verifies that it can reach the connector by calling the connector's side-effect-free metadata endpoint. This probe confirms connectivity without touching your target system.

## Install a custom application

1. In the P0 app, go to **Integrations** and select **Custom application** under **Resources**.
2. Select **Add** to register a new custom application, and give it an ID and a name. The name is what requestors see when they request access.

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2Fgit-blob-062b1bb8ac75e3c57181960afb4322cffd0442e0%2Fgoogle_custom_app_connector_add_app.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

3. Under **Connector hosting**, select where your connector runs:

{% tabs %}
{% tab title="AWS Lambda" %}
Enter the details of your Lambda function:

| Field            | Description                                                     |
| ---------------- | --------------------------------------------------------------- |
| AWS account ID   | The AWS account the connector's Lambda function is deployed in. |
| Connector name   | The name of the Lambda function that hosts your connector.      |
| Connector region | The AWS region the Lambda function is deployed in.              |

P0 derives the function ARN from these values and probes the function to confirm it can invoke it. If the probe fails with an access-denied error, grant P0's role `lambda:InvokeFunction` on the function and retry.

For a full walkthrough of building and deploying the connector itself, see [Deploying a connector to AWS Lambda](/integrations/resource-integrations/custom-application/deploying-a-connector-to-aws-lambda.md).
{% endtab %}

{% tab title="Google Cloud Run" %}
Enter the details of your Cloud Run service:

| Field            | Description                                                                |
| ---------------- | -------------------------------------------------------------------------- |
| GCP project ID   | The Google Cloud project the connector's Cloud Run service is deployed in. |
| Connector name   | The name of the Cloud Run service that hosts your connector.               |
| Connector region | The region the Cloud Run service is deployed in.                           |

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2Fgit-blob-8502ea7b54785427546d133e61603a13b262012d%2Fgoogle_custom_app_connector_configure_app.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

P0 looks up the service's invocation URL and probes it to confirm it can invoke the service. If the service isn't found, finish deploying it and retry. If P0 can't read the service, verify your P0 Google Cloud installation.

For a full walkthrough of building and deploying the connector itself, see [Deploying a connector to Google Cloud Run](/integrations/resource-integrations/custom-application/deploying-a-connector-to-google-cloud-run.md).
{% endtab %}
{% endtabs %}

4. Complete the setup. Once the reachability probe succeeds, the custom application is ready to request access through.

## Request access

A requestor asks for access to a custom application in two parts:

1. **Application**: which registered custom application to request through.
2. **Policy**: one or more policies your connector's `list` primitive serves for that application.

When P0 grants the request, it invokes your connector with the selected policies. When the grant expires or the requestor relinquishes it, P0 invokes the connector again to revoke the same policies. For the requestor's side of this flow, see [Requesting access](/access-management/just-in-time-access/requesting-access.md).

<figure><img src="https://3783273641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FSQNwGQz62W737pY0FzVb%2Fuploads%2Fgit-blob-6b1e4811d5b26d90f1d42fa176ef1bca1296dfe5%2Fgoogle_custom_app_connector_request_access.png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

## Related links

* [Deploying a connector to AWS Lambda](/integrations/resource-integrations/custom-application/deploying-a-connector-to-aws-lambda.md), the full install walkthrough for the AWS Lambda connector
* [Deploying a connector to Google Cloud Run](/integrations/resource-integrations/custom-application/deploying-a-connector-to-google-cloud-run.md), the full install walkthrough for the GCP Cloud Run connector
* [Deploying a connector with Terraform](/integrations/resource-integrations/custom-application/deploying-a-connector-with-terraform.md), which deploys the connector and registers it in one apply
* [Custom resource integration](/integrations/resource-integrations/custom-resource.md), for the event-driven connector model
* [Requesting access](/access-management/just-in-time-access/requesting-access.md)
