Skip to content

Commit

Permalink
chore: address review suggestion
Browse files Browse the repository at this point in the history
  • Loading branch information
gberenice committed Mar 5, 2024
1 parent a338dd4 commit 4f7ce9b
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 91 deletions.
66 changes: 27 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

[![Release](https://img.shields.io/github/release/masterpointio/terraform-datadog-users.svg)](https://github.com/masterpointio/terraform-datadog-users/releases/latest)

This Terraform module is designed to create and manage Datadog user accounts, with a specific focus on security and sensitive data handling.
This Terraform module is designed to create and manage Datadog user accounts.

To ensure the secure handling of DataDog sensitive data for datadog/datadog provider, the module is designed to work with the [SOPS (Secrets OPerationS) provider](https://github.com/mozilla/sops). SOPS is a tool for encrypting and decrypting files containing sensitive data, often used in conjunction with Terraform to manage secrets.
The users are associated with one of the three [out-of-the-box roles](https://docs.datadoghq.com/account_management/rbac/permissions/):

The module utilizes [terraform-secrets-helper](https://github.com/masterpointio/terraform-secrets-helper/tree/main) module - a helper that provides a standard way of managing secrets from different sources, incuding SOPS files.
- Datadog Admin
- Datadog Standard
- Datadog Read Only

## Usage

Expand All @@ -18,54 +20,39 @@ module "datadog_users" {
users = [
{
access_roles = {
"datadog" = true,
"aws" = true,
"datadog" = {
enabled = true,
role = "standard"
},
},
email = "jane.smith@example.com",
name = "Jane Smith",
role = "Editor",
username = "janesmith"
}
]
secret_mapping = [
{
name = "datadog_api_key"
file = "example.yaml"
type = "sops"
},
{
name = "datadog_app_key"
file = "example.yaml"
type = "sops"
}
]
}
```

Check out [examples/complete](examples/complete) for the full example.

To ensure the secure handling of DataDog sensitive data for datadog/datadog provider, the module's example is designed to work with the [SOPS (Secrets OPerationS)](https://github.com/mozilla/sops) provider. SOPS is a tool for encrypting and decrypting files containing sensitive data, often used in conjunction with Terraform to manage secrets. The example also utilizes [terraform-secrets-helper](https://github.com/masterpointio/terraform-secrets-helper/tree/main) module - a helper that provides a standard way of managing secrets from different sources, incuding SOPS files.

❗ We recommend to use AWS KMS, GCP KMS, Azure Key Vault for SOPS files encryption. Don't use the secrets from the example in your real configuration!

Here are some basic SOPS operations that help you to work with the example:

- SOPS provider configuration for the example:
- Pass `age` key to SOPS provider configuration:

```sh
cd ./example/complete
export SOPS_AGE_KEY_FILE=key.txt
```

- Encryption

```sh
sops --encrypt --age age1uafwjn52f8qvdeyqgn5epens4nwpqaqld8ln47xs8an003r3gudqxpzt7m example.raw.yaml > example.yaml
```

- Decryption
- Encryption/decryption via SOPS editior

```sh
sops --age age1uafwjn52f8qvdeyqgn5epens4nwpqaqld8ln47xs8an003r3gudqxpzt7m example.yaml
sops example.yaml
```

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand All @@ -86,27 +73,28 @@ sops --age age1uafwjn52f8qvdeyqgn5epens4nwpqaqld8ln47xs8an003r3gudqxpzt7m exampl

## Modules

| Name | Source | Version |
| -------------------------------------------------------- | ---------------------------- | ------- |
| <a name="module_secrets"></a> [secrets](#module_secrets) | masterpointio/helper/secrets | 0.2.0 |
No modules.

## Resources

| Name | Type |
| -------------------------------------------------------------------------------------------------------------- | ----------- |
| [datadog_user.users](https://registry.terraform.io/providers/datadog/datadog/latest/docs/resources/user) | resource |
| [datadog_role.standard](https://registry.terraform.io/providers/datadog/datadog/latest/docs/data-sources/role) | data source |
| Name | Type |
| --------------------------------------------------------------------------------------------------------------- | ----------- |
| [datadog_user.users](https://registry.terraform.io/providers/datadog/datadog/latest/docs/resources/user) | resource |
| [datadog_role.admin](https://registry.terraform.io/providers/datadog/datadog/latest/docs/data-sources/role) | data source |
| [datadog_role.read_only](https://registry.terraform.io/providers/datadog/datadog/latest/docs/data-sources/role) | data source |
| [datadog_role.standard](https://registry.terraform.io/providers/datadog/datadog/latest/docs/data-sources/role) | data source |

## Inputs

| Name | Description | Type | Default | Required |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | :------: |
| <a name="input_secret_mapping"></a> [secret_mapping](#input_secret_mapping) | The list of secret mappings the application will need.<br>This creates secret values for the component to consume at `local.secrets[name]`. | <pre>list(object({<br> name = string<br> type = string<br> path = optional(string, null)<br> file = string<br> }))</pre> | `[]` | no |
| <a name="input_users"></a> [users](#input_users) | n/a | <pre>list(object({<br> access_roles = map(bool)<br> disabled = optional(bool, false)<br> email = string<br> name = string<br> role = string<br> send_user_invitation = optional(bool, true)<br> username = string<br> }))</pre> | n/a | yes |
| Name | Description | Type | Default | Required |
| ------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | :------: |
| <a name="input_users"></a> [users](#input_users) | n/a | <pre>list(object({<br> access_roles = map(any)<br> disabled = optional(bool, false)<br> email = string<br> name = string<br> role = string<br> send_user_invitation = optional(bool, true)<br> username = string<br> }))</pre> | n/a | yes |

## Outputs

No outputs.
| Name | Description |
| -------------------------------------------------------------------------- | ------------------------------------------------------ |
| <a name="output_datadog_users"></a> [datadog_users](#output_datadog_users) | A map of all Datadog user resources keyed by username. |

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

Expand Down
11 changes: 11 additions & 0 deletions data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
data "datadog_role" "standard" {
filter = "Datadog Standard Role"
}

data "datadog_role" "admin" {
filter = "Datadog Admin Role"
}

data "datadog_role" "read_only" {
filter = "Datadog Read Only Role"
}
8 changes: 4 additions & 4 deletions examples/complete/example.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
datadog_api_key: ENC[AES256_GCM,data:joPOPI58VO5E2g==,iv:G3BamrS3ANDMhJqjyZbn1YhAqf2GJ7g7DdVivrYVzDw=,tag:k2sGvVtoxznn7U8x8I7oUw==,type:int]
datadog_app_key: ENC[AES256_GCM,data:GeerHEomnls2Cg==,iv:9uiNp5vvv/8/6sqNix28FRm1btWy6CF3fnGD3RV3oMI=,tag:LbGRJu7Bz8HdJYR+6iO/vQ==,type:int]
datadog_api_key: ENC[AES256_GCM,data:cGxuKLw01YXMzg==,iv:sqCip8ibQM10cZqPlb3H9xRojvtD45RU5ZP+3WmlWFQ=,tag:wyIH0RnYdraYyFl3BlGEhw==,type:int]
datadog_app_key: ENC[AES256_GCM,data:tjZKfOL4Keulow==,iv:qaVRDuuDa5EY/dvqg1eH5ZtBcuvAIdyRO2FItl+7Rok=,tag:EUql9eObFKKtolab/Zi1MA==,type:int]
sops:
kms: []
gcp_kms: []
Expand All @@ -15,8 +15,8 @@ sops:
ejRyZCthYkxvcnN0bHRJVG5RZlo1UEEKDoY/9Bf5OnbMQoOk7wdsTMhTHfmVLHUz
bYEgOsOwxlL+YEgme0vRFhL3MXGCRJwZISDdGTkFFYz0Rfp4CWksew==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-03-05T15:02:14Z"
mac: ENC[AES256_GCM,data:PlVVXBdphDgl1AkQEk4ZS/EV5KXT6IqPDmzQz7LQvrrXQstuXmpY/7TABWJDEF8Y+SS92J4FKfjFropK3Uf5GG5FnD06xjp0TEVAN6gG7LtyCBqGfYe0rYLRxD3cFmFa/DHitNnnHbfM4545UJgQxVFgLAHcRrP4hOhtqCBXpiI=,iv:qfqqIqyqxEW2zH47STMPR9S83Ky5PQ9owvuLo8VJRKE=,tag:VeAfgPnZwwvnTmE7SgbZww==,type:str]
lastmodified: "2024-03-05T18:39:37Z"
mac: ENC[AES256_GCM,data:T1ziXhQOuU7pvRVVA9kewyn5efhrrLZ1TYarfVCjF/HL09iRXTTlF0ZkRTOjyqoRoXd+0MEfaVvKlRptcE1WxoR4saOCyju+k3zVQ0i1suOvfmwueHfpZvAetClC2Bwg09iOrR+lE8wz7WnqIBkup53tshjJhpXif9TknnSP2vI=,iv:LovT/poawV4dHPAs0GkZ9tyrY/ClHPAah6xDqa67/J0=,tag:LyZaZ0cHN9namt8PvhOMdg==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
users = [
{
access_roles = {
"datadog" = true,
"aws" = false,
"datadog" = {
enabled = true,
role = "standard"
},
},
email = "john.doe@example.com",
name = "John Doe",
Expand All @@ -11,8 +13,10 @@ users = [
},
{
access_roles = {
"datadog" = true,
"aws" = true,
"datadog" = {
enabled = true,
role = "read_only"
},
},
email = "jane.smith@example.com",
name = "Jane Smith",
Expand Down
4 changes: 1 addition & 3 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
module "datadog_user" {
source = "../.."

users = var.users
secret_mapping = var.secret_mapping
users = var.users
}
File renamed without changes.
2 changes: 1 addition & 1 deletion examples/complete/variables.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
variable "users" {
type = list(object({
access_roles = map(bool)
access_roles = map(any)
disabled = optional(bool, false)
email = string
name = string
Expand Down
20 changes: 7 additions & 13 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
locals {
dd_team = {
for member in var.users :
member.username => member if member.access_roles["datadog"]
users = { for u in var.users : u.username => u }
roles = {
"standard" = data.datadog_role.standard.id
"admin" = data.datadog_role.admin.id
"read_only" = data.datadog_role.read_only.id
}
}

data "datadog_role" "standard" {
filter = "Datadog Standard Role"
}

resource "datadog_user" "users" {
for_each = local.dd_team
for_each = local.users
disabled = each.value.disabled
email = each.value.email
name = each.value.name
roles = [data.datadog_role.standard.id]
roles = [local.roles[each.value.access_roles["datadog"].role]]
send_user_invitation = each.value.send_user_invitation

lifecycle {
ignore_changes = [name]
}
}
5 changes: 4 additions & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@

output "datadog_users" {
value = resource.datadog_user.users
description = "A map of all Datadog user resources keyed by username."
}
25 changes: 0 additions & 25 deletions secrets.sops.tf

This file was deleted.

2 changes: 1 addition & 1 deletion variables.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
variable "users" {
type = list(object({
access_roles = map(bool)
access_roles = map(any)
disabled = optional(bool, false)
email = string
name = string
Expand Down

0 comments on commit 4f7ce9b

Please sign in to comment.