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

feat: Fleet app operator permissions #1986

Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
926c088
added module for fleet app operator permissions
hosseingolestani May 28, 2024
59b1c46
some fixes to the module variables
hosseingolestani May 28, 2024
d5c239b
used make docker_generate_docs to correct module input/output documen…
hosseingolestani May 28, 2024
fded424
added an empty-string default value for the user and group variables …
hosseingolestani May 28, 2024
7f504ed
added an example module to leverage fleet-app-operator-permissions
hosseingolestani May 29, 2024
8e77e74
changed app operator principal inputs from <user, group> to <app_oper…
hosseingolestani Jul 2, 2024
fd9b18e
added support for 'principal', 'principalSet, and 'serviceAccount' ap…
hosseingolestani Jul 2, 2024
90473bf
simplified the simple_fleet_app_operator_permissions module
hosseingolestani Jul 2, 2024
893360c
simplified simple_fleet_app_operator_permissions a bit more by removi…
hosseingolestani Jul 2, 2024
f427027
added basic go test for simple_fleet_app_operator_permissions
hosseingolestani Jul 2, 2024
2afd832
fixed readme and issues raised by make docker_test_lint
hosseingolestani Jul 3, 2024
e4f9f05
Merge branch 'master' into fleet-app-operator-permissions
apeabody Jul 3, 2024
67222db
made fleet-app-operator-permissions source path relative in the examp…
hosseingolestani Jul 3, 2024
fcfae5a
changed module variables so that users and groups can be provided as …
hosseingolestani Jul 9, 2024
6d9b72b
changed module variable project_id to fleet_project_id
hosseingolestani Jul 10, 2024
f7f6809
simplified validation of the role module variable
hosseingolestani Jul 10, 2024
9a654cf
corrected READMEs regarding how to use the fleet-app-operator-permiss…
hosseingolestani Jul 10, 2024
1922a50
added config for a new project intended to be used for fleet-specific…
hosseingolestani Jul 10, 2024
2015fa8
added test fixture for simple_fleet_app_operator_permissions to provi…
hosseingolestani Jul 10, 2024
7d08847
small variable and validation fixes for fleet-app-operator-permissions
hosseingolestani Jul 10, 2024
7cdfcf0
Merge branch 'master' into fleet-app-operator-permissions
hosseingolestani Jul 10, 2024
4a4ee3e
made app operator an input to the example module and set it in the te…
hosseingolestani Jul 10, 2024
838e7de
Merge branch 'master' into fleet-app-operator-permissions
hosseingolestani Jul 12, 2024
51a2e1b
put back app operator service account in simple_fleet_app_operator_pe…
hosseingolestani Jul 12, 2024
4bc10fb
added roles to gke-project-fleet to permit creation of fleet scope an…
hosseingolestani Jul 12, 2024
622b266
defined IAM bindings for gke-project-fleet
hosseingolestani Jul 12, 2024
c1ffbee
broke down log view condition check in TestSimpleFleetAppOperatorPerm…
hosseingolestani Jul 17, 2024
0f9e63d
Merge branch 'master' into fleet-app-operator-permissions
hosseingolestani Jul 17, 2024
3940b0a
empty commit to run the tests
hosseingolestani Jul 18, 2024
458cdf6
simplified log view access check in TestSimpleFleetAppOperatorPermiss…
hosseingolestani Jul 18, 2024
41d1838
Merge branch 'master' into fleet-app-operator-permissions
apeabody Jul 19, 2024
769d6f9
small fixes for fleet-app-operator-permissionsNotably, use (some part…
hosseingolestani Jul 19, 2024
04119bb
Merge branch 'master' into fleet-app-operator-permissions
apeabody Jul 19, 2024
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
20 changes: 20 additions & 0 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,26 @@ steps:
- verify simple-autopilot-private-non-default-sa
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleAutopilotPrivateNonDefaultSA --stage teardown --verbose']
- id: init simple-fleet-app-operator-permissions
waitFor:
- create-all
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleFleetAppOperatorPermissions --stage init --verbose']
- id: apply simple-fleet-app-operator-permissions
waitFor:
- init simple-fleet-app-operator-permissions
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleFleetAppOperatorPermissions --stage apply --verbose']
- id: verify simple-fleet-app-operator-permissions
waitFor:
- apply simple-fleet-app-operator-permissions
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleFleetAppOperatorPermissions --stage verify --verbose']
- id: teardown simple-fleet-app-operator-permissions
waitFor:
- verify simple-fleet-app-operator-permissions
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestSimpleFleetAppOperatorPermissions --stage teardown --verbose']
tags:
- 'ci'
- 'integration'
Expand Down
26 changes: 26 additions & 0 deletions examples/simple_fleet_app_operator_permissions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Simple App Operator Permissions Setup for a Fleet Scope

This example illustrates how to create a Fleet Scope for a [team](https://cloud.google.com/kubernetes-engine/fleet-management/docs/team-management) and set up permissions for an app operator in the team.

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| fleet\_project\_id | The project to which the Fleet belongs. | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| fleet\_project\_id | The project to which the Fleet belongs. |
| wait | An output (Fleet Scope RBAC Role Binding IDs) to use when you want to depend on granting permissions finishing. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

To provision this example, run the following from within this directory:
- `terraform init` to get the plugins
- `terraform plan` to see the infrastructure plan
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure

50 changes: 50 additions & 0 deletions examples/simple_fleet_app_operator_permissions/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Copyright 2024 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.
*/

locals {
app_operator_id = "app-operator-id"
app_operator_team = "app-operator-team"
app_operator_role = "VIEW"
}

# Create a Service Account, which can be used as an app operator.
resource "google_service_account" "service_account" {
project = var.fleet_project_id
account_id = local.app_operator_id
display_name = "Test App Operator Service Account"
}

# Create a Fleet Scope for the app operator's team.
resource "google_gke_hub_scope" "scope" {
project = var.fleet_project_id
scope_id = local.app_operator_team
}

# Grant permissions to the app operator to work with the Fleet Scope.
module "permissions" {
source = "../../modules/fleet-app-operator-permissions"

fleet_project_id = var.fleet_project_id
scope_id = google_gke_hub_scope.scope.scope_id
users = ["${local.app_operator_id}@${var.fleet_project_id}.iam.gserviceaccount.com"]
groups = []
role = local.app_operator_role

depends_on = [
google_service_account.service_account
]
}

26 changes: 26 additions & 0 deletions examples/simple_fleet_app_operator_permissions/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright 2024 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 "fleet_project_id" {
description = "The project to which the Fleet belongs."
value = var.fleet_project_id
}

output "wait" {
description = "An output (Fleet Scope RBAC Role Binding IDs) to use when you want to depend on granting permissions finishing."
value = module.permissions.wait
}

21 changes: 21 additions & 0 deletions examples/simple_fleet_app_operator_permissions/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright 2024 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 "fleet_project_id" {
description = "The project to which the Fleet belongs."
type = string
}

31 changes: 31 additions & 0 deletions examples/simple_fleet_app_operator_permissions/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright 2024 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.
*/

terraform {
required_version = ">= 1.2.0"

required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.81.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = ">= 4.81.0"
}
}
}

44 changes: 44 additions & 0 deletions modules/fleet-app-operator-permissions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Terrafrom Module for Fleet App Operator Permissions

This module bundles different permissions (IAM and RBAC Role Bindings) required for [Fleet team management](https://cloud.google.com/kubernetes-engine/fleet-management/docs/team-management). A platform admin can use this module to set up permissions for an app operator (user or group) in a team--including usage of Fleet Scopes, Connect Gateway, logging, and metrics--based on predefined roles (VIEW, EDIT, ADMIN).

## Usage
```tf
Example:
module "fleet_app_operator_permissions" {
source = "terraform-google-modules/kubernetes-engine/google//modules/fleet-app-operator-permissions"

fleet_project_id = "my-project-id"
scope_id = "frontend-team"
users = ["[email protected]", "[email protected]"]
groups = ["[email protected]"]
role = "EDIT"
}
```

To deploy this config, run:
- `terraform init` to get the plugins
- `terraform plan` to see the infrastructure plan
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure


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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| fleet\_project\_id | The project to which the Fleet belongs. | `string` | n/a | yes |
| groups | The list of app operator group principals, e.g., `[email protected]`, `principalSet://iam.googleapis.com/locations/global/workforcePools/my-pool/group/people`. | `list(string)` | n/a | yes |
| role | The principals role for the Fleet Scope (`VIEW`/`EDIT`/`ADMIN`). | `string` | n/a | yes |
| scope\_id | The scope for which IAM and RBAC role bindings are created. | `string` | n/a | yes |
| users | The list of app operator user principals, e.g., `[email protected]`, `principal://iam.googleapis.com/locations/global/workforcePools/my-pool/subject/person`, `serviceAccount:[email protected]`. | `list(string)` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| fleet\_project\_id | The project to which the Fleet belongs. |
| wait | An output to use when you want to depend on Scope RBAC Role Binding creation finishing. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
97 changes: 97 additions & 0 deletions modules/fleet-app-operator-permissions/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* Copyright 2024 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.
*/

locals {
user_principals = [for name in var.users : (
startswith(name, "principal://") ? name : (
endswith(name, "gserviceaccount.com") ? "serviceAccount:${name}" : (
"user:${name}"
)))]

group_principals = [for name in var.groups : (
startswith(name, "principalSet://") ? name : (
"group:${name}"
))]

project_level_scope_role = {
"VIEW" = "roles/gkehub.scopeViewerProjectLevel"
"EDIT" = "roles/gkehub.scopeEditorProjectLevel"
"ADMIN" = "roles/gkehub.scopeEditorProjectLevel" # Same as EDIT
}

resource_level_scope_role = {
"VIEW" = "roles/gkehub.scopeViewer"
"EDIT" = "roles/gkehub.scopeEditor"
"ADMIN" = "roles/gkehub.scopeAdmin"
}
}

resource "google_project_iam_binding" "log_view_permissions" {
project = var.fleet_project_id
role = "roles/logging.viewAccessor"
members = concat(local.user_principals, local.group_principals)
condition {
title = "conditional log view access"
description = "log view access for scope ${var.scope_id}"
expression = "resource.name == \"projects/${var.fleet_project_id}/locations/global/buckets/fleet-o11y-scope-${var.scope_id}/views/fleet-o11y-scope-${var.scope_id}-k8s_container\" || resource.name == \"projects/${var.fleet_project_id}/locations/global/buckets/fleet-o11y-scope-${var.scope_id}/views/fleet-o11y-scope-${var.scope_id}-k8s_pod\""
}
}

resource "google_project_iam_binding" "project_level_scope_permissions" {
project = var.fleet_project_id
role = local.project_level_scope_role[var.role]
members = concat(local.user_principals, local.group_principals)
}

resource "google_gke_hub_scope_iam_binding" "resource_level_scope_permissions" {
project = var.fleet_project_id
scope_id = var.scope_id
role = local.resource_level_scope_role[var.role]
members = concat(local.user_principals, local.group_principals)
}

resource "random_id" "user_rand_suffix" {
for_each = toset(var.users)
byte_length = 4
}

resource "google_gke_hub_scope_rbac_role_binding" "scope_rbac_user_role_bindings" {
for_each = toset(var.users)
project = var.fleet_project_id
scope_rbac_role_binding_id = "tf-${random_id.user_rand_suffix[each.key].hex}"
apeabody marked this conversation as resolved.
Show resolved Hide resolved
scope_id = var.scope_id
user = each.key
role {
predefined_role = var.role
}
}

resource "random_id" "group_rand_suffix" {
for_each = toset(var.groups)
byte_length = 4
}

resource "google_gke_hub_scope_rbac_role_binding" "scope_rbac_group_role_bindings" {
for_each = toset(var.groups)
project = var.fleet_project_id
scope_rbac_role_binding_id = "tf-${random_id.group_rand_suffix[each.key].hex}"
apeabody marked this conversation as resolved.
Show resolved Hide resolved
scope_id = var.scope_id
group = each.key
role {
predefined_role = var.role
}
}

28 changes: 28 additions & 0 deletions modules/fleet-app-operator-permissions/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright 2024 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 "fleet_project_id" {
description = "The project to which the Fleet belongs."
value = var.fleet_project_id
}

output "wait" {
apeabody marked this conversation as resolved.
Show resolved Hide resolved
description = "An output to use when you want to depend on Scope RBAC Role Binding creation finishing."
value = {
for k, v in merge(google_gke_hub_scope_rbac_role_binding.scope_rbac_user_role_bindings, google_gke_hub_scope_rbac_role_binding.scope_rbac_group_role_bindings) : k => v.scope_rbac_role_binding_id
}
}

Loading