Repository navigation
Manage the security-room Cloudflare Access policy from config via a security-team GitHub team - #195
Merged
Merged
Conversation
The Cloudflare Zero Trust Access policy protecting securityroom.modelcontextprotocol.io was hand-edited in the Cloudflare dashboard and allowed four GitHub teams: core-maintainers, lead-maintainers, security-managers and sdk-maintainers. Cloudflare matches direct GitHub team membership only, so SDK maintainers, who sit in child teams such as python-sdk, were denied. Declare the policy in src/config/accessPolicies.ts and sync it with @pulumi/cloudflare (src/cloudflare.ts, optional like the Discord module until cloudflare:apiToken is configured). Add a dedicated `security-room` GitHub team (no parent, so it grants no repository permissions) that the policy allows alongside core-maintainers, lead-maintainers and security-managers, and seed it with the per-SDK leads named in the thread. Validation and tests cover the new config; the deploy and preview workflows pass CLOUDFLARE_API_TOKEN when the secret exists. The existing `Maintainers` policy is adopted via the `import` resource option behind cloudflare:importExistingPolicies, since Pulumi requires imported inputs to match the live resource; a follow-up flips the flag off so the include-rule change is applied. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBarRtzEtwT2HvfcEvRbW7
Pulumi PreviewClick to expand preview output |
The team allowed through the Cloudflare Access policy represents the MCP Security Team as a whole (SDK security leads who coordinate advisories across SDKs), not only sign-in to the security room, so name the role and GitHub team `security-team`. It stays parentless so it inherits no repository permissions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBarRtzEtwT2HvfcEvRbW7
…oken The secret and Pulumi config key are dedicated to Access policy role management (Account > Access: Apps and Policies > Edit only), so name them CLOUDFLARE_ROLE_MANAGEMENT_TOKEN / cloudflare:roleManagementToken. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBarRtzEtwT2HvfcEvRbW7
localden
approved these changes
Sep 29, 2026
localden
pushed a commit
that referenced
this pull request
Sep 29, 2026
#198) The first deploy of #195 adopted the live policy as-is. Turning off the import lets Pulumi replace sdk-maintainers with security-team. Claude-Session: https://claude.ai/code/session_01YBarRtzEtwT2HvfcEvRbW7 Co-authored-by: Claude <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Den Delimarsky, Max Isbey · Slack thread
Before: The Cloudflare Zero Trust Access policy (
Maintainers) protecting https://securityroom.modelcontextprotocol.io was hand-edited in the Cloudflare dashboard. It allowed only four GitHub teams:core-maintainers,lead-maintainers,security-managersandsdk-maintainers. Cloudflare matches direct GitHub team membership only, so SDK maintainers, who sit in child teams such aspython-sdkandtypescript-sdk, were denied.After: The policy is declared in
src/config/accessPolicies.tsand synced by Pulumi (src/cloudflare.ts, using@pulumi/cloudflare). A newsecurity-teamGitHub team represents the MCP Security Team (SDK security leads who coordinate advisories across SDKs) and is managed inusers.tslike every other team; the policy allows it alongsidecore-maintainers,lead-maintainersandsecurity-managers(4 include rules;sdk-maintainersis dropped since it never matched anyone in a child team). The team has no parent team, so it grants no repository permissions by itself; security-room sign-in is its first use. The initial roster is the per-SDK leads named in the thread: maxisbey, Kludex (Python); felixweinberger, mattzcarey, KKonstantinov (TypeScript); yarolegovich, guglielmo-san (Go); daleseo (Rust); halter73 (C#); koic (Ruby). Java, Kotlin, PHP, Swift and MCP Apps leads are still to be decided and will be added in follow-up PRs.How:
src/cloudflare.tsfollows the optional-provider pattern fromdiscord.ts: ifcloudflare:roleManagementTokenis not set it logs "Cloudflare integration disabled: roleManagementToken not configured" and creates nothing, so previews stay green until the secret exists. Otherwise it creates an explicitcloudflare.Providerand oneZeroTrustAccessPolicyperACCESS_POLICIESentry, rendering each role's GitHub team into agithub-organizationinclude rule (identity provider and account ID come fromPulumi.prod.yaml). The token is deliberately named for what it is, a role-management token (CLOUDFLARE_ROLE_MANAGEMENT_TOKENsecret,cloudflare:roleManagementTokenconfig), scoped only to Access policy edits, not a generic Cloudflare API token.npm run validatechecks that every role in a policy exists, has a GitHub team and is not duplicated;npm testchecks the rendered include-rule list. The existingMaintainerspolicy (11a6814e-…) is adopted with Pulumi'simportoption (format<account_id>/<policy_id>, per the provider docs) gated bycloudflare:importExistingPolicies. Because Pulumi refuses an import whose inputs differ from the live resource, the import pass ignores the rule fields; a follow-up PR flipping the flag to"false"then applies the include-rule change, and its preview shows exactly that diff.connectionRulesandsessionDurationare always ignored since the API sets defaults we do not model. The README has a new "Cloudflare Access (security-room)" section with the grant procedure and one-time setup.Before merging
mcp-access: Access policy role management), scoped only to Account → Access: Apps and Policies → Edit, not reused for anything else, and add it as the GitHub Actions secretCLOUDFLARE_ROLE_MANAGEMENT_TOKENin theproductionenvironment.github.Teamcreate (security-team) plus its 10TeamMembershipcreates, and animportof theMaintainersZeroTrustAccessPolicy, and nothing else.cloudflare:importExistingPolicies: "false"inPulumi.prod.yaml; its preview should show only the policy update replacing thesdk-maintainersinclude rule withsecurity-team.Not verified here:
npm run buildfails locally only on the pre-existing@pulumi/googleworkspacegenerated SDK (needspulumi install, which is unavailable in this environment); the new files typecheck clean under the repo's stricttsconfigsettings, andnpm run check(prettier, validate, 40 tests) passes. Nopulumi previewwas run, so any spurious diff onexcludes/requiresafter import would only show up in CI.🤖 Generated with Claude Code
https://claude.ai/code/session_01YBarRtzEtwT2HvfcEvRbW7