> 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/deploying-a-connector-to-aws-lambda.md).

# Deploying a connector to AWS Lambda

Build the P0 connector SDK example, deploy it privately to AWS Lambda, and register it in P0 so requestors can get just-in-time access to your own application.

This guide walks through deploying the `aws-lambda` example from the [connector repository](https://github.com/p0-security/connector) to AWS Lambda and connecting it to P0 Security.

{% 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 %}

## What you're deploying

A custom application connector is a small service that you write and host in your own cloud account. It implements six actions: `validateUser`, `userExists`, `createUser`, `deleteUser`, `setPoliciesForUser`, and `list`. P0 calls `validateUser` to check whether it may act on a principal at all, `userExists` to check whether it already has an account for them, `list` to learn which policies a requestor can ask for, and `createUser`, `deleteUser`, and `setPoliciesForUser` to provision, update, and remove access when a grant starts, changes, or ends.

This guide uses the `aws-lambda` example included in the SDK (`packages/connector-sdk/examples/aws-lambda`) as a starting point. It's a complete, deployable connector that you customize to call your own application instead of its placeholder logic.

### Prerequisites

* An AWS account you can deploy to, and the AWS CLI installed and authenticated with permission to create Lambda functions and IAM roles/policies.
* Node.js 24 or later, to build the example locally. The deployed function runs on the `nodejs22.x` Lambda runtime instead: that's a build-time requirement, not a deploy-time one, since `package.sh` compiles to plain JavaScript.
* An installed P0 AWS integration for the account the connector runs in. P0 assumes this integration's role to invoke your connector, so its role is the identity you'll grant `lambda:InvokeFunction` to. If you don't have it yet, install it first from the [AWS](/integrations/resource-integrations/aws.md) page.
* Admin access to your P0 workspace, to register the connector once it's deployed.

## Part 1: Build the connector

1. Clone the connector SDK repository and copy the example into your own repository:

   ```bash
   git clone --depth 1 https://github.com/p0-security/connector.git p0-connector && cp -r p0-connector/packages/connector-sdk/examples/aws-lambda my-connector && rm -rf p0-connector
   cd my-connector
   ```
2. Implement your actions in `src/actions.ts`. Replace the placeholder logic with calls into your own application's API.
3. Build and package the function:

   ```bash
   ./package.sh
   ```

   This installs dependencies, compiles `src/` to `dist/`, and writes a deployable `connector-lambda.zip` with `dist/`, a production-only `node_modules`, and `package.json` at the zip root.

## Part 2: Deploy to Lambda

AWS IAM is the only gate on this function. P0 calls it by assuming its AWS integration's role and invoking it with `lambda:InvokeFunction`. Whoever holds that permission on the function's ARN can call it, and there's no second, in-connector check to configure.

### Create the execution role

The connector runs under its own execution role, separate from the identity P0 uses to invoke it. Grant this role whatever access your application requires, plus CloudWatch Logs:

```bash
aws iam create-role --role-name p0-custom-app-connector-execution \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": { "Service": "lambda.amazonaws.com" }
    }]
  }'

aws iam attach-role-policy --role-name p0-custom-app-connector-execution \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
```

### Create the function

```bash
aws lambda create-function \
  --function-name p0-custom-app-connector \
  --runtime nodejs22.x \
  --role arn:aws:iam::<your-account-id>:role/p0-custom-app-connector-execution \
  --handler dist/index.handler \
  --zip-file fileb://connector-lambda.zip \
  --timeout 60 \
  --memory-size 512
```

### Grant P0 permission to invoke it

P0 assumes the role created by your AWS integration when it installed: `P0RoleIamManager` if you installed from the P0 app, or the role your `p0_aws_iam_write_staged` resource named if you installed with Terraform. Attach an inline policy scoping `lambda:InvokeFunction` to just this function, as its own, separately-named policy. That keeps it outside the drift check (see [Setting up AWS IAM management](/integrations/resource-integrations/aws/installation-methods.md#unexpected-content-in-p0-identity-policy)) P0 runs against the `P0RoleIamManagerPolicy` inline policy:

```bash
aws iam put-role-policy \
  --role-name P0RoleIamManager \
  --policy-name InvokeCustomConnector \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Sid": "InvokeCustomConnector",
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:<region>:<your-account-id>:function:p0-custom-app-connector"
    }]
  }'
```

## Part 3: Register the connector in P0

Register the connector as a custom application in P0, following [Custom application](/integrations/resource-integrations/custom-application.md#install-a-custom-application). Select **AWS Lambda** hosting and enter your account ID, connector name, and region. P0 derives the function's ARN from these values, so you don't paste it in.

When you complete registration, P0 checks that it can invoke the connector, so the IAM grant above must be in place before this step. Once the check passes, the connector's entitlements appear in P0's request-access picker, and access requests provision, update, and revoke users through the actions you implemented.

## Verify the install

* Request access to one of your entitlements as a test user and confirm the grant provisions correctly. For the requestor's side of this flow, see [Requesting access](/access-management/access-management/just-in-time-access/requesting-access.md).
* Let the grant expire, or revoke it manually, and confirm `deleteUser` and `setPoliciesForUser` behave as expected in your application.
* Check the structured logs the SDK emits per request. Each is tagged with the route and request ID, which is the fastest way to trace a specific grant:

  ```bash
  aws logs tail /aws/lambda/p0-custom-app-connector --follow
  ```

## Troubleshooting

| Symptom                                                         | Likely cause                                                                                                                               |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| P0 reports the connector is unreachable at install time         | P0's role isn't granted `lambda:InvokeFunction` on the function, or the account ID, name, or region don't match a real, deployed function. |
| P0 reports it isn't permitted to invoke the Lambda function     | The invoke policy isn't attached to the role P0 actually assumes. Recheck the role name against your AWS integration.                      |
| The function isn't found                                        | It may still be deploying, or the account/region/name you registered don't match where you created it.                                     |
| A grant provisions, but access doesn't work in your application | Check the `createUser` and `setPoliciesForUser` logs. The connector may be accepting a policy key your application doesn't recognize.      |

## Related links

* [Custom application](/integrations/resource-integrations/custom-application.md), the integration overview and install steps
* [Deploying a connector with Terraform](/integrations/resource-integrations/custom-application/deploying-a-connector-with-terraform.md), if you manage your cloud infrastructure as code
* [AWS](/integrations/resource-integrations/aws.md), which P0 uses to invoke your connector
* [Requesting access](/access-management/access-management/just-in-time-access/requesting-access.md)
