Skip to content

Commit

Permalink
feat: adds secure cloud-function-core sub-module (#20)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Peabody <andrewpeabody@google.com>
Co-authored-by: Grant Sorbo <gtsorbo@google.com>
  • Loading branch information
3 people committed Apr 25, 2023
1 parent 267109b commit c9c197f
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 0 deletions.
101 changes: 101 additions & 0 deletions modules/secure-cloud-function-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Secure Cloud Function (2nd Gen) Core

This module handles the basic deployment core configurations for Cloud Function (2nd Gen) module.

The resources/services/activations/deletions that this module will create/trigger are:

* Creates a Cloud Function (2nd Gen).
* Creates the Cloud Function source bucket in the same location as the Cloud Function.
* Configure the EventArc Google Channel to use Customer Encryption Key in the Cloud Function location.
* **Warning:** If there is another CMEK configured for the same region, it will be overwritten.
* Creates a private worker pool for Cloud Build configured to not use External IP.
* Grants Cloud Functions Invoker to EventArc Trigger Service Account.

## Usage

```hcl
module "secure_cloud_function_core" {
source = "GoogleCloudPlatform/cloud-functions/google//modules/secure-cloud-function-core"
function_name = <FUNCTION-NAME>
function_description = <FUNCTION-DESCRIPTION>
project_id = <PROJECT-ID>
project_number = <PROJECT-NUMBER>
labels = <RESOURCES-LABELS>
location = <FUNCTION-LOCATION>
runtime = <FUNCTION-RUNTIME>
entry_point = <FUNCTION-ENTRY-POINT>
storage_source = <FUNCTION-SOURCE-BUCKET>
build_environment_variables = <FUNCTION-BUILD-ENV-VARS>
event_trigger = <FUNCTION-EVENT-TRIGGER>
encryption_key = <CUSTOMER-ENCRYPTION-KEY>
service_config = {
vpc_connector = <FUNCTION-VPC-CONNECTOR>
service_account_email = <FUNCTION-SERVICE-ACCOUNT-EMAIL>
ingress_settings = "ALLOW_INTERNAL_AND_GCLB"
all_traffic_on_latest_revision = true
vpc_connector_egress_settings = "PRIVATE_RANGES_ONLY"
runtime_env_variables = <FUNCTION-RUNTIME-ENV-VARS>
runtime_secret_env_variables = <FUNCTION-RUNTIME-SECRET-ENV-VARS>
secret_volumes = <FUNCTION-SECRET-VOLUMES>
}
```

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| build\_environment\_variables | A set of key/value environment variable pairs to be used when building the Function. | `map(string)` | `{}` | no |
| encryption\_key | The KMS Key to Encrypt Event Arc, source Bucket, docker repository. | `string` | n/a | yes |
| entry\_point | The name of a method in the function source which will be invoked when the function is executed. | `string` | n/a | yes |
| event\_trigger | A source that fires events in response to a condition in another service. | <pre>object({<br> trigger_region = optional(string)<br> event_type = string<br> service_account_email = string<br> pubsub_topic = optional(string)<br> retry_policy = string<br> event_filters = optional(set(object({<br> attribute = string<br> attribute_value = string<br> operator = optional(string)<br> })))<br> })</pre> | n/a | yes |
| force\_destroy | Set the `force_destroy` attribute on the Cloud Storage. | `bool` | `false` | no |
| function\_description | The description of the Cloud Function to create. | `string` | `""` | no |
| function\_name | The name of the Cloud Function to create. | `string` | n/a | yes |
| labels | Labels to be assigned to resources. | `map(any)` | `{}` | no |
| location | Cloud Function deployment location. | `string` | `"us-east4"` | no |
| project\_id | The project ID to deploy to. | `string` | n/a | yes |
| repo\_source | The source repository where the Cloud Function Source is stored. Do not use combined with source\_path. | <pre>object({<br> project_id = optional(string)<br> repo_name = string<br> branch_name = string<br> dir = optional(string)<br> tag_name = optional(string)<br> commit_sha = optional(string)<br> invert_regex = optional(bool, false)<br> })</pre> | `null` | no |
| runtime | The runtime in which the function will be executed. | `string` | n/a | yes |
| service\_config | Details of the service | <pre>object({<br> max_instance_count = optional(string, 100)<br> min_instance_count = optional(string, 1)<br> available_memory = optional(string, "256M")<br> timeout_seconds = optional(string, 60)<br> runtime_env_variables = optional(map(string), null)<br> runtime_secret_env_variables = optional(set(object({<br> key_name = string<br> project_id = optional(string)<br> secret = string<br> version = string<br> })), null)<br> secret_volumes = optional(set(object({<br> mount_path = string<br> project_id = optional(string)<br> secret = string<br> versions = set(object({<br> version = string<br> path = string<br> }))<br> })), null)<br> vpc_connector = string<br> vpc_connector_egress_settings = optional(string, "PRIVATE_RANGES_ONLY")<br> ingress_settings = optional(string, "ALLOW_INTERNAL_AND_GCLB")<br> service_account_email = string<br> all_traffic_on_latest_revision = optional(bool, true)<br> })</pre> | n/a | yes |
| storage\_source | Get the source from this location in Google Cloud Storage. | <pre>object({<br> bucket = string<br> object = string<br> generation = optional(string, null)<br> })</pre> | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| service\_name | Name of the created service. |
| service\_url | The URL on which the deployed service is available. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

## Requirements

### Software

The following dependencies must be available:

* [Terraform](https://www.terraform.io/downloads.html) >= 0.13.0
* [Terraform Provider for GCP](https://github.com/terraform-providers/terraform-provider-google) plugin < 5.0

### APIs

A project with the following APIs enabled must be used to host the
resources of this module:

* Serverless Project
* Google Cloud Function Service: `cloudfunctions.googleapis.com`
* Google Compute Service: `compute.googleapis.com`

### Service Account

A service account with the following roles must be used to provision
the resources of this module:

* Cloud Function Developer: `roles/cloudfunctions.developer`
* Compute Network User: `roles/compute.networkUser`
* Artifact Registry Reader: `roles/artifactregistry.reader`
94 changes: 94 additions & 0 deletions modules/secure-cloud-function-core/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

data "google_project" "project" {
project_id = var.project_id
}

module "cloudfunction_bucket" {
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "~>3.4"

project_id = var.project_id
labels = var.labels
name = "gcf-v2-sources-${data.google_project.project.number}-${var.location}"
location = var.location
storage_class = "REGIONAL"
force_destroy = var.force_destroy

encryption = {
default_kms_key_name = var.encryption_key
}
}

resource "google_eventarc_google_channel_config" "primary" {
location = var.location
name = "projects/${var.project_id}/locations/${var.location}/googleChannelConfig"
project = var.project_id
crypto_key_name = var.encryption_key
}

resource "google_artifact_registry_repository" "cloudfunction_repo" {
location = var.location
project = var.project_id
repository_id = "rep-cloud-function-${var.function_name}"
description = "This repo stores de image of the secure cloud function"
format = "DOCKER"
kms_key_name = var.encryption_key
}

resource "google_cloudbuild_worker_pool" "pool" {
name = "workerpool"
location = var.location
project = var.project_id
worker_config {
disk_size_gb = 100
machine_type = "e2-standard-8"
no_external_ip = true
}
}

module "cloud_function" {
source = "../../"

function_name = var.function_name
description = var.function_description
project_id = var.project_id
labels = var.labels
function_location = var.location
runtime = var.runtime
entrypoint = var.entry_point
repo_source = var.repo_source
build_env_variables = var.build_environment_variables
event_trigger = var.event_trigger
storage_source = var.storage_source
service_config = var.service_config
docker_repository = google_artifact_registry_repository.cloudfunction_repo.id

depends_on = [
module.cloudfunction_bucket,
google_eventarc_google_channel_config.primary
]
}

// IAM for invoking HTTP functions (roles/cloudfunctions.invoker)
resource "google_cloudfunctions2_function_iam_member" "invokers" {
location = var.location
project = var.project_id
cloud_function = module.cloud_function.function_name
role = "roles/cloudfunctions.invoker"
member = "serviceAccount:${var.event_trigger.service_account_email}"
}
25 changes: 25 additions & 0 deletions modules/secure-cloud-function-core/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "service_name" {
value = module.cloud_function.function_name
description = "Name of the created service."
}

output "service_url" {
value = module.cloud_function.function_uri
description = "The URL on which the deployed service is available."
}
142 changes: 142 additions & 0 deletions modules/secure-cloud-function-core/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


variable "project_id" {
description = "The project ID to deploy to."
type = string
}

variable "encryption_key" {
description = "The KMS Key to Encrypt Event Arc, source Bucket, docker repository."
type = string
}

variable "function_name" {
description = "The name of the Cloud Function to create."
type = string
}

variable "function_description" {
description = "The description of the Cloud Function to create."
type = string
default = ""
}

variable "labels" {
description = "Labels to be assigned to resources."
type = map(any)
default = {}
}

variable "location" {
description = "Cloud Function deployment location."
type = string
default = "us-east4"
}

variable "runtime" {
description = "The runtime in which the function will be executed."
type = string
}

variable "entry_point" {
description = "The name of a method in the function source which will be invoked when the function is executed."
type = string
}

variable "storage_source" {
description = "Get the source from this location in Google Cloud Storage."
type = object({
bucket = string
object = string
generation = optional(string, null)
})
default = null
}

variable "repo_source" {
description = "The source repository where the Cloud Function Source is stored. Do not use combined with source_path."
type = object({
project_id = optional(string)
repo_name = string
branch_name = string
dir = optional(string)
tag_name = optional(string)
commit_sha = optional(string)
invert_regex = optional(bool, false)
})
default = null
}

variable "build_environment_variables" {
type = map(string)
default = {}
description = "A set of key/value environment variable pairs to be used when building the Function."
}

variable "event_trigger" {
type = object({
trigger_region = optional(string)
event_type = string
service_account_email = string
pubsub_topic = optional(string)
retry_policy = string
event_filters = optional(set(object({
attribute = string
attribute_value = string
operator = optional(string)
})))
})
description = "A source that fires events in response to a condition in another service."
}

variable "service_config" {
type = object({
max_instance_count = optional(string, 100)
min_instance_count = optional(string, 1)
available_memory = optional(string, "256M")
timeout_seconds = optional(string, 60)
runtime_env_variables = optional(map(string), null)
runtime_secret_env_variables = optional(set(object({
key_name = string
project_id = optional(string)
secret = string
version = string
})), null)
secret_volumes = optional(set(object({
mount_path = string
project_id = optional(string)
secret = string
versions = set(object({
version = string
path = string
}))
})), null)
vpc_connector = string
vpc_connector_egress_settings = optional(string, "PRIVATE_RANGES_ONLY")
ingress_settings = optional(string, "ALLOW_INTERNAL_AND_GCLB")
service_account_email = string
all_traffic_on_latest_revision = optional(bool, true)
})
description = "Details of the service"
}

variable "force_destroy" {
description = "Set the `force_destroy` attribute on the Cloud Storage."
type = bool
default = false
}
Loading

0 comments on commit c9c197f

Please sign in to comment.