GH-100: Admin Playbook โ
โ Overview ยท Concept Map โ ยท Tools Reference โ ยท Exam Guide โ
Real-World Scenarios for Enterprise Admins
These scenarios test your ability to synthesize knowledge across domains and make decisions under pressure. Each walkthrough shows the decision tree, troubleshooting steps, and links to relevant study material.
Scenario 1: SAML SSO Enforcement Breaks Team Access โ
Situation: You enforce SAML SSO on your enterprise account. The next morning, 15% of your workforce cannot log in. You have 30 minutes to restore access before the daily standupd.
Symptom โ
- Users see: "SAML authentication failed" or "Your identity provider rejected the authentication request"
- Some users can log in; others cannot
- Team sync shows green, but users claim they can't access repos
Diagnosis Checklist โ
- [ ] Step 1: Check IdP health โ Is your SAML provider (Okta, Azure AD, etc.) online? Check status page.
- [ ] Step 2: Verify SAML assertion format โ Does your IdP send the
NameIDfield? GitHub requires it. - [ ] Step 3: Check GitHub's SAML log โ Go to Enterprise Settings โ Authentication & Authorization โ View SAML log. Look for assertion errors.
- [ ] Step 4: Confirm ACS URL โ Is the Assertion Consumer Service (ACS) URL correct? Typo = silent rejection.
- [ ] Step 5: Review user attributes โ Are users linked to existing GitHub accounts? New SAML users need pre-existing GitHub accounts (unless EMU).
Quick Fixes (in order of likelihood) โ
- Wrong ACS URL: Regenerate SAML certificate, copy the correct ACS URL from GitHub, update IdP
- Missing NameID: Configure IdP to send NameID in SAML assertion (not just email)
- Certificate expired: Regenerate SAML certificate in GitHub (Enterprise Settings โ SAML)
- IdP assertion size too large: Some IdP attribute mappings bloat the assertion โ remove unused attributes
Decision Tree โ
All users failing? โ Check IdP status + ACS URL
Only new/recent hires failing? โ Check user account linking
Some users specific to a team failing? โ Check team sync + IdP group membershipMitigation โ
- Disable SAML enforcement temporarily (uncheck "Require SAML authentication") to unblock users while you investigate
- Use a test user account to replicate the error and debug
- Escalate to GitHub Support if SAML log shows "Assertion invalid" with no clear reason
Related Study Material โ
- Domain 2: User Identities & Authentication โ SAML SSO configuration
- Exam Guide: Identity Decision Trees
Scenario 2: Secrets Leaked in a Public Repository (Brand Damage Control) โ
Situation: A developer accidentally commits a GitHub Personal Access Token (PAT) to a public repo. The commit is already on main for 2 hours. You need to minimize exposure.
Immediate Actions (First 5 Minutes) โ
- Revoke the token immediately โ GitHub Personal Settings โ Tokens โ delete the exposed token
- Alert the organization โ Notify security team, don't announce publicly yet
- Check if GitHub detected it โ Go to repo โ Security โ Secret scanning alerts. If GitHub's partner network detected it, GitHub may have already notified the token issuer to revoke it
Remediation Steps โ
Step 1: Scrub History (Choose One Approach) โ
# Option A: BFG Repo Cleaner (RECOMMENDED - faster)
bfg --replace-text passwords.txt my-public-repo.git
# OR
# Option B: git filter-branch (legacy but works)
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch ghp_xxxxx' \
--prune-empty --tag-name-filter cat -- --allWhy BFG over filter-branch?
- BFG is 10-100x faster on large repos
- Simpler syntax, lower risk of mistakes
- GitHub Support recommends it
Step 2: Force-Push Cleaned History โ
git push origin --force-with-lease
git push origin --force-with-lease --tagsCoordination Required
Everyone who cloned the repo must re-clone after the force-push. Notify your team in advance.
Step 3: Verify the Secret Is Gone โ
# Search repo history for any remaining trace
git log -p --all -S "ghp_" | head -20
# Result should be emptyStep 4: Audit & Recover โ
- Check audit logs: Enterprise Settings โ Audit log. Search for token creation/deletion. Who had access?
- Review recent deployments: Did this token deploy anything? Audit those environments.
- Rotate related secrets: If the PAT accessed AWS keys or databases, rotate those too.
Decision Tree โ
Secret is < 1 hour old?
โ Revoke + BFG + force-push (likely minimal exposure)
Secret is > 24 hours old?
โ Revoke + BFG + assume compromise (audit all systems the token touched)
Secret is in a private repo (not public)?
โ Revoke + BFG (lower urgency, check audit logs for who accessed it)Prevention for Future โ
- Enable push protection to block commits with secrets before they enter the repo (enabled at org level)
- Enable secret scanning to alert on detected secrets
- Use environment secrets for production deployments (scoped, require approvals)
- Prefer GitHub Apps over PATs for machine accounts (Apps have short-lived tokens, no expiry gotchas)
Related Study Material โ
- Domain 5: Secret Scanning & History Scrubbing
- Domain 5: Push Protection vs Secret Scanning
- Cheatsheet: Token Types
Scenario 3: Migrating from GitHub Enterprise Server (GHES) to GitHub Enterprise Cloud (GHEC) โ
Situation: Your organization is sunsetting on-premises GHES and migrating to GHEC. You have 100 repos, 500 users, and 3 months to complete the migration without downtime.
Pre-Migration Assessment (Week 1) โ
Inventory & Dependencies โ
- [ ] List all repos, their size, and recent commit activity
- [ ] Document all self-hosted runners โ will these migrate to GitHub-hosted or new self-hosted?
- [ ] Audit all GitHub Apps and OAuth apps โ check if they're GHES-compatible on GHEC
- [ ] Identify any GHES-only configuration (e.g., custom authentication, appliance-specific features)
Identity Strategy Decision โ
Question: How should users authenticate on GHEC?
If current GHES uses LDAP:
โ GHEC doesn't support LDAP directly
โ Options:
(A) Migrate to SAML SSO + SCIM + Team Sync
(B) Enable EMU (Enterprise Managed Users) for full company-control
(C) Switch to OAuth with existing IdP
Recommendation: SAML + SCIM (most common, most control)Capacity Planning โ
- License seats: GHEC is metered by user. Audit inactive users and remove them before migration.
- Data volume: GHEC has limits on repo size and API rate limits. Test with largest repos first.
- Network egress: Moving large repos off-premises = data transfer costs. Plan for this.
Migration Plan (Phased Approach) โ
Phase 1: Pilot (Week 2-3) โ
- Migrate 3 small repos and 50 volunteers to GHEC
- Test SAML SSO with a subset of users
- Verify CI/CD workflows run on GitHub-hosted runners
- Validate team structure and permissions mapping
Phase 2: Parallel Run (Week 4-8) โ
- Migrate 40% of repos to GHEC
- Mirror activity between GHES and GHEC (optional: use GitHub Sync tool or custom scripts)
- Monitor performance, API usage, rate limits
- Collect user feedback on workflows
Phase 3: Cutover (Week 9-12) โ
- Final sync of remaining repos
- Turn off GHES (or put in read-only mode)
- Celebrate! ๐
Key Decisions During Migration โ
| Decision Point | GHES Approach | GHEC Approach | Recommendation |
|---|---|---|---|
| User accounts | LDAP + local users | SAML + SCIM (or EMU) | SAML + SCIM for smooth transition |
| CI/CD runners | Self-hosted (on-prem) | GitHub-hosted or new self-hosted | Evaluate: GitHub-hosted faster? Or keep self-hosted for security? |
| Webhooks/Integrations | Update each app's endpoint | Re-register webhooks on GHEC | Plan webhook re-registration |
| Data storage | On-premises (AWS/Azure for large) | GitHub-hosted (no alternative) | Accept GitHub hosting; audit compliance needs |
Troubleshooting Common Issues โ
Issue: "Users can't log in after SAML setup"
- Cause: ACS URL misconfiguration, missing NameID in assertion, or users don't exist on GHEC yet
- Fix: See Scenario 1
Issue: "Repo history is incomplete after migration"
- Cause: Shallow clone during migration, or large file filtering
- Fix: Re-push with full history:
git push --mirrorinstead of selective push
Issue: "CI/CD pipeline slower on GitHub-hosted runners"
- Cause: GitHub-hosted runners are shared; on-prem runners had dedicated hardware
- Fix: Test runner class (macOS, Windows, Linux with different specs) or use self-hosted runners
Related Study Material โ
- Domain 3: Deployment & Licensing (GHEC vs GHES)
- Domain 2: Identity Management (SAML + SCIM)
- Domain 6: Runners (GitHub-hosted vs self-hosted)
Scenario 4: Enforcing a Least-Privilege Permission Model Across 50 Teams โ
Situation: Your enterprise has grown to 8 organizations, 50 teams, and 200 repositories. Permission creep is real โ many people have admin access who only need write. You need to audit and enforce least privilege without disrupting teams.
Step 1: Audit Current State โ
Repository Permissions Audit โ
# Using GitHub CLI (gh)
for org in org1 org2 org3; do
gh repo list $org --limit 1000 --json name,repositoryTopics --template '{{range .}}{{.name}}{{"\t"}}{{end}}{{"\n"}}'
done
# Then manually inspect each repo's Manage Access tab
# OR use GitHub API to export via Python/ScriptFind Over-Privileged Users โ
- Go to Organization Settings โ Members
- Sort by role (Owner, Member)
- Identify Owners who should be Members (only product leads and principal engineers should be Owners)
- Document which users have admin access on repos (check each repo's Manage Access tab)
Check Outside Collaborators โ
- Outside Collaborators should have repo-level access only, not org-level access
- Verify they're linked to specific repos, not blanket org membership
Step 2: Define Permission Levels โ
Create a policy document:
| Team | Repo Access | Permission | Rationale |
|---|---|---|---|
| Developers (IC) | Feature repo | write | Can merge own PRs, cannot delete repo |
| Developers (Senior/Lead) | Feature repo | maintain | Can manage branch protection, deploy, but cannot delete repo |
| DevOps / Release | Deployment repo | admin | Can configure CI/CD, manage deployments, rotate secrets |
| Security | All repos | maintain (audit-only) | Can view, comment, audit; cannot merge/push |
| Product | Feature repo | triage | Can label, assign, close issues; cannot push |
Principle
Read < Triage < Write < Maintain < Admin
Default to Read; elevate only when necessary.
Step 3: Implement the Model โ
Option A: Team-Based Access (Recommended for Scaling) โ
Create teams aligned to function, not project:
@backend-core(write to backend repo)@devops-core(admin on deployment repos)@security-audit(maintain on all repos)
Grant teams permissions at repo level (not per-user)
Use branch protection rules to enforce code review even if user has write access
Option B: Role-Based Access Control (RBAC) Using Custom Roles (Enterprise Only) โ
Enterprise accounts can define custom repository roles:
- Go to Enterprise Settings โ Roles
- Create roles:
Backend Engineer,Release Manager,Security Reviewer - Assign users to roles; roles grant specific permissions
Automate Role Assignment โ
Use GitHub API to:
# Add user to team
gh api -X POST /orgs/$ORG/teams/$TEAM/memberships/$USERNAME --input -
# Assign team to repo with permission level
gh api -X PUT /repos/$ORG/$REPO/teams/$TEAM --input '{"permission":"write"}'Step 4: Audit & Enforce โ
Monthly Permission Review โ
# Export org members and permissions
gh org-permissions export --org $ORG --output members.csv
# Identify outliers: users with admin who shouldn'tImplement Governance โ
- Branch protection rules: Require PR review even for repo maintainers (prevents accidental force-push)
- Enterprise policy: Set org-level policies (e.g., "only owners can create new teams")
- Audit logging: Monitor
Repository role changedevents in org audit log
Decision Tree โ
User asks for repo admin access?
โ Verify: Is this a deployment automation? (Yes โ maintainer OK)
โ Verify: Is this a one-time need? (Yes โ provide temporary access)
โ Default: Offer write or maintain instead
Team consistently needs admin on multiple repos?
โ Create a dedicated DevOps/Platform team
โ Grant that team admin on shared reposRelated Study Material โ
- Domain 4: Access & Permissions
- Domain 4: Repository Permission Levels
- Cheatsheet: Least Privilege
- Exam Guide: Enterprise vs Org Policies
Scenario 5: GitHub Actions Security Lockdown (Secrets, Runners, and Deployment Gates) โ
Situation: Your CI/CD pipeline runs 500+ workflows daily. You've had two incidents:
- A script accidentally logged a database password to build logs (caught by secret scanning, but scary)
- A self-hosted runner was used by a malicious PR, exposing AWS credentials to an external contributor
You need to enforce guardrails without breaking the development experience.
Step 1: Secrets Security โ
Audit Current Secrets โ
# List all secrets in an org (requires REST API call)
curl -H "Authorization: token $GH_TOKEN" \
"https://api.github.com/orgs/$ORG/actions/secrets" | jq '.secrets[].name'Implement Secret Rotation Policy โ
- Database passwords: Rotate every 90 days
- API keys: Rotate every 30 days
- Cloud credentials (AWS, GCP, Azure): Rotate every 15 days
- GitHub PATs: Rotate every 90 days
Use OIDC Federation (Preferred for Cloud Credentials) โ
Instead of storing AWS_ACCESS_KEY_ID as a GitHub secret:
# Workflow with OIDC (no stored credentials)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::$ACCOUNT:role/GitHubActionsRole
aws-region: us-east-1Benefit: GitHub generates short-lived (1 hour) STS tokens. No long-lived secrets to rotate.
Restrict Secret Access โ
- Go to Organization Settings โ Secrets
- For sensitive secrets (database passwords), restrict to specific repos only or specific environments only
- Do NOT use organization-level secrets for prod credentials (too broad)
Step 2: Self-Hosted Runner Security โ
Risk Assessment โ
- Public repos: NEVER use self-hosted runners (external PRs can access secrets + runner hardware)
- Private repos: OK to use self-hosted runners, but isolate them
Implementation โ
Create runner groups (Organization Settings โ Actions โ Runners):
prod-runners(restricted to deployment repos only)internal-runners(available to all internal repos)- Do NOT allow public repos to use any self-hosted runner
Use machine-type filtering:
yaml# Workflow file runs-on: [self-hosted, prod, linux] # Only runs on labeled self-hosted runnersKeep runners updated:
bash# Self-hosted runner machines sudo apt update && sudo apt upgrade -y # WeeklyMonitor runner usage:
- Go to Organization Settings โ Actions โ Runners
- Check "Recent workflow runs" โ identify unusual activity
- Alert on: unexpected external PR using self-hosted runner
Step 3: Deployment Gates โ
Use GitHub Environments โ
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- run: echo "Deploying to production"Configure Environment Protection Rules โ
- Go to Repository Settings โ Environments โ Add "production"
- Set Required Reviewers: 2 senior engineers (deploys require approval)
- Set Deployment Branches: Only main can deploy to production
- Set Deployment Protection Rules: "Previous deployment must succeed before deploying"
Use Deployment Keys (Not PATs) โ
For automated deployments, create a Deploy Key (repository-scoped SSH key):
# Generate deploy key
ssh-keygen -t ed25519 -f deploy_key -C "deployment"
# Add to repo (Settings โ Deploy keys)
# Use in workflow:
- name: Deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
git clone git@github.com:org/repo.gitWhy Deploy Keys?
- Scoped to one repo only (not org-wide like PAT)
- Cannot access organization resources
- Easier to audit (search repo โ Deploy keys)
Step 4: Audit Logging โ
Monitor Actions Activity โ
# Check if OIDC was used vs secrets
# Audit log entry: "Workflow run deployed" with "token_type": "oidc" vs "secret"Red Flags to Monitor โ
- [ ] Self-hosted runner executing pull request from external user
- [ ] Deployment to production without required approvals (check audit log)
- [ ] Secret creation/rotation by non-admin user
- [ ] Runner group permissions expanded to public repos
Decision Tree โ
Cloud authentication in Actions?
โ Use OIDC (no stored secrets)
Deployment to production?
โ Use GitHub Environment + Required Reviewers
Need runner for heavy compute?
โ Self-hosted runner + runner groups + restrict to private repos only
Secret needed in public repo workflow?
โ STOP. Restructure: use OIDC or separate private deployment repoRelated Study Material โ
- Domain 5: Access Tokens & GitHub Apps
- Domain 5: Enterprise Managed Users (EMU)
- Domain 6: Self-Hosted Runners
- Domain 6: Encrypted Secrets Scope
- Cheatsheet: OIDC Federation
Key Takeaways for Exam Day โ
When faced with a scenario question on the exam:
- Identify the domain โ Is this about identity (2), access (4), security (5), or actions (6)?
- Ask "what's the risk?" โ What's the security/compliance/operational impact?
- Choose least privilege โ The exam rewards answers that minimize access, exposure, or complexity
- Think governance first โ Before implementing anything technical, define the policy
- Know the tradeoffs โ Every choice (GitHub-hosted vs self-hosted, SAML vs SCIM, PAT vs GitHub App) has pros/cons; know them both
โ Overview ยท Concept Map โ ยท Tools Reference โ ยท Exam Guide โ