Using GitHub Apps with the GitHub Actions deployment
About the GitHub Apps profile
Section titled “About the GitHub Apps profile”GitHub Apps are the recommended credential profile for production use of the GitHub Actions only deployment. The Activity collector, orchestrators, and workers create short-lived installation tokens from two private GitHub Apps that your organization or enterprise owns.
- Read app. Used by GitHub tools, admission, control precompute, and the Activity collector (
cao-activity.yml). - Write app. Used only by trusted safe-output processing.
The apps don’t affect how the dashboard is hosted. The dashboard build and deploy jobs never use the apps. They use the automatic github.token and OpenID Connect (OIDC).
Use this profile when any of the following is true:
- Your targets are private or internal, span many repositories, or belong to several organizations in one GitHub Enterprise Cloud enterprise.
- Your campaigns read Actions, security, issue, or pull request evidence across repositories.
- Your review outputs go to a separate repository, or your campaigns write
livesafe outputs. - Your credentials must not depend on one person’s access.
Prerequisites
Section titled “Prerequisites”You need everything in the prerequisites for the GitHub Actions only deployment, plus the following.
| Requirement | Details |
|---|---|
| App ownership | An approved private App pair and access to its keys, or permission to create Apps in the owning organization/enterprise. Public apps aren’t supported. |
| App installation | Appropriate approval for each new organization installation. Repository administrators can extend an already-approved installation to their repositories where organization policy permits. |
| Read app permissions | Read-only access to Actions, Checks, Contents, Issues, Packages, Pull requests, Secret scanning alerts, Security events, Commit statuses, Vulnerability alerts, and Metadata. No write permissions. |
| Write app permissions | Write access to Actions, Contents, Issues, and Pull requests. Read access to Administration and Metadata. |
| Webhooks | Turned off for both apps. |
Grant only the permissions that your installed campaigns need. For more information, see Permissions.
Deploying the dashboard
Section titled “Deploying the dashboard”-
Install the dashboard. For more information, see Deploying the dashboard. Don’t run any workflows yet.
-
Create and install the apps.
-
For already-approved Apps, reuse their client IDs and securely enter their keys instead of registering replacements. This also supports private enterprise Apps installed separately in each enrolled organization.
Terminal window gh cao setup auth github-app \--repo OWNER/CONTROL-REPOSITORY \--read-client-id READ-APP-CLIENT-ID \--write-client-id WRITE-APP-CLIENT-ID \--dry-runRemove
--dry-runto apply. See Reuse approved Apps for approval boundaries and supported GitHub versions. -
For one organization, use the manifest helper. Preview the changes with
--dry-runfirst. If you use GitHub Enterprise Cloud with data residency, setGH_HOSTto your host name. Otherwise, omit it.Terminal window export GH_HOST=HOSTNAMEgh cao setup auth github-app --repo OWNER/CONTROL-REPOSITORY --dry-rungh cao setup auth github-app \--repo OWNER/CONTROL-REPOSITORY \--write-repository OWNER/OUTPUT-REPOSITORY -
For several organizations in one enterprise, create both private apps in your enterprise settings. The manifest helper can’t create apps that an enterprise owns. Install each app on selected repositories in every enrolled organization, then run the following command.
Terminal window gh cao setup auth enterprise-app \--repo OWNER/CONTROL-REPOSITORY \--read-client-id READ-APP-CLIENT-ID \--write-client-id WRITE-APP-CLIENT-ID \--policy .github/workflows/cao.json \--write-repository OWNER/CONTROL-REPOSITORY
Replace the placeholders as follows:
OWNER/CONTROL-REPOSITORYwith your control repository.OWNER/OUTPUT-REPOSITORYwith an approved safe-output repository.READ-APP-CLIENT-IDandWRITE-APP-CLIENT-IDwith the client IDs of your apps.
-
-
For every installation, select Only select repositories.
- Install the read app on the control repository and on every repository that
.github/workflows/cao.jsonallows. - Install the write app only on approved safe-output repositories. By default, that’s only the control repository.
- Setup uses a short-lived App installation token to verify the exact selected repository membership and fails closed rather than relying on manual verification.
- Install the read app on the control repository and on every repository that
-
Add the write App’s
APP-SLUG[bot]login to theon.botsallowlist of every worker workflow that the App may dispatch, then recompile those workflow sources. A run whose pre-activation job succeeds while activation is skipped has not executed the worker. -
Confirm that the helper stored the client IDs as variables and the private keys as secrets. For the names, see Configuration reference. The helper passes private keys to
gh secret setthrough standard input, so they are never written to disk or passed as command arguments. -
Delete any
GH_AW_GITHUB_READ_PAT,GH_AW_GITHUB_WRITE_PAT, orGH_AW_GITHUB_TOKENsecrets. If you leave them in place and an app is misconfigured, CAO silently uses the PAT instead. -
Run the CAO Activity workflow. Its first successful default-branch run triggers the CAO Dashboard workflow automatically. For the remaining steps, see Deploying the dashboard.
-
Before you enable any campaign in
livemode, validate the credentials. For more information, see Validating the credentials.
Configuration reference
Section titled “Configuration reference”| Name | Type | Description |
|---|---|---|
GH_AW_GITHUB_READ_APP_ID | Actions variable | Client ID of the read app |
GH_AW_GITHUB_READ_APP_PRIVATE_KEY | Actions secret | Private key of the read app, in PEM format |
GH_AW_GITHUB_WRITE_APP_ID | Actions variable | Client ID of the write app |
GH_AW_GITHUB_WRITE_APP_PRIVATE_KEY | Actions secret | Private key of the write app, in PEM format |
CAO chooses a credential for each step in this order.
| Step type | Order |
|---|---|
| Read steps | Read app token, then GH_AW_GITHUB_READ_PAT, then GH_AW_GITHUB_TOKEN, then github.token |
| Safe outputs | Write app token, then GH_AW_GITHUB_WRITE_PAT, then GH_AW_GITHUB_TOKEN, then github.token |
An app token is used only when both its variable and its secret are set. CAO looks up installation IDs at runtime from the target owner and repository. It never stores them in policy or dispatch inputs.
The apps control which repositories CAO can reach, not which ones it may act on. The .github/workflows/cao.json file still decides scope and mode.
Monitoring the deployment
Section titled “Monitoring the deployment”This profile uses the same signals as the GitHub Actions only deployment, plus the following.
| Signal | What to check |
|---|---|
| Token selection | The actions/create-github-app-token step in each job shows whether CAO created an app token. If the step was skipped, the run used a PAT or github.token instead. |
| API capacity | Before discovery, admission checks GET /rate_limit for the selected credential. Each app installation has its own rate limit, which grows with the size of the installation. A failed capacity gate points to one installation, and the dashboard shows it as a GitHub API capacity admission gate. |
| Audit logs | Installation token activity appears in organization and enterprise audit logs under the app’s identity, not under a user. |
What this deployment guarantees
Section titled “What this deployment guarantees”- Short-lived tokens. Tokens expire after about one hour and are scoped to one installation. Each safe-output token is limited to the permissions of the selected handler.
- Separate read and write identities. The read app can’t write.
- No dependency on individuals. The credentials keep working if a user loses access or leaves.
- Multi-organization support. One enterprise can span several organizations through separate installations in each organization.
- No inferred access. If an app isn’t configured, CAO skips it. It never infers access from another credential.
What this deployment does not guarantee
Section titled “What this deployment does not guarantee”- Protection from silent fallback. If an app variable or secret is missing, the run uses the next available credential. CAO can’t tell whether that was intended, so delete PAT secrets that you don’t use.
- Access outside the enterprise. A private app can’t be installed outside the organization or enterprise that owns it. For unrelated owners, use separate control planes.
- Access from an enterprise installation. Installing an app on the enterprise doesn’t grant access to any repositories. Every organization needs its own installation on selected repositories.
- Automatic key rotation. Private keys don’t expire. You must rotate them.
- Policy changes. Installation scope doesn’t widen or narrow CAO policy. CAO still refuses a repository that the app can reach but policy doesn’t allow.
Validating the credentials
Section titled “Validating the credentials”- For every enrolled organization, create a read token and confirm that it can read the expected repositories but can’t write.
- In an approved output repository, use only the write app to make a reversible change, then undo it.
- Confirm that neither app is installed on unrelated repositories.
Rotating and revoking credentials
Section titled “Rotating and revoking credentials”- Generate a new private key for each app, and replace the matching secret.
- Run a bounded
reviewrun for each installed campaign. - Delete the old private keys, then review the installations and permissions again.
If you suspect that a key was exposed:
- Set the kill switch for each affected campaign to
false. - Cancel active runs.
- Delete the private key, or suspend the installation.
- Investigate the exposure.
For more information, see Rotation and revocation.
Further reading
Section titled “Further reading”- Deploying the dashboard with GitHub Actions
- Using a fine-grained PAT with the GitHub Actions deployment
- Configure authentication
- Authentication profiles
- Credentials
- Admission gates, including Diagnose a skipped run
- About creating GitHub Apps in the GitHub documentation
- Making authenticated API requests with a GitHub App in a GitHub Actions workflow in the GitHub documentation