diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index 0ad9ef0..0000000 --- a/CODEOWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -# These owners will be the default owners for everything in the repo. -* @drata/infrastructure diff --git a/README.md b/README.md index d7958d3..4c8e6d9 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,63 @@ -# Terraform Module Template - -**Next steps** -1. Update the top section of this file to tell people about this module. -2. Update `versions.tf` to include the required providers for the module. -3. Add resources and variables to solve the problem. -4. Add outputs for relevant details the consumer may want -5. Add example uses to the bottom of this file -6. Update the generated portion of this file using `terraform-docs .` - +# gcp-terraform-drata-setup + +GCP terraform module to create the Drata Read Only service account. + +## Example Usage + +The example below uses `ref=main` (which is appended in the URL), but it is recommended to use a specific tag version (i.e. `ref=1.0.0`) to avoid breaking changes. Go to the release page for a list of published versions. [releases page](https://github.com/drata/gcp-terraform-drata-setup/releases) for a list of published versions. + +Replace `YOUR_ORGANIZATION_DOMAIN` with the organization domain. i.e. `your_org.com`. +``` +module "service_account_creation" { + source = "git::https://github.com/drata/gcp-terraform-drata-setup.git?ref=main" + gcp_org_domain = "YOUR_ORGANIZATION_DOMAIN" + # gcp_project_id = "YOUR_PROJECT_ID" # if it's unset, the project by default is used + # drata_role_name = "YOUR_ROLE_NAME" # if it's unset, the default name is DrataReadOnly +} + +output "drata_service_account_key" { + value = module.service_account_creation.drata_service_account_key + description = "Service Account Key" + sensitive = true +} +``` + +After you apply this terraform, run the following command to retrieve the key file `drata-gcp-private-key.json` +``` +terraform output -raw drata_service_account_key > drata-gcp-private-key.json +``` + +## Setup + +The following steps demonstrate how to connect GCP in Drata when using this terraform module. + +1. Add the code above to your terraform project. +2. Make sure the service account to authenticate this script has the roles `Organization Administrator`, `Service Account Admin`, `Service Account Key Admin` and ` Service Usage Admin`. +3. Replace `main` in `ref=main` with the latest version from the [releases page](https://github.com/drata/gcp-terraform-drata-setup/releases). +4. Replace `YOUR_ORGANIZATION_DOMAIN` with the GCP organization domain. +5. Replace `YOUR_PROJECT_ID` if the desired project is not the default project in your organization. +6. Replace the given `drata_role_name` if you don't want the role added to be the default: `DrataReadOnly`. +7. Back in your terminal, run `terraform init` to download/update the module. +8. Run `terraform apply` and **IMPORTANT** review the plan output before typing `yes`. +9. If successful, run the command to generate the json key file + - `terraform output -raw drata_service_account_key > drata-gcp-private-key.json` . +11. Verify the file has been generated. +12. Go to the GCP connection drawer and select Upload File to upload the `drata-gcp-private-key.json` file. +13. Select the `Save & Test Connection` button. ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.15 | +| [terraform](#requirement\_terraform) | >= 0.13.0 | +| [google](#requirement\_google) | 5.16.0 | ## Providers | Name | Version | |------|---------| -| [null](#provider\_null) | n/a | +| [google](#provider\_google) | 5.16.0 | ## Modules @@ -30,22 +67,29 @@ No modules. | Name | Type | |------|------| -| [null_resource.nope](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [google_organization_iam_custom_role.drata_org_role](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/organization_iam_custom_role) | resource | +| [google_organization_iam_member.organization](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/organization_iam_member) | resource | +| [google_project_iam_custom_role.drata_project_role](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/project_iam_custom_role) | resource | +| [google_project_iam_member.drata_member_project_role](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/project_iam_member) | resource | +| [google_project_iam_member.drata_viewer_role](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/project_iam_member) | resource | +| [google_project_service.services](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/project_service) | resource | +| [google_service_account.drata](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/service_account) | resource | +| [google_service_account_key.drata_key](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/resources/service_account_key) | resource | +| [google_organization.gcp_organization](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/data-sources/organization) | data source | +| [google_project.gcp_project](https://registry.terraform.io/providers/hashicorp/google/5.16.0/docs/data-sources/project) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [this](#input\_this) | Replace me with a real variable. | `str` | `"nope"` | no | +| [drata\_role\_name](#input\_drata\_role\_name) | Role name. | `string` | `"DrataReadOnly"` | no | +| [gcp\_org\_domain](#input\_gcp\_org\_domain) | GCP Organization domain. | `string` | n/a | yes | +| [gcp\_project\_id](#input\_gcp\_project\_id) | Project identifier of the gcp organization. If it is not provided, the provider project is used. | `string` | `null` | no | +| [gcp\_services](#input\_gcp\_services) | List of services to enable. | `list(string)` |
[
"cloudresourcemanager.googleapis.com",
"compute.googleapis.com",
"admin.googleapis.com",
"sqladmin.googleapis.com",
"monitoring.googleapis.com"
]
| no | ## Outputs | Name | Description | |------|-------------| -| [nope](#output\_nope) | TODO: Remove this and add your own outputs | -| [true](#output\_true) | n/a | +| [drata\_service\_account\_key](#output\_drata\_service\_account\_key) | Service Account Key | - -## Examples - -**TODO:** Add examples here diff --git a/main.tf b/main.tf index c9d879a..f4ea253 100644 --- a/main.tf +++ b/main.tf @@ -1,2 +1,72 @@ -# TODO: Remove this and add your own resources. -resource "null_resource" "nope" {} +# get default project +data "google_project" "gcp_project" { + count = var.gcp_project_id == null ? 1 : 0 +} + +# get organization data +data "google_organization" "gcp_organization" { + domain = var.gcp_org_domain +} + +# set project id in local variable +locals { + PROJECT_ID = var.gcp_project_id == null ? data.google_project.gcp_project[0].project_id : var.gcp_project_id +} + +# enable services +resource "google_project_service" "services" { + for_each = toset(var.gcp_services) + service = each.value + disable_on_destroy = false + project = local.PROJECT_ID +} + +# create project custom role +resource "google_project_iam_custom_role" "drata_project_role" { + role_id = "${var.drata_role_name}ProjectRole" + title = "Drata Read-Only Project Role" + description = "Service Account for Drata Autopilot to get read access to all project resources" + permissions = ["storage.buckets.get", "storage.buckets.getIamPolicy"] + project = local.PROJECT_ID +} + +# create organizational role +resource "google_organization_iam_custom_role" "drata_org_role" { + role_id = "${var.drata_role_name}OrganizationalRole" + title = "Drata Read-Only Organizational Role" + description = "Service Account with read-only access for Drata Autopilot to get organizational IAM data" + permissions = ["resourcemanager.organizations.getIamPolicy", "storage.buckets.get", "storage.buckets.getIamPolicy"] + org_id = data.google_organization.gcp_organization.org_id +} + +# creation of the service account +resource "google_service_account" "drata" { + account_id = lower(var.drata_role_name) + display_name = "dratareadonly" + project = local.PROJECT_ID +} + +# create json key file +resource "google_service_account_key" "drata_key" { + service_account_id = google_service_account.drata.id +} + +# assignation of roles to the service account +# project role +resource "google_project_iam_member" "drata_member_project_role" { + project = local.PROJECT_ID + role = google_project_iam_custom_role.drata_project_role.name + member = "serviceAccount:${google_service_account.drata.email}" +} +# organization role +resource "google_organization_iam_member" "organization" { + org_id = data.google_organization.gcp_organization.org_id + role = google_organization_iam_custom_role.drata_org_role.name + member = "serviceAccount:${google_service_account.drata.email}" +} +# viewer role +resource "google_project_iam_member" "drata_viewer_role" { + project = local.PROJECT_ID + role = "roles/viewer" + member = "serviceAccount:${google_service_account.drata.email}" +} diff --git a/outputs.tf b/outputs.tf index 5890ffa..9698c55 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,8 +1,5 @@ -# TODO: Remove this and add your own outputs -output "nope" { - value = null_resource.nope.id -} - -output "true" { - value = true +output "drata_service_account_key" { + value = base64decode(google_service_account_key.drata_key.private_key) + description = "Service Account Key" + sensitive = true } diff --git a/variables.tf b/variables.tf index 4a18fac..19f4493 100644 --- a/variables.tf +++ b/variables.tf @@ -1,6 +1,22 @@ -# TODO: Add your own input variables -variable "this" { - type = str - description = "Replace me with a real variable." - default = "nope" +variable "gcp_project_id" { + type = string + description = "Project identifier of the gcp organization. If it is not provided, the provider project is used." + default = null +} + +variable "gcp_org_domain" { + type = string + description = "GCP Organization domain." +} + +variable "gcp_services" { + type = list(string) + default = ["cloudresourcemanager.googleapis.com", "compute.googleapis.com", "admin.googleapis.com", "sqladmin.googleapis.com", "monitoring.googleapis.com"] + description = "List of services to enable." +} + +variable "drata_role_name" { + type = string + description = "Role name." + default = "DrataReadOnly" } diff --git a/versions.tf b/versions.tf index 7e90134..26ede44 100644 --- a/versions.tf +++ b/versions.tf @@ -1,7 +1,10 @@ terraform { - required_version = ">= 0.15" + required_version = ">= 0.13.0" required_providers { - # TODO: define the providers required by this module + google = { + source = "hashicorp/google" + version = "5.16.0" + } } }