diff --git a/certifications/github/gh-100/admin-playbook.md b/certifications/github/gh-100/admin-playbook.md new file mode 100644 index 0000000..f5138b7 --- /dev/null +++ b/certifications/github/gh-100/admin-playbook.md @@ -0,0 +1,482 @@ +--- +title: "GH-100 - Admin Playbook" +description: "Real-world GitHub administration scenarios, troubleshooting steps, and decision frameworks for enterprise admins" +head: + - - meta + - name: keywords + content: gh-100, admin playbook, scenarios, troubleshooting, decision framework, github administration, enterprise +--- + +# GH-100: Admin Playbook + +[← Overview](./index.md) · [Concept Map →](./concept-map.md) · [Tools Reference →](./tools-reference.md) · [Exam Guide →](./exam-guide.md) + +::: info 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 `NameID` field? 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) +1. **Wrong ACS URL**: Regenerate SAML certificate, copy the correct ACS URL from GitHub, update IdP +2. **Missing NameID**: Configure IdP to send NameID in SAML assertion (not just email) +3. **Certificate expired**: Regenerate SAML certificate in GitHub (Enterprise Settings → SAML) +4. **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 membership +``` + +### Mitigation +- **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](./domain-2.md) — SAML SSO configuration +- [Exam Guide: Identity Decision Trees](./exam-guide.md#which-identity--authentication-approach) + +--- + +## 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) +1. **Revoke the token immediately** — GitHub Personal Settings → Tokens → delete the exposed token +2. **Alert the organization** — Notify security team, don't announce publicly yet +3. **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) +```bash +# 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 -- --all +``` + +**Why 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 +```bash +git push origin --force-with-lease +git push origin --force-with-lease --tags +``` + +::: warning Coordination 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 +```bash +# Search repo history for any remaining trace +git log -p --all -S "ghp_" | head -20 +# Result should be empty +``` + +#### Step 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.md#scrubbing-sensitive-data-from-git-history) +- [Domain 5: Push Protection vs Secret Scanning](./domain-5.md#push-protection) +- [Cheatsheet: Token Types](./cheatsheet.md#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](#scenario-1-saml-sso-enforcement-breaks-team-access) + +**Issue**: "Repo history is incomplete after migration" +- **Cause**: Shallow clone during migration, or large file filtering +- **Fix**: Re-push with full history: `git push --mirror` instead 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-3.md) +- [Domain 2: Identity Management (SAML + SCIM)](./domain-2.md) +- [Domain 6: Runners (GitHub-hosted vs self-hosted)](./domain-6.md) + +--- + +## 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 +```bash +# 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/Script +``` + +#### Find Over-Privileged Users +1. Go to Organization Settings → Members +2. Sort by role (Owner, Member) +3. Identify **Owners who should be Members** (only product leads and principal engineers should be Owners) +4. 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 | + +::: tip 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) +1. 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) + +2. Grant teams permissions at repo level (not per-user) + +3. 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: +1. Go to Enterprise Settings → Roles +2. Create roles: `Backend Engineer`, `Release Manager`, `Security Reviewer` +3. Assign users to roles; roles grant specific permissions + +#### Automate Role Assignment +Use **GitHub API** to: +```bash +# 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 +```bash +# Export org members and permissions +gh org-permissions export --org $ORG --output members.csv + +# Identify outliers: users with admin who shouldn't +``` + +#### Implement 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 changed` events 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 repos +``` + +### Related Study Material +- [Domain 4: Access & Permissions](./domain-4.md) +- [Domain 4: Repository Permission Levels](./domain-4.md#repository-permission-levels) +- [Cheatsheet: Least Privilege](./cheatsheet.md#admin-core-principles-slg) +- [Exam Guide: Enterprise vs Org Policies](./exam-guide.md#what-should-be-done-first) + +--- + +## 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: +1. A script accidentally logged a database password to build logs (caught by secret scanning, but scary) +2. 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 +```bash +# 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: +```yaml +# 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-1 +``` + +**Benefit**: GitHub generates short-lived (1 hour) STS tokens. No long-lived secrets to rotate. + +#### Restrict Secret Access +1. Go to Organization Settings → Secrets +2. For sensitive secrets (database passwords), restrict to **specific repos only** or **specific environments only** +3. 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 +1. **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 + +2. **Use machine-type filtering**: + ```yaml + # Workflow file + runs-on: [self-hosted, prod, linux] # Only runs on labeled self-hosted runners + ``` + +3. **Keep runners updated**: + ```bash + # Self-hosted runner machines + sudo apt update && sudo apt upgrade -y # Weekly + ``` + +4. **Monitor 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 +```yaml +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: production + url: https://example.com + steps: + - run: echo "Deploying to production" +``` + +#### Configure Environment Protection Rules +1. Go to Repository Settings → Environments → Add "production" +2. Set **Required Reviewers**: 2 senior engineers (deploys require approval) +3. Set **Deployment Branches**: Only main can deploy to production +4. 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): +```bash +# 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.git +``` + +**Why 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 +```bash +# 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 repo +``` + +### Related Study Material +- [Domain 5: Access Tokens & GitHub Apps](./domain-5.md#access-token-types-and-github-apps) +- [Domain 5: Enterprise Managed Users (EMU)](./domain-5.md#enterprise-managed-users) +- [Domain 6: Self-Hosted Runners](./domain-6.md#self-hosted-runners) +- [Domain 6: Encrypted Secrets Scope](./domain-6.md#encrypted-secrets-and-scope) +- [Cheatsheet: OIDC Federation](./cheatsheet.md#terminology-check) + +--- + +## Key Takeaways for Exam Day + +When faced with a scenario question on the exam: + +1. **Identify the domain** — Is this about identity (2), access (4), security (5), or actions (6)? +2. **Ask "what's the risk?"** — What's the security/compliance/operational impact? +3. **Choose least privilege** — The exam rewards answers that minimize access, exposure, or complexity +4. **Think governance first** — Before implementing anything technical, define the *policy* +5. **Know the tradeoffs** — Every choice (GitHub-hosted vs self-hosted, SAML vs SCIM, PAT vs GitHub App) has pros/cons; know them both + +--- + +[← Overview](./index.md) · [Concept Map →](./concept-map.md) · [Tools Reference →](./tools-reference.md) · [Exam Guide →](./exam-guide.md) diff --git a/certifications/github/gh-100/cheatsheet.md b/certifications/github/gh-100/cheatsheet.md index 1ac1c15..6698d03 100755 --- a/certifications/github/gh-100/cheatsheet.md +++ b/certifications/github/gh-100/cheatsheet.md @@ -9,7 +9,7 @@ head: # GH-100: Cheatsheet -[← Overview](./index.md) · [← Exam Guide](./exam-guide.md) +[← Overview](./index.md) · [← Admin Playbook](./admin-playbook.md) · [← Concept Map](./concept-map.md) · [← Tools Reference](./tools-reference.md) · [← Exam Guide](./exam-guide.md) ::: danger Exam Day Reference Review this page 5 minutes before the exam. @@ -73,6 +73,8 @@ Review this page 5 minutes before the exam. | **BFG Repo Cleaner** | Removes secrets from Git history (recommended) | | **filter-branch** | Git-native history rewrite (slower, legacy) | | **Deploy Key** | Repo-scoped SSH key for server/CI access | +| **Environment** | Deployment-scoped approvals, secrets, and branch controls | +| **OIDC** | Short-lived cloud auth without storing long-lived cloud secrets | --- @@ -115,6 +117,12 @@ Review this page 5 minutes before the exam. **Need to access on-prem resources in CI?** → Self-hosted runner +**Need approval gates or protected production secrets?** +→ GitHub Environment + +**Need cloud authentication without storing long-lived credentials?** +→ OIDC federation + **Secret committed to history?** → Revoke first → BFG to purge → GitHub Support if public @@ -144,6 +152,8 @@ Review this page 5 minutes before the exam. - **Runner group**: Access control layer for self-hosted runners — restricts which orgs/repos can use them. - **Reusable workflow**: A `workflow_call`-triggered workflow callable from other workflows to share CI logic. - **Deploy Key**: An SSH key scoped to a single repository. Preferred for read-only server access. +- **Environment**: A deployment target with its own protection rules, secrets, and branch restrictions. +- **OIDC**: OpenID Connect federation for getting short-lived cloud credentials in Actions without storing static secrets. --- diff --git a/certifications/github/gh-100/concept-map.md b/certifications/github/gh-100/concept-map.md new file mode 100644 index 0000000..ac84d7c --- /dev/null +++ b/certifications/github/gh-100/concept-map.md @@ -0,0 +1,311 @@ +--- +title: "GH-100 - Cross-Domain Concept Map" +description: "Visual guide showing how GitHub administration concepts interweave across domains" +head: + - - meta + - name: keywords + content: gh-100, concept map, cross-domain, architecture, github administration +--- + +# GH-100: Cross-Domain Concept Map + +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Tools Reference →](./tools-reference.md) · [Exam Guide →](./exam-guide.md) + +::: info Understanding Domain Relationships +The GH-100 exam tests **individual domains**, but **real-world scenarios** require understanding how domains interact. This map shows the critical connections. +::: + +--- + +## The Big Picture: How Domains Connect + +``` +┌─────────────────────────────────────────────────────────────┐ +│ ENTERPRISE FOUNDATION │ +│ Domain 3: Products (GHEC/GHES), Licensing, Deployment │ +└──────────────────────┬──────────────────────────────────────┘ + │ + ┌──────────────┼──────────────┐ + ↓ ↓ ↓ + ┌─────────┐ ┌────────────┐ ┌──────────┐ + │Domain 2 │ │ Domain 4 │ │ Domain 5 │ + │Identity │→ │Access & │→ │Security &│→ Domain 6 + │& Auth │ │Permissions │ │Compliance│ (Actions) + └────┬────┘ └────┬───────┘ └────┬─────┘ + │ │ │ + └────────────┼──────────────┘ + ↓ + ┌─────────────────────────┐ + │ Domain 1: Support & │ + │ Governance (Cross-all) │ + └─────────────────────────┘ +``` + +--- + +## Domain-by-Domain Relationships + +### Domain 2 (Identity) → The Gatekeeper + +**What it controls**: Who can log in and which GitHub account they use. + +**Flows to Domain 4 (Access)**: +- SAML SSO authenticates users +- Team Sync mirrors IdP groups into GitHub teams +- Teams grant repository permissions (Domain 4) + +``` +IdP (Okta, Azure AD) + ↓ +SAML SSO (Domain 2: Authentication) + ↓ +User is now logged in as @alice + ↓ +Team Sync (Domain 2) mirrors IdP group "Backend-Team" + ↓ +@alice is added to "Backend-Team" GitHub team + ↓ +"Backend-Team" has "write" access to backend-repo + ↓ +@alice can now push to backend-repo (Domain 4) +``` + +**Flows to Domain 5 (Security)**: +- SAML enforcement (Domain 2) ensures only IdP users can access +- EMU (Enterprise Managed Users) locks accounts to company-managed only +- These restrictions prevent unauthorized access to sensitive resources + +--- + +### Domain 4 (Access) → The Gatekeeper of Permissions + +**What it controls**: Who can do what to repos, teams, and organizations. + +**Connects to Domain 2**: +- Permission structure depends on user identity (SAML, EMU, etc.) +- Outside collaborators (Domain 4) bypass org membership but still need identity + +**Flows to Domain 5 (Security)**: +- Repository permission levels determine secret access scope +- Org owners (Domain 4: highest permission) can configure security features (Domain 5) +- Branch protection rules (Domain 4) enforce code review before secrets/sensitive code lands + +``` +Domain 4: Repository Roles +├─ Admin role → Can manage branch protection & enable secret scanning +├─ Maintain role → Can enable CodeQL, configure environments +├─ Write role → Can create/commit but not change permissions +└─ Read role → View-only (lower security risk) + ↓ + Domain 5: Security Features + These features are only as good as the + permissions you grant to who can access them. +``` + +**Flows to Domain 6 (Actions)**: +- Environment protection rules (Domain 4 + Domain 6) require approvals before deployment +- Runner groups (Domain 6) restrict which repos/orgs can use self-hosted runners +- Permission levels determine who can manage GitHub Actions secrets (Domain 6) + +--- + +### Domain 5 (Security) → The Locksmith + +**What it controls**: Detection and prevention of vulnerabilities and secrets. + +**Depends on Domain 4**: +- Secret scanning alerts are viewable only by users with appropriate repo permissions (Domain 4) +- CodeQL results visibility tied to repo access level +- Audit logs (Domain 5) show **who changed permissions** (Domain 4) + +**Flows to Domain 6 (Actions)**: +- GitHub Actions workflows **run** code (Domain 6) +- Secret scanning (Domain 5) detects secrets in commits *before* they reach Actions +- OIDC federation (Domain 5 + Domain 6) eliminates long-lived secrets in workflows +- Push protection (Domain 5) blocks secrets before CI/CD even starts (Domain 6) + +``` +Development Flow: +Developer writes code + ↓ +Push to GitHub + ↓ +Push Protection (Domain 5) blocks if secret detected + ↓ +Workflow triggers (Domain 6) only if push succeeds + ↓ +Workflow needs cloud credentials for deployment + ↓ +OIDC (Domain 5 + Domain 6) provides short-lived token + ↓ +Deployment succeeds without storing long-lived secrets +``` + +**Flows to Domain 2 (via Audit)**: +- Audit logs (Domain 5) record identity changes (SAML updates, user provisioning via SCIM — Domain 2) +- Audit logs show who enabled/disabled security features +- EMU (Domain 2) + Audit logs (Domain 5) = complete identity + action trail + +--- + +### Domain 6 (Actions) → The Executor + +**What it controls**: Automation, CI/CD pipelines, and deployment. + +**Depends on Domain 4**: +- Only users with repo `write` or higher can write workflows +- Runner groups (Domain 6) restricted by org/repo access (Domain 4) + +**Depends on Domain 5**: +- Secrets scope (Domain 5 + Domain 6) controls which workflows can access sensitive data +- Push protection (Domain 5) prevents malicious workflows from committing secrets +- Dependabot security updates (Domain 5) trigger PRs with automated fixes + +**Depends on Domain 2**: +- GitHub App tokens (Domain 6 workflows) use GitHub identity (Domain 2) +- SCIM-provisioned users (Domain 2) can trigger workflows + +``` +Workflow Execution Chain: +User pushes code + ↓ +SAML validates identity (Domain 2) + ↓ +Push protection scans for secrets (Domain 5) + ↓ +Workflow is triggered (Domain 6) + ↓ +Workflow runs on GitHub-hosted or self-hosted runner + ↓ +Workflow accesses org secret (Domain 6) with permission level (Domain 4) + ↓ +Secret scope (Domain 6) determines which repos can use this secret + ↓ +Audit log records "Workflow deployed to production" (Domain 5) +``` + +--- + +## Critical Intersection Points (High Exam Probability) + +These are scenarios where **multiple domains interact**: + +### 1. **Identity + Security + Audit (Domains 2 + 5 + Admin)** +**Scenario**: "A contractor's SAML account was deprovisioned via SCIM (Domain 2). How do you audit what they accessed?" + +**Answer Flow**: +- Check audit log (Domain 5) with filter: `user:contractor-name action:repo.access` +- Verify SCIM deprovisioning (Domain 2) happened correctly +- Review secret access logs (Domain 5) to see if contractor accessed any org secrets +- Related: Domain 1 (governance) — define contractor access review process + +### 2. **Permissions + Secrets + Workflows (Domains 4 + 5 + 6)** +**Scenario**: "A junior dev accidentally has `admin` on the production repo. They can see the database password stored there. What's wrong?" + +**Answer Flow**: +- **Domain 4 issue**: Junior dev should have `write` not `admin` +- **Domain 5 issue**: Database password shouldn't be stored in repo secret; use OIDC + cloud vault (Domain 6) +- **Domain 6 issue**: Production workflows should not run on commits from junior devs +- **Fix**: Reduce permission (Domain 4) + migrate to OIDC (Domain 5/6) + environment protection rules (Domain 4/6) + +### 3. **Authentication Enforcement + Access Control (Domains 2 + 4)** +**Scenario**: "We enforced SAML SSO last night. 30% of teams can't access their repos today." + +**Answer Flow**: +- **Domain 2 diagnosis**: SAML enforcement blocks non-SAML users +- **Domain 4 impact**: Outside collaborators (who bypass org SAML) are now blocked from non-member repos +- **Domain 2 fix**: Review which accounts are SAML-linked; outside collaborators need special handling +- **Domain 4 mitigation**: Temporarily remove outside collaborators from SAML enforcement or migrate them + +### 4. **Deployments + Identity + Secrets (Domains 6 + 2 + 5)** +**Scenario**: "We want production deployments to only work for core team members, with no stored secrets." + +**Answer Flow**: +- **Domain 2**: EMU or SCIM ensures only company-managed accounts exist +- **Domain 6**: GitHub Environment with required reviewers (must be core team) +- **Domain 5**: OIDC federation to get temporary cloud credentials (no secrets stored) +- **Domain 6**: Self-hosted runner in VPC (isolate from internet) +- **Result**: Deployment is identity-verified (Domain 2), gated (Domain 6), and credential-safe (Domain 5) + +--- + +## The "Dependency Chain" — Questions You'll See + +**Question Type**: "To accomplish X, which must come first?" + +### Example 1: Secret Scanning → Audit Logging +``` +Goal: "We need to prove to auditors that secrets are scanned" +Step 1 (Domain 5): Enable secret scanning (repo-level) +Step 2 (Domain 5): Push a test credential, verify alert fires +Step 3 (Domain 5): Enable audit logging (org-level) +Step 4 (Domain 5): Query audit log for "secret.push_protection_bypass" +Exam question: "To audit secret scanning enforcement, which comes first?" +Answer: Audit logging is useless without secret scanning enabled first. +``` + +### Example 2: SAML + Team Sync +``` +Goal: "Sync Azure AD groups to GitHub teams" +Step 1 (Domain 2): Enable SAML SSO +Step 2 (Domain 2): Enable Team Sync +Step 3 (Domain 2): Ensure IdP sends group claims in SAML assertion +Exam question: "Team Sync isn't mirroring groups. You've checked IdP. What's next?" +Answer: Verify SAML is working first; team sync depends on successful SAML authentication. +``` + +### Example 3: Runners + Security + Permissions +``` +Goal: "Use self-hosted runners for production, safely" +Step 1 (Domain 4): Create runner group, restrict to production repo only +Step 2 (Domain 6): Deploy self-hosted runner in private VPC (not internet-accessible) +Step 3 (Domain 5): Disable public workflows from using this runner +Step 4 (Domain 6): Use OIDC to avoid storing cloud credentials in GitHub Secrets +Exam question: "Self-hosted runner was compromised. Which protection failed first?" +Answer: If it was exposed to the internet, Step 2 failed. If public PR used it, Step 3 failed. +``` + +--- + +## Study Strategy: Using the Concept Map + +### By Domain Weight + +| Domain | Weight | Key Connections | Study Priority | +|--------|--------|---|---| +| **5** | 36% | Hub connecting to 2, 4, 6 | Master thoroughly; see how it touches other domains | +| **4** | 18% | Gateway between 2, 5, 6 | Understand permission scope deeply | +| **6** | 16% | Executor; depends on 2, 4, 5 | Know security requirements *before* deploying | +| **2** | 11% | Gatekeeper; upstream of 4 | Understand identity flow impact on access | +| **1, 3** | 9% | Support + governance (cross-domain) | Use these to frame other domains | + +### By Study Method + +**If you're a visual learner**: +- Trace the flow: Identity → Access → Security → Actions +- For each scenario, follow the chain of command/dependencies + +**If you're a logical learner**: +- Learn Domain 2 first (who can log in?) +- Then Domain 4 (what can they do?) +- Then Domain 5 (how do we protect it?) +- Then Domain 6 (how do we automate it?) + +**If you're a practical learner**: +- Work through [Admin Playbook scenarios](./admin-playbook.md) +- Pause at each step and ask: "Which domain handles this?" + +--- + +## Key Takeaway: Domains Don't Exist in Isolation + +- **Domain 2 without Domain 4** = Identity but no access control (useless) +- **Domain 4 without Domain 5** = Permissions but no security (vulnerable) +- **Domain 5 without Domain 6** = Security but no automation (manual and error-prone) +- **Domain 6 without Domains 2+4+5** = Automation but no governance (dangerous) + +**Exam tip**: If an answer isolates a single domain and ignores dependencies, it's likely wrong. Real admin decisions require thinking across domains. + +--- + +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Tools Reference →](./tools-reference.md) · [Exam Guide →](./exam-guide.md) diff --git a/certifications/github/gh-100/domain-4.md b/certifications/github/gh-100/domain-4.md index fff93ca..9a86391 100644 --- a/certifications/github/gh-100/domain-4.md +++ b/certifications/github/gh-100/domain-4.md @@ -142,6 +142,19 @@ The **most permissive** permission that applies wins. When a question asks how to give a user "the minimum required permissions," the answer involves checking their team memberships and only granting what's needed for the task — never defaulting to Admin or Write if Read or Triage suffices. ::: +### Custom Organization Roles and Custom Repository Roles + +On **GitHub Enterprise Cloud**, admins can go beyond the built-in roles: + +- **Custom organization roles** let you delegate selected administrative capabilities without making someone a full owner +- **Custom repository roles** let you create a more granular role by extending a base repository role with additional capabilities + +This is useful when the built-in roles are either too weak or too broad. + +::: tip Exam Tip +If the scenario is "delegate one narrow admin capability without full ownership," think **custom organization role**. If it is "grant repo access that sits between built-in repo roles," think **custom repository role**. +::: + --- ## Least Privilege in Practice diff --git a/certifications/github/gh-100/domain-5.md b/certifications/github/gh-100/domain-5.md index f962437..dff8ab2 100644 --- a/certifications/github/gh-100/domain-5.md +++ b/certifications/github/gh-100/domain-5.md @@ -228,6 +228,18 @@ GitHub supports multiple token types. The exam tests your knowledge of when and - **GitHub App Installation Token**: 5,000 requests/hour per installation + 15,000 requests/hour at enterprise level - **Unauthenticated**: 60 requests/hour +### PAT Policies and Approval Controls + +Organizations can place guardrails around PAT usage: + +- Require approval for **fine-grained PATs** before they can access organization resources +- Restrict or block **classic PAT** access to org-owned resources +- Use shorter lifetimes for user-scoped credentials where policy allows + +::: warning Trap +Fine-grained PATs are safer than classic PATs, but for machine identity the exam still prefers **GitHub Apps** over either PAT model. +::: + --- ## GitHub Apps vs OAuth Apps diff --git a/certifications/github/gh-100/domain-6.md b/certifications/github/gh-100/domain-6.md index af32773..855906a 100644 --- a/certifications/github/gh-100/domain-6.md +++ b/certifications/github/gh-100/domain-6.md @@ -210,6 +210,44 @@ For high-security environments, secrets can be stored externally and retrieved a secret/data/prod db_password | DB_PASSWORD ``` +--- + +## Environments and Deployment Protection Rules + +GitHub **Environments** add policy controls around deployments. + +### What Environments Can Enforce + +- **Required reviewers** before deployment jobs continue +- **Wait timers** before deployment begins +- **Branch and tag restrictions** so only approved refs can deploy +- **Custom deployment protection rules** via GitHub Apps + +### Environment Secrets + +- Environment secrets are available only to jobs that target that environment +- If approvals are required, the job does not receive those secrets until the protection gate passes + +::: tip Exam Tip +If the question is about protecting production deployments, adding approval gates, or scoping secrets to production only, the answer often involves a **GitHub Environment**, not just a repository secret. +::: + +--- + +## OIDC for Cloud Authentication + +GitHub Actions can use **OpenID Connect (OIDC)** to authenticate to cloud providers without storing long-lived cloud credentials in GitHub. + +- The workflow requests an identity token from GitHub +- The cloud provider trusts GitHub as an identity provider +- The workflow exchanges that token for short-lived credentials + +Common examples include AWS, Azure, GCP, Vault, and package registries that support trusted publishing. + +::: tip Exam Tip +If the question is "how do we avoid storing long-lived cloud secrets in GitHub Actions?", the strongest answer is usually **OIDC federation**. +::: + diff --git a/certifications/github/gh-100/exam-guide.md b/certifications/github/gh-100/exam-guide.md index 2c60e2c..67e5395 100755 --- a/certifications/github/gh-100/exam-guide.md +++ b/certifications/github/gh-100/exam-guide.md @@ -9,7 +9,7 @@ head: # GH-100: Exam Guide -[← Overview](./index.md) · [Cheatsheet →](./cheatsheet.md) +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Cheatsheet →](./cheatsheet.md) --- @@ -45,6 +45,8 @@ The GH-100 exam is for **GitHub Administrators** (system administrators, IT prof | "Isolate runner access by team or org" | **Runner groups** | | "Store secrets outside GitHub" | **Third-party vault** (HashiCorp Vault, etc.) | | "Enforce policy across all organizations" | **Enterprise policy** (not org policy) | +| "Approval gate before production deployment" | **GitHub Environment** | +| "Cloud auth without long-lived secrets" | **OIDC federation** | --- @@ -58,6 +60,8 @@ The GH-100 exam is for **GitHub Administrators** (system administrators, IT prof - **filter-branch vs BFG**: Both remove sensitive data from Git history. **BFG Repo Cleaner** is faster, simpler, and recommended for large repositories. `git filter-branch` is the older built-in Git approach — correct but slow. - **Org-level vs Enterprise-level policies**: Enterprise policies **override** org-level settings. If the question asks how to enforce a rule across all organizations in an enterprise, the answer is an enterprise policy — not configuring each org individually. - **PAT vs GitHub App for machine accounts**: The exam prefers **GitHub Apps** for machine/bot accounts — they have installable, scoped permissions, don't expire by default, and aren't tied to a specific user's account lifecycle. +- **Repository secret vs Environment secret**: Environment secrets sit behind deployment controls like required reviewers and branch restrictions. Use them when the scenario is specifically about protected deployments. +- **Stored cloud credential vs OIDC**: If the goal is to avoid long-lived cloud credentials in Actions, prefer **OIDC federation** over storing another secret in GitHub. ::: --- @@ -93,6 +97,13 @@ Custom hardware, on-prem resources, IP restrictions → Self-hosted runner Restrict runner access by team or org → Runner groups ``` +### "How should I secure a deployment?" +``` +Need approval before production deploys → GitHub Environment with required reviewers +Need to limit which branches can deploy → Environment branch/tag restrictions +Need cloud auth without long-lived credentials → OIDC federation +``` + ### "What should be done first?" ``` Always: Define enterprise policy, assess org structure, establish governance @@ -117,4 +128,4 @@ Unauthorized app access → OAuth/GitHub App approval policy --- -[← Overview](./index.md) · [Cheatsheet →](./cheatsheet.md) +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Concept Map →](./concept-map.md) · [Tools Reference →](./tools-reference.md) · [Cheatsheet →](./cheatsheet.md) diff --git a/certifications/github/gh-100/index.md b/certifications/github/gh-100/index.md old mode 100755 new mode 100644 index 5319dea..e9804e1 --- a/certifications/github/gh-100/index.md +++ b/certifications/github/gh-100/index.md @@ -14,7 +14,11 @@ An intermediate-level certification for system administrators, software develope **Exam**: 100 min · Intermediate level · Pearson VUE (proctored) · Valid 2 years ::: info This is a governance and administration exam -Think like a GitHub Enterprise Admin. Questions focus on access control, security policy, compliance, identity management, and automation — not day-to-day developer workflows. +Think like a GitHub Enterprise Admin. Questions focus on access control, security policy, compliance, identity management, and automation, not day-to-day developer workflows. +::: + +::: tip Official blueprint note +These notes follow the **live GH-100 certification page**. As of **March 17, 2026**, the official exam page lists **6 measured domains** under "Assessed on this exam." ::: - + + + --- @@ -42,67 +46,76 @@ A podcast-style walkthrough of key exam tactics — generated using [NotebookLM] { id: 'domain-1', label: 'Domain 1: Support GitHub Enterprise (9%)', + link: 'https://docs.github.com/github/working-with-github-support/about-github-support', children: [ - { id: 'd1-admin-support', label: 'Admin vs GitHub Support boundaries' }, - { id: 'd1-diagnostics', label: 'Support bundles & diagnostics' }, - { id: 'd1-workflows', label: 'Developer workflow standards' }, - { id: 'd1-marketplace', label: 'GitHub Marketplace & App vs Action' }, - { id: 'd1-api', label: 'GitHub APIs for admin tasks' } + { id: 'd1-admin-support', label: 'Admin vs GitHub Support boundaries', link: 'https://docs.github.com/github/working-with-github-support/about-github-support' }, + { id: 'd1-diagnostics', label: 'Support bundles & diagnostics', link: 'https://docs.github.com/en/enterprise-server%403.20/support/contacting-github-support/providing-data-to-github-support' }, + { id: 'd1-workflows', label: 'Developer workflow standards', link: 'https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches' }, + { id: 'd1-marketplace', label: 'Marketplace Apps vs Actions', link: 'https://docs.github.com/en/actions/get-started/actions-vs-apps' }, + { id: 'd1-api', label: 'GitHub APIs for admin tasks', link: 'https://docs.github.com/en/rest' } ] }, { id: 'domain-2', label: 'Domain 2: Manage User Identities & Authentication (11%)', + link: 'https://docs.github.com/articles/about-authentication-with-saml-single-sign-on', children: [ - { id: 'd2-saml', label: 'SAML SSO (org vs enterprise)' }, - { id: 'd2-2fa', label: '2FA enforcement' }, - { id: 'd2-scim', label: 'SCIM provisioning & providers' }, - { id: 'd2-teamsync', label: 'Team synchronization vs SCIM' } + { id: 'd2-saml', label: 'SAML SSO (org vs enterprise)', link: 'https://docs.github.com/github/setting-up-and-managing-your-enterprise/configuring-identity-and-access-management-for-your-enterprise-account' }, + { id: 'd2-2fa', label: '2FA enforcement', link: 'https://docs.github.com/articles/about-two-factor-authentication-and-saml-single-sign-on' }, + { id: 'd2-scim', label: 'SCIM provisioning & providers', link: 'https://docs.github.com/admin/identity-and-access-management/provisioning-user-accounts-for-enterprise-managed-users' }, + { id: 'd2-teamsync', label: 'Team synchronization vs SCIM', link: 'https://docs.github.com/en/organizations/managing-saml-single-sign-on-for-your-organization/managing-team-synchronization-for-your-organization' } ] }, { id: 'domain-3', label: 'Domain 3: Deployment, Distribution & Licensing (9%)', + link: 'https://docs.github.com/en/billing/managing-billing-for-your-products/about-billing-for-github-actions', children: [ - { id: 'd3-products', label: 'GHEC vs GHES vs GHAE' }, - { id: 'd3-pricing', label: 'Actions & Packages pricing' }, - { id: 'd3-licenses', label: 'License usage statistics' } + { id: 'd3-products', label: 'GHEC vs GHES vs managed isolation', link: 'https://learn.microsoft.com/en-us/credentials/certifications/github-administration/?practice-assessment-type=certification' }, + { id: 'd3-pricing', label: 'Actions & Packages pricing', link: 'https://docs.github.com/en/billing/managing-billing-for-your-products/about-billing-for-github-actions' }, + { id: 'd3-licenses', label: 'License usage statistics', link: 'https://docs.github.com/github/setting-up-and-managing-your-enterprise-account/managing-users-in-your-enterprise-account' } ] }, { id: 'domain-4', label: 'Domain 4: Access & Permissions (18%)', + link: 'https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization', children: [ - { id: 'd4-orgs', label: 'Single org vs multiple orgs' }, - { id: 'd4-roles', label: 'Org roles & outside collaborators' }, - { id: 'd4-teams', label: 'Team permissions & AD sync' }, - { id: 'd4-repo', label: 'Repository permission levels' } + { id: 'd4-orgs', label: 'Single org vs multiple orgs', link: 'https://docs.github.com/en/enterprise-cloud%40latest/admin/managing-accounts-and-repositories/managing-repositories-in-your-enterprise/configuring-the-repository-visibility-policy-in-your-enterprise' }, + { id: 'd4-roles', label: 'Org roles & outside collaborators', link: 'https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization' }, + { id: 'd4-teams', label: 'Team permissions & repo roles', link: 'https://docs.github.com/organizations/organizing-members-into-teams/about-teams' }, + { id: 'd4-repo', label: 'Repository permission levels', link: 'https://docs.github.com/organizations/managing-user-access-to-your-organizations-repositories/repository-roles-for-an-organization' } ] }, { id: 'domain-5', - label: 'Domain 5: Secure Software Development & Compliance (36%)', + label: 'Domain 5: Secure Development & Compliance (36%)', + link: 'https://docs.github.com/en/code-security', children: [ - { id: 'd5-scanning', label: 'Secret scanning & code scanning (CodeQL)' }, - { id: 'd5-dependabot', label: 'Dependabot & dependency graph' }, - { id: 'd5-auditlog', label: 'Audit log APIs (REST & GraphQL)' }, - { id: 'd5-tokens', label: 'Access tokens & GitHub Apps vs OAuth Apps' }, - { id: 'd5-emu', label: 'Enterprise Managed Users (EMU)' }, - { id: 'd5-scrub', label: 'Scrubbing sensitive data (BFG/filter-branch)' } + { id: 'd5-scanning', label: 'Secret scanning & code scanning (CodeQL)', link: 'https://docs.github.com/en/code-security/secret-scanning/working-with-secret-scanning-and-push-protection' }, + { id: 'd5-dependabot', label: 'Dependabot & dependency graph', link: 'https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph' }, + { id: 'd5-auditlog', label: 'Audit log APIs', link: 'https://docs.github.com/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization' }, + { id: 'd5-tokens', label: 'Access tokens & GitHub Apps vs OAuth Apps', link: 'https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/deciding-when-to-build-a-github-app' }, + { id: 'd5-emu', label: 'Enterprise Managed Users (EMU)', link: 'https://docs.github.com/admin/authentication/managing-your-enterprise-users-with-your-identity-provider/about-enterprise-managed-users' }, + { id: 'd5-scrub', label: 'Scrubbing sensitive data from history', link: 'https://docs.github.com/code-security/secret-scanning/working-with-secret-scanning-and-push-protection' } ] }, { id: 'domain-6', label: 'Domain 6: Manage GitHub Actions (16%)', + link: 'https://docs.github.com/en/actions/concepts/runners', children: [ - { id: 'd6-runners', label: 'GitHub-hosted vs self-hosted runners' }, - { id: 'd6-runnergroups', label: 'Runner groups & IP allow lists' }, - { id: 'd6-secrets', label: 'Encrypted secrets scope & access' }, - { id: 'd6-reusable', label: 'Reusable workflows & enterprise distribution' }, - { id: 'd6-packages', label: 'GitHub Packages (types, workflows, vs releases)' } + { id: 'd6-runners', label: 'GitHub-hosted vs self-hosted runners', link: 'https://docs.github.com/en/actions/concepts/runners' }, + { id: 'd6-runnergroups', label: 'Runner groups & IP allow lists', link: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-access-to-self-hosted-runners-using-groups' }, + { id: 'd6-secrets', label: 'Encrypted secrets scope & access', link: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions' }, + { id: 'd6-reusable', label: 'Reusable workflows & enterprise distribution', link: 'https://docs.github.com/en/actions/using-workflows/reusing-workflows' }, + { id: 'd6-packages', label: 'GitHub Packages in workflows', link: 'https://docs.github.com/packages/learn-github-packages/introduction-to-github-packages' } ] }, { id: 'exam-guide', label: 'Reviewed exam guide & traps' }, + { id: 'admin-playbook', label: 'Worked through admin playbook scenarios' }, + { id: 'concept-map', label: 'Studied cross-domain relationships' }, + { id: 'tools-reference', label: 'Reviewed CLI & API reference' }, { id: 'cheatsheet', label: 'Reviewed cheatsheet' }, { id: 'ready', label: 'Ready for exam' } ]" @@ -112,9 +125,8 @@ A podcast-style walkthrough of key exam tactics — generated using [NotebookLM] ## Official Resources -- [GH-100 Exam Page](https://learn.microsoft.com/en-us/credentials/certifications/github-administration/) +- [GH-100 Exam Page](https://learn.microsoft.com/en-us/credentials/certifications/github-administration/?practice-assessment-type=certification) - [GH-100 Study Guide](https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/gh-100) -- [Exam Sandbox Demo](https://GHCertDemo.starttest.com) - [GitHub Enterprise Documentation](https://docs.github.com/en/enterprise-cloud@latest) ## External Resources @@ -122,7 +134,9 @@ A podcast-style walkthrough of key exam tactics — generated using [NotebookLM] - [GitHub Skills](https://skills.github.com/) - [GitHub Learning Pathways](https://resources.github.com/learn/pathways/) - [Microsoft Learn: GitHub Administration Path](https://learn.microsoft.com/en-us/training/browse/?products=github) +- [ExamTopics GH-100](https://www.examtopics.com/exams/microsoft/gh-100/) — offers a set of free verified practice questions (note: some questions beyond the free tier require login) +- [EduSum GH-100 Sample Questions](https://www.edusum.com/microsoft/microsoft-github-administration-gh-100-certification-sample-questions) — free sample questions representing the real exam style --- -[Start Study Notes →](./domain-1.md) · [Cheatsheet →](./cheatsheet.md) +[Start Study Notes →](./domain-1.md) · [Admin Playbook →](./admin-playbook.md) · [Concept Map →](./concept-map.md) · [Tools Reference →](./tools-reference.md) · [Cheatsheet →](./cheatsheet.md) diff --git a/certifications/github/gh-100/tools-reference.md b/certifications/github/gh-100/tools-reference.md new file mode 100644 index 0000000..886cf55 --- /dev/null +++ b/certifications/github/gh-100/tools-reference.md @@ -0,0 +1,589 @@ +--- +title: "GH-100 - Tools & CLI Reference" +description: "Command-line tools, APIs, and scripts for GitHub administration tasks" +head: + - - meta + - name: keywords + content: gh-100, tools, cli, rest api, graphql, github enterprise, administration, commands +--- + +# GH-100: Tools & CLI Reference + +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Concept Map →](./concept-map.md) · [Exam Guide →](./exam-guide.md) + +::: info Hands-On Reference for Exam Prep +This page documents real commands and APIs you'll use as a GitHub administrator. Familiarity with these tools strengthens exam confidence. +::: + +--- + +## GitHub CLI (gh) — The Modern Admin Tool + +The **GitHub CLI** is the recommended way to manage GitHub from the command line. + +### Installation +```bash +# macOS (Homebrew) +brew install gh + +# Linux (Debian/Ubuntu) +sudo apt-get install gh + +# Verify installation +gh --version +``` + +### Authentication +```bash +# Authenticate with GitHub +gh auth login + +# Select: GitHub.com +# Select: HTTPS or SSH (HTTPS recommended) +# Paste your Personal Access Token (PAT) when prompted +# Select: GitHub CLI + +# Verify authentication +gh auth status +``` + +--- + +## Essential gh Commands for Admins + +### Organization Management + +```bash +# List all org members +gh org-members list --org $ORG + +# Export org members to CSV +gh api -X GET /orgs/$ORG/members --paginate --jq '.[] | [.login, .id, .type]' > members.csv + +# Promote user to org owner +gh api -X PUT /orgs/$ORG/members/$USERNAME/role -f role=admin + +# Demote owner to member +gh api -X PUT /orgs/$ORG/members/$USERNAME/role -f role=member + +# Remove user from org +gh api -X DELETE /orgs/$ORG/members/$USERNAME +``` + +### Repository Management + +```bash +# List all repos in an org +gh repo list $ORG --limit 1000 --json name,url,isPrivate + +# Export repos with permission info +gh repo list $ORG --limit 1000 --json name,visibility,pushedAt + +# Enable secret scanning on a repo +gh api -X PATCH /repos/$ORG/$REPO -f security_and_analysis='{"secret_scanning":{"status":"enabled"}}' + +# Enable push protection +gh api -X PATCH /repos/$ORG/$REPO -f security_and_analysis='{"secret_scanning_push_protection":{"status":"enabled"}}' + +# Require pull request reviews on main branch +gh api -X PUT /repos/$ORG/$REPO/branches/main/protection \ + -f required_pull_request_reviews='{"required_approving_review_count":2}' + +# Add team to repo with permission level +gh api -X PUT /repos/$ORG/$REPO/teams/$TEAM_SLUG -f permission=write +``` + +### Team Management + +```bash +# List all teams in an org +gh api -X GET /orgs/$ORG/teams --paginate + +# Add user to team +gh api -X PUT /orgs/$ORG/teams/$TEAM_SLUG/memberships/$USERNAME -f role=member + +# List team members +gh api -X GET /orgs/$ORG/teams/$TEAM_SLUG/members + +# Grant team repo access +gh api -X PUT /repos/$ORG/$REPO/teams/$TEAM_SLUG -f permission=write + +# Remove team from repo +gh api -X DELETE /repos/$ORG/$REPO/teams/$TEAM_SLUG +``` + +### Audit Log Queries + +```bash +# Export org audit log (last 90 days) +gh api -X GET /orgs/$ORG/audit-log --paginate -f include=all > audit-log.json + +# Filter audit log with jq (see below) +gh api -X GET /orgs/$ORG/audit-log --paginate -f include=all | \ + jq '.[] | select(.action=="repo.destroy") | {actor: .actor.login, timestamp: .created_at, repo: .data.repository}' + +# Search for secret scanning bypasses +gh api -X GET /orgs/$ORG/audit-log --paginate | \ + jq '.[] | select(.action | contains("secret"))' + +# Identify users who changed permissions +gh api -X GET /orgs/$ORG/audit-log --paginate | \ + jq '.[] | select(.action | contains("member")) | {user: .actor.login, action: .action, target: .user.login}' +``` + +--- + +## REST API — Core Admin Operations + +### Base URL +``` +https://api.github.com +``` + +### Authentication +```bash +# Using curl with PAT +curl -H "Authorization: token $GH_TOKEN" https://api.github.com/user + +# Using gh CLI (handles auth automatically) +gh api +``` + +### Organization Endpoints + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/orgs/$ORG/members` | GET | List org members | +| `/orgs/$ORG/members/$USERNAME` | PUT/DELETE | Add/remove member | +| `/orgs/$ORG/audit-log` | GET | Query audit log | +| `/orgs/$ORG/teams` | GET/POST | List/create teams | +| `/orgs/$ORG/teams/$TEAM_SLUG/members` | GET/PUT/DELETE | Manage team membership | +| `/orgs/$ORG/secrets` | GET | List org secrets | + +### Repository Endpoints + +| Endpoint | Method | Purpose | +|----------|--------|---------| +| `/repos/$ORG/$REPO/vulnerability-alerts` | GET | List Dependabot alerts | +| `/repos/$ORG/$REPO/secret-scanning/alerts` | GET | List secret scanning alerts | +| `/repos/$ORG/$REPO/code-scanning/alerts` | GET | List CodeQL alerts | +| `/repos/$ORG/$REPO/branches/BRANCH/protection` | GET/PUT | Manage branch protection | +| `/repos/$ORG/$REPO/teams` | GET | List teams with repo access | + +### Example: Exporting All Repos with Their Security Status + +```bash +gh api -X GET /orgs/$ORG/repos --paginate \ + --jq '.[] | {name: .name, secret_scanning: .security_and_analysis.secret_scanning.status, push_protection: .security_and_analysis.secret_scanning_push_protection.status}' \ + | jq -s 'sort_by(.name)' > security-status.json +``` + +--- + +## GraphQL — Advanced Queries + +GitHub's **GraphQL API** allows complex, nested queries in a single request. + +### Basic Query Structure +```graphql +query { + organization(login: "your-org") { + name + members(first: 100) { + edges { + node { + login + name + } + } + } + } +} +``` + +### Running GraphQL Queries + +```bash +# Using gh CLI +gh api graphql -f query=' + query { + organization(login: "'$ORG'") { + name + members(first: 10) { + edges { + node { + login + } + } + } + } + } +' + +# Save to file for reuse +cat > query.graphql << 'EOF' +query { + organization(login: "your-org") { + teams(first: 100) { + edges { + node { + name + members(first: 100) { + totalCount + } + } + } + } + } +} +EOF + +gh api graphql --input query.graphql +``` + +### Example: Audit Log via GraphQL + +```graphql +query { + organization(login: "your-org") { + auditLog(first: 100, query: "action:repo.destroy") { + edges { + node { + action + actor { + login + } + createdAt + ... on AuditLogEvent { + resourcePath + } + } + } + } + } +} +``` + +--- + +## jq — JSON Processing for Audit Logs & API Responses + +**jq** is a powerful JSON query tool. Essential for parsing audit logs and API responses. + +### Installation +```bash +# macOS +brew install jq + +# Linux +sudo apt-get install jq +``` + +### Common Patterns for Admin Tasks + +#### Filter audit log for specific action +```bash +# Find all "repo.destroy" events +gh api /orgs/$ORG/audit-log --paginate | jq '.[] | select(.action=="repo.destroy")' + +# Find secret scanning bypasses +gh api /orgs/$ORG/audit-log --paginate | jq '.[] | select(.action | contains("secret_scanning"))' +``` + +#### Extract specific fields +```bash +# Get login, action, and timestamp +gh api /orgs/$ORG/audit-log --paginate | jq '.[] | {user: .actor.login, action, created_at}' +``` + +#### Count events by action +```bash +gh api /orgs/$ORG/audit-log --paginate | jq 'group_by(.action) | map({action: .[0].action, count: length}) | sort_by(.count) | reverse' +``` + +#### Filter by date +```bash +# Events from the last 7 days +gh api /orgs/$ORG/audit-log --paginate | jq " + now as \$now | + .[] | + select((.created_at | fromdateiso8601) > (\$now - 604800)) +" +``` + +#### Identify over-privileged users +```bash +# Find users with "owner" role +gh api /orgs/$ORG/members --paginate | jq '.[] | select(.role=="admin") | .login' +``` + +--- + +## GitHub Enterprise Server (GHES) — Admin Tools + +### Support Bundle (Diagnostics) + +```bash +# SSH into GHES appliance +ssh admin@github.example.com + +# Generate support bundle +ghe-support-bundle -o /tmp/support-bundle.tar.gz + +# The bundle includes: +# - System logs +# - Configuration files (sanitized) +# - Diagnostics (disk space, memory, processes) +# - Database stats +# - Git operations stats + +# SCP bundle to local machine for analysis +scp admin@github.example.com:/tmp/support-bundle.tar.gz . + +# Extract and review +tar -xzf support-bundle.tar.gz +ls -la support-bundle/ +cat support-bundle/diagnostics.json +``` + +### Common GHES Admin Commands + +```bash +# Check GHES version +ssh admin@github.example.com ghe-version + +# Check system health +ssh admin@github.example.com ghe-health-check + +# Manage services +ssh admin@github.example.com ghe-service-status +ssh admin@github.example.com ghe-service-stop +ssh admin@github.example.com ghe-service-start + +# Reindex search +ssh admin@github.example.com ghe-es-index-rebuild + +# Backup GHES +ssh admin@github.example.com ghe-backup + +# Restore from backup +ssh admin@github.example.com ghe-restore 192.168.1.100 BACKUP_SNAPSHOT +``` + +--- + +## Secret Management & History Scrubbing + +### BFG Repo Cleaner (Recommended for Removing Secrets) + +```bash +# Install BFG +brew install bfg # macOS +sudo apt-get install bfg # Linux + +# Create a list of secrets to remove +cat > secrets.txt << 'EOF' +ghp_xxxxxxxxxxxxxxxxxxx +sk_live_xxxxxxxxxxxxx +dB_PASSWORD= +EOF + +# Mirror the repo (no working directory, just objects) +git clone --mirror https://github.com/$ORG/$REPO.git $REPO.git + +# Use BFG to remove secrets +bfg --replace-text secrets.txt $REPO.git + +# Remove BFG's reflog to finalize +cd $REPO.git +git reflog expire --expire=now --all +git gc --prune=now --aggressive + +# Force-push cleaned history +git push --force-with-lease + +# Everyone must re-clone +``` + +### Git Filter-Branch (Legacy but Valid) + +```bash +# Remove a file from all commits +git filter-branch --force --index-filter \ + 'git rm --cached --ignore-unmatch config/secrets.yml' \ + --prune-empty --tag-name-filter cat -- --all + +# Remove lines matching a pattern +git filter-branch --force -f \ + --tree-filter 'sed -i "/password=/d" config.env' \ + --prune-empty -- --all + +# After filtering, force-push +git push origin --force-with-lease --all +``` + +--- + +## Audit Log Streaming (Advanced) + +### Export Audit Log to SIEM (Splunk, Datadog, etc.) + +```bash +# Fetch and stream audit log to Splunk HTTP Event Collector +curl -H "Authorization: Splunk $SPLUNK_HEC_TOKEN" \ + -X POST https://splunk.example.com:8088/services/collector \ + -d @audit-log.json +``` + +### Webhook-Based Audit Log Ingestion + +```bash +# GitHub can send audit log events to a webhook +# Configure in Enterprise Settings → Audit Log → Webhook configuration + +# Example webhook receiver (Node.js) +const express = require('express'); +const crypto = require('crypto'); + +app.post('/webhook', (req, res) => { + // Verify GitHub signature + const signature = req.headers['x-hub-signature-256']; + const payload = JSON.stringify(req.body); + const hash = 'sha256=' + crypto + .createHmac('sha256', WEBHOOK_SECRET) + .update(payload) + .digest('hex'); + + if (signature !== hash) return res.status(401).send('Unauthorized'); + + // Process audit log event + const auditLog = req.body.audit_log; + console.log(`Action: ${auditLog.action}, User: ${auditLog.actor.login}`); + + res.status(200).send('OK'); +}); +``` + +--- + +## Useful Admin Scripts + +### Bulk Enable Secret Scanning Across Organization + +```bash +#!/bin/bash +ORG=$1 + +# Get all repos +REPOS=$(gh repo list $ORG --limit 1000 -q '.[] | .name') + +for REPO in $REPOS; do + echo "Enabling secret scanning on $REPO..." + gh api -X PATCH /repos/$ORG/$REPO \ + -f security_and_analysis='{"secret_scanning":{"status":"enabled"}}' 2>/dev/null && \ + echo "✓ $REPO" || echo "✗ $REPO (might be archived or private)" +done +``` + +### Identify Users with Admin Access on Multiple Repos + +```bash +#!/bin/bash +ORG=$1 + +# Get all repos +REPOS=$(gh repo list $ORG --limit 1000 -q '.[] | .name') + +# Store results +declare -A ADMIN_USERS + +for REPO in $REPOS; do + # Get collaborators with admin access + ADMINS=$(gh api /repos/$ORG/$REPO/collaborators --paginate | \ + jq -r '.[] | select(.permissions.admin==true) | .login') + + for ADMIN in $ADMINS; do + ADMIN_USERS[$ADMIN]=$((${ADMIN_USERS[$ADMIN]:-0} + 1)) + fi +done + +# Print users with admin on multiple repos +for USER in "${!ADMIN_USERS[@]}"; do + if [ ${ADMIN_USERS[$USER]} -gt 1 ]; then + echo "$USER: ${ADMIN_USERS[$USER]} repos" + fi +done | sort -t: -k2 -rn +``` + +### Audit Team Permissions Matrix + +```bash +#!/bin/bash +ORG=$1 + +echo "Team,Repository,Permission" > permissions.csv + +TEAMS=$(gh api /orgs/$ORG/teams --paginate -q '.[] | .slug') + +for TEAM in $TEAMS; do + REPOS=$(gh api /orgs/$ORG/teams/$TEAM/repos --paginate -q '.[] | .name') + + for REPO in $REPOS; do + PERMS=$(gh api /repos/$ORG/$REPO/teams/$TEAM -q '.permission') + echo "$TEAM,$REPO,$PERMS" >> permissions.csv + fi +done + +echo "Saved to permissions.csv" +``` + +--- + +## Troubleshooting: Common Command Patterns + +### Check Authentication +```bash +# Verify gh auth +gh auth status + +# Test API access +gh api /user +``` + +### Debug API Calls +```bash +# Add verbose flag to see request/response +gh api --input /repos/$ORG/$REPO -v + +# Format JSON output +gh api /repos/$ORG/$REPO -q '.name, .visibility' +``` + +### Handle Rate Limiting +```bash +# Check rate limit status +gh api /rate_limit + +# GraphQL queries have separate rate limits +gh api graphql -f query='{ viewer { login } }' # Shows rate limit in response headers + +# Wait before retrying +sleep 60 +``` + +--- + +## Study Tip: Tool-Domain Mapping + +| Tool | Relevant Domain | Use Case | +|------|---|---| +| `gh repo list` | Domain 4 | Audit repository inventory | +| `gh api /audit-log` | Domain 5 | Track security and access changes | +| `ghe-support-bundle` | Domain 1 | Troubleshoot GHES issues | +| BFG / `git filter-branch` | Domain 5 | Remove secrets from history | +| `jq` | Domain 5 | Parse audit log for compliance reports | +| GraphQL audit log | Domain 5 | Complex queries (e.g., "who accessed production secrets?") | + +--- + +[← Overview](./index.md) · [Admin Playbook →](./admin-playbook.md) · [Concept Map →](./concept-map.md) · [Exam Guide →](./exam-guide.md) diff --git a/public/audio/certifications/gh-100/Exam_Refreshers___GH-100.m4a b/public/audio/certifications/gh-100/Exam_Refreshers___GH-100.m4a new file mode 100644 index 0000000..d066c5e Binary files /dev/null and b/public/audio/certifications/gh-100/Exam_Refreshers___GH-100.m4a differ diff --git a/public/images/certifications/gh-100/infographic.png b/public/images/certifications/gh-100/infographic.png new file mode 100644 index 0000000..b79d78d Binary files /dev/null and b/public/images/certifications/gh-100/infographic.png differ