diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/README.md b/blueprints/third-party-solutions/wordpress/cloudrun/README.md new file mode 100644 index 00000000..849eca53 --- /dev/null +++ b/blueprints/third-party-solutions/wordpress/cloudrun/README.md @@ -0,0 +1,139 @@ +# Wordpress deployment on Cloud Run + +43% of the Web is built on Wordpress. Because of its simplicity and versatility, Wordpress can be used for internal websites as well as customer facing e-commerce platforms in small to large businesses, while still offering security. + +This repository contains the necessary Terraform files to deploy a functioning new Wordpress website exposed to the public internet with minimal technical overhead. + +This architecture can be used for the following use cases and more: + +* Blog +* Intranet / internal Wiki +* E-commerce platform + +# Architecture + +![Wordpress on Cloud Run](images/architecture.png "Wordpress on Cloud Run") + +The main components that are deployed in this architecture are the following (you can learn about them by following the hyperlinks): + +* [Cloud Run](https://cloud.google.com/run): serverless PaaS offering to host containers for web-oriented applications, while offering security, scalability and easy versioning +* [Cloud SQL](https://cloud.google.com/sql): Managed solution for SQL databases +* [VPC Serverless Connector](https://cloud.google.com/vpc/docs/serverless-vpc-access): Solution to access the CloudSQL VPC from Cloud Run, using only internal IP addresses + +# Setup + +## Prerequisites + +### Setting up the project for the deployment + +This example will deploy all its resources into the project defined by the `project_id` variable. Please note that we assume this project already exists. However, if you provide the appropriate values to the `project_create` variable, the project will be created as part of the deployment. + +If `project_create` is left to null, the identity performing the deployment needs the `owner` role on the project defined by the `project_id` variable. Otherwise, the identity performing the deployment needs `resourcemanager.projectCreator` on the resource hierarchy node specified by `project_create.parent` and `billing.user` on the billing account specified by `project_create.billing_account_id`. + +## Deployment + +### Step 0: Cloning the repository + +If you want to deploy from your Cloud Shell, click on the image below, sign in if required and when the prompt appears, click on “confirm”. + +[
string
| ✓ | |
+| [wordpress_image](variables.tf#L83) | Image to run with Cloud Run, starts with \"gcr.io\" | string
| ✓ | |
+| [cloud_run_invoker](variables.tf#L18) | IAM member authorized to access the end-point (for example, 'user:YOUR_IAM_USER' for only you or 'allUsers' for everyone) | string
| | "allUsers"
|
+| [cloudsql_password](variables.tf#L24) | CloudSQL password (will be randomly generated by default) | string
| | null
|
+| [create_connector](variables.tf#L30) | Should a VPC serverless connector be created or not | bool
| | true
|
+| [ip_ranges](variables.tf#L37) | CIDR blocks: VPC serverless connector, Private Service Access(PSA) for CloudSQL, CloudSQL VPC | object({…})
| | {…}
|
+| [prefix](variables.tf#L51) | Unique prefix used for resource names. Not used for project if 'project_create' is null. | string
| | ""
|
+| [principals](variables.tf#L57) | List of users to give rights to (CloudSQL admin, client and instanceUser, Logging admin, Service Account User and TokenCreator), eg 'user@domain.com'. | list(string)
| | []
|
+| [project_create](variables.tf#L63) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…})
| | null
|
+| [region](variables.tf#L77) | Region for the created resources | string
| | "europe-west4"
|
+| [wordpress_password](variables.tf#L94) | Password for the Wordpress user (will be randomly generated by default) | string
| | null
|
+| [wordpress_port](variables.tf#L88) | Port for the Wordpress image | number
| | 8080
|
+
+## Outputs
+
+| name | description | sensitive |
+|---|---|:---:|
+| [cloud_run_service](outputs.tf#L17) | CloudRun service URL | ✓ |
+| [cloudsql_password](outputs.tf#L23) | CloudSQL password | ✓ |
+| [wp_password](outputs.tf#L34) | Wordpress user password | ✓ |
+| [wp_user](outputs.tf#L29) | Wordpress username | |
+
+
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/cloudsql.tf b/blueprints/third-party-solutions/wordpress/cloudrun/cloudsql.tf
new file mode 100644
index 00000000..11e6e311
--- /dev/null
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/cloudsql.tf
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2022 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.
+ */
+
+
+resource "random_password" "cloudsql_password" {
+ length = 8
+}
+
+# create a VPC for CloudSQL
+module "vpc" {
+ source = "../../../../modules/net-vpc"
+ project_id = module.project.project_id
+ name = "${local.prefix}sql-vpc"
+ subnets = [
+ {
+ ip_cidr_range = var.ip_ranges.sql_vpc
+ name = "subnet"
+ region = var.region
+ secondary_ip_range = {}
+ }
+ ]
+
+ # Private Service Access
+ psa_config = {
+ ranges = {
+ cloud-sql = var.ip_ranges.psa
+ }
+ routes = null
+ }
+}
+
+
+# create a VPC connector for the ClouSQL VPC
+resource "google_vpc_access_connector" "connector" {
+ count = var.create_connector ? 1 : 0
+ project = module.project.project_id
+ name = "${local.prefix}wp-connector"
+ region = var.region
+ ip_cidr_range = var.ip_ranges.connector
+ network = module.vpc.self_link
+}
+
+
+# Set up CloudSQL
+module "cloudsql" {
+ source = "../../../../modules/cloudsql-instance"
+ project_id = module.project.project_id
+ network = module.vpc.self_link
+ name = "${local.prefix}mysql"
+ region = var.region
+ database_version = local.cloudsql_conf.database_version
+ tier = local.cloudsql_conf.tier
+ databases = [local.cloudsql_conf.db]
+ users = {
+ "${local.cloudsql_conf.user}" = "${local.cloudsql_conf.pass}"
+ }
+}
\ No newline at end of file
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/images/architecture.png b/blueprints/third-party-solutions/wordpress/cloudrun/images/architecture.png
new file mode 100644
index 00000000..ad914ecc
Binary files /dev/null and b/blueprints/third-party-solutions/wordpress/cloudrun/images/architecture.png differ
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/images/button.png b/blueprints/third-party-solutions/wordpress/cloudrun/images/button.png
new file mode 100644
index 00000000..21a3f3de
Binary files /dev/null and b/blueprints/third-party-solutions/wordpress/cloudrun/images/button.png differ
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/main.tf b/blueprints/third-party-solutions/wordpress/cloudrun/main.tf
new file mode 100644
index 00000000..3264619c
--- /dev/null
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/main.tf
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2022 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.
+ */
+
+
+locals {
+ all_principals_iam = [for k in var.principals : "user:${k}"]
+ cloudsql_conf = {
+ database_version = "MYSQL_8_0"
+ tier = "db-g1-small"
+ db = "wp-mysql"
+ user = "admin"
+ pass = var.cloudsql_password == null ? random_password.cloudsql_password.result : var.cloudsql_password
+ }
+ iam = {
+ # CloudSQL
+ "roles/cloudsql.admin" = local.all_principals_iam
+ "roles/cloudsql.client" = local.all_principals_iam
+ "roles/cloudsql.instanceUser" = local.all_principals_iam
+ # common roles
+ "roles/logging.admin" = local.all_principals_iam
+ "roles/iam.serviceAccountUser" = local.all_principals_iam
+ "roles/iam.serviceAccountTokenCreator" = local.all_principals_iam
+ }
+ connector = var.connector == null ? google_vpc_access_connector.connector.0.self_link : var.connector
+ prefix = var.prefix == null ? "" : "${var.prefix}-"
+ wp_user = "user"
+ wp_pass = var.wordpress_password == null ? random_password.wp_password.result : var.wordpress_password
+}
+
+
+# either create a project or set up the given one
+module "project" {
+ source = "../../../../modules/project"
+ name = var.project_id
+ parent = try(var.project_create.parent, null)
+ billing_account = try(var.project_create.billing_account_id, null)
+ project_create = var.project_create != null
+ prefix = var.project_create == null ? null : var.prefix
+ iam = var.project_create != null ? local.iam : {}
+ iam_additive = var.project_create == null ? local.iam : {}
+ services = [
+ "run.googleapis.com",
+ "logging.googleapis.com",
+ "monitoring.googleapis.com",
+ "sqladmin.googleapis.com",
+ "sql-component.googleapis.com",
+ "vpcaccess.googleapis.com",
+ "servicenetworking.googleapis.com"
+ ]
+}
+
+
+resource "random_password" "wp_password" {
+ length = 8
+}
+
+
+# create the Cloud Run service
+module "cloud_run" {
+ source = "../../../../modules/cloud-run"
+ project_id = module.project.project_id
+ name = "${local.prefix}cr-wordpress"
+ region = var.region
+
+ containers = [{
+ image = var.wordpress_image
+ ports = [{
+ name = "http1"
+ protocol = null
+ container_port = var.wordpress_port
+ }]
+ options = {
+ command = null
+ args = null
+ env_from = null
+ # set up the database connection
+ env = {
+ "APACHE_HTTP_PORT_NUMBER" : var.wordpress_port
+ "WORDPRESS_DATABASE_HOST" : module.cloudsql.ip
+ "WORDPRESS_DATABASE_NAME" : local.cloudsql_conf.db
+ "WORDPRESS_DATABASE_USER" : local.cloudsql_conf.user
+ "WORDPRESS_DATABASE_PASSWORD" : local.cloudsql_conf.pass
+ "WORDPRESS_USERNAME" : local.wp_user
+ "WORDPRESS_PASSWORD" : local.wp_pass
+ }
+ }
+ resources = null
+ volume_mounts = null
+ }]
+
+ iam = {
+ "roles/run.invoker" : [var.cloud_run_invoker]
+ }
+
+ revision_annotations = {
+ autoscaling = {
+ min_scale = 1
+ max_scale = 2
+ }
+ # connect to CloudSQL
+ cloudsql_instances = [module.cloudsql.connection_name]
+ vpcaccess_connector = null
+ # allow all traffic
+ vpcaccess_egress = "all-traffic"
+ vpcaccess_connector = local.connector
+ }
+ ingress_settings = "all"
+}
\ No newline at end of file
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/outputs.tf b/blueprints/third-party-solutions/wordpress/cloudrun/outputs.tf
new file mode 100644
index 00000000..3bd300c9
--- /dev/null
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/outputs.tf
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2022 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 "cloud_run_service" {
+ description = "CloudRun service URL"
+ value = module.cloud_run.service.status[0].url
+ sensitive = true
+}
+
+output "cloudsql_password" {
+ description = "CloudSQL password"
+ value = local.cloudsql_conf.pass
+ sensitive = true
+}
+
+output "wp_user" {
+ description = "Wordpress username"
+ value = local.wp_user
+}
+
+output "wp_password" {
+ description = "Wordpress user password"
+ value = local.wp_pass
+ sensitive = true
+}
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/terraform.tfvars.sample b/blueprints/third-party-solutions/wordpress/cloudrun/terraform.tfvars.sample
new file mode 100644
index 00000000..5c71954c
--- /dev/null
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/terraform.tfvars.sample
@@ -0,0 +1,3 @@
+prefix = "wp"
+project_id = "my-wordpress-project"
+wordpress_image = "gcr.io/my-wordpress-project/wordpress"
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/variables.tf b/blueprints/third-party-solutions/wordpress/cloudrun/variables.tf
new file mode 100644
index 00000000..eaa2543b
--- /dev/null
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/variables.tf
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2022 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.
+ */
+
+# Documentation: https://cloud.google.com/run/docs/securing/managing-access#making_a_service_public
+variable "cloud_run_invoker" {
+ type = string
+ description = "IAM member authorized to access the end-point (for example, 'user:YOUR_IAM_USER' for only you or 'allUsers' for everyone)"
+ default = "allUsers"
+}
+
+variable "cloudsql_password" {
+ type = string
+ description = "CloudSQL password (will be randomly generated by default)"
+ default = null
+}
+
+variable "connector" {
+ type = string
+ description = "Existing VPC serverless connector to use if not creating a new one"
+ default = null
+}
+
+variable "create_connector" {
+ type = bool
+ description = "Should a VPC serverless connector be created or not"
+ default = true
+}
+
+# PSA: documentation: https://cloud.google.com/vpc/docs/configure-private-services-access#allocating-range
+variable "ip_ranges" {
+ description = "CIDR blocks: VPC serverless connector, Private Service Access(PSA) for CloudSQL, CloudSQL VPC"
+ type = object({
+ connector = string
+ psa = string
+ sql_vpc = string
+ })
+ default = {
+ connector = "10.8.0.0/28"
+ psa = "10.60.0.0/24"
+ sql_vpc = "10.0.0.0/20"
+ }
+}
+
+variable "prefix" {
+ description = "Unique prefix used for resource names. Not used for project if 'project_create' is null."
+ type = string
+ default = ""
+}
+
+variable "principals" {
+ description = "List of users to give rights to (CloudSQL admin, client and instanceUser, Logging admin, Service Account User and TokenCreator), eg 'user@domain.com'."
+ type = list(string)
+ default = []
+}
+
+variable "project_create" {
+ description = "Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format."
+ type = object({
+ billing_account_id = string
+ parent = string
+ })
+ default = null
+}
+
+variable "project_id" {
+ description = "Project id, references existing project if `project_create` is null."
+ type = string
+}
+
+variable "region" {
+ type = string
+ description = "Region for the created resources"
+ default = "europe-west4"
+}
+
+variable "wordpress_image" {
+ type = string
+ description = "Image to run with Cloud Run, starts with \"gcr.io\""
+}
+
+variable "wordpress_port" {
+ type = number
+ description = "Port for the Wordpress image"
+ default = 8080
+}
+
+variable "wordpress_password" {
+ type = string
+ description = "Password for the Wordpress user (will be randomly generated by default)"
+ default = null
+}
\ No newline at end of file