> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Repo has multiple admins remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are concise, step‑by‑step instructions to reduce excessive repository admins in GitHub using the web console (GitHub.com UI).

        ***

        ## 1. Confirm You Have Permission

        You must be:

        * An **Organization Owner** (for org repos), or
        * A **Repository Admin** (for personal or org repos)

        to change admin permissions.

        ***

        ## 2. List Current Admins for a Repository

        1. Sign in to **GitHub.com**.
        2. Open the repository:\
           `https://github.com/<org-or-user>/<repo-name>`
        3. Click **Settings** (top menu in the repo).
        4. In the left sidebar, click:
           * **Collaborators and teams** (for org repos: “Manage access”)
        5. Under **Manage access**, review:
           * **Teams** with access and their permission level
           * **Individuals** with access and their permission level

        Anyone with **Admin** permission here is effectively a repo admin.

        ***

        ## 3. Reduce Individual Admins to Lower Roles

        For each user who doesn’t truly need admin rights:

        1. In **Settings → Manage access**, find the **person** with **Admin** access.
        2. Click the **gear icon** (or three-dot menu) next to that user.
        3. Under **Repository access**, change:
           * From: **Admin**
           * To: **Maintain** (for maintainers) or **Write** (for regular contributors)
        4. Click **Save** or **Update access**.

        Repeat for all users who should not be admins.

        ***

        ## 4. Use Teams Instead of Individual Admins (Org Repos)

        If you are in an organization:

        1. Go to the org page: `https://github.com/<org>`
        2. Click **Teams**.
        3. Create or choose a team (e.g. `repo-maintainers`).
        4. Click the team → **Repositories** → **Add a repository to this team**.
        5. Select the repository and set **permission** to:
           * **Maintain** for people who manage issues/PRs but don’t need admin, or
           * **Write** for regular contributors.
        6. Remove **individual Admin** access for those now covered by the team (same method as step 3).

        ***

        ## 5. Remove Unnecessary Teams with Admin Access

        1. In the repository, go to **Settings → Manage access**.
        2. Under **Teams**, find any **team** with **Admin** level.
        3. Click the **gear icon** next to the team.
        4. Change permission:
           * From **Admin**
           * To **Maintain** or **Write**, as appropriate.
        5. Save changes.

        ***

        ## 6. Restrict Who Can Be a Repo Admin at Org Level (Optional)

        For organizations to keep admin counts low going forward:

        1. Go to the **Organization** page.
        2. Click **Settings**.
        3. In the left sidebar, review:
           * **Member privileges** / **Repository creation** / **Base permissions**.
        4. Set:
           * **Base permissions** to **Read** (or lower), not **Admin**.
           * Restrict who can create repositories or manage settings to **Organization owners** only.
        5. Ensure only a small set of **Organization Owners** exist (Org Settings → **People** → change role from Owner to Member where appropriate).

        ***

        ## 7. Periodically Audit Admins

        1. On a schedule (e.g. monthly), for each critical repo:
           * Go to **Settings → Manage access**.
           * Export or screenshot current access.
        2. Remove or downgrade permissions that are no longer needed.

        ***

        If you share your repo type (personal vs organization) and current number of admins/teams, I can suggest an exact target layout (e.g., “1 owner + 1 maintainers team + write-only contributors”).
      </Accordion>

      <Accordion title="Using CLI">
        Below is a concise, step‑by‑step way to identify and reduce excessive repo admins using the GitHub CLI (`gh`).

        Assumptions:

        * You have `gh` installed and authenticated (`gh auth login`).
        * You’re an admin/owner on the repo or org.
        * Replace `OWNER` (user/org) and `REPO` with your values.

        ***

        ### 1. List who has admin access on a repository

        #### A. List collaborators and their permissions (classic collaborators)

        ```bash theme={null}
        gh api \
          repos/OWNER/REPO/collaborators \
          --paginate \
          --jq '.[] | select(.permissions.admin == true) | {login, permissions}'
        ```

        This shows logins that have `admin: true` via direct collaborator access.

        #### B. List teams with admin access (for org repos)

        ```bash theme={null}
        gh api \
          repos/OWNER/REPO/teams \
          --paginate \
          --jq '.[] | select(.permission == "admin") | {name, slug, permission}'
        ```

        Members of these teams may effectively be “repo admins” depending on team permission.

        #### C. (Optional) List org members with admin role (org‑wide)

        ```bash theme={null}
        gh api \
          orgs/OWNER/members \
          --paginate \
          --jq '.[] | select(.role == "admin") | .login'
        ```

        Use this to identify who can manage repos/org settings globally.

        ***

        ### 2. Decide the minimal required admins

        Offline step:

        * For each admin user or team, decide:
          * Keep as admin,
          * Downgrade to `maintain` or `push`, or
          * Remove.

        Document the desired target state: user/team → new permission.

        ***

        ### 3. Downgrade or remove individual repo admins

        #### A. Change a collaborator’s permission (e.g., admin → maintain)

        ```bash theme={null}
        gh api \
          --method PUT \
          -H "Accept: application/vnd.github+json" \
          repos/OWNER/REPO/collaborators/USERNAME \
          -f permission=maintain
        ```

        Valid values: `pull`, `triage`, `push`, `maintain`, `admin`.

        #### B. Remove a collaborator entirely

        ```bash theme={null}
        gh api \
          --method DELETE \
          repos/OWNER/REPO/collaborators/USERNAME
        ```

        ***

        ### 4. Downgrade or remove admin teams

        #### A. Change team permission on the repo (admin → maintain, for example)

        ```bash theme={null}
        gh api \
          --method PUT \
          -H "Accept: application/vnd.github+json" \
          orgs/OWNER/teams/TEAM_SLUG/repos/OWNER/REPO \
          -f permission=maintain
        ```

        #### B. Remove team access to the repo

        ```bash theme={null}
        gh api \
          --method DELETE \
          orgs/OWNER/teams/TEAM_SLUG/repos/OWNER/REPO
        ```

        ***

        ### 5. Reduce organization‑wide admins (if needed)

        Use this carefully—org admins lose global powers.

        #### A. List current org admins

        ```bash theme={null}
        gh api \
          orgs/OWNER/members \
          --paginate \
          --jq '.[] | select(.role == "admin") | .login'
        ```

        #### B. Change a user’s org role from admin → member

        ```bash theme={null}
        gh api \
          --method PUT \
          orgs/OWNER/memberships/USERNAME \
          -f role=member
        ```

        #### C. Remove a user from the org (if appropriate)

        ```bash theme={null}
        gh api \
          --method DELETE \
          orgs/OWNER/members/USERNAME
        ```

        ***

        ### 6. Re‑verify effective repo admins

        Re‑run checks:

        ```bash theme={null}
        # Direct collaborators with admin
        gh api repos/OWNER/REPO/collaborators --paginate \
          --jq '.[] | select(.permissions.admin == true) | {login, permissions}'

        # Teams with admin
        gh api repos/OWNER/REPO/teams --paginate \
          --jq '.[] | select(.permission == "admin") | {name, slug, permission}'
        ```

        Confirm the list is limited to the strictly necessary admins.
      </Accordion>

      <Accordion title="Using Python">
        Below is a practical, step‑by‑step way to reduce excessive repo admins in GitHub using Python (via the GitHub REST API and/or PyGithub).

        ***

        ## 1. Preparation

        1. **Decide the policy** you want to enforce, for example:
           * Only a specific team(s) can be admin.
           * Or max N admin users per repo.
        2. **Create a GitHub Personal Access Token (PAT)** with at least:
           * `repo`
           * `admin:org` (if managing org repos, teams, etc.)

        Export it as an environment variable (recommended):

        ```bash theme={null}
        export GITHUB_TOKEN="ghp_XXXXXXXXXXXXXXXXXXXX"
        export GITHUB_ORG="your-org-name"
        ```

        ***

        ## 2. Install Python dependencies

        ```bash theme={null}
        pip install PyGithub requests
        ```

        ***

        ## 3. Enumerate Admins and Decide Remediations

        ### 3.1. Using PyGithub to list repos and their admins

        ```python theme={null}
        from github import Github
        import os

        token = os.environ["GITHUB_TOKEN"]
        org_name = os.environ["GITHUB_ORG"]

        g = Github(token)
        org = g.get_organization(org_name)

        for repo in org.get_repos():
            print(f"\nRepo: {repo.full_name}")

            # Direct collaborators
            print("  Direct admins:")
            for collab in repo.get_collaborators(permission="admin"):
                print(f"    USER: {collab.login}")

            # Teams with admin permission
            print("  Teams with admin:")
            for team in repo.get_teams():
                if team.permission == "admin":  # 'admin', 'push', 'pull', 'maintain', etc.
                    print(f"    TEAM: {team.slug}")
        ```

        Use this output to decide which users/teams should **no longer** have admin rights.

        ***

        ## 4. Implement Least-Privilege Changes

        ### 4.1. Define allowed admins (policy)

        Example: only one “core-admins” team plus maybe some specific user(s) per repo.

        ```python theme={null}
        ALLOWED_ADMIN_TEAMS = {"core-admins"}  # team slugs
        ALLOWED_ADMIN_USERS = {"repo-owner-1"}  # usernames allowed to stay admin
        DEFAULT_USER_PERMISSION = "push"  # downgrade excess admins to 'push'
        ```

        ### 4.2. Downgrade or remove excessive admins

        ```python theme={null}
        from github import Github
        import os

        token = os.environ["GITHUB_TOKEN"]
        org_name = os.environ["GITHUB_ORG"]

        ALLOWED_ADMIN_TEAMS = {"core-admins"}
        ALLOWED_ADMIN_USERS = {"repo-owner-1"}
        DEFAULT_USER_PERMISSION = "push"  # or 'pull'

        g = Github(token)
        org = g.get_organization(org_name)

        for repo in org.get_repos():
            print(f"\nProcessing repo: {repo.full_name}")

            # --- Handle teams with admin permissions ---
            for team in repo.get_teams():
                if team.permission == "admin":
                    if team.slug not in ALLOWED_ADMIN_TEAMS:
                        print(f"  Downgrading/removing TEAM admin: {team.slug}")
                        # Option 1: downgrade to 'push'
                        team.update_team_repository(repo, permission="push")
                        # Option 2 (alternative): remove team access completely
                        # team.remove_from_repos(repo)

            # --- Handle direct users with admin permissions ---
            for collab in repo.get_collaborators(permission="admin"):
                if collab.login not in ALLOWED_ADMIN_USERS:
                    print(f"  Downgrading USER admin: {collab.login}")
                    # Option 1: downgrade to 'push'
                    repo.add_to_collaborators(collab.login, permission=DEFAULT_USER_PERMISSION)
                    # Option 2 (alternative): remove access completely
                    # repo.remove_from_collaborators(collab.login)
        ```

        Run in **dry-run mode** first by commenting out the change lines and just printing what would happen.

        ***

        ## 5. Safer: Dry-run / Audit Mode

        Add a `DRY_RUN = True` flag:

        ```python theme={null}
        DRY_RUN = True  # Set False to apply changes

        for repo in org.get_repos():
            print(f"\nProcessing repo: {repo.full_name}")

            for team in repo.get_teams():
                if team.permission == "admin" and team.slug not in ALLOWED_ADMIN_TEAMS:
                    print(f"  Would downgrade TEAM {team.slug} from admin to push")
                    if not DRY_RUN:
                        team.update_team_repository(repo, permission="push")

            for collab in repo.get_collaborators(permission="admin"):
                if collab.login not in ALLOWED_ADMIN_USERS:
                    print(f"  Would downgrade USER {collab.login} from admin to {DEFAULT_USER_PERMISSION}")
                    if not DRY_RUN:
                        repo.add_to_collaborators(collab.login, permission=DEFAULT_USER_PERMISSION)
        ```

        ***

        ## 6. (Optional) Using Raw REST API via `requests`

        If you prefer not to use PyGithub:

        * List collaborators with permission:
          `GET /repos/{owner}/{repo}/collaborators?permission=admin`
        * Change a collaborator’s permission:
          `PUT /repos/{owner}/{repo}/collaborators/{username}` with body:
          `{"permission": "push"}`

        Minimal example:

        ```python theme={null}
        import os
        import requests

        token = os.environ["GITHUB_TOKEN"]
        org = os.environ["GITHUB_ORG"]
        headers = {"Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json"}

        def list_repos():
            url = f"https://api.github.com/orgs/{org}/repos"
            r = requests.get(url, headers=headers)
            r.raise_for_status()
            return r.json()

        def list_admin_collaborators(repo):
            url = f"https://api.github.com/repos/{org}/{repo}/collaborators"
            r = requests.get(url, headers=headers, params={"permission": "admin"})
            r.raise_for_status()
            return [c["login"] for c in r.json()]

        def downgrade_user(repo, user, perm="push"):
            url = f"https://api.github.com/repos/{org}/{repo}/collaborators/{user}"
            r = requests.put(url, headers=headers, json={"permission": perm})
            r.raise_for_status()

        for r in list_repos():
            repo_name = r["name"]
            admins = list_admin_collaborators(repo_name)
            for user in admins:
                if user not in {"repo-owner-1"}:
                    print(f"Downgrading {user} on {repo_name}")
                    downgrade_user(repo_name, user, "push")
        ```

        ***

        ## 7. Governance

        * Run the audit/remediation script periodically (e.g., as a GitHub Action or CI job).
        * Log all changes.
        * Optionally notify affected users/teams before/after changes.

        If you describe your exact policy (who should remain admin and in what cases), I can adjust the Python logic and permissions transitions precisely to match it.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # GitHub repository (maps to github-applicationintegration-scm-repository)
        resource "github_repository" "repo" {
          name        = "REPO_NAME"     # replace with the repository name
          description = "REPO_DESCRIPTION"
          visibility  = "private"
        }

        # SINGLE admin (keep admin here)
        resource "github_repository_collaborator" "admin" {
          repository = github_repository.repo.name
          username   = "PRIMARY_ADMIN_USERNAME"  # replace with the single intended admin
          permission = "admin"
        }

        # All other users: drop down from admin/push to lower permission (e.g., pull)
        resource "github_repository_collaborator" "read_only_collaborators" {
          for_each   = toset([
            "USER_1_USERNAME",  # replace with each non-admin user that previously had admin/push
            "USER_2_USERNAME",
            # ...
          ])
          repository = github_repository.repo.name
          username   = each.value
          permission = "pull"  # or "triage" / "maintain" as policy allows, but not "admin" or "push"
        }
        ```

        Changing a collaborator’s `permission` does not replace the repository; it updates access in place, but it is immediately effective and may block previous admin/push actions.

        For verification, `terraform plan` should show:

        * No change to `github_repository.repo`
        * `github_repository_collaborator.admin` with `permission = "admin"`
        * All other `github_repository_collaborator.*` changing from `admin`/`push` to the lower permission you chose (e.g., `pull`).
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
