Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/tests/test_security_automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,32 @@ def test_registry_refresh_tracks_computed_tag_inputs():
} <= paths


def test_registry_refresh_requests_required_app_permissions():
workflow = load_workflow(
REPO_ROOT / ".github" / "workflows" / "update-registry.yml"
)
steps = workflow["jobs"]["update-registry"]["steps"]
token_step = next(
step for step in steps
if uses_action(step, "actions/create-github-app-token")
)

assert token_step["id"] == "app_token"
assert {
key: value for key, value in token_step["with"].items()
if key.startswith("permission-")
} == {
"permission-contents": "write",
"permission-pull-requests": "write",
}

publish_step = next(
step for step in steps
if step.get("name") == "Commit updated registry to a PR"
)
assert publish_step["env"]["GH_TOKEN"] == "${{ steps.app_token.outputs.token }}"


def test_registry_refresh_cannot_rewrite_or_self_approve_generated_prs():
path = REPO_ROOT / ".github" / "workflows" / "update-registry.yml"
workflow = load_workflow(path)
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,37 @@ and promotion criteria.
Catalog changes can also trigger **Update Registry**. Generated updates reach
`main` through a separate reviewed registry PR, not automatic merging.

## Registry App setup

[Update Registry](update-registry.yml) uses an installation token for
`discovery-registry-bot` to push its branch and create its PR. The App needs these
repository permissions:

| Permission | Required access |
| --- | --- |
| Contents | Read and write |
| Pull requests | Read and write |

An App owner must configure these permissions, and a Microsoft
organization/installation administrator must approve any updated grant for the
installation covering `microsoft/discovery`. Changing the App configuration
alone does not establish installation approval. Keep `REGISTRY_APP_ID` and
`REGISTRY_APP_PRIVATE_KEY` configured; a permission change does not require
rotating these credentials.

The workflow explicitly requests `permission-contents: write` and
`permission-pull-requests: write` for its current-repository token. These inputs
cannot elevate the App's approved installation permissions: token creation fails
if the requested grant is unavailable.

A branch push rejected with HTTP 403 for `discovery-registry-bot[bot]` is an
authorization failure. Check both the App's Contents write permission and the
installation's approval. Successful token creation without explicit permission
requests does not prove write access. Do not broaden workflow-level
`permissions` to fix an App token: those permissions govern `GITHUB_TOKEN`, which
remains read-only. Registry PRs still require human/CODEOWNER review and
maintainer-controlled merging.

## Release refresh automation

Three workflows work together to keep the mutable `current` tag, the
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/update-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ jobs:
# because the default GITHUB_TOKEN is read-only. The App
# (discovery-registry-bot) must have Contents: Write and Pull requests:
# Write on microsoft/discovery.
# Explicit token requests cannot grant permissions the installation lacks.
# This App still creates PRs; it does not approve or enroll auto-merge.
# If REGISTRY_APP_ID is unset (App not yet wired up), this step is
# skipped and the workflow fails without pushing any branch.
Expand All @@ -189,6 +190,8 @@ jobs:
with:
app-id: ${{ secrets.REGISTRY_APP_ID }}
private-key: ${{ secrets.REGISTRY_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write

- name: Commit updated registry to a PR
if: steps.diff.outputs.changed == 'true' && steps.app_check.outputs.configured == 'true'
Expand Down
Loading