Skip to content

Commit

Permalink
feat: Add service identity provisioning support (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
umairidris authored Sep 15, 2020
1 parent d9a7731 commit 3954a89
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ determining that location is as follows:

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| activate\_api\_identities | The list of service identities (Google Managed service account for the API) to force-create for the project (e.g. in order to grant additional roles). APIs in this list will automatically be appended to `activate_apis`. Not including the API in this list will follow the default behaviour for identity creation (which is usually when the first resource using the API is created). | object | `<list>` | no |
| activate\_apis | The list of apis to activate within the project | list(string) | `<list>` | no |
| auto\_create\_network | Create the default network | bool | `"false"` | no |
| billing\_account | The ID of the billing account to associate this project with | string | n/a | yes |
Expand Down
11 changes: 11 additions & 0 deletions examples/project_services/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ provider "google" {
version = "~> 3.30"
}

provider "google-beta" {
version = "~> 3.38"
}

module "project-services" {
source = "../../modules/project_services"
project_id = var.project_id
Expand All @@ -31,4 +35,11 @@ module "project-services" {
"sqladmin.googleapis.com",
"bigquery-json.googleapis.com",
]
activate_api_identities = [{
api = "healthcare.googleapis.com"
roles = [
"roles/healthcare.serviceAgent",
"roles/bigquery.jobUser",
]
}]
}
10 changes: 9 additions & 1 deletion examples/simple_project/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ provider "google" {

provider "google-beta" {
credentials = file(local.credentials_file_path)
version = "~> 3.30"
version = "~> 3.38"
}

provider "null" {
Expand All @@ -47,4 +47,12 @@ module "project-factory" {
billing_account = var.billing_account
credentials_path = local.credentials_file_path
default_service_account = "deprivilege"

activate_api_identities = [{
api = "healthcare.googleapis.com"
roles = [
"roles/healthcare.serviceAgent",
"roles/bigquery.jobUser",
]
}]
}
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module "project-factory" {
folder_id = var.folder_id
sa_role = var.sa_role
activate_apis = var.activate_apis
activate_api_identities = var.activate_api_identities
usage_bucket_name = var.usage_bucket_name
usage_bucket_prefix = var.usage_bucket_prefix
credentials_path = var.credentials_path
Expand Down
6 changes: 3 additions & 3 deletions modules/core_project_factory/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ resource "google_resource_manager_lien" "lien" {
module "project_services" {
source = "../project_services"

project_id = google_project.main.project_id
activate_apis = local.activate_apis

project_id = google_project.main.project_id
activate_apis = local.activate_apis
activate_api_identities = var.activate_api_identities
disable_services_on_destroy = var.disable_services_on_destroy
disable_dependent_services = var.disable_dependent_services
}
Expand Down
9 changes: 9 additions & 0 deletions modules/core_project_factory/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ variable "activate_apis" {
default = ["compute.googleapis.com"]
}

variable "activate_api_identities" {
description = "The list of service identities (Google Managed service account for the API) to force-create for the project (e.g. in order to grant additional roles). APIs in this list will automatically be appended to `activate_apis`. Not including the API in this list will follow the default behaviour for identity creation (which is usually when the first resource using the API is created)."
type = list(object({
api = string
roles = list(string)
}))
default = []
}

variable "usage_bucket_name" {
description = "Name of a GCS bucket to store GCE usage reports in (optional)"
type = string
Expand Down
4 changes: 3 additions & 1 deletion modules/project_services/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ See [examples/project_services](./examples/project_services) for a full example

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| activate\_apis | The list of apis to activate within the project | list(string) | n/a | yes |
| activate\_api\_identities | The list of service identities (Google Managed service account for the API) to force-create for the project (e.g. in order to grant additional roles). APIs in this list will automatically be appended to `activate_apis`. Not including the API in this list will follow the default behaviour for identity creation (which is usually when the first resource using the API is created). | object | `<list>` | no |
| activate\_apis | The list of apis to activate within the project | list(string) | `<list>` | no |
| disable\_dependent\_services | Whether services that are enabled and which depend on this service should also be disabled when this service is destroyed. https://www.terraform.io/docs/providers/google/r/google_project_service.html#disable_dependent_services | string | `"true"` | no |
| disable\_services\_on\_destroy | Whether project services will be disabled when the resources are destroyed. https://www.terraform.io/docs/providers/google/r/google_project_service.html#disable_on_destroy | string | `"true"` | no |
| enable\_apis | Whether to actually enable the APIs. If false, this module is a no-op. | string | `"true"` | no |
Expand All @@ -49,6 +50,7 @@ See [examples/project_services](./examples/project_services) for a full example

| Name | Description |
|------|-------------|
| enabled\_api\_identities | Enabled API identities in the project |
| enabled\_apis | Enabled APIs in the project |
| project\_id | The GCP project you want to enable APIs on |

Expand Down
31 changes: 29 additions & 2 deletions modules/project_services/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,44 @@
*/

locals {
api_set = var.enable_apis ? toset(var.activate_apis) : []
services = toset(concat(var.activate_apis, [for i in var.activate_api_identities : i.api]))
service_identities = flatten([
for i in var.activate_api_identities : [
for r in i.roles :
{ api = i.api, role = r }
]
])
}

/******************************************
APIs configuration
*****************************************/
resource "google_project_service" "project_services" {
for_each = local.api_set
for_each = local.services
project = var.project_id
service = each.value
disable_on_destroy = var.disable_services_on_destroy
disable_dependent_services = var.disable_dependent_services
}

resource "google_project_service_identity" "project_service_identities" {
for_each = {
for i in var.activate_api_identities :
i.api => i
}

provider = google-beta
project = var.project_id
service = each.value.api
}

resource "google_project_iam_member" "project_service_identity_roles" {
for_each = {
for si in local.service_identities :
"${si.api} ${si.role}" => si
}

project = var.project_id
role = each.value.role
member = "serviceAccount:${google_project_service_identity.project_service_identities["${each.value.api}"].email}"
}
5 changes: 5 additions & 0 deletions modules/project_services/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ output "enabled_apis" {
description = "Enabled APIs in the project"
value = [for api in google_project_service.project_services : api.service]
}

output "enabled_api_identities" {
description = "Enabled API identities in the project"
value = { for i in google_project_service_identity.project_service_identities : i.service => i.email }
}
11 changes: 10 additions & 1 deletion modules/project_services/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ variable "enable_apis" {
variable "activate_apis" {
description = "The list of apis to activate within the project"
type = list(string)
default = []
}

variable "activate_api_identities" {
description = "The list of service identities (Google Managed service account for the API) to force-create for the project (e.g. in order to grant additional roles). APIs in this list will automatically be appended to `activate_apis`. Not including the API in this list will follow the default behaviour for identity creation (which is usually when the first resource using the API is created)."
type = list(object({
api = string
roles = list(string)
}))
default = []
}

variable "disable_services_on_destroy" {
Expand All @@ -39,4 +49,3 @@ variable "disable_dependent_services" {
default = "true"
type = string
}

9 changes: 9 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ variable "activate_apis" {
default = ["compute.googleapis.com"]
}

variable "activate_api_identities" {
description = "The list of service identities (Google Managed service account for the API) to force-create for the project (e.g. in order to grant additional roles). APIs in this list will automatically be appended to `activate_apis`. Not including the API in this list will follow the default behaviour for identity creation (which is usually when the first resource using the API is created)."
type = list(object({
api = string
roles = list(string)
}))
default = []
}

variable "usage_bucket_name" {
description = "Name of a GCS bucket to store GCE usage reports in (optional)"
type = string
Expand Down

0 comments on commit 3954a89

Please sign in to comment.