Cloud Run Function (gen2)
Event-driven or HTTP gen2 function with source upload, dedicated runtime SA and Eventarc trigger wiring.
Verification
Plan-validatedPassed: module logic verified on a mocked plan — inputs, validation rules, conditional creation and outputs resolve (no real provider, no cloud).
Conformance
- Static validation (fmt · validate · tflint)
- Security scan: findings disclosed (Checkov)
- Plan tests (mocked: validation rules · outputs)
Provenance
- SHA-256 checksum
- Signature (pending)
Functional
- Live test pending (no cloud run yet)
Last verified 2026-06-28 · how we verify
Documentation
gcp-cloud-function
A Cloud Run function (gen2) — HTTP or event-driven — with the source zip
uploaded to GCS, a dedicated runtime service account, least-privilege Secret
Manager grants wired automatically, optional Eventarc trigger, VPC egress, and
private invoker IAM. One module call gives you a production function whose
identity is not the default compute service account and whose HTTP surface is
locked down unless you explicitly open it. Works with Terraform and
OpenTofu (>= 1.6), Google provider >= 7.0, < 8.0.
Status: static-validated, live-test pending. Validated with
tofu validate+tflint+checkovagainst thehashicorp/googleprovider. Not yet applied against a live GCP project (no cloud sandbox), so it ships under live-test quarantine.
Design & secure defaults
- Dedicated runtime service account (
<name>-fn) — never the default compute SA. Supply your own withcreate_service_account = false. - Private by default: no invoker IAM unless you list
invoker_members;allUsersonly via the explicitallow_unauthenticated = trueopt-in. - Least-privilege secrets:
roles/secretmanager.secretAccessoris granted per referenced secret, not project-wide. Cross-project secrets are left for you to grant where they live. - Content-addressed source: the uploaded object name defaults to
<name>/<md5>.zip, so a changed zip forces a fresh build. - Cost cap:
max_instance_count = 10by default;gen2request concurrency starts at 1 (raise deliberately). - VPC egress via a Serverless VPC Access connector,
PRIVATE_RANGES_ONLYby default.
Usage
module "http_function" {
source = "./gcp-cloud-function"
project_id = "my-project"
name = "checkout-fn"
location = "us-central1"
runtime = "nodejs22"
entry_point = "handler"
source_bucket = "my-project-fn-source" # private, uniform-access bucket
source_zip_path = "${path.module}/build/checkout.zip"
environment_variables = { LOG_LEVEL = "info" }
secret_environment_variables = { DATABASE_URL = { secret = "checkout-db-url" } }
invoker_members = ["serviceAccount:[email protected]"]
labels = { environment = "prod" }
}
Event-driven (Pub/Sub) function — omit invoker_members, supply
event_trigger:
event_trigger = {
event_type = "google.cloud.pubsub.topic.v1.messagePublished"
pubsub_topic = "projects/my-project/topics/orders"
retry_policy = "RETRY_POLICY_RETRY"
}
For Cloud Storage triggers, use event_type = "google.cloud.storage.object.v1.finalized" and event_filters = { bucket = "my-bucket" }.
When event_trigger is set the module grants the runtime SA
roles/eventarc.eventReceiver + roles/run.invoker before the function (and,
for google.cloud.storage.* events, roles/pubsub.publisher to the Cloud
Storage service agent) so Eventarc accepts the trigger and the event-driven
path applies in a single apply.
Requirements
| Requirement | Version |
|---|---|
| Terraform / OpenTofu | >= 1.6 |
hashicorp/google | >= 7.0, < 8.0 |
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
project_id | string | — | GCP project ID (required) |
name | string | — | Function name (required) |
location | string | — | Region (required) |
runtime | string | — | Language runtime e.g. nodejs22 (required) |
entry_point | string | — | Exported function/method to run (required) |
source_bucket | string | — | GCS bucket for the source zip (required) |
source_zip_path | string | — | Local path to the source zip (required) |
source_object_name | string | null | Object name (defaults to content-addressed) |
description | string | null | Function description |
available_memory | string | "256Mi" | Memory per instance |
available_cpu | string | null | CPU per instance (null = derived) |
timeout_seconds | number | 60 | Request timeout (1–3600) |
min_instance_count | number | 0 | Warm instances (0 = scale to zero) |
max_instance_count | number | 10 | Max instances (cost cap) |
max_instance_request_concurrency | number | 1 | Concurrent requests per instance |
environment_variables | map(string) | {} | Plain runtime env vars |
build_environment_variables | map(string) | {} | Build-time env vars |
secret_environment_variables | map(object) | {} | Env vars from Secret Manager (secret, version, project_id) |
ingress_settings | string | ALLOW_ALL | Ingress restriction |
all_traffic_on_latest_revision | bool | true | Route all traffic to latest revision |
vpc_connector | string | null | Serverless VPC Access connector |
vpc_connector_egress_settings | string | PRIVATE_RANGES_ONLY | VPC egress mode |
create_service_account | bool | true | Create dedicated runtime SA |
service_account_email | string | null | Existing runtime SA (when not creating one) |
grant_secret_access | bool | true | Auto-grant secretAccessor on referenced secrets |
event_trigger | object | null | Eventarc trigger (null = HTTP function) |
allow_unauthenticated | bool | false | Grant allUsers invoker |
invoker_members | list(string) | [] | Members granted roles/run.invoker |
labels | map(string) | {} | Function labels |
Outputs
| Name | Description |
|---|---|
function_id | Fully-qualified function ID |
function_name | Function name |
function_uri | HTTPS URL of the underlying Cloud Run service |
service_account_email | Runtime SA email |
source_object | GCS bucket + object of the uploaded build source |
state | Lifecycle state (e.g. ACTIVE) |
License
Commercial — LicenseRef-IaCBazaar-Commercial. See the IaC Bazaar terms.