Cloud Run CLI default change for unauthenticated access in gcloud 2023.08.00
0 reputation · 07 Aug 2022, 13:37 UTC
0 reputation · 07 Aug 2022, 13:37 UTC
29275 reputation · 07 Aug 2022, 14:56 UTC
Yes — always declare the intent explicitly in IaC. Set allowUnauthenticated: false (or the Terraform equivalent, simply not granting roles/run.invoker to allUsers) in every template, and treat the gcloud CLI default as a convenience for interactive use, never as a control. A default that changed once (in 2023.08.00, from implicit public to private-by-default) can change again, and your security posture should not depend on which SDK version happens to be installed on a runner.
Confirmed: the gcloud CLI changed its deploy behavior around version 2023.08.00 so that omitting --allow-unauthenticated no longer makes a new service public; the CLI now prompts or defaults toward private. What is not guaranteed is that this default persists across future releases, or that every deployment path (older SDKs pinned in CI, Cloud Deploy, third-party tooling) behaves identically. Treat the current default as an extra safety net, not the mechanism of enforcement.
google_cloud_run_service resource is private unless you attach a google_cloud_run_service_iam_member binding roles/run.invoker to allUsers. The failure mode to guard against is an overly broad reusable module that adds that binding by default. If you deploy via gcloud run deploy in scripts, pass --no-allow-unauthenticated explicitly so the script's meaning is stable regardless of SDK version.iam.allowedPolicyMemberDomains, so a stray allUsers binding is rejected at the API rather than discovered later.Two checks cover the real risk. First, confirm no invoker binding grants public access:
gcloud run services get-iam-policy SERVICE \
--region REGION \
--format="table(bindings.role, bindings.members)"There should be no roles/run.invoker entry containing allUsers or allAuthenticatedUsers. Second, do a functional check — an unauthenticated request must be rejected:
curl -s -o /dev/null -w "%{http_code}\n" https://SERVICE-URLA private service returns 403 (or 404 in some configurations) without credentials; 200 means it is publicly reachable. Note that get-iam-policy on the service is the authoritative check — a project-level policy listing can miss service-level bindings. Automate both checks as a post-deploy step in CI and fail the pipeline on a 200 response.
Yes, and this is the most common real-world bypass: the CLI flag only affects what the deploy command itself sets. A separate Terraform module, a manual console action, or another pipeline can add an allUsers invoker binding afterward, and nothing about --no-allow-unauthenticated prevents that. This is why the periodic audit (the IAM policy check above, run on a schedule across all services) matters more than the deploy-time flag. Drift detection in your IaC pipeline will catch bindings managed by Terraform, but only the audit catches bindings created outside it.
The exact CLI prompt behavior and default wording vary slightly across gcloud versions, so verify against the release notes of the specific SDK you pin. The IaC-side recommendation — explicit declaration, org-level guardrails, post-deploy verification — is stable regardless.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.