From d22c54693474494c83f12b328cf72605ad36df34 Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 13 Jul 2023 17:30:53 +0200 Subject: [PATCH 01/21] Manage users on Datadog with Terraform A Terraform module has been created similar to the existing modules to manage team access to Datadog. --- .../team-members-datadog/.terraform.lock.hcl | 24 ++++++++++ terraform/team-members-datadog/README.md | 24 ++++++++++ terraform/team-members-datadog/_terraform.tf | 22 +++++++++ terraform/team-members-datadog/users.tf | 46 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 terraform/team-members-datadog/.terraform.lock.hcl create mode 100644 terraform/team-members-datadog/README.md create mode 100644 terraform/team-members-datadog/_terraform.tf create mode 100644 terraform/team-members-datadog/users.tf diff --git a/terraform/team-members-datadog/.terraform.lock.hcl b/terraform/team-members-datadog/.terraform.lock.hcl new file mode 100644 index 000000000..0546475f2 --- /dev/null +++ b/terraform/team-members-datadog/.terraform.lock.hcl @@ -0,0 +1,24 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/datadog/datadog" { + version = "3.24.1" + constraints = "3.24.1" + hashes = [ + "h1:7FvwbbxieQGQqBctXwxVEBZgJeXXgVQ3rbuynJSy9y0=", + "zh:0a3149e789d7edffd889fd02b3598ee43c66d2ebcf0d3f608e1cfe305e70f56a", + "zh:104452645c4226356c46cb92389079c55ed17e11021c1d9bd36f2217ed586f1e", + "zh:200f69afa9825ea930d7da912c9b72374396cce750db21acb202bfc66ebd27b7", + "zh:357fa63c72f4fb78ea66d28f7b18fff8c880d315f23c8670dce788cdbac1996c", + "zh:55eba04889342a55e65be762be69a5360e71fe0c68b92482eaa435e0dcd74013", + "zh:6a17c224f9b20511ffd79c924d188721560d2e7887cb93aeb032202c2d26c893", + "zh:70e5b36790b108844947fc322342a2b521ed6972a6039702799252fc00f89838", + "zh:7887b230c73f7cd3fb630812b0a2df79b726f4c3b937b2da62e3c8ac5ebc07b4", + "zh:835b2c802980118ff122587f836f343db819050024cefe735e6b646f1c43e27c", + "zh:a4485631340ae00b5b97ace7d1a5a2a5375ec257de144837996023a79614c43e", + "zh:a8807355cb035ffae29991fc4251f17fcc159b78e4ddd64175b3b9d4a0049e0b", + "zh:bacc5961ec34e63322ca96d9e9dd6fd3711d31ed63522beae43b58471ce2e86b", + "zh:bad741f97b083ba722cd0d2f0fdd523c4d83a7bdc43dcee6acc4b715f797d94c", + "zh:c1c6acc6d13abbe6c3aa98187537766d280941ae3a89e09ff891ed55a71732ca", + ] +} diff --git a/terraform/team-members-datadog/README.md b/terraform/team-members-datadog/README.md new file mode 100644 index 000000000..3ac48af64 --- /dev/null +++ b/terraform/team-members-datadog/README.md @@ -0,0 +1,24 @@ +# Team Members on Datadog + +This Terraform configuration manages user accounts on Datadog. When a user is +added to [`users.tf`](users.tf), they get invited to join our Datadog account. + +## Roles + +Datadog uses _roles_ to manage who can do what on the platform. + +Members of the infra-admins team are assigned the `Datadog Admin Role` role. +Members of other teams get the `Datadog Standard Role` role. + +## Usage + +Applying the Terraform configuration requires an API key as well as an app key. +Both can be found on the [Datadog API keys page][api-keys]. + +```shell +export DD_API_KEY="datadog-api-key" +export DD_APP_KEY="datadog-app-key" +terraform plan +``` + +[api-keys]: https://app.datadoghq.com/organization-settings/api-keys diff --git a/terraform/team-members-datadog/_terraform.tf b/terraform/team-members-datadog/_terraform.tf new file mode 100644 index 000000000..df6e24da5 --- /dev/null +++ b/terraform/team-members-datadog/_terraform.tf @@ -0,0 +1,22 @@ +// Configuration for Terraform itself. + +terraform { + required_version = "~> 1" + + required_providers { + datadog = { + source = "datadog/datadog" + version = "3.24.1" + } + } + + backend "s3" { + bucket = "rust-terraform" + key = "simpleinfra/team-members-datadog.tfstate" + region = "us-west-1" + dynamodb_table = "terraform-state-lock" + encrypt = true + } +} + +provider "datadog" {} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf new file mode 100644 index 000000000..0a460c065 --- /dev/null +++ b/terraform/team-members-datadog/users.tf @@ -0,0 +1,46 @@ +locals { + users = { + "jdn" = { + login = "jandavidnose@rustfoundation.org" + name = "Jan David Nose" + role = "Datadog Admin Role" + } + "joel" = { + login = "joelmarcey@rustfoundation.org" + name = "Joel Marcey" + role = "Datadog Admin Role" + } + "mark" = { + login = "mark.simulacrum@gmail.com" + name = "Mark Rousskov" + role = "DataDog Admin Role" + } + "pietro" = { + login = "pietro@pietroalbini.org" + name = "Pietro Albini" + role = "DataDog Admin Role" + } + "rustfoundation" = { + login = "infra@rustfoundation.org" + name = "Rust Foundation Infrastructure" + role = "Datadog Admin Role" + } + } +} + +data "datadog_role" "role" { + for_each = toset(values({ + for index, user in local.users : user.login => user.role + })) + + filter = each.value +} + +resource "datadog_user" "users" { + for_each = local.users + + email = each.value.login + name = each.value.name + roles = [data.datadog_role.role[each.value.role].id] + send_user_invitation = true +} From aa973fd8510a211f8a9c4b81759a70882381c82f Mon Sep 17 00:00:00 2001 From: Jan David Date: Wed, 16 Aug 2023 17:10:32 +0200 Subject: [PATCH 02/21] Add account for Rust admin --- terraform/team-members-datadog/users.tf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 0a460c065..1e729209f 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -1,5 +1,10 @@ locals { users = { + "admin" = { + login = "admin@rust-lang.org" + name = "Rust Admin" + role = "Datadog Admin Role" + } "jdn" = { login = "jandavidnose@rustfoundation.org" name = "Jan David Nose" From 1775650513f5aed21b3c2ea5947330d365d1a79a Mon Sep 17 00:00:00 2001 From: Jan David Date: Tue, 3 Oct 2023 15:14:55 +0200 Subject: [PATCH 03/21] Add accounts for Rust Foundation staff --- terraform/team-members-datadog/users.tf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 1e729209f..25244828b 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -20,6 +20,11 @@ locals { name = "Mark Rousskov" role = "DataDog Admin Role" } + "paullenz" = { + login = "paullenz@rustfoundation.org" + name = "Paul Lenz" + role = "Datadog Read Only Role" + } "pietro" = { login = "pietro@pietroalbini.org" name = "Pietro Albini" @@ -30,6 +35,11 @@ locals { name = "Rust Foundation Infrastructure" role = "Datadog Admin Role" } + "tobias" = { + login = "tobiasbieniek@rustfoundation.org" + name = "Tobias Bieniek" + role = "Datadog Standard Role" + } } } From c251c642ce25e30188111140600e0caad3111fc6 Mon Sep 17 00:00:00 2001 From: Jan David Date: Fri, 6 Oct 2023 14:54:59 +0200 Subject: [PATCH 04/21] Create teams on Datadog --- .../team-members-datadog/.terraform.lock.hcl | 34 ++++++------- terraform/team-members-datadog/_terraform.tf | 2 +- terraform/team-members-datadog/teams.tf | 50 +++++++++++++++++++ 3 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 terraform/team-members-datadog/teams.tf diff --git a/terraform/team-members-datadog/.terraform.lock.hcl b/terraform/team-members-datadog/.terraform.lock.hcl index 0546475f2..33c9bfbcf 100644 --- a/terraform/team-members-datadog/.terraform.lock.hcl +++ b/terraform/team-members-datadog/.terraform.lock.hcl @@ -2,23 +2,23 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/datadog/datadog" { - version = "3.24.1" - constraints = "3.24.1" + version = "3.30.0" + constraints = "3.30.0" hashes = [ - "h1:7FvwbbxieQGQqBctXwxVEBZgJeXXgVQ3rbuynJSy9y0=", - "zh:0a3149e789d7edffd889fd02b3598ee43c66d2ebcf0d3f608e1cfe305e70f56a", - "zh:104452645c4226356c46cb92389079c55ed17e11021c1d9bd36f2217ed586f1e", - "zh:200f69afa9825ea930d7da912c9b72374396cce750db21acb202bfc66ebd27b7", - "zh:357fa63c72f4fb78ea66d28f7b18fff8c880d315f23c8670dce788cdbac1996c", - "zh:55eba04889342a55e65be762be69a5360e71fe0c68b92482eaa435e0dcd74013", - "zh:6a17c224f9b20511ffd79c924d188721560d2e7887cb93aeb032202c2d26c893", - "zh:70e5b36790b108844947fc322342a2b521ed6972a6039702799252fc00f89838", - "zh:7887b230c73f7cd3fb630812b0a2df79b726f4c3b937b2da62e3c8ac5ebc07b4", - "zh:835b2c802980118ff122587f836f343db819050024cefe735e6b646f1c43e27c", - "zh:a4485631340ae00b5b97ace7d1a5a2a5375ec257de144837996023a79614c43e", - "zh:a8807355cb035ffae29991fc4251f17fcc159b78e4ddd64175b3b9d4a0049e0b", - "zh:bacc5961ec34e63322ca96d9e9dd6fd3711d31ed63522beae43b58471ce2e86b", - "zh:bad741f97b083ba722cd0d2f0fdd523c4d83a7bdc43dcee6acc4b715f797d94c", - "zh:c1c6acc6d13abbe6c3aa98187537766d280941ae3a89e09ff891ed55a71732ca", + "h1:oN61IZ1rl+rfzXw0UVVnmFZ/Ulk8bKBsALN6O+p5vqs=", + "zh:01fc43eae96ea3801d95f81e83f151e64ef91dc4b1aedd3ee857c073a891a05d", + "zh:169ca1d8ae0cbb613fa9a7039babffa0a9bc62200d5ac5a027e259b98d8df33e", + "zh:22d75dc6dd9fde39ca1b2b5ceac7026aed2ad801cf81a587dd93e25b94c56ca4", + "zh:4bccc0639a881d44be4e7e2868fe1e0dbc1f0a6ebad1e1e554808bc80979c02c", + "zh:6295eb99ff106e00da52dba699e0b7fcba8b4d0535eac26d61eb17ddde5c2c53", + "zh:68c7de436a0e33ae06e93a5e989445dcc944a102faaec7e9f84762688520bd3c", + "zh:7c3ab23ebe2269c9952a8e91ddc6b05889186c81bb472eed0fdd6cd730350d6f", + "zh:85508c9c377211bd44531824464bf81830badb47e02877b008fce5de02204639", + "zh:8bb6a27c39e7d81d5d8bae00a159aa6a9e665e365393e65602839268893da1cc", + "zh:97f542f3e33df80a245b9f85fb29582fd3598bca4be3ceafd8aa012ba15f88c2", + "zh:cc051226ba800ae5c73a219c775c4fd883203381a4baaa2b1e211545407e42f3", + "zh:cea8b53a4bba00b1c452af5bb5a16d46e56f9d04dacfbcf794397aea105e17c6", + "zh:d56c39142843e945a08b23da9b147817b9b67f8f293b6a8253cd932c095f61b4", + "zh:d7aa186ec0dff53ee776472c902685437d76abe31e9a6872d74c03f0ae25ff3b", ] } diff --git a/terraform/team-members-datadog/_terraform.tf b/terraform/team-members-datadog/_terraform.tf index df6e24da5..4e7036be4 100644 --- a/terraform/team-members-datadog/_terraform.tf +++ b/terraform/team-members-datadog/_terraform.tf @@ -6,7 +6,7 @@ terraform { required_providers { datadog = { source = "datadog/datadog" - version = "3.24.1" + version = "3.30.0" } } diff --git a/terraform/team-members-datadog/teams.tf b/terraform/team-members-datadog/teams.tf new file mode 100644 index 000000000..ed73ac637 --- /dev/null +++ b/terraform/team-members-datadog/teams.tf @@ -0,0 +1,50 @@ +locals { + infra_admins = { + admin = datadog_user.users["admin"].id, + jdn = datadog_user.users["jdn"].id, + mark = datadog_user.users["mark"].id, + pietro = datadog_user.users["pietro"].id, + } +} + +resource "datadog_team" "infra_admins" { + description = "Administrators of the infra-team" + handle = "infra-admins" + name = "infra-admins" +} + +resource "datadog_team_membership" "infra_admins" { + for_each = local.infra_admins + + team_id = datadog_team.infra_admins.id + user_id = each.value +} + +resource "datadog_team" "infra" { + description = "The infrastructure team" + handle = "infra" + name = "infra" +} + +resource "datadog_team_membership" "infra" { + for_each = merge(local.infra_admins, { + }) + + team_id = datadog_team.infra.id + user_id = each.value +} + +resource "datadog_team" "crates_io" { + description = "The crates.io team" + handle = "crates-io" + name = "crates.io" +} + +resource "datadog_team_membership" "crates_io" { + for_each = merge(local.infra_admins, { + tobias = datadog_user.users["tobias"].id, + }) + + team_id = datadog_team.crates_io.id + user_id = each.value +} From 6fbee796f4cadfa851bc3c95523a5d5a11b6af54 Mon Sep 17 00:00:00 2001 From: Jan David Date: Mon, 23 Oct 2023 13:06:34 +0200 Subject: [PATCH 05/21] Use roles for RBAC Instead of relying on teams to tag incoming resources and to use them in restriction queries, we are using teams and the `service` or `app` tag to control access to resources. The teams have been removed again, and a more limited role for contributors and a "marker role" for the crates.io team have been created. --- terraform/team-members-datadog/roles.tf | 26 +++++++++++++ terraform/team-members-datadog/teams.tf | 50 ------------------------- terraform/team-members-datadog/users.tf | 24 ++++++------ 3 files changed, 38 insertions(+), 62 deletions(-) create mode 100644 terraform/team-members-datadog/roles.tf delete mode 100644 terraform/team-members-datadog/teams.tf diff --git a/terraform/team-members-datadog/roles.tf b/terraform/team-members-datadog/roles.tf new file mode 100644 index 000000000..d840ab7e5 --- /dev/null +++ b/terraform/team-members-datadog/roles.tf @@ -0,0 +1,26 @@ +# Fetch all available permissions +data "datadog_permissions" "all" {} + +resource "datadog_role" "contributor" { + name = "Contributor" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.logs_read_index_data, + data.datadog_permissions.all.permissions.logs_read_data, + data.datadog_permissions.all.permissions.logs_live_tail, + data.datadog_permissions.all.permissions.logs_read_archives, + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + +# This is a marker role that is applied to users on top of their other roles. +# It grants access to the log assets for crates.io. +resource "datadog_role" "crates_io" { + name = "crates.io" +} diff --git a/terraform/team-members-datadog/teams.tf b/terraform/team-members-datadog/teams.tf deleted file mode 100644 index ed73ac637..000000000 --- a/terraform/team-members-datadog/teams.tf +++ /dev/null @@ -1,50 +0,0 @@ -locals { - infra_admins = { - admin = datadog_user.users["admin"].id, - jdn = datadog_user.users["jdn"].id, - mark = datadog_user.users["mark"].id, - pietro = datadog_user.users["pietro"].id, - } -} - -resource "datadog_team" "infra_admins" { - description = "Administrators of the infra-team" - handle = "infra-admins" - name = "infra-admins" -} - -resource "datadog_team_membership" "infra_admins" { - for_each = local.infra_admins - - team_id = datadog_team.infra_admins.id - user_id = each.value -} - -resource "datadog_team" "infra" { - description = "The infrastructure team" - handle = "infra" - name = "infra" -} - -resource "datadog_team_membership" "infra" { - for_each = merge(local.infra_admins, { - }) - - team_id = datadog_team.infra.id - user_id = each.value -} - -resource "datadog_team" "crates_io" { - description = "The crates.io team" - handle = "crates-io" - name = "crates.io" -} - -resource "datadog_team_membership" "crates_io" { - for_each = merge(local.infra_admins, { - tobias = datadog_user.users["tobias"].id, - }) - - team_id = datadog_team.crates_io.id - user_id = each.value -} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 25244828b..3669f2e3e 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -3,50 +3,50 @@ locals { "admin" = { login = "admin@rust-lang.org" name = "Rust Admin" - role = "Datadog Admin Role" + roles = ["Datadog Admin Role"] } "jdn" = { login = "jandavidnose@rustfoundation.org" name = "Jan David Nose" - role = "Datadog Admin Role" + roles = ["Datadog Admin Role"] } "joel" = { login = "joelmarcey@rustfoundation.org" name = "Joel Marcey" - role = "Datadog Admin Role" + roles = ["Datadog Admin Role"] } "mark" = { login = "mark.simulacrum@gmail.com" name = "Mark Rousskov" - role = "DataDog Admin Role" + roles = ["DataDog Admin Role"] } "paullenz" = { login = "paullenz@rustfoundation.org" name = "Paul Lenz" - role = "Datadog Read Only Role" + roles = ["Datadog Read Only Role"] } "pietro" = { login = "pietro@pietroalbini.org" name = "Pietro Albini" - role = "DataDog Admin Role" + roles = ["DataDog Admin Role"] } "rustfoundation" = { login = "infra@rustfoundation.org" name = "Rust Foundation Infrastructure" - role = "Datadog Admin Role" + roles = ["Datadog Admin Role"] } "tobias" = { login = "tobiasbieniek@rustfoundation.org" name = "Tobias Bieniek" - role = "Datadog Standard Role" + roles = ["Contributor", "crates.io"] } } } data "datadog_role" "role" { - for_each = toset(values({ - for index, user in local.users : user.login => user.role - })) + for_each = toset(flatten(values({ + for index, user in local.users : user.login => user.roles + }))) filter = each.value } @@ -56,6 +56,6 @@ resource "datadog_user" "users" { email = each.value.login name = each.value.name - roles = [data.datadog_role.role[each.value.role].id] + roles = [for role in each.value.roles : data.datadog_role.role[role].id] send_user_invitation = true } From d8012d1508275ee52598989e8a20c204ee5f044f Mon Sep 17 00:00:00 2001 From: Jan David Date: Tue, 14 Nov 2023 16:12:54 +0100 Subject: [PATCH 06/21] Create role for board members Some board members are interested in some of our metrics as part of their work in the different committees of the board. A very limited read-only role has been created to grant them access to our organization. --- terraform/team-members-datadog/roles.tf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/terraform/team-members-datadog/roles.tf b/terraform/team-members-datadog/roles.tf index d840ab7e5..0a92a742c 100644 --- a/terraform/team-members-datadog/roles.tf +++ b/terraform/team-members-datadog/roles.tf @@ -1,6 +1,21 @@ # Fetch all available permissions data "datadog_permissions" "all" {} +resource "datadog_role" "board_member" { + name = "Board Member" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + + resource "datadog_role" "contributor" { name = "Contributor" From 7e88c5449d09ec7fc675ca4b13a74065e2efd73e Mon Sep 17 00:00:00 2001 From: Jan David Date: Fri, 8 Dec 2023 17:14:27 +0100 Subject: [PATCH 07/21] Refactor role for crates.io The marker role did not work as expected, since contributors had unrestricted access to logs. The `Contributor` role has been removed for this reason, and its permissions are now explicitly granted to members of the `crates-io` role. --- terraform/team-members-datadog/roles.tf | 12 ++---------- terraform/team-members-datadog/users.tf | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/terraform/team-members-datadog/roles.tf b/terraform/team-members-datadog/roles.tf index 0a92a742c..64225d6be 100644 --- a/terraform/team-members-datadog/roles.tf +++ b/terraform/team-members-datadog/roles.tf @@ -15,13 +15,11 @@ resource "datadog_role" "board_member" { } } - -resource "datadog_role" "contributor" { - name = "Contributor" +resource "datadog_role" "crates_io" { + name = "crates.io" dynamic "permission" { for_each = toset([ - data.datadog_permissions.all.permissions.logs_read_index_data, data.datadog_permissions.all.permissions.logs_read_data, data.datadog_permissions.all.permissions.logs_live_tail, data.datadog_permissions.all.permissions.logs_read_archives, @@ -33,9 +31,3 @@ resource "datadog_role" "contributor" { } } } - -# This is a marker role that is applied to users on top of their other roles. -# It grants access to the log assets for crates.io. -resource "datadog_role" "crates_io" { - name = "crates.io" -} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 3669f2e3e..ac508c08b 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -38,7 +38,7 @@ locals { "tobias" = { login = "tobiasbieniek@rustfoundation.org" name = "Tobias Bieniek" - roles = ["Contributor", "crates.io"] + roles = ["Datadog Standard Role", "crates.io"] } } } From 509508ca4bd911bd95270d10078fac41f9c3ff01 Mon Sep 17 00:00:00 2001 From: Jan David Date: Tue, 12 Dec 2023 14:49:49 +0100 Subject: [PATCH 08/21] Add board members --- terraform/team-members-datadog/users.tf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index ac508c08b..48038341a 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -20,11 +20,21 @@ locals { name = "Mark Rousskov" roles = ["DataDog Admin Role"] } + "nell" = { + login = "nells@microsoft.com" + name = "Nell Shamrell-Harrington" + roles = ["Board Member"] + } "paullenz" = { login = "paullenz@rustfoundation.org" name = "Paul Lenz" roles = ["Datadog Read Only Role"] } + "peixin" = { + login = "peixin.hou@gmail.com" + name = "Peixin Hou" + roles = ["Board Member"] + } "pietro" = { login = "pietro@pietroalbini.org" name = "Pietro Albini" @@ -35,6 +45,11 @@ locals { name = "Rust Foundation Infrastructure" roles = ["Datadog Admin Role"] } + "seth" = { + login = "smarkle.aws@gmail.com" + name = "Seth Markle" + roles = ["Board Member"] + } "tobias" = { login = "tobiasbieniek@rustfoundation.org" name = "Tobias Bieniek" From 84901d396aae87fd1e9d219052fdb2fb2f5a1056 Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 8 Feb 2024 13:43:43 +0100 Subject: [PATCH 09/21] Split users into multiple files The list of users has been split into multiple files, each representing a single team. This makes it much easier to manage the access for individual teams. An unsolved problem is that users can be members of multiple teams, which is not modelled yet. --- terraform/team-members-datadog/crates-io.tf | 8 +++ .../team-members-datadog/foundation-board.tf | 16 +++++ terraform/team-members-datadog/foundation.tf | 8 +++ .../team-members-datadog/infra-admins.tf | 28 +++++++++ terraform/team-members-datadog/outputs.tf | 3 + terraform/team-members-datadog/users.tf | 63 ++----------------- 6 files changed, 69 insertions(+), 57 deletions(-) create mode 100644 terraform/team-members-datadog/crates-io.tf create mode 100644 terraform/team-members-datadog/foundation-board.tf create mode 100644 terraform/team-members-datadog/foundation.tf create mode 100644 terraform/team-members-datadog/infra-admins.tf create mode 100644 terraform/team-members-datadog/outputs.tf diff --git a/terraform/team-members-datadog/crates-io.tf b/terraform/team-members-datadog/crates-io.tf new file mode 100644 index 000000000..ef5c738de --- /dev/null +++ b/terraform/team-members-datadog/crates-io.tf @@ -0,0 +1,8 @@ +locals { + crates_io = { + "tobias" = { + login = "tobiasbieniek@rustfoundation.org" + name = "Tobias Bieniek" + } + } +} diff --git a/terraform/team-members-datadog/foundation-board.tf b/terraform/team-members-datadog/foundation-board.tf new file mode 100644 index 000000000..05aa5c1a3 --- /dev/null +++ b/terraform/team-members-datadog/foundation-board.tf @@ -0,0 +1,16 @@ +locals { + foundation_board = { + "nell" = { + login = "nells@microsoft.com" + name = "Nell Shamrell-Harrington" + } + "peixin" = { + login = "peixin.hou@gmail.com" + name = "Peixin Hou" + } + "seth" = { + login = "smarkle.aws@gmail.com" + name = "Seth Markle" + } + } +} diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf new file mode 100644 index 000000000..e977e7d54 --- /dev/null +++ b/terraform/team-members-datadog/foundation.tf @@ -0,0 +1,8 @@ +locals { + foundation = { + "paullenz" = { + login = "paullenz@rustfoundation.org" + name = "Paul Lenz" + } + } +} diff --git a/terraform/team-members-datadog/infra-admins.tf b/terraform/team-members-datadog/infra-admins.tf new file mode 100644 index 000000000..f26548f8d --- /dev/null +++ b/terraform/team-members-datadog/infra-admins.tf @@ -0,0 +1,28 @@ +locals { + infra_admins = { + "admin" = { + login = "admin@rust-lang.org" + name = "Rust Admin" + } + "jdn" = { + login = "jandavidnose@rustfoundation.org" + name = "Jan David Nose" + } + "joel" = { + login = "joelmarcey@rustfoundation.org" + name = "Joel Marcey" + } + "mark" = { + login = "mark.simulacrum@gmail.com" + name = "Mark Rousskov" + } + "pietro" = { + login = "pietro@pietroalbini.org" + name = "Pietro Albini" + } + "rustfoundation" = { + login = "infra@rustfoundation.org" + name = "Rust Foundation Infrastructure" + } + } +} diff --git a/terraform/team-members-datadog/outputs.tf b/terraform/team-members-datadog/outputs.tf new file mode 100644 index 000000000..b06caa212 --- /dev/null +++ b/terraform/team-members-datadog/outputs.tf @@ -0,0 +1,3 @@ +output "users" { + value = local.users +} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 48038341a..04608573e 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -1,61 +1,10 @@ locals { - users = { - "admin" = { - login = "admin@rust-lang.org" - name = "Rust Admin" - roles = ["Datadog Admin Role"] - } - "jdn" = { - login = "jandavidnose@rustfoundation.org" - name = "Jan David Nose" - roles = ["Datadog Admin Role"] - } - "joel" = { - login = "joelmarcey@rustfoundation.org" - name = "Joel Marcey" - roles = ["Datadog Admin Role"] - } - "mark" = { - login = "mark.simulacrum@gmail.com" - name = "Mark Rousskov" - roles = ["DataDog Admin Role"] - } - "nell" = { - login = "nells@microsoft.com" - name = "Nell Shamrell-Harrington" - roles = ["Board Member"] - } - "paullenz" = { - login = "paullenz@rustfoundation.org" - name = "Paul Lenz" - roles = ["Datadog Read Only Role"] - } - "peixin" = { - login = "peixin.hou@gmail.com" - name = "Peixin Hou" - roles = ["Board Member"] - } - "pietro" = { - login = "pietro@pietroalbini.org" - name = "Pietro Albini" - roles = ["DataDog Admin Role"] - } - "rustfoundation" = { - login = "infra@rustfoundation.org" - name = "Rust Foundation Infrastructure" - roles = ["Datadog Admin Role"] - } - "seth" = { - login = "smarkle.aws@gmail.com" - name = "Seth Markle" - roles = ["Board Member"] - } - "tobias" = { - login = "tobiasbieniek@rustfoundation.org" - name = "Tobias Bieniek" - roles = ["Datadog Standard Role", "crates.io"] - } - } + users = merge( + { for name, user in local.crates_io : name => merge(user, { roles = ["crates.io"] }) }, + { for name, user in local.foundation : name => merge(user, { roles = ["Datadog Read Only Role"] }) }, + { for name, user in local.foundation_board : name => merge(user, { roles = ["Board Member"] }) }, + { for name, user in local.infra_admins : name => merge(user, { roles = ["Datadog Admin Role"] }) }, + ) } data "datadog_role" "role" { From b7fc567e12ef9fba75535555da0359a607106d08 Mon Sep 17 00:00:00 2001 From: Jan David Date: Fri, 9 Feb 2024 15:50:48 +0100 Subject: [PATCH 10/21] Create teams on Datadog Teams are a relatively new feature on Datadog that makes it easier to share resources with a specific subset of users. For example, dashboards can be owned by teams and surfaced more prominently to members of that team. --- terraform/team-members-datadog/_data.tf | 2 ++ terraform/team-members-datadog/crates-io.tf | 30 +++++++++++++++++ .../team-members-datadog/foundation-board.tf | 27 +++++++++++++++ terraform/team-members-datadog/foundation.tf | 13 ++++++++ .../team-members-datadog/infra-admins.tf | 13 ++++++++ terraform/team-members-datadog/roles.tf | 33 ------------------- 6 files changed, 85 insertions(+), 33 deletions(-) create mode 100644 terraform/team-members-datadog/_data.tf delete mode 100644 terraform/team-members-datadog/roles.tf diff --git a/terraform/team-members-datadog/_data.tf b/terraform/team-members-datadog/_data.tf new file mode 100644 index 000000000..58e29fae4 --- /dev/null +++ b/terraform/team-members-datadog/_data.tf @@ -0,0 +1,2 @@ +# Fetch all available permissions +data "datadog_permissions" "all" {} diff --git a/terraform/team-members-datadog/crates-io.tf b/terraform/team-members-datadog/crates-io.tf index ef5c738de..dbcaae2d8 100644 --- a/terraform/team-members-datadog/crates-io.tf +++ b/terraform/team-members-datadog/crates-io.tf @@ -6,3 +6,33 @@ locals { } } } + +resource "datadog_role" "crates_io" { + name = "crates.io" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.logs_read_data, + data.datadog_permissions.all.permissions.logs_live_tail, + data.datadog_permissions.all.permissions.logs_read_archives, + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + +resource "datadog_team" "crates_io" { + name = "crates.io" + description = "The team working on crates.io" + handle = "crates-io" +} + +resource "datadog_team_membership" "crates_io" { + for_each = local.crates_io + + team_id = datadog_team.crates_io.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/foundation-board.tf b/terraform/team-members-datadog/foundation-board.tf index 05aa5c1a3..cc197d704 100644 --- a/terraform/team-members-datadog/foundation-board.tf +++ b/terraform/team-members-datadog/foundation-board.tf @@ -14,3 +14,30 @@ locals { } } } + +resource "datadog_role" "board_member" { + name = "Board Member" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + +resource "datadog_team" "foundation_board" { + name = "Rust Foundation Board" + description = "The board of the Rust Foundation" + handle = "foundation-board" +} + +resource "datadog_team_membership" "foundation_board" { + for_each = local.foundation_board + + team_id = datadog_team.foundation_board.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf index e977e7d54..bfd825b5f 100644 --- a/terraform/team-members-datadog/foundation.tf +++ b/terraform/team-members-datadog/foundation.tf @@ -6,3 +6,16 @@ locals { } } } + +resource "datadog_team" "foundation" { + name = "Rust Foundation" + description = "The staff of the Rust Foundation" + handle = "foundation" +} + +resource "datadog_team_membership" "foundation" { + for_each = local.foundation + + team_id = datadog_team.foundation.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/infra-admins.tf b/terraform/team-members-datadog/infra-admins.tf index f26548f8d..623a2e88c 100644 --- a/terraform/team-members-datadog/infra-admins.tf +++ b/terraform/team-members-datadog/infra-admins.tf @@ -26,3 +26,16 @@ locals { } } } + +resource "datadog_team" "infra_admins" { + name = "Infrastructure Admins" + description = "The infra-admins" + handle = "infra-admins" +} + +resource "datadog_team_membership" "infra_admins" { + for_each = local.infra_admins + + team_id = datadog_team.infra_admins.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/roles.tf b/terraform/team-members-datadog/roles.tf deleted file mode 100644 index 64225d6be..000000000 --- a/terraform/team-members-datadog/roles.tf +++ /dev/null @@ -1,33 +0,0 @@ -# Fetch all available permissions -data "datadog_permissions" "all" {} - -resource "datadog_role" "board_member" { - name = "Board Member" - - dynamic "permission" { - for_each = toset([ - data.datadog_permissions.all.permissions.dashboards_write, - ]) - - content { - id = permission.value - } - } -} - -resource "datadog_role" "crates_io" { - name = "crates.io" - - dynamic "permission" { - for_each = toset([ - data.datadog_permissions.all.permissions.logs_read_data, - data.datadog_permissions.all.permissions.logs_live_tail, - data.datadog_permissions.all.permissions.logs_read_archives, - data.datadog_permissions.all.permissions.dashboards_write, - ]) - - content { - id = permission.value - } - } -} From 9f454b05683b42633086cf1a8fc92efd37d818ae Mon Sep 17 00:00:00 2001 From: Jan David Date: Fri, 9 Feb 2024 17:34:11 +0100 Subject: [PATCH 11/21] Merge roles for each user When a user is part of multiple teams, they might have multiple roles. These are now all assigned to the user, and Datadog will determine the user's permissions based on that list. --- terraform/team-members-datadog/outputs.tf | 3 -- terraform/team-members-datadog/users.tf | 52 ++++++++++++++++++++--- 2 files changed, 46 insertions(+), 9 deletions(-) delete mode 100644 terraform/team-members-datadog/outputs.tf diff --git a/terraform/team-members-datadog/outputs.tf b/terraform/team-members-datadog/outputs.tf deleted file mode 100644 index b06caa212..000000000 --- a/terraform/team-members-datadog/outputs.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "users" { - value = local.users -} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 04608573e..07e64d67a 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -1,22 +1,62 @@ locals { - users = merge( - { for name, user in local.crates_io : name => merge(user, { roles = ["crates.io"] }) }, + # This is a list of all users from all teams. When a user is part of multiple teams, this list will contain multiple + # entries for that user (one for each team). These entries will have different roles. + # + # Example: + # + # [ + # { "alice" = { login = "Alice", email = "alice@example.com", roles = ["crates.io"] } }, + # { "bob" = { login = "Bob", email = "bob@example.com", roles = ["Board Member"] } }, + # { "alice" = { login = "Alice", email = "alice@example.com", roles = ["Foundation Staff"] } }, + # ] + _do_not_use_all_teams = [ + { for name, user in local.crates_io : name => merge(user, { roles = [datadog_role.crates_io.name] }) }, { for name, user in local.foundation : name => merge(user, { roles = ["Datadog Read Only Role"] }) }, - { for name, user in local.foundation_board : name => merge(user, { roles = ["Board Member"] }) }, + { for name, user in local.foundation_board : name => merge(user, { roles = [datadog_role.board_member.name] }) }, { for name, user in local.infra_admins : name => merge(user, { roles = ["Datadog Admin Role"] }) }, - ) + ] + + # This is an intermediate list that contains a single entry per user, but only with the roles from the first team. + # The list is used in the next step to merge all roles for each user. + # Example: + # + # { + # "alice" = { login = "Alice", email = "alice@example.com", roles = ["crates.io"] }, + # "bob" = { login = "Bob", email = "bob@example.com", roles = ["Board Member"] } + # } + _do_not_use_all_users_with_single_role = merge(local._do_not_use_all_teams...) + + # This list contains a single entry per user, with all the roles that user has across all teams. + # + # Example: + # + # [ + # { "alice" = { login = "Alice", email = "alice@example.com", roles = ["crates.io", "Foundation Staff"] } }, + # { "bob" = { login = "Bob", email = "bob@example.com", roles = ["Board Member"] } }, + # ] + all_user_with_merged_roles = { + for name, user in local._do_not_use_all_users_with_single_role : name => { + login = user.login + name = user.name + roles = distinct(flatten([ + for team in local._do_not_use_all_teams : concat([ + for inner_name, user in team : user.roles if name == inner_name + ]) + ])) + } + } } data "datadog_role" "role" { for_each = toset(flatten(values({ - for index, user in local.users : user.login => user.roles + for index, user in local.all_user_with_merged_roles : user.login => user.roles }))) filter = each.value } resource "datadog_user" "users" { - for_each = local.users + for_each = local.all_user_with_merged_roles email = each.value.login name = each.value.name From 4a29baf8babb44ae1567c533d1c92b81447a1572 Mon Sep 17 00:00:00 2001 From: Jan David Date: Mon, 12 Feb 2024 13:39:45 +0100 Subject: [PATCH 12/21] Restore access to logs for crates.io team --- terraform/team-members-datadog/crates-io.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/terraform/team-members-datadog/crates-io.tf b/terraform/team-members-datadog/crates-io.tf index dbcaae2d8..b4f23ce11 100644 --- a/terraform/team-members-datadog/crates-io.tf +++ b/terraform/team-members-datadog/crates-io.tf @@ -12,6 +12,7 @@ resource "datadog_role" "crates_io" { dynamic "permission" { for_each = toset([ + data.datadog_permissions.all.permissions.logs_read_index_data, data.datadog_permissions.all.permissions.logs_read_data, data.datadog_permissions.all.permissions.logs_live_tail, data.datadog_permissions.all.permissions.logs_read_archives, From 0a7ee08d4d2b310ba3e24566375925286ca30239 Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 15 Feb 2024 11:44:09 +0100 Subject: [PATCH 13/21] Add Foundation staff to foundation team --- terraform/team-members-datadog/crates-io.tf | 4 ++++ terraform/team-members-datadog/foundation.tf | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/terraform/team-members-datadog/crates-io.tf b/terraform/team-members-datadog/crates-io.tf index b4f23ce11..64d0d6f82 100644 --- a/terraform/team-members-datadog/crates-io.tf +++ b/terraform/team-members-datadog/crates-io.tf @@ -1,5 +1,9 @@ locals { crates_io = { + "adam" = { + login = "adamharvey@rustfoundation.org" + name = "Adam Harvey" + } "tobias" = { login = "tobiasbieniek@rustfoundation.org" name = "Tobias Bieniek" diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf index bfd825b5f..db3ecee0f 100644 --- a/terraform/team-members-datadog/foundation.tf +++ b/terraform/team-members-datadog/foundation.tf @@ -1,9 +1,29 @@ locals { foundation = { + "adam" = { + login = "adamharvey@rustfoundation.org" + name = "Adam Harvey" + } + "jdn" = { + login = "jandavidnose@rustfoundation.org" + name = "Jan David Nose" + } + "joel" = { + login = "joelmarcey@rustfoundation.org" + name = "Joel Marcey" + } "paullenz" = { login = "paullenz@rustfoundation.org" name = "Paul Lenz" } + "rustfoundation" = { + login = "infra@rustfoundation.org" + name = "Rust Foundation Infrastructure" + } + "tobias" = { + login = "tobiasbieniek@rustfoundation.org" + name = "Tobias Bieniek" + } } } From df2f4671b637b071d964a4a1ee9e65fd35868f46 Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 15 Feb 2024 12:01:09 +0100 Subject: [PATCH 14/21] Create role for Rust Foundation staff --- terraform/team-members-datadog/foundation.tf | 14 ++++++++++++++ terraform/team-members-datadog/users.tf | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf index db3ecee0f..e8a97fbce 100644 --- a/terraform/team-members-datadog/foundation.tf +++ b/terraform/team-members-datadog/foundation.tf @@ -27,6 +27,20 @@ locals { } } +resource "datadog_role" "foundation" { + name = "Rust Foundation" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + resource "datadog_team" "foundation" { name = "Rust Foundation" description = "The staff of the Rust Foundation" diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 07e64d67a..0345bda58 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -11,7 +11,7 @@ locals { # ] _do_not_use_all_teams = [ { for name, user in local.crates_io : name => merge(user, { roles = [datadog_role.crates_io.name] }) }, - { for name, user in local.foundation : name => merge(user, { roles = ["Datadog Read Only Role"] }) }, + { for name, user in local.foundation : name => merge(user, { roles = [datadog_role.foundation.name] }) }, { for name, user in local.foundation_board : name => merge(user, { roles = [datadog_role.board_member.name] }) }, { for name, user in local.infra_admins : name => merge(user, { roles = ["Datadog Admin Role"] }) }, ] From 1fc9d81b88cac2db45577360a3e114bd9ec2625c Mon Sep 17 00:00:00 2001 From: Jan David Date: Wed, 13 Mar 2024 15:15:48 +0100 Subject: [PATCH 15/21] Refactor team member module for Datadog --- terraform/team-members-datadog/crates-io.tf | 10 +--- .../team-members-datadog/foundation-board.tf | 15 ++---- terraform/team-members-datadog/foundation.tf | 30 +++-------- .../team-members-datadog/infra-admins.tf | 30 +++-------- terraform/team-members-datadog/users.tf | 51 +++++++++++++++++++ 5 files changed, 68 insertions(+), 68 deletions(-) diff --git a/terraform/team-members-datadog/crates-io.tf b/terraform/team-members-datadog/crates-io.tf index 64d0d6f82..19d46fd6d 100644 --- a/terraform/team-members-datadog/crates-io.tf +++ b/terraform/team-members-datadog/crates-io.tf @@ -1,13 +1,7 @@ locals { crates_io = { - "adam" = { - login = "adamharvey@rustfoundation.org" - name = "Adam Harvey" - } - "tobias" = { - login = "tobiasbieniek@rustfoundation.org" - name = "Tobias Bieniek" - } + "adam" = local.users.adam + "tobias" = local.users.tobias } } diff --git a/terraform/team-members-datadog/foundation-board.tf b/terraform/team-members-datadog/foundation-board.tf index cc197d704..ddbbe0599 100644 --- a/terraform/team-members-datadog/foundation-board.tf +++ b/terraform/team-members-datadog/foundation-board.tf @@ -1,17 +1,8 @@ locals { foundation_board = { - "nell" = { - login = "nells@microsoft.com" - name = "Nell Shamrell-Harrington" - } - "peixin" = { - login = "peixin.hou@gmail.com" - name = "Peixin Hou" - } - "seth" = { - login = "smarkle.aws@gmail.com" - name = "Seth Markle" - } + "nell" = local.users.nell + "peixin" = local.users.peixin + "seth" = local.users.seth } } diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf index e8a97fbce..3af19223c 100644 --- a/terraform/team-members-datadog/foundation.tf +++ b/terraform/team-members-datadog/foundation.tf @@ -1,29 +1,11 @@ locals { foundation = { - "adam" = { - login = "adamharvey@rustfoundation.org" - name = "Adam Harvey" - } - "jdn" = { - login = "jandavidnose@rustfoundation.org" - name = "Jan David Nose" - } - "joel" = { - login = "joelmarcey@rustfoundation.org" - name = "Joel Marcey" - } - "paullenz" = { - login = "paullenz@rustfoundation.org" - name = "Paul Lenz" - } - "rustfoundation" = { - login = "infra@rustfoundation.org" - name = "Rust Foundation Infrastructure" - } - "tobias" = { - login = "tobiasbieniek@rustfoundation.org" - name = "Tobias Bieniek" - } + "adam" = local.users.adam + "jdn" = local.users.jdn + "joel" = local.users.joel + "paullenz" = local.users.paullenz + "rustfoundation" = local.users.rustfoundation + "tobias" = local.users.tobias } } diff --git a/terraform/team-members-datadog/infra-admins.tf b/terraform/team-members-datadog/infra-admins.tf index 623a2e88c..c6919fedf 100644 --- a/terraform/team-members-datadog/infra-admins.tf +++ b/terraform/team-members-datadog/infra-admins.tf @@ -1,29 +1,11 @@ locals { infra_admins = { - "admin" = { - login = "admin@rust-lang.org" - name = "Rust Admin" - } - "jdn" = { - login = "jandavidnose@rustfoundation.org" - name = "Jan David Nose" - } - "joel" = { - login = "joelmarcey@rustfoundation.org" - name = "Joel Marcey" - } - "mark" = { - login = "mark.simulacrum@gmail.com" - name = "Mark Rousskov" - } - "pietro" = { - login = "pietro@pietroalbini.org" - name = "Pietro Albini" - } - "rustfoundation" = { - login = "infra@rustfoundation.org" - name = "Rust Foundation Infrastructure" - } + "admin" = local.users.admin + "jdn" = local.users.jdn + "joel" = local.users.joel + "mark" = local.users.mark + "pietro" = local.users.pietro + "rustfoundation" = local.users.rustfoundation } } diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 0345bda58..85177be75 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -1,4 +1,55 @@ locals { + users = { + "adam" = { + login = "adamharvey@rustfoundation.org" + name = "Adam Harvey" + } + "admin" = { + login = "admin@rust-lang.org" + name = "Rust Admin" + } + "jdn" = { + login = "jandavidnose@rustfoundation.org" + name = "Jan David Nose" + } + "joel" = { + login = "joelmarcey@rustfoundation.org" + name = "Joel Marcey" + } + "mark" = { + login = "mark.simulacrum@gmail.com" + name = "Mark Rousskov" + } + "nell" = { + login = "nells@microsoft.com" + name = "Nell Shamrell-Harrington" + } + "paullenz" = { + login = "paullenz@rustfoundation.org" + name = "Paul Lenz" + } + "peixin" = { + login = "peixin.hou@gmail.com" + name = "Peixin Hou" + } + "pietro" = { + login = "pietro@pietroalbini.org" + name = "Pietro Albini" + } + "rustfoundation" = { + login = "infra@rustfoundation.org" + name = "Rust Foundation Infrastructure" + } + "seth" = { + login = "smarkle.aws@gmail.com" + name = "Seth Markle" + } + "tobias" = { + login = "tobiasbieniek@rustfoundation.org" + name = "Tobias Bieniek" + } + } + # This is a list of all users from all teams. When a user is part of multiple teams, this list will contain multiple # entries for that user (one for each team). These entries will have different roles. # From 98bc9409c2c4fc408e1969e45401306601eb07bb Mon Sep 17 00:00:00 2001 From: Jan David Date: Wed, 20 Mar 2024 16:02:46 +0100 Subject: [PATCH 16/21] Create Datadog account for Jakub --- terraform/team-members-datadog/infra.tf | 40 +++++++++++++++++++++++++ terraform/team-members-datadog/users.tf | 5 ++++ 2 files changed, 45 insertions(+) create mode 100644 terraform/team-members-datadog/infra.tf diff --git a/terraform/team-members-datadog/infra.tf b/terraform/team-members-datadog/infra.tf new file mode 100644 index 000000000..a0b96e35d --- /dev/null +++ b/terraform/team-members-datadog/infra.tf @@ -0,0 +1,40 @@ +locals { + infra = { + "admin" = local.users.admin + "jakub" = local.users.jakub + "jdn" = local.users.jdn + "mark" = local.users.mark + "pietro" = local.users.pietro + } +} + +resource "datadog_role" "infra" { + name = "infra" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.logs_read_index_data, + data.datadog_permissions.all.permissions.logs_read_data, + data.datadog_permissions.all.permissions.logs_live_tail, + data.datadog_permissions.all.permissions.logs_read_archives, + data.datadog_permissions.all.permissions.dashboards_write, + ]) + + content { + id = permission.value + } + } +} + +resource "datadog_team" "infra" { + name = "infra-team" + description = "The infra-team" + handle = "infra" +} + +resource "datadog_team_membership" "infra" { + for_each = local.infra + + team_id = datadog_team.infra.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 85177be75..296223140 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -8,6 +8,10 @@ locals { login = "admin@rust-lang.org" name = "Rust Admin" } + "jakub" = { + login = "berykubik@gmail.com" + name = "Jakub Beránek" + } "jdn" = { login = "jandavidnose@rustfoundation.org" name = "Jan David Nose" @@ -64,6 +68,7 @@ locals { { for name, user in local.crates_io : name => merge(user, { roles = [datadog_role.crates_io.name] }) }, { for name, user in local.foundation : name => merge(user, { roles = [datadog_role.foundation.name] }) }, { for name, user in local.foundation_board : name => merge(user, { roles = [datadog_role.board_member.name] }) }, + { for name, user in local.infra : name => merge(user, { roles = [datadog_role.infra.name] }) }, { for name, user in local.infra_admins : name => merge(user, { roles = ["Datadog Admin Role"] }) }, ] From ed4f1c3b423290f64d010c47005b357b98dc9b14 Mon Sep 17 00:00:00 2001 From: Jan David Date: Wed, 20 Mar 2024 16:03:41 +0100 Subject: [PATCH 17/21] Document how to add users and teams --- terraform/team-members-datadog/README.md | 49 ++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/terraform/team-members-datadog/README.md b/terraform/team-members-datadog/README.md index 3ac48af64..85cf4a4ea 100644 --- a/terraform/team-members-datadog/README.md +++ b/terraform/team-members-datadog/README.md @@ -3,13 +3,6 @@ This Terraform configuration manages user accounts on Datadog. When a user is added to [`users.tf`](users.tf), they get invited to join our Datadog account. -## Roles - -Datadog uses _roles_ to manage who can do what on the platform. - -Members of the infra-admins team are assigned the `Datadog Admin Role` role. -Members of other teams get the `Datadog Standard Role` role. - ## Usage Applying the Terraform configuration requires an API key as well as an app key. @@ -21,4 +14,46 @@ export DD_APP_KEY="datadog-app-key" terraform plan ``` +### Add a user + +Adding a user is a two-step process. First, add the user to the `users.tf` file. +Then, add them to their respective team, referencing the user in `users.tf`. + +For example, `jdn` has first been added as a users in `users.tf`: + +```hcl +locals { + users = { + "jdn" = { + // ... + } + } +} +``` + +And then to the `infra` team in `infra.tf`: + +```hcl +locals { + infra = { + "jdn" = local.users.jdn + } +} +``` + +### Add a Team + +The easiest way to add a team is to copy an existing team and update its +resources. Go through the following steps before applying the configuration: + +1. At the top of the file, update the `locals` block to include the correct team + members. +2. Then update the `datadog_role` for the team and assign the appropriate + permissions to the team. +3. Update the `datadog_team` with the proper name and description. + +Then, register the team in `users.tf` in the `_do_not_use_all_teams` local. +Without this step, no team memberships will be assigned and users won't be +created. + [api-keys]: https://app.datadoghq.com/organization-settings/api-keys From 4a615fa595a1426aec42ba19efe59b3cf425028e Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 30 May 2024 13:27:19 +0200 Subject: [PATCH 18/21] Grant infra team permissions to manage API keys --- terraform/team-members-datadog/infra.tf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/terraform/team-members-datadog/infra.tf b/terraform/team-members-datadog/infra.tf index a0b96e35d..9464658a9 100644 --- a/terraform/team-members-datadog/infra.tf +++ b/terraform/team-members-datadog/infra.tf @@ -18,6 +18,9 @@ resource "datadog_role" "infra" { data.datadog_permissions.all.permissions.logs_live_tail, data.datadog_permissions.all.permissions.logs_read_archives, data.datadog_permissions.all.permissions.dashboards_write, + data.datadog_permissions.all.permissions.api_keys_read, + data.datadog_permissions.all.permissions.api_keys_write, + data.datadog_permissions.all.permissions.user_app_keys, ]) content { From c1717405904f5793c32a49711057caec583a238b Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 30 May 2024 13:27:53 +0200 Subject: [PATCH 19/21] Create Datadog account for Walter --- terraform/team-members-datadog/foundation.tf | 1 + terraform/team-members-datadog/users.tf | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/terraform/team-members-datadog/foundation.tf b/terraform/team-members-datadog/foundation.tf index 3af19223c..966b040e8 100644 --- a/terraform/team-members-datadog/foundation.tf +++ b/terraform/team-members-datadog/foundation.tf @@ -6,6 +6,7 @@ locals { "paullenz" = local.users.paullenz "rustfoundation" = local.users.rustfoundation "tobias" = local.users.tobias + "walter" = local.users.walter } } diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index 296223140..f16bb71cb 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -52,6 +52,10 @@ locals { login = "tobiasbieniek@rustfoundation.org" name = "Tobias Bieniek" } + "walter" = { + login = "walterpearce@rustfoundation.org" + name = "Walter Pearce" + } } # This is a list of all users from all teams. When a user is part of multiple teams, this list will contain multiple From 5acc6dd9ca14d75cd4501bc03d508ff4b0fe521f Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 30 May 2024 14:07:07 +0200 Subject: [PATCH 20/21] Create team for crater --- terraform/team-members-datadog/crater.tf | 34 ++++++++++++++++++++++++ terraform/team-members-datadog/users.tf | 1 + 2 files changed, 35 insertions(+) create mode 100644 terraform/team-members-datadog/crater.tf diff --git a/terraform/team-members-datadog/crater.tf b/terraform/team-members-datadog/crater.tf new file mode 100644 index 000000000..89829f64f --- /dev/null +++ b/terraform/team-members-datadog/crater.tf @@ -0,0 +1,34 @@ +locals { + crater = { + "walter" = local.users.walter + } +} + +resource "datadog_role" "crater" { + name = "crater" + + dynamic "permission" { + for_each = toset([ + data.datadog_permissions.all.permissions.dashboards_write, + data.datadog_permissions.all.permissions.api_keys_read, + data.datadog_permissions.all.permissions.user_app_keys, + ]) + + content { + id = permission.value + } + } +} + +resource "datadog_team" "crater" { + name = "crater" + description = "The team maintaining crater" + handle = "crater" +} + +resource "datadog_team_membership" "crater" { + for_each = local.crater + + team_id = datadog_team.crater.id + user_id = datadog_user.users[each.key].id +} diff --git a/terraform/team-members-datadog/users.tf b/terraform/team-members-datadog/users.tf index f16bb71cb..e59da0c3a 100644 --- a/terraform/team-members-datadog/users.tf +++ b/terraform/team-members-datadog/users.tf @@ -69,6 +69,7 @@ locals { # { "alice" = { login = "Alice", email = "alice@example.com", roles = ["Foundation Staff"] } }, # ] _do_not_use_all_teams = [ + { for name, user in local.crater : name => merge(user, { roles = [datadog_role.crater.name] }) }, { for name, user in local.crates_io : name => merge(user, { roles = [datadog_role.crates_io.name] }) }, { for name, user in local.foundation : name => merge(user, { roles = [datadog_role.foundation.name] }) }, { for name, user in local.foundation_board : name => merge(user, { roles = [datadog_role.board_member.name] }) }, From 433efb52073f7583796e8957a2a8f688ff739312 Mon Sep 17 00:00:00 2001 From: Jan David Date: Thu, 30 May 2024 15:44:02 +0200 Subject: [PATCH 21/21] Grant the infra-team permissions to create saved views Saved views on Datadog are globally shared across an organization, so we want to limit who can create them to ensure a high signal-to-noise ratio. We can consider loosening this restriction as we gain more experience with the platform. --- terraform/team-members-datadog/infra.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/terraform/team-members-datadog/infra.tf b/terraform/team-members-datadog/infra.tf index 9464658a9..aa4d668dd 100644 --- a/terraform/team-members-datadog/infra.tf +++ b/terraform/team-members-datadog/infra.tf @@ -18,6 +18,7 @@ resource "datadog_role" "infra" { data.datadog_permissions.all.permissions.logs_live_tail, data.datadog_permissions.all.permissions.logs_read_archives, data.datadog_permissions.all.permissions.dashboards_write, + data.datadog_permissions.all.permissions.saved_views_write, data.datadog_permissions.all.permissions.api_keys_read, data.datadog_permissions.all.permissions.api_keys_write, data.datadog_permissions.all.permissions.user_app_keys,