Skip to content

Commit b0626cb

Browse files
authored
Merge pull request #35 from mmontan/safe-sql
Added a module for MySQL for configurations that are safer than the default
2 parents 02a3a5d + 2bcb32a commit b0626cb

File tree

31 files changed

+1413
-21
lines changed

31 files changed

+1413
-21
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ In order to operate with the Service Account you must activate the following API
2929

3030
- Cloud SQL API
3131

32+
In order to use Private Service Access, required for using Private IPs, you must activate
33+
the following APIs on the project where your VPC resides:
34+
35+
- Cloud SQL Admin API
36+
- Compute Engine API
37+
- Service Networking API
38+
- Cloud Resource Manager API
39+
3240
#### Service Account Credentials
3341

3442
You can pass the service account credentials into this module by setting the following environment variables:
@@ -62,7 +70,7 @@ The integration tests for this module leverage kitchen-terraform and kitchen-ins
6270
You must set up by manually before running the integration test:
6371

6472
```sh
65-
for instance in mysql-simple mysql-ha postgresql-simple postgresql-ha; do
73+
for instance in mysql-simple mysql-ha postgresql-simple postgresql-ha safer-mysql-simple; do
6674
cp "test/fixtures/$instance/terraform.tfvars.example" "test/fixtures/$instance/terraform.tfvars"
6775
$EDITOR "test/fixtures/$instance/terraform.tfvars"
6876
done
@@ -72,6 +80,8 @@ And then, you should pass the service account credentials for running inspec by
7280

7381
- `GOOGLE_APPLICATION_CREDENTIALS`
7482

83+
The project used for testing needs the Cloud Resource Manager API service enabled, and the service account should be assigned `roles/compute.networkAdmin` (in addition to `roles/cloudsql.admin`) to instantiate the VPC required in the tests.
84+
7585
The tests will do the following:
7686

7787
- Perform `bundle install` command

examples/mysql-and-postgres/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ chmod +x cloud_sql_proxy
2828
```bash
2929
MYSQL_CONN_NAME=$(terraform output mysql_conn)
3030
PSQL_CONN_NAME=$(terraform output psql_conn)
31+
SAFER_MYSQL_CONN_NAME=$(terraform output safer_mysql_conn)
3132

32-
./cloud_sql_proxy -instances=${MYSQL_CONN_NAME}=tcp:3306,${PSQL_CONN_NAME}=tcp:5432 &
33+
./cloud_sql_proxy -instances=${MYSQL_CONN_NAME}=tcp:3306,${PSQL_CONN_NAME}=tcp:5432,${MYSQL_CONN_NAME}=tcp:6306 &
3334
```
3435

3536
3. Get the generated user passwords:
3637

3738
```
3839
echo MYSQL_PASSWORD=$(terraform output mysql_user_pass)
3940
echo PSQL_PASSWORD=$(terraform output psql_user_pass)
41+
echo SAFER_MYSQL_PASSWORD=$(terraform output safer_mysql_user_pass)
4042
```
4143

4244
4. Test the MySQL connection:
@@ -55,6 +57,14 @@ psql -h 127.0.0.1 --user default
5557

5658
> When prompted, enter the value of PSQL_PASSWORD
5759
60+
4. Test the MySQL connection to the safer second instance:
61+
62+
```
63+
mysql -udefault -p --host 127.0.0.1 --port 6306 default
64+
```
65+
66+
> When prompted, enter the value of SAFER_MYSQL_PASSWORD
67+
5868
## Cleanup
5969

6070
1. Stop the Cloud SQL Proxy:

examples/mysql-and-postgres/main.tf

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,33 @@ provider "google" {
3838
region = "${var.region}"
3939
}
4040

41+
provider "google-beta" {
42+
region = "${var.region}"
43+
}
44+
4145
variable "network_name" {
4246
default = "mysql-psql-example"
4347
}
4448

49+
data "google_client_config" "current" {}
50+
51+
variable "project_id" {}
52+
4553
resource "google_compute_network" "default" {
54+
project = "${var.project_id}"
4655
name = "${var.network_name}"
47-
auto_create_subnetworks = "false"
56+
auto_create_subnetworks = false
4857
}
4958

5059
resource "google_compute_subnetwork" "default" {
60+
project = "${var.project_id}"
5161
name = "${var.network_name}"
5262
ip_cidr_range = "10.127.0.0/20"
5363
network = "${google_compute_network.default.self_link}"
5464
region = "${var.region}"
5565
private_ip_google_access = true
5666
}
5767

58-
data "google_client_config" "current" {}
59-
6068
resource "random_id" "name" {
6169
byte_length = 2
6270
}
@@ -65,10 +73,12 @@ module "mysql-db" {
6573
source = "../../modules/mysql"
6674
name = "example-mysql-${random_id.name.hex}"
6775
database_version = "${var.mysql_version}"
68-
project_id = "${data.google_client_config.current.project}"
76+
project_id = "${var.project_id}"
6977
zone = "c"
7078

7179
ip_configuration = [{
80+
ipv4_enabled = true
81+
7282
authorized_networks = [{
7383
name = "${var.network_name}"
7484
value = "${google_compute_subnetwork.default.ip_cidr_range}"
@@ -87,29 +97,71 @@ module "postgresql-db" {
8797
source = "../../modules/postgresql"
8898
name = "example-postgresql-${random_id.name.hex}"
8999
database_version = "${var.postgresql_version}"
90-
project_id = "${data.google_client_config.current.project}"
100+
project_id = "${var.project_id}"
91101
zone = "c"
92102

93103
ip_configuration = [{
104+
ipv4_enabled = true
105+
94106
authorized_networks = [{
95107
name = "${var.network_name}"
96108
value = "${google_compute_subnetwork.default.ip_cidr_range}"
97109
}]
98110
}]
99111
}
100112

113+
// We define a connection with the VPC of the Cloud SQL instance.
114+
module "private-service-access" {
115+
source = "../../modules/private_service_access"
116+
project_id = "${var.project_id}"
117+
vpc_network = "${google_compute_network.default.self_link}"
118+
}
119+
120+
module "safer-mysql-db" {
121+
source = "../../modules/safer_mysql"
122+
name = "example-safer-mysql-${random_id.name.hex}"
123+
database_version = "${var.mysql_version}"
124+
project_id = "${var.project_id}"
125+
region = "${var.region}"
126+
zone = "c"
127+
128+
# By default, all users will be permitted to connect only via the
129+
# Cloud SQL proxy.
130+
additional_users = [{
131+
name = "app"
132+
},
133+
{
134+
name = "readonly"
135+
},
136+
]
137+
138+
assign_public_ip = true
139+
vpc_network = "${google_compute_network.default.self_link}"
140+
141+
// Used to enforce ordering in the creation of resources.
142+
peering_completed = "${module.private-service-access.peering_completed}"
143+
}
144+
101145
output "mysql_conn" {
102-
value = "${data.google_client_config.current.project}:${var.region}:${module.mysql-db.instance_name}"
146+
value = "${module.mysql-db.instance_connection_name}"
103147
}
104148

105149
output "mysql_user_pass" {
106150
value = "${module.mysql-db.generated_user_password}"
107151
}
108152

109153
output "psql_conn" {
110-
value = "${data.google_client_config.current.project}:${var.region}:${module.postgresql-db.instance_name}"
154+
value = "${module.postgresql-db.instance_connection_name}"
111155
}
112156

113157
output "psql_user_pass" {
114158
value = "${module.postgresql-db.generated_user_password}"
115159
}
160+
161+
output "safer_mysql_conn" {
162+
value = "${module.safer-mysql-db.instance_connection_name}"
163+
}
164+
165+
output "safer_mysql_user_pass" {
166+
value = "${module.safer-mysql-db.generated_user_password}"
167+
}

kitchen.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ suites:
3737
name: terraform
3838
root_module_directory: test/fixtures/postgresql-ha
3939
command_timeout: 1800
40+
- name: safer-mysql-simple
41+
driver:
42+
name: terraform
43+
root_module_directory: test/fixtures/safer-mysql-simple
44+
command_timeout: 1800
45+
- name: private-service-access
46+
driver:
47+
name: terraform
48+
root_module_directory: test/fixtures/private-service-access
49+
command_timeout: 1800

modules/mysql/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ resource "google_sql_database_instance" "default" {
3535
activation_policy = "${var.activation_policy}"
3636
authorized_gae_applications = ["${var.authorized_gae_applications}"]
3737
backup_configuration = ["${var.backup_configuration}"]
38-
ip_configuration = "${local.ip_configurations["${local.ip_configuration_enabled ? "enabled" : "disabled"}"]}"
38+
ip_configuration = ["${local.ip_configurations["${local.ip_configuration_enabled ? "enabled" : "disabled"}"]}"]
3939

4040
disk_autoresize = "${var.disk_autoresize}"
4141

modules/postgresql/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ resource "google_sql_database_instance" "default" {
3535
availability_type = "${var.availability_type}"
3636
authorized_gae_applications = ["${var.authorized_gae_applications}"]
3737
backup_configuration = ["${var.backup_configuration}"]
38-
ip_configuration = "${local.ip_configurations["${local.ip_configuration_enabled ? "enabled" : "disabled"}"]}"
38+
ip_configuration = ["${local.ip_configurations["${local.ip_configuration_enabled ? "enabled" : "disabled"}"]}"]
3939

4040
disk_autoresize = "${var.disk_autoresize}"
4141
disk_size = "${var.disk_size}"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Submodule for VPC peering Cloud SQL services
2+
3+
MySQL [Private IP](https://cloud.google.com/sql/docs/mysql/private-ip)
4+
configurations require a special peering between your VPC network and a
5+
VPC managed by Google. The module supports creating such a peering.
6+
7+
It is sufficient to instantiate this module once for all MySQL instances
8+
that are connected to the same VPC.
9+
10+
> NOTE: See the linked [documentation](https://cloud.google.com/sql/docs/mysql/private-ip)
11+
> for all requirements for accessing a MySQL instance via its Private IP.
12+
13+
[^]: (autogen_docs_start)
14+
15+
## Inputs
16+
17+
| Name | Description | Type | Default | Required |
18+
|------|-------------|:----:|:-----:|:-----:|
19+
| address | First IP address of the IP range to allocate to CLoud SQL instances and other Private Service Access services. If not set, GCP will pick a valid one for you. | string | `""` | no |
20+
| ip\_version | IP Version for the allocation. Can be IPV4 or IPV6. | string | `""` | no |
21+
| labels | The key/value labels for the IP range allocated to the peered network. | map | `<map>` | no |
22+
| prefix\_length | Prefix length of the IP range reserved for Cloud SQL instances and other Private Service Access services. Defaults to /16. | string | `"16"` | no |
23+
| project\_id | The project ID of the VPC network to peer. This can be a shared VPC host projec. | string | n/a | yes |
24+
| vpc\_network | Name of the VPC network to peer. | string | n/a | yes |
25+
26+
## Outputs
27+
28+
| Name | Description |
29+
|------|-------------|
30+
| address | First IP of the reserved range. |
31+
| google\_compute\_global\_address\_name | URL of the reserved range. |
32+
| peering\_completed | Use for enforce ordering between resource creation |
33+
34+
[^]: (autogen_docs_end)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// We define a VPC peering subnet that will be peered with the
18+
// Cloud SQL instance network. The Cloud SQL instance will
19+
// have a private IP within the provided range.
20+
// https://cloud.google.com/vpc/docs/configure-private-services-access
21+
resource "google_compute_global_address" "google-managed-services-range" {
22+
provider = "google-beta"
23+
project = "${var.project_id}"
24+
name = "google-managed-services-${var.vpc_network}"
25+
purpose = "VPC_PEERING"
26+
address = "${var.address}"
27+
prefix_length = "${var.prefix_length}"
28+
ip_version = "${var.ip_version}"
29+
labels = "${var.labels}"
30+
address_type = "INTERNAL"
31+
network = "${var.vpc_network}"
32+
}
33+
34+
# Creates the peering with the producer network.
35+
resource "google_service_networking_connection" "private_service_access" {
36+
provider = "google-beta"
37+
network = "${google_compute_global_address.google-managed-services-range.network}"
38+
service = "servicenetworking.googleapis.com"
39+
reserved_peering_ranges = ["${google_compute_global_address.google-managed-services-range.name}"]
40+
}
41+
42+
resource "null_resource" "dependency_setter" {
43+
depends_on = [
44+
"google_service_networking_connection.private_service_access",
45+
]
46+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
output "address" {
18+
value = "${google_compute_global_address.google-managed-services-range.address}"
19+
description = "First IP of the reserved range."
20+
}
21+
22+
output "google_compute_global_address_name" {
23+
value = "${google_compute_global_address.google-managed-services-range.name}"
24+
description = "URL of the reserved range."
25+
}
26+
27+
output "peering_completed" {
28+
value = "${null_resource.dependency_setter.id}"
29+
description = "Use for enforce ordering between resource creation"
30+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright 2018 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
variable "project_id" {
18+
description = "The project ID of the VPC network to peer. This can be a shared VPC host projec."
19+
}
20+
21+
variable "vpc_network" {
22+
description = "Name of the VPC network to peer."
23+
}
24+
25+
variable "address" {
26+
description = "First IP address of the IP range to allocate to CLoud SQL instances and other Private Service Access services. If not set, GCP will pick a valid one for you."
27+
default = ""
28+
}
29+
30+
variable "prefix_length" {
31+
description = "Prefix length of the IP range reserved for Cloud SQL instances and other Private Service Access services. Defaults to /16."
32+
default = "16"
33+
}
34+
35+
variable "ip_version" {
36+
description = "IP Version for the allocation. Can be IPV4 or IPV6."
37+
default = ""
38+
}
39+
40+
variable "labels" {
41+
description = "The key/value labels for the IP range allocated to the peered network."
42+
default = {}
43+
}

0 commit comments

Comments
 (0)