Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ GitHub users or organizations. Complete documentation is
### Guides

* [GitHub App authentication](docs/github-app.adoc)
* [Multi-Organization GitHub App Credentials](docs/multi-org-github-app-credentials.adoc)
* [Extension points provided by this plugin](docs/implementation.adoc)

## Extension plugins
Expand Down
354 changes: 354 additions & 0 deletions docs/multi-org-github-app-credentials.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,354 @@
= Multi-Organization GitHub App Credentials

== Overview

The Multi-Organization GitHub App Credentials provides enhanced support for GitHub Apps that are installed across multiple GitHub organizations. This credential type eliminates the need to create duplicate credentials for each organization where your GitHub App is installed.

== Features

* *Single Credential for Multiple Organizations*: Use a single credential for a GitHub App installed across multiple organizations.
* *Automatic Organization Discovery*: Automatically discovers and caches the list of organizations where the app is installed.
* *Seamless Integration*: Works with existing GitHub SCM sources and navigators without requiring changes to your job configurations.
* *Organization-specific Token Generation*: Automatically generates the correct token for each organization when needed.
* *Token Caching*: Caches tokens per organization to minimize API calls and improve performance.
* *Rate Limiting Protection*: Built-in protection against GitHub API rate limits.
* *Fallback Support*: Gracefully handles cases where an organization may not be in the cached list.

== Usage

=== Creating the Credential

. Navigate to *Manage Jenkins > Manage Credentials*
. Add a new credential of type *GitHub App (Multi-Organization)*
. Provide the GitHub App ID and Private Key
. Optionally configure the API endpoint (defaults to GitHub.com)
. Click "Test Connection" to verify the setup and see available organizations

=== Using with GitHub SCM Sources

When configuring a GitHub SCM source or navigator:

. Select your Multi-Org GitHub App credential from the credentials dropdown
. The system will automatically use the appropriate token for the target organization
. No additional configuration is needed - the credential handles organization selection automatically

=== Managing Organizations

The credential automatically:

* Discovers all organizations where your GitHub App is installed
* Caches the organization list for performance (1 hour TTL)
* Refreshes the list when you test the connection or force a refresh
* Handles organization-specific token generation on demand

== How It Works

=== Automatic Organization Detection

When you create or use the credential, it:

. Uses your GitHub App credentials to authenticate with GitHub
. Retrieves the list of all installations for your app
. Caches this list to avoid repeated API calls
. Uses the cached list for organization validation and token generation

=== Token Generation Per Organization

When a GitHub SCM source needs to access a repository:

. The system determines which organization owns the repository
. Generates a token specifically for that organization's app installation
. Caches the token until it expires or becomes stale
. Automatically refreshes tokens as needed

=== Credential Selection Logic

The plugin uses the following logic when selecting credentials:

. If a `MultiOrgGitHubAppCredentials` is selected and the target organization is available, creates organization-specific credentials
. If the organization is not in the cached list, still attempts to use the credential (useful for newly installed apps)
. Falls back to standard GitHub App credential behavior if needed

== Migration from Standard GitHub App Credentials

The Multi-Organization GitHub App Credentials is backward compatible with the standard GitHub App Credentials. You can:

. Create a new Multi-Organization GitHub App Credential with the same app ID and private key
. Update your configurations to use the new credential ID
. Remove the old single-organization credentials

[NOTE]
====
No code changes are required when switching from standard to multi-organization credentials. Existing job configurations will continue to work.
====

== Troubleshooting

=== Organization Not Listed

If an expected organization doesn't appear in the available organizations list:

. Verify the GitHub App is installed to that organization
. Check that the app has the necessary permissions
. Test the connection to refresh the organization list
. Verify network connectivity to GitHub

=== Connection Issues

If you encounter connection problems:

. Verify the App ID is correct
. Ensure the private key is in PKCS#8 format
. Check the API endpoint configuration
. Verify network connectivity to GitHub
. Check Jenkins logs for detailed error messages

=== Token Generation Issues

If tokens are not being generated correctly:

. Verify the GitHub App has the required permissions in the target organization
. Check that the app installation is active
. Ensure the private key hasn't expired or been revoked
. Review logs for specific error messages

== Logging

Enable debug logging to troubleshoot issues:

[source]
----
Logger: org.jenkinsci.plugins.github_branch_source.MultiOrgGitHubAppCredentials
Level: FINE
----

This will provide detailed information about organization discovery and token generation.

Additional logging for connector behavior:

[source]
----
Logger: org.jenkinsci.plugins.github_branch_source.Connector
Level: FINE
----

== Best Practices

=== GitHub App Configuration

* Grant minimal required permissions to your GitHub App
* Install the app only in organizations where it's needed
* Regularly review app installations and permissions
* Use meaningful names and descriptions for your GitHub Apps

=== Jenkins Configuration

* Use descriptive names for your Multi-Org credentials
* Test connections after creating or updating credentials
* Monitor Jenkins logs for any authentication issues
* Consider using credential domains to scope access appropriately

=== Security Considerations

* Store private keys securely and rotate them regularly
* Monitor GitHub App activity through GitHub's audit logs
* Use Jenkins' credential masking features in build logs
* Restrict access to credential management to authorized users only

== API Rate Limiting

The Multi-Organization GitHub App Credentials helps manage GitHub API rate limits by:

* Caching organization lists to reduce discovery API calls
* Caching tokens per organization to minimize token generation calls
* Using organization-specific tokens which have separate rate limits
* Providing rate limit information in test connection results

[TIP]
====
GitHub Apps have higher rate limits than personal access tokens, making them ideal for organizations with high API usage.
====

== Multi-Organization GitHub App Credentials Binding

The Multi-Organization GitHub App Credentials Binding allows you to use multi-org credentials in pipeline scripts and build environments. This binding provides access to GitHub tokens for multiple organizations through environment variables.

=== Features

* *Automatic Mode*: Automatically provides tokens for all organizations where the app is installed
* *Manual Mode*: Provides a token for a specific organization
* *Environment Variable Support*: Exposes tokens through environment variables in build steps
* *Pipeline Integration*: Works seamlessly with Jenkins Pipeline scripts

=== Usage in Pipelines

==== Automatic Mode

In automatic mode, the binding provides environment variables for all organizations:

[source,groovy]
----
pipeline {
agent any
environment {
// Automatically binds tokens for all organizations
GITHUB_CREDENTIALS = credentials('multi-org-github-app-creds')
}
stages {
stage('Access Multiple Orgs') {
steps {
script {
// Available environment variables:
// GITHUB_ORGS - comma-separated list of organizations
// GITHUB_TOKEN_<ORGNAME> - token for each organization

echo "Available organizations: ${env.GITHUB_ORGS}"

// Use organization-specific tokens
sh 'curl -H "Authorization: token ${GITHUB_TOKEN_MYORG}" https://api.github.com/orgs/myorg/repos'
sh 'curl -H "Authorization: token ${GITHUB_TOKEN_ANOTHERCORP}" https://api.github.com/orgs/anothercorp/repos'
}
}
}
}
}
----

==== Manual Mode

In manual mode, specify a single organization and custom variable name:

[source,groovy]
----
pipeline {
agent any
stages {
stage('Access Specific Org') {
steps {
withCredentials([
multiOrgGitHubApp(
credentialsId: 'multi-org-github-app-creds',
tokenVariable: 'GITHUB_TOKEN',
orgName: 'myorg'
)
]) {
sh 'curl -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/orgs/myorg/repos'
}
}
}
}
}
----

=== Using in Freestyle Jobs

For freestyle jobs, add the "Multi-Organization GitHub App credentials" binding in the build environment:

. Check "Use secret text(s) or file(s)"
. Add "Multi-Organization GitHub App credentials"
. Configure either automatic or manual mode
. Use the environment variables in your build steps

=== Environment Variables

==== Automatic Mode

* `GITHUB_ORGS`: Comma-separated list of available organizations
* `GITHUB_TOKEN_<ORGNAME>`: GitHub token for the specified organization (organization name is sanitized for environment variable use)

==== Manual Mode

* `<TOKEN_VARIABLE>`: The GitHub token for the specified organization (using your custom variable name)

== Configuration as Code (JCasC)

The Multi-Organization GitHub App Credentials can be configured using Jenkins Configuration as Code (JCasC).

=== Basic Credential Configuration

[source,yaml]
----
credentials:
system:
domainCredentials:
- credentials:
- multiOrgGitHubApp:
scope: GLOBAL
id: "multi-org-github-app"
description: "Multi-Org GitHub App for CI/CD"
appID: "123456"
privateKey: |
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD...
-----END PRIVATE KEY-----
apiUri: "https://api.github.com"
----

=== Advanced Configuration with Custom API Endpoint

[source,yaml]
----
credentials:
system:
domainCredentials:
- domain:
name: "github-enterprise"
description: "GitHub Enterprise credentials"
credentials:
- multiOrgGitHubApp:
scope: GLOBAL
id: "enterprise-multi-org-app"
description: "GitHub Enterprise Multi-Org App"
appID: "789012"
privateKey: |
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD...
-----END PRIVATE KEY-----
apiUri: "https://github-enterprise.company.com/api/v3"
----

=== Multiple Credentials Configuration

[source,yaml]
----
credentials:
system:
domainCredentials:
- credentials:
- multiOrgGitHubApp:
scope: GLOBAL
id: "multi-org-github-app"
description: "Multi-Organization GitHub App"
appID: "${GITHUB_APP_ID}"
privateKey: "${GITHUB_APP_PRIVATE_KEY}"
apiUri: "https://api.github.com"
- multiOrgGitHubApp:
scope: GLOBAL
id: "backup-multi-org-app"
description: "Backup Multi-Org GitHub App"
appID: "${BACKUP_GITHUB_APP_ID}"
privateKey: "${BACKUP_GITHUB_APP_PRIVATE_KEY}"
apiUri: "https://api.github.com"
----

=== Using Environment Variables for Secrets

[source,yaml]
----
credentials:
system:
domainCredentials:
- credentials:
- multiOrgGitHubApp:
scope: GLOBAL
id: "multi-org-github-app"
description: "Multi-Org GitHub App from Environment"
appID: "${GITHUB_APP_ID}"
privateKey: "${readFile:${GITHUB_APP_PRIVATE_KEY_FILE}}"
apiUri: "${GITHUB_API_URL:-https://api.github.com}"
----

[NOTE]
====
When using JCasC, ensure that sensitive values like private keys and app IDs are provided through environment variables or external secret management systems rather than hardcoding them in the configuration files.
====
Loading