Skip to content

Commit 4c0472e

Browse files
authored
feat: extended the postgresql module to accept IAM users and services accounts (#218)
* feat: extended the postgresql module to accept IAM users and services accounts. * feat: extended the postgresql module to accept IAM users and services accounts.
1 parent b81ff73 commit 4c0472e

File tree

18 files changed

+571
-1
lines changed

18 files changed

+571
-1
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Cloud SQL Database Example
2+
3+
This example shows how to create the public Postgres Cloud SQL database using the Terraform module with IAM accounts.
4+
5+
## Run Terraform
6+
7+
Create resources with terraform:
8+
9+
```bash
10+
terraform init
11+
terraform plan
12+
terraform apply
13+
```
14+
15+
To remove all resources created by terraform:
16+
17+
```bash
18+
terraform destroy
19+
```
20+
21+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
22+
## Inputs
23+
24+
| Name | Description | Type | Default | Required |
25+
|------|-------------|------|---------|:--------:|
26+
| authorized\_networks | List of mapped public networks authorized to access to the instances. Default - short range of GCP health-checkers IPs | `list(map(string))` | <pre>[<br> {<br> "name": "sample-gcp-health-checkers-range",<br> "value": "130.211.0.0/28"<br> }<br>]</pre> | no |
27+
| cloudsql\_pg\_sa | IAM service account user created for Cloud SQL. | `string` | n/a | yes |
28+
| db\_name | The name of the SQL Database instance | `string` | `"example-postgres-public"` | no |
29+
| project\_id | The ID of the project in which resources will be provisioned. | `string` | n/a | yes |
30+
31+
## Outputs
32+
33+
| Name | Description |
34+
|------|-------------|
35+
| name | The name for Cloud SQL instance |
36+
| project\_id | The project to run tests against |
37+
| psql\_conn | The connection name of the master instance to be used in connection strings |
38+
| psql\_user\_pass | The password for the default user. If not set, a random one will be generated and available in the generated\_user\_password output variable. |
39+
| public\_ip\_address | The first public (PRIMARY) IPv4 address assigned for the master instance |
40+
41+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright 2019 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+
provider "google" {
18+
version = "~> 3.22"
19+
}
20+
21+
provider "google-beta" {
22+
version = "~> 3.5"
23+
}
24+
25+
provider "null" {
26+
version = "~> 2.1"
27+
}
28+
29+
provider "random" {
30+
version = "~> 2.2"
31+
}
32+
33+
module "postgresql-db" {
34+
source = "../../modules/postgresql"
35+
name = var.db_name
36+
random_instance_name = true
37+
database_version = "POSTGRES_9_6"
38+
project_id = var.project_id
39+
zone = "us-central1-c"
40+
region = "us-central1"
41+
tier = "db-f1-micro"
42+
43+
deletion_protection = false
44+
45+
ip_configuration = {
46+
ipv4_enabled = true
47+
private_network = null
48+
require_ssl = true
49+
authorized_networks = var.authorized_networks
50+
}
51+
52+
database_flags = [
53+
{
54+
name = "cloudsql.iam_authentication"
55+
value = "On"
56+
},
57+
]
58+
59+
additional_users = [
60+
{
61+
name = "tftest2"
62+
password = "abcdefg"
63+
host = "localhost"
64+
},
65+
{
66+
name = "tftest3"
67+
password = "abcdefg"
68+
host = "localhost"
69+
},
70+
]
71+
72+
# Supports creation of both IAM Users and IAM Service Accounts with provided emails
73+
iam_user_emails = [
74+
var.cloudsql_pg_sa,
75+
76+
]
77+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright 2019 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 "project_id" {
18+
value = var.project_id
19+
description = "The project to run tests against"
20+
}
21+
22+
output "name" {
23+
description = "The name for Cloud SQL instance"
24+
value = module.postgresql-db.instance_name
25+
}
26+
27+
output "psql_conn" {
28+
value = module.postgresql-db.instance_connection_name
29+
description = "The connection name of the master instance to be used in connection strings"
30+
}
31+
32+
output "psql_user_pass" {
33+
value = module.postgresql-db.generated_user_password
34+
description = "The password for the default user. If not set, a random one will be generated and available in the generated_user_password output variable."
35+
}
36+
37+
output "public_ip_address" {
38+
description = "The first public (PRIMARY) IPv4 address assigned for the master instance"
39+
value = module.postgresql-db.public_ip_address
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Copyright 2019 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 ID of the project in which resources will be provisioned."
19+
type = string
20+
}
21+
22+
variable "authorized_networks" {
23+
default = [{
24+
name = "sample-gcp-health-checkers-range"
25+
value = "130.211.0.0/28"
26+
}]
27+
type = list(map(string))
28+
description = "List of mapped public networks authorized to access to the instances. Default - short range of GCP health-checkers IPs"
29+
}
30+
31+
variable "db_name" {
32+
description = "The name of the SQL Database instance"
33+
default = "example-postgres-public"
34+
}
35+
36+
variable "cloudsql_pg_sa" {
37+
type = string
38+
description = "IAM service account user created for Cloud SQL."
39+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright 2019 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+
terraform {
18+
required_version = ">=0.12.6"
19+
}

kitchen.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ suites:
4040
name: terraform
4141
root_module_directory: test/fixtures/postgresql-public
4242
command_timeout: 1800
43+
- name: postgresql-public-iam
44+
driver:
45+
name: terraform
46+
root_module_directory: test/fixtures/postgresql-public-iam
47+
command_timeout: 1800
4348
- name: mysql-private
4449
driver:
4550
name: terraform

modules/postgresql/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Note: CloudSQL provides [disk autoresize](https://cloud.google.com/sql/docs/mysq
2626
| enable\_default\_db | Enable or disable the creation of the default database | `bool` | `true` | no |
2727
| enable\_default\_user | Enable or disable the creation of the default user | `bool` | `true` | no |
2828
| encryption\_key\_name | The full path to the encryption key used for the CMEK disk encryption | `string` | `null` | no |
29+
| iam\_user\_emails | A list of IAM users to be created in your cluster | `list(string)` | `[]` | no |
2930
| insights\_config | The insights\_config settings for the database. | <pre>object({<br> query_string_length = number<br> record_application_tags = bool<br> record_client_address = bool<br> })</pre> | `null` | no |
3031
| ip\_configuration | The ip configuration for the master instances. | <pre>object({<br> authorized_networks = list(map(string))<br> ipv4_enabled = bool<br> private_network = string<br> require_ssl = bool<br> })</pre> | <pre>{<br> "authorized_networks": [],<br> "ipv4_enabled": true,<br> "private_network": null,<br> "require_ssl": null<br>}</pre> | no |
3132
| maintenance\_window\_day | The day of week (1-7) for the master instance maintenance. | `number` | `1` | no |

modules/postgresql/main.tf

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ locals {
2626

2727
databases = { for db in var.additional_databases : db.name => db }
2828
users = { for u in var.additional_users : u.name => u }
29+
iam_users = [for iu in var.iam_user_emails : {
30+
email = iu,
31+
is_account_sa = trimsuffix(iu, "gserviceaccount.com") == iu ? false : true
32+
}]
2933
}
3034

3135
resource "random_id" "suffix" {
@@ -173,6 +177,40 @@ resource "google_sql_user" "additional_users" {
173177
depends_on = [null_resource.module_depends_on, google_sql_database_instance.default]
174178
}
175179

180+
resource "google_project_iam_member" "iam_binding" {
181+
for_each = {
182+
for iu in local.iam_users :
183+
"${iu.email} ${iu.is_account_sa}" => iu
184+
}
185+
project = var.project_id
186+
role = "roles/cloudsql.instanceUser"
187+
member = each.value.is_account_sa ? (
188+
"serviceAccount:${each.value.email}"
189+
) : (
190+
"user:${each.value.email}"
191+
)
192+
}
193+
194+
resource "google_sql_user" "iam_account" {
195+
for_each = {
196+
for iu in local.iam_users :
197+
"${iu.email} ${iu.is_account_sa}" => iu
198+
}
199+
project = var.project_id
200+
name = each.value.is_account_sa ? (
201+
trimsuffix(each.value.email, ".gserviceaccount.com")
202+
) : (
203+
each.value.email
204+
)
205+
instance = google_sql_database_instance.default.name
206+
type = each.value.is_account_sa ? "CLOUD_IAM_SERVICE_ACCOUNT" : "CLOUD_IAM_USER"
207+
208+
depends_on = [
209+
null_resource.module_depends_on,
210+
google_project_iam_member.iam_binding,
211+
]
212+
}
213+
176214
resource "null_resource" "module_depends_on" {
177215
triggers = {
178216
value = length(var.module_depends_on)

modules/postgresql/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ variable "additional_users" {
244244
default = []
245245
}
246246

247+
variable "iam_user_emails" {
248+
description = "A list of IAM users to be created in your cluster"
249+
type = list(string)
250+
default = []
251+
}
252+
247253
variable "create_timeout" {
248254
description = "The optional timout that is applied to limit long database creates."
249255
type = string
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright 2019 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+
module "example" {
18+
source = "../../../examples/postgresql-public-iam"
19+
20+
project_id = var.project_id
21+
authorized_networks = var.authorized_networks
22+
db_name = var.db_name
23+
cloudsql_pg_sa = var.cloudsql_pg_sa
24+
}

0 commit comments

Comments
 (0)