For the complete documentation index, see llms.txt. This page is also available as Markdown.

GitHub Repositories

Install P0 for a GitHub organization so its members can request just-in-time roles on its repositories.

This page documents how to install P0 for a GitHub organization so its members can request just-in-time roles on its repositories. A member requests a role on one repository. When the request is approved, P0 makes them a direct collaborator with that role, and when access ends, P0 puts back the direct role they had before.

The GitHub Repositories integration is in beta. Functionality and configuration may change.

To manage access to GitHub teams instead, see the GitHub integration.

How it works

  • You own the GitHub App. P0 acts on your organization through a GitHub App that you create and install, and only on the repositories you select for it.

  • The private key stays in your AWS account. You store the app's private key in AWS Secrets Manager, under a name you choose. P0 never reads the key. The connector does.

  • The connector runs in your AWS account. You deploy P0's connector on AWS Lambda, from a shell script or Terraform that the installer generates. P0 invokes the connector to read and change roles, and the connector calls GitHub as your app.

  • P0 changes direct roles only. P0 counts only a person's direct role on a repository, and never changes access that comes from a team or from the organization's base permission.

For what happens to a role when access ends, see Requesting GitHub repository access.

Before you begin

You deploy the connector on AWS Lambda, and store the GitHub App's private key in AWS Secrets Manager. You need:

  • An owner of the GitHub organization, to create and install the GitHub App. Only organization owners can install it.

  • A verified domain for the organization. P0 matches each requestor to their GitHub account by email. Each requestor needs a verified email address in GitHub, on one of the organization's verified domains, that matches the email they sign in to P0 with.

  • AWS IAM management for the account the connector runs in. P0 invokes the connector through it.

  • AWS Secrets Manager integration for the account that holds the key, if you install from the P0 app. The installer lists only the accounts where it's installed. That account needs AWS IAM management installed first.

  • Bash, or Terraform 1.4 or later, to deploy the connector. Run either where Docker and the AWS CLI are installed, with the AWS CLI signed in to the connector's account. Both copy P0's connector image from Docker Hub into Amazon ECR.

The connector and the private key's secret must be in commercial AWS regions. GitHub Repositories doesn't support AWS GovCloud, China, ISO or European Sovereign Cloud regions.

Install GitHub Repositories

Each organization gets its own GitHub App, private key and connector, so repeat these steps for every GitHub organization whose repositories you want P0 to manage.

  1. Open the P0 dashboard at p0.app and log in to your organization.

  2. In the sidebar, click Integrations. Under Resources, click GitHub Repositories.

  3. Select the Repository access component, and click Add Organization.

The installer then takes you through three pages: the form for a new organization in step 1, the organization's setup page in steps 2 to 5, and its configure page in step 6.

Step 1: Add the organization

The form is titled Installing a new Organization. Where the private key is stored, the secret's name and where the connector runs can't change once you add the organization, so decide them now. You store the key in the secret in step 3.

  1. In Organization login, enter your organization's login, as in github.com/<login>.

  2. Secret manager provider is already set to AWS Secrets Manager, and Connector hosting to AWS Lambda.

  3. Fill in the fields:

Field
What to enter

Installation, under Secret manager provider

The account the secret is in. The list shows the accounts where P0's AWS Secrets Manager integration is installed.

Secrets region

The secret's region, such as us-west-2

Private key secret

The name you'll store the key under. Enter the name, not the ARN.

AWS account ID, under Connector hosting

The account the connector runs in. The list shows the accounts where P0's AWS IAM management is installed.

Connector name

The Lambda function's name, 2 to 64 characters

Connector region

An AWS region, such as us-west-2

  1. Click Next. P0 saves the organization and opens its setup page, titled Configuring Organization, followed by the organization's login.

Each list of accounts selects its first account for you, so check both before you click Next. If a list is empty, install the integration it names first. See Before you begin.

A connector name uses lowercase letters, digits and single hyphens, and starts with a letter and ends with a letter or digit. Each organization's connector needs its own name.

The connector reads the secret by its name, in the account and region you chose under Secret manager provider, so the secret can be in a different account from the connector. You can create the secret before or after you add the organization. Its name can't end in a hyphen and six letters or digits, such as -AbCdEf, because Secrets Manager reads that as the suffix of a full ARN.

A secret in another account must be encrypted with a customer-managed KMS key, and both the secret's resource policy and the key's policy must allow the connector's role. In step 5, the connector's shell script won't run until you set the key's ARN in KMS_KEY_ARN, and its Terraform won't apply until you set it in kms_key_arn.

If P0 can't save the organization, it shows why at the top of the form, under Error configuring GitHub Repositories. See When you add the organization for each message. Fix it, then click Next again.

Step 2: Create the GitHub App

On the setup page, click Create the GitHub App. GitHub opens a new GitHub App form for your organization, filled in with these settings:

Setting
Value

GitHub App name

P0 repo access <org>, cut to GitHub's limit of 34 characters. App names are unique across GitHub, so GitHub may say this one is taken. If it does, enter another. Any name works, and you can rename the app later.

Webhook

Inactive, with no events

Repository permissions

Administration: Read and write. Metadata: Read-only.

Organization permissions

Members: Read-only. Custom repository roles: Read-only.

Where can this GitHub App be installed?

Only on this account

Review the settings, then click Create GitHub App.

The app needs each permission for these jobs:

Permission
What P0 uses it for

Administration (read and write)

Give a requestor their role on a repository, put back their previous role when access ends, and cancel invitations the app sent

Metadata (read-only)

List the repositories the app is installed on, and read a requestor's current role

Members (read-only)

Match a requestor to their GitHub account, check that they're a member of the organization, and read the organization's base permission

Custom repository roles (read-only)

List the organization's custom repository roles

Step 3: Save the private key

  1. Once you create the app, GitHub opens its settings page. Under Private keys, click Generate a private key. GitHub downloads a .pem file.

  2. Store the file's contents in the secret you named in step 1, in the account and region you chose there. The setup page shows the secret's name and where it goes. Then delete the download. For example, from the command line:

For a secret in another account, also pass --kms-key-id <kms-key-arn> with the customer-managed key from step 1. If the secret already exists, store the key in it as a new version with aws secretsmanager put-secret-value instead.

Step 4: Install the app on your organization

On the setup page, this is the step titled Install the app on, followed by your organization's login. An owner of the organization installs the app:

  1. Click the step's button to open your organization's GitHub Apps, and open your app's settings page.

  2. Click Install App, then click Install next to your organization.

  3. Under Repository access, choose Only select repositories, and select the repositories P0 should manage.

  4. Click Install.

Requestors can ask for roles only on the repositories you select. You can change the selection later in the app's installation settings. If you remove a repository while someone holds a role on it through P0, P0 can't remove that role when their access ends. See If removing a role fails.

Step 5: Deploy the connector

The setup page has the connector's shell script and its Terraform, on the Shell and Terraform tabs at the bottom. Both are filled in with the values from step 1, pin P0's connector image by digest, and create the same resources. Deploy each organization's connector with one or the other, because the script won't change a connector that the Terraform deployed.

To deploy with the shell script:

  1. Copy the script from the Shell tab, and save it as a file, such as deploy-connector.sh.

  2. If a customer-managed KMS key encrypts the secret, set KMS_KEY_ARN near the top of the script to that key's ARN.

  3. Run it with bash deploy-connector.sh. If the AWS CLI is signed in to another account, the script stops before it changes anything.

  4. Click Next.

To deploy with Terraform:

  1. Copy the Terraform from the Terraform tab.

  2. Add the Terraform to your configuration. Before you apply it:

    • The Terraform has its own required_providers block for the docker provider. If your configuration already has one, move docker into yours and delete the snippet's block.

    • Add the credential settings your other AWS providers use, such as profile or assume_role, to the aws provider that the Terraform declares for the connector's account and region.

    • If a customer-managed KMS key encrypts the secret, set kms_key_arn to that key's ARN.

  3. Apply it.

  4. Click Next.

Step 6: Validate

P0 opens the organization's configure page. It lists the steps again, with the first four done, and keeps the connector's Terraform and shell script under Show the connector's Terraform and Show the connector's shell script. The fields from step 1 show below the steps, but you can't change them.

  1. In GitHub App ID, enter the app's App ID. It's on the app's settings page, under About. To find it, click the link to your organization's GitHub Apps in the field's description, and click Edit beside the app.

  2. Click Finish. P0 validates the install, and checks these in order:

    1. P0 can invoke the connector, and the connector can read the private key.

    2. GitHub accepts the private key for the app ID.

    3. The app is installed on the organization.

    4. The installation isn't suspended, and has all four permissions from step 2.

P0 stops at the first check that fails. For the last check, one message names both problems if the installation is suspended and also missing permissions. When every check passes, P0 installs the organization.

If a check fails, P0 shows what to fix at the top of the page, under Error configuring GitHub Repositories. See When P0 validates the install for each message. Fix it, then click Finish again. If P0 or the connector is denied access right after you deploy the connector, wait a few seconds and click Finish again.

What the connector's deployment creates

The shell script and the Terraform create the same resources. They give the connector read access to the private key's secret and no other secret. P0 gets only what it needs to invoke the connector.

Resource
What it's for

An ECR repository

Holds the copy of P0's connector image that Lambda runs. Its tags can't be overwritten, so pushing to the repository can't replace the image the connector runs.

A CloudWatch log group, /aws/lambda/<connector-name>

The connector's logs, kept for 30 days. Change LOG_RETENTION_DAYS in the script, or log_retention_days in the Terraform, to keep them for longer or shorter.

An IAM role for the connector

secretsmanager:GetSecretValue on the private key's secret, and on no other secret. kms:Decrypt on the secret's KMS key, through Secrets Manager only, if you set the key's ARN. logs:CreateLogStream and logs:PutLogEvents on its own log group.

The Lambda function

Runs the connector. It calls api.github.com over the internet, so it needs no VPC.

A policy on P0's role in the account

lambda:InvokeFunction on the connector's function, and nothing else.

Install with Terraform

Instead of the installer, you can install GitHub Repositories with the p0_github_repositories resource of the P0 Terraform provider. You still create the GitHub App, store its private key and install the app on your organization:

  1. Open https://github.com/organizations/<org>/settings/apps/new and create the app with the settings in step 2.

  2. Store its private key in the secret that the resource names, as in step 3.

  3. Install the app on your organization, as in step 4.

The resource takes the place of the installer's other steps. Copy the connector's Terraform from the resource's example in the provider's docs, and put the resource in the same configuration. Pin the connector image to a published tag and its digest, as in Change the install later. Applying the resource has P0 validate the install through the connector. If a check fails, the apply fails with P0's message.

For the organization my-github-org, the resource looks like this:

The depends_on list holds back the validation until P0 can invoke the connector and the connector can read the key. IAM changes can take a few seconds to take effect, so if the first validation is denied access, apply again.

If you already added the organization in the P0 app, the apply fails with The GitHub organization <org> is already added. Import it into the resource instead:

Changing app_id updates the installation in place, and P0 validates it again. Changing org, vault, hosting or private_key_secret_name replaces the installation, so change them only when no one holds a role through P0 on the organization's repositories. Check for active grants on the Activity tab of Access Management. Otherwise, a removal that comes due while the organization isn't installed fails, and needs Retry revoke once it's installed again.

Access policies

In access policies, GitHub Repositories is the service github-repositories, and its access type is role.

Available filters

A rule can filter on these properties of a request, each with the key name:

Filter
What it matches
Example

organization

The organization's login, as you entered it in P0

my-github-org

repository

The repository, as <org>/<repo>, with the repository's name as GitHub spells it

my-github-org/api

role

A built-in role's name in access policies, listed in Roles, or a custom role's name as GitHub shows it

push

P0 records a built-in role by its name in access policies, whichever name the requestor used, so a rule for Write has to match push, not write. Patterns are unanchored, case-sensitive regular expressions. Use ^ and $ to match a whole name.

Example access policy

These policies send requests for Read, Triage or Write on the api and web repositories to your Security Reviewers, and deny Admin on every repository:

Error messages

P0 shows these messages when you add an organization, when it validates the install, and on requests, where requestors and approvers see them. Once you've fixed the cause, retry what failed.

When you add the organization

P0 checks the form when you click Next in step 1, and doesn't save the organization if a check fails. The message shows at the top of the form, under Error configuring GitHub Repositories. Fix the field it names, then click Next again.

Message
What to do

The GitHub organization <org> is already added. To change its GitHub App ID, open <org> from the list of organizations. To change anything else, remove <org> and add it again.

Open the organization from the list instead. To change anything other than its GitHub App ID, see Change the install later.

Enter the name of the secret that holds, or will hold, the GitHub App's private key.

Fill in Private key secret.

That doesn't look like a secret name. Enter the name of the secret that holds the key, not its ARN or the key itself.

Enter the secret's name, not its ARN. Never paste the key itself into the form.

Secrets Manager can't find a secret by its name when the name ends in a hyphen and six characters, like -AbCdEf. Use a secret whose name doesn't end that way.

Choose a secret name that doesn't end in a hyphen and six letters or digits.

Enter the organization's GitHub login, as in github.com/<login>

Enter the login from your organization's URL on GitHub.

Use 2 to 64 characters for the connector name: lowercase letters, digits and single hyphens, starting with a letter and ending with a letter or digit.

Choose a Connector name that follows the rule.

Enter the AWS region the connector runs in, such as us-west-2., or a message like it for another account or region field

Enter that field as the message says.

GitHub Repositories doesn't support AWS GovCloud or China regions yet.

Use a commercial AWS region for the secret and the connector.

When P0 validates the install

P0 validates the install when you click Finish on the organization's configure page in step 6, and when you click Update after a change to the install. A failed check shows at the top of the page, under Error configuring GitHub Repositories. Fix the cause, then click Finish or Update again.

Message
What to do

Enter the GitHub App ID. It's on the app's settings page, under About.

Fill in GitHub App ID.

The GitHub App ID is a number. Find it on the app's settings page.

Enter the App ID, not the app's name or its Client ID.

The connector isn't allowed to read the GitHub App private key secret <secret>. Grant the connector's identity secretsmanager:GetSecretValue on that secret, and kms:Decrypt on its KMS key if it uses a customer-managed key.

Deploy the connector again from the setup page, as in step 5. If a customer-managed KMS key encrypts the secret, set its ARN too, and for a secret in another account, set its policies as in step 1.

The connector couldn't find the GitHub App private key secret <secret>. Check the private key secret in the P0 install, and that the secret still exists.

Store the key under the secret's name and in the place that the setup page shows, as in step 3. If you named the wrong secret in step 1, remove the organization and add it again.

GitHub rejected the credentials for GitHub App <app-id>. Check that the app ID and the private key in your secret manager belong to the same app, and that the key hasn't been revoked.

Check that GitHub App ID is the App ID on the app's settings page, and that the secret holds one of the app's current private keys.

The private key for GitHub App <app-id> isn't a valid PEM private key. Store the .pem file GitHub generated for the app.

Store the contents of the downloaded .pem file in the secret as a new version, as in step 3.

A message that starts Error in service and ends (account=<account-id> region=<region>), such as an access-denied error from AWS Lambda

P0 couldn't invoke the connector. Deploy the connector from the setup page, as in step 5, and check that Connector name and Connector region match the function it deployed. Right after you apply it, wait a few seconds and retry.

P0 invoked the Lambda function <arn>, but it didn't answer as the GitHub Repositories connector. Check that the function runs the connector's image, and check its logs, then retry.

Check that the function at <arn> is the one you deployed in step 5, and deploy it again. If it is, check the function's logs.

GitHub App <app-id> isn't installed on <org>. An owner of <org> needs to install it, then retry.

Install the app as in step 4. If it's installed, check that the organization you added in P0 is the one you installed it on.

GitHub App <app-id>'s installation on <org> is suspended. An owner of <org> needs to unsuspend it, then retry.

An owner of the organization unsuspends the installation, in the organization's GitHub App settings.

GitHub App <app-id>'s installation on <org> is missing <permissions>. Add them in the app's permission settings, have an owner of <org> accept the change, then retry.

In the app's settings, give it each permission at the level in step 2. An owner of the organization then accepts the new permissions on the installation. The message names a permission as GitHub's API does, such as organization_custom_roles=read for Custom repository roles (read-only).

GitHub App <app-id>'s installation on <org> is suspended and is missing <permissions>. An owner of <org> needs to unsuspend it. Add the missing permissions in the app's permission settings, have an owner of <org> accept the change, then retry.

Unsuspend the installation, and give the app the missing permissions, as in the two rows above.

On requests

Requestors and approvers see these messages on a request. Either problem with the private key's secret shows on a request as P0 couldn't read the GitHub App's private key. Ask your P0 admin to check the GitHub Repositories install. To see which one it is, validate the install again: open the organization's page in P0 and click Update. A revoke that failed has a Retry revoke button on the request's page. For a role that P0 couldn't remove when access ended, see If removing a role fails.

Message
What to do

GitHub rejected the GitHub App credentials for <org>. Check that the app ID and the private key in the connector's secret manager belong to the same app, that the key hasn't been revoked, and that the connector's clock is accurate.

Check that GitHub App ID is the App ID on the app's settings page, and that the secret holds one of the app's current private keys.

The GitHub App isn't installed on <org>. Install it on the org, or check the org name in the P0 install, then retry.

Install the app as in step 4. If it's installed, check that the organization you added in P0 is the one you installed it on.

The GitHub App's installation on <org> is suspended. Ask an owner of <org> to unsuspend it in the org's GitHub App settings, then retry.

An owner of the organization unsuspends the installation.

The GitHub App for <org> is missing <permission>. Grant it in the app's settings and accept the update on the installation., or the same message with a permission this call needs in place of a permission's name

In the app's settings, give it the permission at the level in step 2. An owner of the organization then accepts the new permissions on the installation. The message names a permission as GitHub's API does, such as organization_custom_roles=read for Custom repository roles (read-only).

<login> isn't a member of <org>, so P0 can't give them a role on <repo>. GitHub may have sent them an invitation to <repo> instead, and P0 couldn't make sure it was cancelled. Check the repo's collaborator settings, and cancel any pending invitation from the GitHub App.

P0 refused the grant. Cancel any invitation that the GitHub App sent them, in the repository's collaborator settings. They need to join the organization before they request access again.

<login> isn't a member of <org> and has no direct role on <repo>, but P0 couldn't make sure an invitation it sent to <login> for <repo> was cancelled. Check the repo's collaborator settings, and cancel any pending invitation from the GitHub App.

P0 removed their direct role when their access ended. Cancel any invitation that the GitHub App sent them, in the repository's collaborator settings, then click Retry revoke.

Change the install later

  • Use another GitHub App. Install the new app on the organization, as in step 4, and store its private key in the same secret as a new version, as in step 3. Then, on the organization's page in P0, change GitHub App ID, and click Update. Until you click Update, P0 can't change roles on the organization's repositories. P0 validates the install again, as in step 6. The GitHub App ID is the only setting you can change in place.

  • Rotate the private key. Generate a new private key on the app's settings page, and store it in the same secret as a new version, such as with aws secretsmanager put-secret-value. The connector uses the new version from its next call, so you can then delete the old key in GitHub. Nothing changes in P0 or in the connector's Terraform.

  • Update the connector. To move to a new connector image, change the image's pin and deploy the connector again. In the shell script, the pin is IMAGE_TAG and IMAGE_DIGEST, and you run the script again. You can also copy the current script from the organization's page in P0, under Show the connector's shell script. In the Terraform, the pin is image_tag and image_digest, and you apply it again. If the apply stops with The connector image's tag doesn't resolve to the digest pinned here, the tag on Docker Hub and the digest you pinned are different images, and Terraform changes nothing. To find a tag's digest, run docker buildx imagetools inspect p0security/p0-connector-github-repositories:<tag> and copy the Digest it prints. P0 publishes the connector's tags on Docker Hub.

  • Use a different secret, or move the connector. Where the private key is stored, the secret's name and where the connector runs are fixed once you add an organization. To change any of them, remove the organization from the integration, then add it again and follow the install steps with the new values. Do this only when no one holds a role through P0 on the organization's repositories. Check for active grants on the Activity tab of Access Management. Otherwise, a removal that comes due while the organization isn't installed fails, and needs Retry revoke once it's installed again.

Limitations

  • P0 grants roles only to members of the organization, and never invites anyone to it. Outside collaborators can't be granted a role.

  • Requestors can ask for roles only on repositories in the GitHub App's repository selection.

  • Custom repository roles need GitHub Enterprise Cloud.

  • P0 changes direct collaborator roles only. Team membership and the organization's base permission stay as they are.

  • P0 can't take back a role from an account that GitHub hides, such as an account flagged as spam. The account can keep its role until an admin removes it by hand. See GitHub hides the person's account.

  • The connector runs on AWS Lambda, and you store the private key in AWS Secrets Manager.

  • Each organization needs its own GitHub App and its own connector.

  • The connector and the private key's secret must be in commercial AWS regions, not in GovCloud, China, ISO or European Sovereign Cloud regions.

Last updated