terraform-provider-google
terraform-provider-google copied to clipboard
Cloud Functions: Allow / Disable unauthenticated invocations
Community Note
- Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment. If the issue is assigned to the "modular-magician" user, it is either in the process of being autogenerated, or is planned to be autogenerated soon. If the issue is assigned to a user, that user is claiming responsibility for the issue. If the issue is assigned to "hashibot", a community member has claimed the issue already.
Description
Hey there, I am struggling to replicate the functionality of Cloud Functions GUI to stop allowing unauthenticated invocations. In the resources, I have uploaded a imgur picture of the tick box that I am trying to disable.
I have tried the recommendation for creating a google_cloudfunctions_function_iam_binding resource with the cloudfunctions.invoker role on a service account, however, this will still allow any account connect to the cloud function.
New or Affected Resource(s)
- google_cloudfunctions_cloud_function
- google_cloudfunctions_function_iam_binding
Potential Terraform Configuration
resource "google_cloudfunctions_function" "function-api" {
unauthenticated_invocations = true / false
}
References
https://imgur.com/a/eukK8oy https://www.terraform.io/docs/providers/google/d/datasource_cloudfunctions_function.html
b/274817429
Hey @JordanStebbings! We actually have an example of how to do this in our docs: https://www.terraform.io/docs/providers/google/r/cloudfunctions_function.html. Take a look at the first example :)
Just kidding, I can read. Reopening for a bit more detailed response later on how to remove the binding.
Hey Dana, thanks for the response, I will describe what I have tried below:
To replicate what I have test please use the follow:
-
Create a Google Cloud Function with Python 3.7, keep everything the default settings however under Authentication Untick the Checkbox for Allow Unauthenticated Invocations
-
When the function is deployed, click the HTTP Trigger and you should receive the message:
"Your client does not have permission to get URL /CLOUD_FUNCTION_NAME from this server."\
-
Visit the Cloud Function Details page, click Source and Download Zip to get a copy of the default Python 3.7 functionality. Put this into the root of your new terraform module and save it as "function-source-terraform-test.zip"
-
Deploy the following terraform functionality by running terraform init, plan, apply:
provider "google" {
project = "YOUR PROJECT NAME"
region = "YOUR PROJECT REGION"
zone = "YOUR PROJECT ZONE"
credentials = "YOUR DEFAULT CREDENTIALS / PATH TO FILE"
}
resource "google_storage_bucket" "resource-storage" {
name = "temp-gcf-code"
}
resource "google_storage_bucket_object" "storage-object-code-api" {
bucket = google_storage_bucket.resource-storage.name
name = "index-api.zip"
source = "function-source-terraform-test.zip"
}
resource "google_cloudfunctions_function" "function-api" {
name = "test-invocation-terraform"
runtime = "python37"
timeout = 540
trigger_http = true
entry_point = "hello_world"
source_archive_bucket = google_storage_bucket.resource-storage.name
source_archive_object = google_storage_bucket_object.storage-object-code-api.name
}
# IAM entry for a single user to invoke the function
resource "google_cloudfunctions_function_iam_member" "invoker" {
project = google_cloudfunctions_function.function-api.project
region = google_cloudfunctions_function.function-api.region
cloud_function = google_cloudfunctions_function.function-api.name
role = "roles/cloudfunctions.invoker"
member = "user:[email protected]" / "serviceAccount:SERVICE_ACCOUNT"
}
- Visit the URL that the new Cloud Function is deployed from, you will be able to see: "Hello World!"
Also just been looking at the Gcloud documentation for deploying Cloud Functions, there is a Flag which can be set for --allow-unauthenticated, could this be replicated for this?
https://cloud.google.com/sdk/gcloud/reference/functions/deploy
@JordanStebbings when you create a function through google_cloudfunctions_function, the provider calls api service https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions/create. Currently by default, api creates google_cloudfunctions_function and implicitly creates an iam object which binds allUsers to roles/cloudfunctions.invoker role. These are all done inside API service. At the provider level, currently there is no code yet that can disable the default iam object creation. To work around this in order to achieve disable unauthenticated invocation, you may create google_cloudfunctions_function_iam_policy, similar to below code, to override that default iam object.
data "google_iam_policy" "admin" {
binding {
role = "roles/viewer"
members = [
"serviceAccount:[email protected]",
]
}
}
resource "google_cloudfunctions_function_iam_policy" "editor" {
project = google_cloudfunctions_function.function.project
region = google_cloudfunctions_function.function.region
cloud_function = google_cloudfunctions_function.function.name
policy_data = data.google_iam_policy.admin.policy_data
}
@c2thorn Please note As of January 15, 2020, HTTP functions require authentication by default. (https://cloud.google.com/functions/docs/securing/managing-access-iam) We'd better update the provider code accordingly.
@JordanStebbings when you create a function through google_cloudfunctions_function, the provider calls api service https://cloud.google.com/functions/docs/reference/rest/v1/projects.locations.functions/create. Currently by default, api creates google_cloudfunctions_function and implicitly creates an iam object which binds allUsers to roles/cloudfunctions.invoker role. These are all done inside API service. At the provider level, currently there is no code yet that can disable the default iam object creation.
This is correct, until a while ago allUsers was added by default to any cloud function created, which required explicit removal.
To work around this in order to achieve disable unauthenticated invocation, you may create google_cloudfunctions_function_iam_policy, similar to below code, to override that default iam object.
A less elegant but likely more self-explanatory way to go about this at the time was to explicitly remove the IAM binding.
resource "null_resource" "rm-iam-unauthenticated-invocations" {
depends_on = [google_cloudfunctions_function.myfunction]
provisioner "local-exec" {
command = " gcloud beta functions --project=${var.project} remove-iam-policy-binding ${google_cloudfunctions_function.myfunction.name} --member=\"allUsers\" --role=\"roles/cloudfunctions.invoker\";"
}
triggers = { timestamp = "${timestamp()}" }
}
@c2thorn Please note As of January 15, 2020, HTTP functions require authentication by default. (https://cloud.google.com/functions/docs/securing/managing-access-iam) We'd better update the provider code accordingly.
Also, the documentation has been updated accordingly at some point this year:

If using an API Gateway, it is essential for the cloud function to have ingress_settings = "ALLOW_ALL",
The other values won't allow Cloud API Gateway to access the function. Regardless of IAM settings. Then protect the function with IAM to limit access to a service account or user.
This may help others if it is more clearly documented.
Following Google documentation about IAM permissions on Cloud Functions and Terraform Google Provider documentation you can use allUsers as a member to allow invocations as seen below:
...
resource "google_cloudfunctions_function" "function" { ... }
resource "google_cloudfunctions_function_iam_member" "member" {
project = google_cloudfunctions_function.function.project
region = google_cloudfunctions_function.function.region
cloud_function = google_cloudfunctions_function.function.name
role = "roles/cloudfunctions.invoker"
member = "allUsers"
}
On the interface:

Though it would be simpler to have a param inside google_cloudfunctions_function resource as @JordanStebbings initially suggested.
Can anyone else simply not find the mythical "Authentication section on the Configuration panel" in the google cloud console? This is completely confusing.
@meropis are you referring to this section during Clound Function creation?

Does anyone know how to do the same for Gen2 functions? Am unable to find similar solution for gen2 functions!
Does anyone know how to do the same for Gen2 functions? Am unable to find similar solution for gen2 functions!
Documentation from Terraform Registry: google_cloudfunctions2_function
Does anyone know how to do the same for Gen2 functions? Am unable to find similar solution for gen2 functions!
Documentation from Terraform Registry: google_cloudfunctions2_function
Can you please specify where? :D I really dont see any exact example of allowing unauth invocation within terraform gen2 docs which allows allUsers, the example given simply allows a service account which has to pass an authentication anyway.
But anyway Got it i looked up your earlier reply and found some reference from troubleshooting#unauthorized-client and managing-access#make-service-public,
Anyone looking up for gen2, change to cloud run instead of cloud function iam binding for gen2 like below:
resource "google_cloud_run_service_iam_binding" "default" {
location = google_cloudfunctions2_function.resolver_function.location
service = google_cloudfunctions2_function.resolver_function.name
role = "roles/run.invoker"
members = [
"allUsers"
]
}
Changes after applying within cloud run :

Edit : Note google_cloudfunctions2_function_iam_member doesnt work, it has to be google_cloud_run_service_iam_binding
@Ripeey thank you so much! The google_cloud_run_service_iam_binding worked! How did you figure that out? It's so unintuitive
FYI, if you want to specify IAM role for a specific account on a Gen2 Cloud Function, you must use google_cloud_run_service_iam (binding, member, ...) too. google_cloudfunctions2_function_iam_member does not work. This also reflects on GCP console, where you must specify the permission on Cloud Run service to work. Specifying permission on Cloud Function will not work for Gen2 function.
@toandm I wish I could find your comment earlier. After struggling with http trigger gen2 function and cloud scheduler I eventually realized I need to set not just google_cloudfunctions2_function_iam_member with roles/cloudfunctions.invoker, but also google_cloud_run_service_iam_member with roles/run.invoker to associated cloud run service. It was not obvious from documentation which btw contains wrong gcloud commands sometimes.
Adding this seems to work for me:
resource "google_cloudfunctions2_function_iam_member" "cloud_function_invoker" {
project = google_cloudfunctions2_function.function.project
location = google_cloudfunctions2_function.function.location
cloud_function = google_cloudfunctions2_function.function.name
role = "roles/cloudfunctions.invoker"
member = "allUsers"
}
resource "google_cloud_run_service_iam_member" "cloud_run_invoker" {
project = google_cloudfunctions2_function.function.project
location = google_cloudfunctions2_function.function.location
service = google_cloudfunctions2_function.function.name
role = "roles/run.invoker"
member = "allUsers"
}
I got that from here
With that, when I go to the web console, I see that access is granted to allUsers in the PERMISSIONS sections.
What surprises me is that deploying the functions using the command line does not show me that allUsers in the PERMISSIONS section but my function url still works. Any one knows why this difference?
This would be an example of my gcloud command line:
gcloud functions deploy terra-test \
--memory=128Mi \
--timeout=60 \
--max-instances=1 \
--region=europe-west1 \
--project=dmproject-1 \
--gen2 \
--trigger-http \
--allow-unauthenticated \
--runtime=python311 \
--entry-point=main_http \
--source=src