Skip to content

Commit

Permalink
feat: adds secure-cloud-function + cloud sql example (#30)
Browse files Browse the repository at this point in the history
Co-authored-by: Prabhu <18209477+prabhu34@users.noreply.github.com>
Co-authored-by: Maria Eduarda Martins <mariamartins@ciandt.com>
  • Loading branch information
3 people committed May 26, 2023
1 parent 2ac3d91 commit 8d1005c
Show file tree
Hide file tree
Showing 23 changed files with 1,468 additions and 42 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,8 @@ credentials.json

# tf lock file
.terraform.lock.hcl

# zip files
**/*.zip

**.vscode
100 changes: 89 additions & 11 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

timeout: 3600s
timeout: 7200s
steps:
- id: prepare
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
Expand All @@ -21,37 +21,115 @@ steps:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'

- id: cloud-func-init
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
- id: cloud-func-apply
waitFor:
- prepare

- id: cloud-func-gcs-source-apply
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2GCSSource --stage apply --verbose']
waitFor:
- cloud-func-init
- id: cloud-func-gcs-source-verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2GCSSource --stage verify --verbose']
waitFor:
- cloud-func-gcs-source-apply
- id: cloud-func-gcs-source-teardown
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2GCSSource --stage teardown --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- cloud-func-gcs-source-verify

- id: secure-cloud-func-sql-apply
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2CloudSQL --stage apply --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- cloud-func-init
- id: secure-cloud-func-sql-verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2CloudSQL --stage verify --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- secure-cloud-func-sql-apply
- id: secure-cloud-func-sql-teardown
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2CloudSQL --stage teardown --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- secure-cloud-func-sql-verify

- id: cloud-func-pubsub-trigger-apply
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2PubSubTrigger --stage apply --verbose']
waitFor:
- cloud-func-init
- id: cloud-func-pubsub-trigger-verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2PubSubTrigger --stage verify --verbose']
waitFor:
- cloud-func-pubsub-trigger-apply
- id: cloud-func-pubsub-trigger-teardown
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestGCF2PubSubTrigger --stage teardown --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- cloud-func-pubsub-trigger-verify

- id: secure-cloud-func-bigquery-apply
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage apply --verbose']
args: ['/bin/bash', '-c', 'cft test run TestGCF2BigqueryTrigger --stage apply --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
- id: cloud-func-verify
waitFor:
- cloud-func-init
- id: secure-cloud-func-bigquery-verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage verify --verbose']
args: ['/bin/bash', '-c', 'cft test run TestGCF2BigqueryTrigger --stage verify --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
- id: cloud-func-teardown
waitFor:
- secure-cloud-func-bigquery-apply
- id: secure-cloud-func-bigquery-teardown
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage teardown --verbose']
args: ['/bin/bash', '-c', 'cft test run TestGCF2BigqueryTrigger --stage teardown --verbose']
env:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
waitFor:
- secure-cloud-func-bigquery-verify
tags:
- 'ci'
- 'integration'
- "ci"
- "integration"
substitutions:
_DOCKER_IMAGE_DEVELOPER_TOOLS: 'cft/developer-tools'
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: '1.12'
_DOCKER_IMAGE_DEVELOPER_TOOLS: "cft/developer-tools"
_DOCKER_TAG_VERSION_DEVELOPER_TOOLS: "1.12"
32 changes: 16 additions & 16 deletions examples/secure_cloud_function_bigquery_trigger/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -146,22 +146,22 @@ module "bigquery" {
module "secure_cloud_function" {
source = "../../modules/secure-cloud-function"

function_name = "secure-cloud-function-bigquery"
function_description = "Logs when there is a new row in the BigQuery"
location = local.location
region = local.region
serverless_project_id = module.secure_harness.serverless_project_ids[0]
vpc_project_id = module.secure_harness.network_project_id[0]
kms_project_id = module.secure_harness.security_project_id
key_name = "key-secure-cloud-function"
keyring_name = "krg-secure-cloud-function"
service_account_email = module.secure_harness.service_account_email[module.secure_harness.serverless_project_ids[0]]
connector_name = "con-secure-cloud-function"
subnet_name = module.secure_harness.service_subnet[0]
create_subnet = false
shared_vpc_name = module.secure_harness.service_vpc[0].network.name
prevent_destroy = false
ip_cidr_range = "10.0.0.0/28"
function_name = "secure-cloud-function-bigquery"
function_description = "Logs when there is a new row in the BigQuery"
location = local.location
serverless_project_id = module.secure_harness.serverless_project_ids[0]
serverless_project_number = module.secure_harness.serverless_project_numbers[module.secure_harness.serverless_project_ids[0]]
vpc_project_id = module.secure_harness.network_project_id[0]
kms_project_id = module.secure_harness.security_project_id
key_name = "key-secure-cloud-function"
keyring_name = "krg-secure-cloud-function"
service_account_email = module.secure_harness.service_account_email[module.secure_harness.serverless_project_ids[0]]
connector_name = "con-secure-cloud-function"
subnet_name = module.secure_harness.service_subnet[0]
create_subnet = false
shared_vpc_name = module.secure_harness.service_vpc[0].network.name
prevent_destroy = false
ip_cidr_range = "10.0.0.0/28"
labels = {
env = "development"
billable = "true"
Expand Down
178 changes: 178 additions & 0 deletions examples/secure_cloud_function_with_sql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Secure Cloud Function With Cloud SQL Example

This examples shows how to connect Secure Cloud Function (2nd Gen) with Cloud SQL in different project
using a Shared VPC and multiple projects.

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

* secure-serverless-harness module will apply:
* Creates Security Project
* Creates Shared VPC Project
* Creates Shared Network
* Deny all Egress Rule
* Allow Internal APIs Firewall Rule
* Configure Private Connect
* Creates Cloud Function project
* Creates Cloud SQL project

* secure-serverless-network module will apply:
* Creates Firewall rules on your **VPC Project**.
* Serverless to VPC Connector
* VPC Connector to Serverless
* VPC Connector Health Checks
* Creates a sub network to VPC Connector usage purpose.
* Creates Serverless Connector on your **VPC Project** or **Serverless Project**. Refer the comparison below:
* Advantages of creating connectors in the [VPC Project](https://cloud.google.com/run/docs/configuring/connecting-shared-vpc#host-project)
* Advantages of creating connectors in the [Serverless Project](https://cloud.google.com/run/docs/configuring/connecting-shared-vpc#service-projects)
* Grant the necessary roles for Cloud Function are able to use VPC Connector on your Shared VPC when creating VPC Connector in host project.
* Grant Network User role to Cloud Services service account.
* Grant VPC Access User to Cloud Function Service Identity when deploying VPC Access.

* secure-cloud-serverless-security module will apply:
* Creates KMS Keyring and Key for [customer managed encryption keys](https://cloud.google.com/run/docs/securing/using-cmek) in the **KMS Project** to be used by Cloud Function (2nd Gen).
* Enables Organization Policies related to Cloud Function (2nd Gen) in the **Serverless Project**.
* Allow Ingress only from internal and Cloud Load Balancing.
* Allow VPC Egress to Private Ranges Only.
* When groups emails are provided, this module will grant the roles for each persona.
* Serverless administrator - Service Project
* roles/run.admin
* roles/cloudfunctions.admin
* roles/compute.networkViewer
* compute.networkUser
* Servervless Security Administrator - Security project
* roles/cloudfunctions.viewer
* roles/run.viewer
* roles/cloudkms.viewer
* roles/artifactregistry.reader
* Cloud Function (2nd Gen) developer - Security project
* roles/cloudfunctions.developer
* roles/artifactregistry.writer
* roles/cloudkms.cryptoKeyEncrypter
* Cloud Function (2nd Gen) user - Service project
* roles/cloudfunctions.invoker

* secure-cloud-function-core module will apply:
* 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.
* Enables Container Registry Automatic Scanning.

* The Example will create besides all secure-cloud-function resources:
* Cloud SQL Private Access
* Cloud SQL Instance
* Cloud SQL MYSQL database
* Storage Bucket to store Cloud Function source Code
* KMS Keys to be used by:
* Pub/Sub
* Cloud SQL
* Secret Manager
* Cloud Scheduler
* Pub/Sub Topic
* Secret Manager
* Cloud SQL User
* Secret Manager version saving Database user password
* Firewall rule to allow to connect on Cloud SQL using Private IP
* Import a sample database

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| access\_context\_manager\_policy\_id | The id of the default Access Context Manager policy. Can be obtained by running `gcloud access-context-manager policies list --organization YOUR_ORGANIZATION_ID --format="value(name)"`. This variable must be provided if `create_access_context_manager_access_policy` is set to `false` | `number` | `null` | no |
| access\_level\_members | The list of members who will be in the access level. | `list(string)` | n/a | yes |
| billing\_account | The ID of the billing account to associate this project with. | `string` | n/a | yes |
| create\_access\_context\_manager\_access\_policy | Defines if Access Context Manager will be created by Terraform. If set to `false`, you must provide `access_context_manager_policy_id`. More information about Access Context Manager creation in [this documentation](https://cloud.google.com/access-context-manager/docs/create-access-level). | `bool` | n/a | yes |
| egress\_policies | A list of all [egress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#egress-rules-reference), each list object has a `from` and `to` value that describes egress\_from and egress\_to.<br><br>Example: `[{ from={ identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`<br><br>Valid Values:<br>`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`<br>`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)<br>`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions). | <pre>list(object({<br> from = any<br> to = any<br> }))</pre> | `[]` | no |
| folder\_id | The ID of a folder to host the infrastructure created in this example. | `string` | `""` | no |
| ingress\_policies | A list of all [ingress policies](https://cloud.google.com/vpc-service-controls/docs/ingress-egress-rules#ingress-rules-reference), each list object has a `from` and `to` value that describes ingress\_from and ingress\_to.<br><br>Example: `[{ from={ sources={ resources=[], access_levels=[] }, identities=[], identity_type="ID_TYPE" }, to={ resources=[], operations={ "SRV_NAME"={ OP_TYPE=[] }}}}]`<br><br>Valid Values:<br>`ID_TYPE` = `null` or `IDENTITY_TYPE_UNSPECIFIED` (only allow indentities from list); `ANY_IDENTITY`; `ANY_USER_ACCOUNT`; `ANY_SERVICE_ACCOUNT`<br>`SRV_NAME` = "`*`" (allow all services) or [Specific Services](https://cloud.google.com/vpc-service-controls/docs/supported-products#supported_products)<br>`OP_TYPE` = [methods](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions) or [permissions](https://cloud.google.com/vpc-service-controls/docs/supported-method-restrictions). | <pre>list(object({<br> from = any<br> to = any<br> }))</pre> | `[]` | no |
| org\_id | The organization ID. | `string` | n/a | yes |
| terraform\_service\_account | The e-mail of the service account who will impersionate when creating infrastructure. | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| cloud\_function\_name | The service account email created to be used by Cloud Function. |
| cloud\_sql\_kms\_key | The KMS Key create to encrypt Cloud SQL. |
| cloudfunction\_bucket | The Cloud Function source bucket. |
| cloudfunction\_bucket\_name | Name of the Cloud Function source bucket. |
| cloudfunction\_url | The URL on which the deployed service is available. |
| cloudsql\_project\_id | The Cloud SQL project id. |
| connector\_id | VPC serverless connector ID. |
| mysql\_conn | The connection name of the master instance to be used in connection strings. |
| mysql\_name | The name for Cloud SQL instance. |
| mysql\_private\_ip\_address | The first private (PRIVATE) IPv4 address assigned for the master instance. |
| mysql\_public\_ip\_address | The first public (PRIMARY) IPv4 address assigned for the master instance. |
| mysql\_user | The user created in database instance. |
| network\_project\_id | The network project id. |
| restricted\_access\_level\_name | Access level name. |
| restricted\_service\_perimeter\_name | Service Perimeter name. |
| scheduler\_name | Cloud Scheduler Job name. |
| secret\_kms\_key | The KMS Key create to encrypt Secrets. |
| secret\_manager\_id | Secret Manager id created to store Database password. |
| secret\_manager\_name | Secret Manager name created to store Database password. |
| secret\_manager\_version | Secret Manager version created to store Database password. |
| security\_project\_id | The security project id. |
| security\_project\_number | The security project number. |
| serverless\_project\_id | The serverless project id. |
| serverless\_project\_number | The serverless project number. |
| service\_account\_email | The service account email created to be used by Cloud Function. |
| service\_vpc\_name | The Network self-link created in harness. |
| service\_vpc\_self\_link | The Network self-link created in harness. |
| service\_vpc\_subnet\_name | The sub-network name created in harness. |
| topic\_id | The Pub/Sub topic which will trigger Cloud Function. |
| topic\_kms\_key | The KMS Key create to encrypt Pub/Sub Topic messages. |

<!-- 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) < 5.0

### APIs

The Secure-cloud-function module will enable the following APIs to the Serverlesss Project:

* Google VPC Access API: `vpcaccess.googleapis.com`
* Compute API: `compute.googleapis.com`
* Container Registry API: `container.googleapis.com`
* Cloud Function API: `run.googleapis.com`

The Secure-cloud-function module will enable the following APIs to the VPC Project:

* Google VPC Access API: `vpcaccess.googleapis.com`
* Compute API: `compute.googleapis.com`

The Secure-cloud-function module will enable the following APIs to the KMS Project:

* Cloud KMS API: `cloudkms.googleapis.com`

### Service Account

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

* VPC Project
* Compute Shared VPC Admin: `roles/compute.xpnAdmin`
* Network Admin: `roles/compute.networkAdmin`
* Security Admin: `roles/compute.securityAdmin`
* Serverless VPC Access Admin: `roles/vpcaccess.admin`
* KMS Project
* Cloud KMS Admin: `roles/cloudkms.admin`
* Serverless Project
* Security Admin: `roles/compute.securityAdmin`
* Serverless VPC Access Admin: `roles/vpcaccess.admin`
* Cloud Function Developer: `roles/run.developer`
* Compute Network User: `roles/compute.networkUser`
* Artifact Registry Reader: `roles/artifactregistry.reader`

**Note:** [Secret Manager Secret Accessor](https://cloud.google.com/run/docs/configuring/secrets#access-secret) role must be granted to the Cloud Function service account to allow read access on the secret.
Loading

0 comments on commit 8d1005c

Please sign in to comment.