docs(cloud-security): GCP serverless scopes — Cloud Run + Cloud Functions - #329
Draft
maximelb wants to merge 3 commits into
Draft
docs(cloud-security): GCP serverless scopes — Cloud Run + Cloud Functions#329maximelb wants to merge 3 commits into
maximelb wants to merge 3 commits into
Conversation
…ions Cloud Run and Cloud Functions inventory is now collected, with a verdict on whether each workload can be invoked from the internet with no authentication. This documents the scopes that verdict needs, before anyone discovers them as a silent denial. - The required baseline (roles/viewer + roles/iam.securityReviewer) already covers it, so nothing changes for a customer following the standard setup; said explicitly so the two new rows are not read as new requirements. - roles/run.viewer + roles/cloudfunctions.viewer are added to the OPTIONAL table (and the setup script) for the least-privilege alternative, where they are what turns serverless coverage on. - Both halves of each grant are called out: without getIamPolicy we can list a service but cannot tell whether anyone on the internet can invoke it, and we report NO verdict rather than guess — so findings are absent, not empty, which is a different thing from "you have none". - The 2nd-gen trap is documented: a 2nd-gen function's invoker permission lives on its underlying Cloud Run service (roles/run.invoker), not on the function (roles/cloudfunctions.invoker is 1st-gen), so a grant with cloudfunctions.viewer but not run.viewer lists 2nd-gen functions while leaving every one of them without a public-access verdict. - New `serverless` row in the preflight-check table and two troubleshooting rows, including the symptom that looks like good news: services listed, none ever flagged public, because getIamPolicy is denied. - run.googleapis.com + cloudfunctions.googleapis.com added to the enable list, and the page intro now mentions serverless. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7CkEf1fEa9Y8dBn5Utrx1
lcbill
previously approved these changes
Jul 30, 2026
maximelb
commented
Jul 30, 2026
Contributor
Author
|
Open finding (details inline):
No public-repo hygiene issues found (no customer names, internal repo names, internal URLs, or org ids); the role/permission table and the gen2- |
A Cloud Run service set to "internal and Cloud Load Balancing" cannot be reached at its own run.app URL but CAN be published to the internet through an external load balancer in front of it. We do not collect load balancers yet, so it is inventoried without being reported as internet-facing — a customer needs to know that, rather than read the absence as safety. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7CkEf1fEa9Y8dBn5Utrx1
lcbill
previously approved these changes
Jul 30, 2026
maximelb
commented
Jul 30, 2026
The 2nd-gen note asserted that a grant with cloudfunctions.viewer but not run.viewer leaves 2nd-gen functions without a verdict. The underlying fact is solid — a 2nd-gen function's invoker permission lives on the Cloud Run service — but whether roles/cloudfunctions.viewer already carries the Cloud Run reads is a claim about predefined-role contents that could not be confirmed, and a doc should not assert what it cannot check. Reworded to state the observable mechanism and point at 'provider test' as the authority: its serverless check exercises both APIs and reports each separately, so an operator learns which half is missing instead of reasoning about role contents. The least-privilege advice is unchanged (grant both), which is correct either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7CkEf1fEa9Y8dBn5Utrx1
lcbill
approved these changes
Jul 30, 2026
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.
What was asked
Cloud Run and Cloud Functions inventory is now collected for Google Cloud connections, together
with a verdict on whether each workload can be invoked from the internet with no authentication.
Document the scopes that verdict needs — before a customer discovers them as a silent denial.
What was done
All in
docs/cloud-security/provider-setup/gcp.md.roles/viewer+roles/iam.securityReviewergrant both the list and the
getIamPolicyreads, so nothing changes for a customer followingthe standard setup. Said explicitly, so the two new rows are not misread as new requirements.
roles/run.viewerandroles/cloudfunctions.viewer— for theleast-privilege alternative (
roles/browserplus per-service viewers), where they are whatturns serverless coverage on. Added to the setup script too.
getIamPolicywe can list a service butcannot tell whether anyone on the internet can invoke it, and we report no verdict rather
than guess — so serverless exposure findings are absent, not empty, which is a different
thing from "you have none".
lives on the underlying Cloud Run service (
roles/run.invoker), not on the function(
roles/cloudfunctions.invokeris the 1st-gen role). So a grant withroles/cloudfunctions.viewerbut notroles/run.viewerlists 2nd-gen functions whileleaving every one of them without a public-access verdict.
serverlessrow in the preflight-check table, and two troubleshooting rows — includingthe symptom that looks like good news: services listed, none ever flagged public, because
getIamPolicyis denied.run.googleapis.com+cloudfunctions.googleapis.comadded to the enable list; the page intronow mentions serverless alongside compute.
Testing
names (
run.services.list,run.services.getIamPolicy,cloudfunctions.functions.list,cloudfunctions.functions.getIamPolicy), the role names, and the 2nd-gen invoker behaviour(the Cloud Functions access-control page documents granting
roles/run.invokertoallUsersvia
gcloud run services add-iam-policy-binding).touched, so the list-numbering check is unaffected.
mkdocsis not installed locally, so therendered-site checks run in CI.
🤖 Generated with Claude Code
https://claude.ai/code/session_01L7CkEf1fEa9Y8dBn5Utrx1