Skip to content

Commit

Permalink
Add a parameter 'registry_project_id'
Browse files Browse the repository at this point in the history
The PR allows configuring the project holding the GCR registry when
used in connection with 'create_service_account'=true and
grant_registry_access=true.

Holding the GCR is a project with other resources increases the risk of
exposing sensitive data to the service account running the nodes, as the
required permissions of role roles/storage.objectViewer provide access
to all storage objects in the project.
  • Loading branch information
mmontan committed Oct 4, 2019
1 parent 81eb717 commit 55ade20
Show file tree
Hide file tree
Showing 23 changed files with 145 additions and 11 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ Then perform the following commands on the root folder:
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure

## Upgrade to v3.0.0

v3.0.0 is a breaking release. Refer to the
[Upgrading to v3.0 guide][upgrading-to-v3.0] for details.

## Upgrade to v2.0.0

v2.0.0 is a breaking release. Refer to the
[Upgrading to v2.0 guide][upgrading-to-v2.0] for details.

## Upgrade to v1.0.0

Version 1.0.0 of this module introduces a breaking change: adding the `disable-legacy-endpoints` metadata field to all node pools. This metadata is required by GKE and [determines whether the `/0.1/` and `/v1beta1/` paths are available in the nodes' metadata server](https://cloud.google.com/kubernetes-engine/docs/how-to/protecting-cluster-metadata#disable-legacy-apis). If your applications do not require access to the node's metadata server, you can leave the default value of `true` provided by the module. If your applications require access to the metadata server, be sure to read the linked documentation to see if you need to set the value for this field to `false` to allow your applications access to the above metadata server paths.

In either case, upgrading to module version `v1.0.0` will trigger a recreation of all node pools in the cluster.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

Expand Down Expand Up @@ -151,6 +167,7 @@ Then perform the following commands on the root folder:
| project\_id | The project ID to host the cluster in (required) | string | n/a | yes |
| region | The region to host the cluster in (required) | string | n/a | yes |
| regional | Whether is a regional cluster (zonal cluster if set false. WARNING: changing this after cluster creation is destructive!) | bool | `"true"` | no |
| registry\_project\_id | Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project. | string | `""` | no |
| remove\_default\_node\_pool | Remove default node pool while setting up the cluster | bool | `"false"` | no |
| service\_account | The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created. | string | `""` | no |
| stub\_domains | Map of stub domains and their resolvers to forward DNS queries for a certain domain to an external DNS server | map(list(string)) | `<map>` | no |
Expand Down Expand Up @@ -212,6 +229,9 @@ following project roles:
- roles/iam.serviceAccountUser
- roles/resourcemanager.projectIamAdmin (only required if `service_account` is set to `create`)

Additionally, if `service_account` is set to `create` and `grant_registry_access` is requested, the service account requires the following role on the `registry_project_id` project:
- roles/resourcemanager.projectIamAdmin

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:

Expand Down
3 changes: 3 additions & 0 deletions autogen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ following project roles:
- roles/iam.serviceAccountUser
- roles/resourcemanager.projectIamAdmin (only required if `service_account` is set to `create`)

Additionally, if `service_account` is set to `create` and `grant_registry_access` is requested, the service account requires the following role on the `registry_project_id` project:
- roles/resourcemanager.projectIamAdmin

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:

Expand Down
2 changes: 1 addition & 1 deletion autogen/sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ resource "google_project_iam_member" "cluster_service_account-monitoring_viewer"

resource "google_project_iam_member" "cluster_service_account-gcr" {
count = var.create_service_account && var.grant_registry_access ? 1 : 0
project = var.project_id
project = var.registry_project_id == "" ? var.project_id : var.registry_project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.cluster_service_account[0].email}"
}
Expand Down
6 changes: 6 additions & 0 deletions autogen/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ variable "grant_registry_access" {
default = false
}

variable "registry_project_id" {
type = string
description = "Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project."
default = ""
}

variable "service_account" {
type = string
description = "The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created."
Expand Down
5 changes: 3 additions & 2 deletions examples/workload_metadata_config/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ module "gke" {
subnetwork = var.subnetwork
ip_range_pods = var.ip_range_pods
ip_range_services = var.ip_range_services
create_service_account = false
service_account = var.compute_engine_service_account
create_service_account = true
grant_registry_access = true
registry_project_id = var.registry_project_id
enable_private_endpoint = true
enable_private_nodes = true
master_ipv4_cidr_block = "172.16.0.0/28"
Expand Down
5 changes: 2 additions & 3 deletions examples/workload_metadata_config/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ variable "ip_range_services" {
description = "The secondary ip range to use for pods"
}

variable "compute_engine_service_account" {
description = "Service account to associate to the nodes in the cluster"
variable "registry_project_id" {
description = "Project name for the GCR registry"
}

4 changes: 4 additions & 0 deletions modules/beta-private-cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ In either case, upgrading to module version `v1.0.0` will trigger a recreation o
| project\_id | The project ID to host the cluster in (required) | string | n/a | yes |
| region | The region to host the cluster in (required) | string | n/a | yes |
| regional | Whether is a regional cluster (zonal cluster if set false. WARNING: changing this after cluster creation is destructive!) | bool | `"true"` | no |
| registry\_project\_id | Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project. | string | `""` | no |
| remove\_default\_node\_pool | Remove default node pool while setting up the cluster | bool | `"false"` | no |
| resource\_usage\_export\_dataset\_id | The dataset id for which network egress metering for this cluster will be enabled. If enabled, a daemonset will be created in the cluster to meter network egress traffic. | string | `""` | no |
| sandbox\_enabled | (Beta) Enable GKE Sandbox (Do not forget to set `image_type` = `COS_CONTAINERD` and `node_version` = `1.12.7-gke.17` or later to use it). | bool | `"false"` | no |
Expand Down Expand Up @@ -258,6 +259,9 @@ following project roles:
- roles/iam.serviceAccountUser
- roles/resourcemanager.projectIamAdmin (only required if `service_account` is set to `create`)

Additionally, if `service_account` is set to `create` and `grant_registry_access` is requested, the service account requires the following role on the `registry_project_id` project:
- roles/resourcemanager.projectIamAdmin

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:

Expand Down
2 changes: 1 addition & 1 deletion modules/beta-private-cluster/sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ resource "google_project_iam_member" "cluster_service_account-monitoring_viewer"

resource "google_project_iam_member" "cluster_service_account-gcr" {
count = var.create_service_account && var.grant_registry_access ? 1 : 0
project = var.project_id
project = var.registry_project_id == "" ? var.project_id : var.registry_project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.cluster_service_account[0].email}"
}
Expand Down
6 changes: 6 additions & 0 deletions modules/beta-private-cluster/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ variable "grant_registry_access" {
default = false
}

variable "registry_project_id" {
type = string
description = "Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project."
default = ""
}

variable "service_account" {
type = string
description = "The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created."
Expand Down
4 changes: 4 additions & 0 deletions modules/beta-public-cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ In either case, upgrading to module version `v1.0.0` will trigger a recreation o
| project\_id | The project ID to host the cluster in (required) | string | n/a | yes |
| region | The region to host the cluster in (required) | string | n/a | yes |
| regional | Whether is a regional cluster (zonal cluster if set false. WARNING: changing this after cluster creation is destructive!) | bool | `"true"` | no |
| registry\_project\_id | Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project. | string | `""` | no |
| remove\_default\_node\_pool | Remove default node pool while setting up the cluster | bool | `"false"` | no |
| resource\_usage\_export\_dataset\_id | The dataset id for which network egress metering for this cluster will be enabled. If enabled, a daemonset will be created in the cluster to meter network egress traffic. | string | `""` | no |
| sandbox\_enabled | (Beta) Enable GKE Sandbox (Do not forget to set `image_type` = `COS_CONTAINERD` and `node_version` = `1.12.7-gke.17` or later to use it). | bool | `"false"` | no |
Expand Down Expand Up @@ -249,6 +250,9 @@ following project roles:
- roles/iam.serviceAccountUser
- roles/resourcemanager.projectIamAdmin (only required if `service_account` is set to `create`)

Additionally, if `service_account` is set to `create` and `grant_registry_access` is requested, the service account requires the following role on the `registry_project_id` project:
- roles/resourcemanager.projectIamAdmin

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:

Expand Down
2 changes: 1 addition & 1 deletion modules/beta-public-cluster/sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ resource "google_project_iam_member" "cluster_service_account-monitoring_viewer"

resource "google_project_iam_member" "cluster_service_account-gcr" {
count = var.create_service_account && var.grant_registry_access ? 1 : 0
project = var.project_id
project = var.registry_project_id == "" ? var.project_id : var.registry_project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.cluster_service_account[0].email}"
}
Expand Down
6 changes: 6 additions & 0 deletions modules/beta-public-cluster/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ variable "grant_registry_access" {
default = false
}

variable "registry_project_id" {
type = string
description = "Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project."
default = ""
}

variable "service_account" {
type = string
description = "The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created."
Expand Down
4 changes: 4 additions & 0 deletions modules/private-cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ In either case, upgrading to module version `v1.0.0` will trigger a recreation o
| project\_id | The project ID to host the cluster in (required) | string | n/a | yes |
| region | The region to host the cluster in (required) | string | n/a | yes |
| regional | Whether is a regional cluster (zonal cluster if set false. WARNING: changing this after cluster creation is destructive!) | bool | `"true"` | no |
| registry\_project\_id | Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project. | string | `""` | no |
| remove\_default\_node\_pool | Remove default node pool while setting up the cluster | bool | `"false"` | no |
| service\_account | The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created. | string | `""` | no |
| stub\_domains | Map of stub domains and their resolvers to forward DNS queries for a certain domain to an external DNS server | map(list(string)) | `<map>` | no |
Expand Down Expand Up @@ -237,6 +238,9 @@ following project roles:
- roles/iam.serviceAccountUser
- roles/resourcemanager.projectIamAdmin (only required if `service_account` is set to `create`)

Additionally, if `service_account` is set to `create` and `grant_registry_access` is requested, the service account requires the following role on the `registry_project_id` project:
- roles/resourcemanager.projectIamAdmin

### Enable APIs
In order to operate with the Service Account you must activate the following APIs on the project where the Service Account was created:

Expand Down
2 changes: 1 addition & 1 deletion modules/private-cluster/sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ resource "google_project_iam_member" "cluster_service_account-monitoring_viewer"

resource "google_project_iam_member" "cluster_service_account-gcr" {
count = var.create_service_account && var.grant_registry_access ? 1 : 0
project = var.project_id
project = var.registry_project_id == "" ? var.project_id : var.registry_project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.cluster_service_account[0].email}"
}
Expand Down
6 changes: 6 additions & 0 deletions modules/private-cluster/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ variable "grant_registry_access" {
default = false
}

variable "registry_project_id" {
type = string
description = "Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project."
default = ""
}

variable "service_account" {
type = string
description = "The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created."
Expand Down
2 changes: 1 addition & 1 deletion sa.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ resource "google_project_iam_member" "cluster_service_account-monitoring_viewer"

resource "google_project_iam_member" "cluster_service_account-gcr" {
count = var.create_service_account && var.grant_registry_access ? 1 : 0
project = var.project_id
project = var.registry_project_id == "" ? var.project_id : var.registry_project_id
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.cluster_service_account[0].email}"
}
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/shared/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,6 @@ output "service_account" {
value = module.example.service_account
}

output "registry_project_id" {
value = var.registry_project_id
}
4 changes: 4 additions & 0 deletions test/fixtures/shared/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ variable "compute_engine_service_account" {
description = "The email address of the service account to associate with the GKE cluster"
}

variable "registry_project_id" {
description = "Project to use for granting access to the GCR registry, if requested"
}

37 changes: 36 additions & 1 deletion test/fixtures/workload_metadata_config/example.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,28 @@
module "example" {
source = "../../../examples/workload_metadata_config"

<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> 5258f89... Removing a few conflicting files.
=======
>>>>>>> 244108e... Removing a few conflicting files.
=======
>>>>>>> 5258f89... Removing a few conflicting files.
project_id = var.project_id
cluster_name_suffix = "-${random_string.suffix.result}"
region = var.region
zones = slice(var.zones, 0, 1)
network = google_compute_network.main.name
subnetwork = google_compute_subnetwork.main.name
ip_range_pods = google_compute_subnetwork.main.secondary_ip_range[0].range_name
ip_range_services = google_compute_subnetwork.main.secondary_ip_range[1].range_name
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
project_id = var.project_id
cluster_name_suffix = "-${random_string.suffix.result}"
region = var.region
Expand All @@ -25,5 +47,18 @@ module "example" {
subnetwork = google_compute_subnetwork.main.name
ip_range_pods = google_compute_subnetwork.main.secondary_ip_range[0].range_name
ip_range_services = google_compute_subnetwork.main.secondary_ip_range[1].range_name
compute_engine_service_account = var.compute_engine_service_account
<<<<<<< HEAD
<<<<<<< HEAD
>>>>>>> d791335... Removed the custom test for create_service_account
=======
>>>>>>> 5258f89... Removing a few conflicting files.
=======
>>>>>>> e7f04bb... Removed the custom test for create_service_account
=======
>>>>>>> 244108e... Removing a few conflicting files.
=======
>>>>>>> d791335... Removed the custom test for create_service_account
=======
>>>>>>> 5258f89... Removing a few conflicting files.
registry_project_id = var.registry_project_id
}
18 changes: 18 additions & 0 deletions test/integration/workload_metadata_config/controls/gcloud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
# limitations under the License.

project_id = attribute('project_id')
registry_project_id = attribute('registry_project_id')
location = attribute('location')
cluster_name = attribute('cluster_name')
service_account = attribute('service_account')

control "gcloud" do
title "Google Compute Engine GKE configuration"
Expand Down Expand Up @@ -55,4 +57,20 @@
end
end
end

describe command("gcloud projects get-iam-policy #{registry_project_id} --format=json") do
its(:exit_status) { should eq 0 }
its(:stderr) { should eq '' }

let!(:iam) do
if subject.exit_status == 0
JSON.parse(subject.stdout)
else
{}
end
end
it "has expected registry roles" do
expect(iam['bindings']).to include("members" => ["serviceAccount:#{service_account}"], "role" => "roles/storage.objectViewer")
end
end
end
6 changes: 6 additions & 0 deletions test/integration/workload_metadata_config/inspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ attributes:
- name: project_id
required: true
type: string
- name: service_account
required: true
type: string
- name: registry_project_id
required: false
type: string
3 changes: 3 additions & 0 deletions test/setup/make_source.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ echo "#!/usr/bin/env bash" > ../source.sh
project_id=$(terraform output project_id)
echo "export TF_VAR_project_id='$project_id'" >> ../source.sh

# We use the same project for registry project in the tests.
echo "export TF_VAR_registry_project_id='$project_id'" >> ../source.sh

sa_json=$(terraform output sa_key)
# shellcheck disable=SC2086
echo "export SERVICE_ACCOUNT_JSON='$(echo $sa_json | base64 --decode)'" >> ../source.sh
Expand Down
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ variable "grant_registry_access" {
default = false
}

variable "registry_project_id" {
type = string
description = "Project holding the Google Container Registry. If empty, we use the cluster project. If grant_registry_access is true, storage.objectViewer role is assigned on this project."
default = ""
}

variable "service_account" {
type = string
description = "The service account to run nodes as if not overridden in `node_pools`. The create_service_account variable default value (true) will cause a cluster-specific service account to be created."
Expand Down

0 comments on commit 55ade20

Please sign in to comment.