GitHub Integration via API

Purpose

This guide explains how to generate a GitHub Personal Access Token and use it in Logsign USO to ingest GitHub organization audit log events (and a periodic inventory of members without two-factor authentication) for security analytics and forensic purposes, as part of the shipped GitHub Organization Audit Log API integration.

Important scope note: this integration calls GitHub's organization-level audit log endpoint (GET /orgs/{organization}/audit-log) plus the organization members endpoint (GET /orgs/{organization}/members?filter=2fa_disabled), both at the fixed public host api.github.com. It covers a single GitHub organization per configured source. GitHub's separate enterprise-level audit log (/enterprises/{enterprise}/audit-log, which aggregates every organization under a GitHub Enterprise account) is not called by this poller; if you need enterprise-wide coverage, a source must be configured per organization. Because the host is hardcoded to api.github.com, GitHub Enterprise Server (self-hosted GitHub) is not supported: there is no field to point the integration at a different host.

Prerequisites

Your GitHub organization must be on the GitHub Enterprise Cloud plan. The audit log endpoint this poller calls is restricted to that plan (GitHub's API marks it githubCloudOnly); on Free, Team, or a plan without Enterprise Cloud, the endpoint is not available and requests return 403/404.

The token used must be a classic Personal Access Token with the read:audit_log scope, and the GitHub account generating it must hold the organization owner role. This is a GitHub platform restriction, not a Logsign choice: GitHub does not offer a scoped "audit-log-only" role for this endpoint: the token is tied to a full org-owner account, all or nothing. If your organization can designate a dedicated bot/service-account owner for this token rather than a personal owner account, that is recommended so the token is not attached to an individual's account. Fine-grained personal access tokens are not confirmed to support this endpoint as of this writing; use a classic PAT.

Step 1: Generate a Personal Access Token

  1. Sign in to GitHub with an account that has the organization owner role in the target organization.
  2. Go to Settings > Developer settings > Personal access tokens > Tokens (classic).
  3. Click Generate new token (classic).
  4. Give it a name (for example, "Logsign USO integration") and choose an expiration. GitHub does not require a permanent token; set a realistic expiration and plan to rotate it, since an expired token stops collection with repeated 401 errors until it is regenerated and updated in Logsign.
  5. Under scopes, select read:audit_log. No other scope is required for this integration.
  6. Click Generate token and copy the value immediately. GitHub will not show it again.

Note down the organization's login/slug as well: it is the segment right after github.com/ in your organization's URL (for example, the org at https://github.com/my-org has the slug my-org).

Step 2: Configure the Integration in Logsign USO

Log in to Logsign USO and add a new GitHub (Organization Audit Log API) data source. You will be asked for:

FieldValue
organizationThe organization slug from Step 1 (for example my-org). Enter the slug only, not the full URL. Correct: my-org. Incorrect: https://github.com/my-org or github.com/my-org/; either form will make the request fail.
access_tokenThe classic PAT value from Step 1. Logsign sends it as Authorization: token <value>; enter only the token itself.
snapshot_interval_hoursOptional, default 24. Controls how often the members-without-2FA inventory (see below) is re-collected. Set to 0 to collect it on every poll.

There is no host/region field: the integration always calls https://api.github.com, GitHub's single public API host. GitHub Enterprise Cloud does not use per-tenant hostnames for the REST API the way some SaaS products do.

What Gets Collected

The integration runs two independent collection modes on every poll:

  • Audit log events (incremental): calls GET /orgs/{organization}/audit-log with include=all (so repository, Git, and workflow-level events are included, not just web UI actions) and pages forward using GitHub's cursor (Link header, rel="next") until caught up. Position is tracked by each event's created_at timestamp, so a restart resumes from the last event actually processed rather than re-sending history.
  • Members without 2FA (periodic snapshot, not incremental): calls GET /orgs/{organization}/members?filter=2fa_disabled. This endpoint has no time cursor: it always returns the organization's current full list of members without two-factor authentication, so the poller only runs it once per snapshot_interval_hours (default once a day) and re-sends the complete current list each time, rather than only "new" members. Expect the same member(s) to reappear in every snapshot for as long as their 2FA stays disabled; this is expected behavior, not duplicate data.

Use Case Coverage

Use caseHow it's covered
A member is promoted to organization OwnerAudit log action org.update_member where the new permission is admin/owner.
An Owner's role is downgraded to a regular memberAudit log action org.update_member where the new permission is member. Note this is a different action from a member being removed from the organization entirely (org.remove_member): a role downgrade and a full removal are two separate events and are reported separately.
A user outside the organization's domain is invitedAudit log actions org.invite_member (organization-level invite) and org.add_outside_collaborator (repository-level outside collaborator).
An account is created/kept without MFA enabledGitHub's audit log has no single event for "account created without MFA". MFA status is a per-account attribute, not an auditable action. This use case is covered instead by the periodic members-without-2FA snapshot described above, which is not real-time: a newly created account without 2FA is reported on the next scheduled snapshot (at most snapshot_interval_hours later), not the moment it is created.

Field mapping highlights: actionEvent.Action, actor/actor_idSource.UserName/Source.ID, actor_ipSource.IP, user (the affected member) → TargetUser.Name, org_idOrganization.ID, repo/repositoryObject.Name, and for the members snapshot, membership without 2FA is reported via Account.MultiFactorAuth.

Notes and Limits

  • Enterprise Cloud only: the audit-log endpoint requires the GitHub Enterprise Cloud plan; other plans return 403/404 regardless of credentials.
  • Single organization per source: one configured source covers one organization value. An enterprise account with multiple organizations needs one source per organization.
  • Rate limit: the audit-log endpoint has its own dedicated limit, separate from GitHub's general 5,000/hour PAT limit. Per GitHub's own August 2023 changelog announcement, this was set at 1,750 requests/hour per user+IP+organization; GitHub stated an intent to later tighten this to 15 requests/minute, but that later change was not independently reconfirmed as of this writing; treat the exact current figure as informational. Either way, the poller stays well under both bounds: at most 50 page requests (100 records/page) per polling cycle, with a 1-second pause between pages.
  • Pagination: GitHub's standard Link-header cursor (RFC 5988); the poller follows rel="next" until the response has no further page.
  • Default lookback: on first run there is no prior event history, so the poller starts from GitHub's phrase=created:>=<now> equivalent going forward. Historical events from before the source was configured are not backfilled.
  • Unclassified event types: because include=all is used, repository/Git/workflow-level audit actions outside the four use cases above also arrive through this source. Any action not explicitly mapped falls back to a generic Identity / Other / Info classification rather than being dropped.

Troubleshooting / Error Codes

CodeLikely causeWhat to check
401The PAT is invalid, expired, or was revoked.Regenerate the classic PAT in GitHub and update the access_token field in Logsign.
403(a) the PAT is missing the read:audit_log scope, (b) the token's account is not an organization owner, or (c) the organization is not on the GitHub Enterprise Cloud plan.Check the token's scopes and the account's role in GitHub organization settings, and confirm the org's plan tier.
404The organization value is wrong, or the audit-log endpoint is not exposed for this plan.Confirm the organization slug matches the URL segment after github.com/, and confirm the Enterprise Cloud plan.
429The endpoint's dedicated rate limit was hit.No action needed: the poller logs the hit and picks up remaining records on the next scheduled poll; it does not currently implement an in-cycle retry/backoff.
Was this article helpful?
0 out of 0 found this helpful

Articles in this section

See more
Become a Certified Logsign User/Administrator
Sign-up for Logsign Academy and take the courses to learn about Logsign USO Platform in detail. Enjoy the courses, and get your badges and certificates. In these courses, you'll learn how to use Logsign in your work and add value to your career.
Visit Our Blog
Our Logsign USO Platform illustrate our expertise. So do the blog. Through our blog posts, deepen your knowledge on various SecOps topics or get updated about important news & modern approaches for cybersecurity. Get into the habit of reading valuable information provided by Logsign. Be a step ahead.