> 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/getting-started/get-started-with-the-p0-terraform-provider.md).

# Get started with the P0 Terraform provider

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. [Authenticate to P0](#authenticate-to-p0)
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 install integrations as code.
* **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.

## Authenticate to P0

The provider authenticates to P0 with a bearer token, supplied as the `P0_API_TOKEN` environment variable (or the `api_token` attribute). You have three ways to get one—see [Authenticating with the P0 API](/getting-started/authenticating-with-the-p0-api.md) for the full details:

* **Google Cloud service-account token** (recommended for CI) — a short-lived token minted for a service account, with no long-lived secret in your pipeline.
* **P0 CLI session** (local development) — run `p0 login <your-org>` and the provider uses your CLI session automatically, with no token to set.
* **API key** (legacy) — a long-lived key generated in the dashboard.

For example, to authenticate a Google Cloud pipeline as a service account, mint an identity token whose audience is your organization URL and export it as `P0_API_TOKEN`:

```bash
export P0_API_TOKEN="$(gcloud auth print-identity-token \
  --impersonate-service-account="p0-ci@my-project.iam.gserviceaccount.com" \
  --audiences="https://p0.app/o/my-org" \
  --include-email)"
```

{% hint style="warning" %}
Never commit a token to version control. Use an environment variable or a secrets manager, and prefer a short-lived token over a long-lived API key.
{% 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 token from the `P0_API_TOKEN` environment variable you set earlier, or from your P0 CLI session when no token is set. 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.md) 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.md).
* **Manage access policies as code** — Define access policies and approvals with the `p0_access_policy` resource, which replaces the deprecated `p0_routing_rule`. See [Configure access policies](/getting-started/configuring-access-policies.md) for the concepts.
