Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fabric project submodule initial import #201

Merged
merged 3 commits into from
May 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions modules/fabric-project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Google Cloud Simple Project Creation

This module allows simple Google Cloud Platform project creation, with minimal service and project-level IAM binding management. It's designed to be used for architectural design and rapid prototyping, as part of the [Cloud Foundation Fabric](https://github.com/terraform-google-modules/cloud-foundation-fabric) environments.

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

- one project
- zero or one project metadata items for OSLogin activation
- zero or more project service activations
- zero or more project-level IAM bindings
- zero or more project-level custom roles
- zero or one project liens

## Usage

Basic usage of this module is as follows:

```hcl
module "project_myproject" {
source = "terraform-google-modules/project-factory/google//modules/fabric-project"
parent_id = "1234567890"
parent_type = "folder"
billing_account = "ABCD-1234-ABCD-1234"
prefix = "staging"
name = "myproject"
oslogin = true
owners = ["group:[email protected]"]
oslogin_admins = ["group:[email protected]"]
gce_service_account_roles = ["foo-project:roles/compute.networkUser"]
}
```

[^]: (autogen_docs_start)

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| name | Project name and id suffix. | string | n/a | yes |
| parent\_id | Id of the resource under which the folder will be placed. | string | n/a | yes |
| prefix | Prefix used to generate project id and name | string | n/a | yes |
| activate\_apis | Service APIs to enable. | list | `<list>` | no |
| auto\_create\_network | Whether to create the default network for the project | string | `"false"` | no |
| billing\_account | Billing account id. | string | `""` | no |
| custom\_roles | Map of role name => comma-delimited list of permissions to create in this project. | map | `<map>` | no |
| editors | Optional list of IAM-format members to set as project editor. | list | `<list>` | no |
| extra\_bindings\_members | List of comma-delimited IAM-format members for additional IAM bindings, one item per role. | list | `<list>` | no |
| extra\_bindings\_roles | List of roles for additional IAM bindings, pair with members list below. | list | `<list>` | no |
| gce\_service\_account\_roles | List of project id=>role to assign to the default GCE service account. | list | `<list>` | no |
| labels | Resource labels. | map | `<map>` | no |
| lien\_reason | If non-empty, creates a project lien with this description. | string | `""` | no |
| oslogin | Enable oslogin. | string | `"false"` | no |
| oslogin\_admins | List of IAM-format members that will get OS Login admin role. | list | `<list>` | no |
| oslogin\_users | List of IAM-format members that will get OS Login user role. | list | `<list>` | no |
| owners | Optional list of IAM-format members to set as project owners. | list | `<list>` | no |
| parent\_type | Type of the parent resource, defaults to organization. | string | `"organization"` | no |
| viewers | Optional list of IAM-format members to set as project viewers. | list | `<list>` | no |

## Outputs

| Name | Description |
|------|-------------|
| custom\_roles | Ids of the created custom roles. |
| gce\_service\_account | Default GCE service account (depends on services). |
| gke\_service\_account | Default GKE service account (depends on services). |
| number | Project number (depends on services). |
| project\_id | Project id (depends on services). |

[^]: (autogen_docs_end)
145 changes: 145 additions & 0 deletions modules/fabric-project/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* Copyright 2018 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.
*/

# lifecycle can't be set dynamically, see
# https://github.com/hashicorp/terraform/issues/3116

locals {
all_oslogin_users = "${concat(var.oslogin_users, var.oslogin_admins)}"
num_oslogin_users = "${length(var.oslogin_users) + length(var.oslogin_admins)}"
gce_service_account = "${google_project.project.number}[email protected]"
gke_service_account = "service-${google_project.project.number}@container-engine-robot.iam.gserviceaccount.com"
}

resource "google_project" "project" {
org_id = "${var.parent_type == "organization" ? var.parent_id : ""}"
folder_id = "${var.parent_type == "folder" ? var.parent_id : ""}"
project_id = "${var.prefix}-${var.name}"
name = "${var.prefix}-${var.name}"
billing_account = "${var.billing_account}"
auto_create_network = "${var.auto_create_network}"
labels = "${var.labels}"
}

resource "google_project_services" "services" {
count = "${length(var.activate_apis) > 0 ? 1 : 0}"
project = "${google_project.project.project_id}"

services = [
# "compute.googleapis.com",
# "iam.googleapis.com",
# "oslogin.googleapis.com",
"${var.activate_apis}",
]
}

# this will fail for external users, who need to be manually added so they
# can accept the email invitation to join the project
resource "google_project_iam_member" "owners" {
count = "${length(var.owners)}"
project = "${google_project.project.project_id}"
role = "roles/owner"
member = "${element(var.owners, count.index)}"
}

resource "google_project_iam_member" "editors" {
count = "${length(var.editors)}"
project = "${google_project.project.project_id}"
role = "roles/editor"
member = "${element(var.editors, count.index)}"
}

resource "google_project_iam_member" "viewers" {
count = "${length(var.viewers)}"
project = "${google_project.project.project_id}"
role = "roles/viewer"
member = "${element(var.viewers, count.index)}"
}

resource "google_compute_project_metadata_item" "oslogin_meta" {
count = "${var.oslogin}"
project = "${google_project.project.project_id}"
key = "enable-oslogin"
value = "TRUE"

# depend on services or it will fail on destroy
depends_on = ["google_project_services.services"]
}

resource "google_project_iam_member" "oslogin_admins" {
count = "${var.oslogin ? length(var.oslogin_admins) : 0}"
project = "${google_project.project.project_id}"
role = "roles/compute.osAdminLogin"
member = "${element(var.oslogin_admins, count.index)}"
}

resource "google_project_iam_member" "oslogin_users" {
count = "${var.oslogin ? length(var.oslogin_users) : 0}"
project = "${google_project.project.project_id}"
role = "roles/compute.osLogin"
member = "${element(var.oslogin_users, count.index)}"
}

resource "google_project_iam_member" "oslogin_sa_users" {
count = "${var.oslogin ? local.num_oslogin_users : 0}"
project = "${google_project.project.project_id}"
role = "roles/iam.serviceAccountUser"
member = "${element(local.all_oslogin_users, count.index)}"
}

# this grants the project viewer role to OS Login users, so that they can
# use the CLI to get the list of instances
resource "google_project_iam_member" "oslogin_viewers" {
count = "${var.oslogin ? local.num_oslogin_users : 0}"
project = "${google_project.project.project_id}"
role = "roles/viewer"
member = "${element(local.all_oslogin_users, count.index)}"
}

resource "google_project_iam_custom_role" "roles" {
count = "${length(var.custom_roles)}"
project = "${google_project.project.project_id}"
role_id = "${element(keys(var.custom_roles), count.index)}"
title = "Custom role ${element(keys(var.custom_roles), count.index)}"
description = "Terraform-managed"

permissions = [
"${split(",", element(values(var.custom_roles), count.index))}",
]
}

resource "google_project_iam_binding" "extra" {
count = "${length(var.extra_bindings_roles)}"
project = "${google_project.project.project_id}"
role = "${element(var.extra_bindings_roles, count.index)}"
members = ["${split(",", element(var.extra_bindings_members, count.index))}"]
depends_on = ["google_project_iam_custom_role.roles"]
}

resource "google_resource_manager_lien" "lien" {
count = "${var.lien_reason != "" ? 1 : 0}"
parent = "projects/${google_project.project.number}"
restrictions = ["resourcemanager.projects.delete"]
origin = "created-by-terraform"
reason = "${var.lien_reason}"
}

resource "google_project_iam_member" "gce_service_account" {
count = "${length(var.gce_service_account_roles)}"
project = "${element(split("=>", element(var.gce_service_account_roles, count.index)), 0)}"
role = "${element(split("=>", element(var.gce_service_account_roles, count.index)), 1)}"
member = "serviceAccount:${local.gce_service_account}"
}
44 changes: 44 additions & 0 deletions modules/fabric-project/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright 2018 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 "project_id" {
description = "Project id (depends on services)."
value = "${google_project.project.project_id}"
depends_on = ["google_project_services.services"]
}

output "number" {
description = "Project number (depends on services)."
value = "${google_project.project.number}"
depends_on = ["google_project_services.services"]
}

output "gce_service_account" {
description = "Default GCE service account (depends on services)."
value = "${local.gce_service_account}"
depends_on = ["google_project_services.services"]
}

output "gke_service_account" {
description = "Default GKE service account (depends on services)."
value = "${local.gke_service_account}"
depends_on = ["google_project_services.services"]
}

output "custom_roles" {
description = "Ids of the created custom roles."
value = ["${google_project_iam_custom_role.roles.*.role_id}"]
}
110 changes: 110 additions & 0 deletions modules/fabric-project/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* Copyright 2018 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.
*/

variable "parent_id" {
description = "Id of the resource under which the folder will be placed."
}

variable "parent_type" {
description = "Type of the parent resource, defaults to organization."
default = "organization"
}

variable "prefix" {
description = "Prefix used to generate project id and name"
}

variable "name" {
description = "Project name and id suffix."
}

variable "billing_account" {
description = "Billing account id."
default = ""
}

variable "activate_apis" {
description = "Service APIs to enable."
default = []
}

variable "owners" {
description = "Optional list of IAM-format members to set as project owners."
default = []
}

variable "editors" {
description = "Optional list of IAM-format members to set as project editor."
default = []
}

variable "viewers" {
description = "Optional list of IAM-format members to set as project viewers."
default = []
}

variable "lien_reason" {
description = "If non-empty, creates a project lien with this description."
default = ""
}

variable "oslogin" {
description = "Enable oslogin."
default = false
}

variable "oslogin_admins" {
description = "List of IAM-format members that will get OS Login admin role."
default = []
}

variable "oslogin_users" {
description = "List of IAM-format members that will get OS Login user role."
default = []
}

# TODO: revert to a single map once the following issue is fixed
# https://github.com/hashicorp/terraform/issues/12570

variable "extra_bindings_roles" {
description = "List of roles for additional IAM bindings, pair with members list below."
default = []
}

variable "extra_bindings_members" {
description = "List of comma-delimited IAM-format members for additional IAM bindings, one item per role."
default = []
}

variable "auto_create_network" {
description = "Whether to create the default network for the project"
default = false
}

variable "custom_roles" {
description = "Map of role name => comma-delimited list of permissions to create in this project."
default = {}
}

variable "gce_service_account_roles" {
description = "List of project id=>role to assign to the default GCE service account."
default = []
}

variable "labels" {
description = "Resource labels."
default = {}
}