Skip to content

Commit

Permalink
Merge pull request #19 from nlamirault/feat/modules
Browse files Browse the repository at this point in the history
Refactoring using Google modules
  • Loading branch information
nlamirault authored Nov 17, 2021
2 parents 47415da + 53b6233 commit b4f5f42
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 42 deletions.
5 changes: 4 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ repos:
- id: check-yaml
- id: check-added-large-files
- repo: git://github.com/antonbabenko/pre-commit-terraform
rev: v1.50.0
rev: v1.56.0
hooks:
- id: terraform_fmt
- id: terraform_docs
- id: terraform_tflint
files: \.tf$
args:
- '--args=--enable-rule=terraform_deprecated_interpolation'
- '--args=--enable-rule=terraform_deprecated_index'
Expand All @@ -42,3 +43,5 @@ repos:
- '--args=--enable-rule=terraform_unused_required_providers'
- '--args=--enable-rule=terraform_standard_module_structure'
- id: terraform_tfsec
args:
- '--args=--config-file __GIT_WORKING_DIR__/.tfsec.yml'
16 changes: 16 additions & 0 deletions .tfsec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (C) 2021 Nicolas Lamirault <[email protected]>
#
# 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.

---
exclude:
52 changes: 51 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,55 @@ keyring_location = "europe-west1"
## Documentation

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

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_google"></a> [google](#requirement\_google) | >= 3.54.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | >= 3.54.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_bucket"></a> [bucket](#module\_bucket) | terraform-google-modules/cloud-storage/google//modules/simple_bucket | 3.0.0 |
| <a name="module_custom_role"></a> [custom\_role](#module\_custom\_role) | terraform-google-modules/iam/google//modules/custom_role_iam | 7.3.0 |
| <a name="module_iam_service_accounts"></a> [iam\_service\_accounts](#module\_iam\_service\_accounts) | terraform-google-modules/iam/google//modules/service_accounts_iam | 7.3.0 |
| <a name="module_iam_storage_buckets"></a> [iam\_storage\_buckets](#module\_iam\_storage\_buckets) | terraform-google-modules/iam/google//modules/storage_buckets_iam | 7.3.0 |
| <a name="module_service_account"></a> [service\_account](#module\_service\_account) | terraform-google-modules/service-accounts/google | 4.0.3 |

## Resources

| Name | Type |
|------|------|
| [google_kms_crypto_key.velero](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/kms_crypto_key) | resource |
| [google_kms_crypto_key_iam_binding.binding](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/kms_crypto_key_iam_binding) | resource |
| [google_kms_key_ring.velero](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/kms_key_ring) | resource |
| [google_storage_project_service_account.gcs_account](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/storage_project_service_account) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_bucket_labels"></a> [bucket\_labels](#input\_bucket\_labels) | Map of labels to apply to the bucket | `map(string)` | <pre>{<br> "made-by": "terraform"<br>}</pre> | no |
| <a name="input_bucket_location"></a> [bucket\_location](#input\_bucket\_location) | The bucket location | `string` | n/a | yes |
| <a name="input_bucket_storage_class"></a> [bucket\_storage\_class](#input\_bucket\_storage\_class) | Bucket storage class. | `string` | `"MULTI_REGIONAL"` | no |
| <a name="input_enable_kms"></a> [enable\_kms](#input\_enable\_kms) | Enable custom KMS key | `bool` | n/a | yes |
| <a name="input_keyring_location"></a> [keyring\_location](#input\_keyring\_location) | The KMS keyring location | `string` | n/a | yes |
| <a name="input_lifecycle_rules"></a> [lifecycle\_rules](#input\_lifecycle\_rules) | The bucket's Lifecycle Rules configuration. | <pre>list(object({<br> # Object with keys:<br> # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.<br> # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.<br> action = any<br><br> # Object with keys:<br> # - age - (Optional) Minimum age of an object in days to satisfy this condition.<br> # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.<br> # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".<br> # - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.<br> # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.<br> condition = any<br> }))</pre> | <pre>[<br> {<br> "action": {<br> "type": "Delete"<br> },<br> "condition": {<br> "age": 365,<br> "with_state": "ANY"<br> }<br> }<br>]</pre> | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | The Kubernetes namespace | `string` | n/a | yes |
| <a name="input_project"></a> [project](#input\_project) | The project in which the resource belongs | `string` | n/a | yes |
| <a name="input_service_account"></a> [service\_account](#input\_service\_account) | The Kubernetes service account | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_service_account"></a> [service\_account](#output\_service\_account) | Service Account for Velero |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
15 changes: 10 additions & 5 deletions kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
# limitations under the License.

resource "google_kms_key_ring" "velero" {
name = local.service_name
count = var.enable_kms ? 1 : 0
name = local.service
location = var.keyring_location
}

resource "google_kms_crypto_key" "velero" {
name = local.service_name
key_ring = google_kms_key_ring.velero.id
count = var.enable_kms ? 1 : 0
name = local.service
key_ring = google_kms_key_ring.velero[0].id
rotation_period = "100000s"

# lifecycle {
Expand All @@ -31,8 +33,11 @@ data "google_storage_project_service_account" "gcs_account" {
}

resource "google_kms_crypto_key_iam_binding" "binding" {
crypto_key_id = google_kms_crypto_key.velero.id
count = var.enable_kms ? 1 : 0
crypto_key_id = google_kms_crypto_key.velero[0].id
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"

members = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"]
members = [
"serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"
]
}
2 changes: 1 addition & 1 deletion locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
# limitations under the License.

locals {
service_name = format("%s-velero", var.project)
service = "velero"
}
2 changes: 1 addition & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

terraform {
required_version = ">= 0.14.0"
required_version = ">= 1.0.0"

required_providers {
google = {
Expand Down
2 changes: 1 addition & 1 deletion outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@

output "service_account" {
description = "Service Account for Velero"
value = google_service_account.velero.email
value = module.service_account.email
}
36 changes: 36 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ variable "bucket_labels" {
}
}

variable "lifecycle_rules" {
description = "The bucket's Lifecycle Rules configuration."
type = list(object({
# Object with keys:
# - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.
# - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.
action = any

# Object with keys:
# - age - (Optional) Minimum age of an object in days to satisfy this condition.
# - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.
# - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".
# - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.
# - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.
condition = any
}))
default = [{
action = {
type = "Delete"
}
condition = {
age = 365
with_state = "ANY"
}
}]
}

# Workload Identity

variable "namespace" {
Expand All @@ -55,6 +82,15 @@ variable "service_account" {
description = "The Kubernetes service account"
}

#
# KMS
#

variable "enable_kms" {
type = bool
description = "Enable custom KMS key"
}

variable "keyring_location" {
type = string
description = "The KMS keyring location"
Expand Down
103 changes: 71 additions & 32 deletions velero.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,28 @@

# Doc: https://github.com/vmware-tanzu/velero-plugin-for-gcp#setup

resource "google_service_account" "velero" {
account_id = local.service_name
display_name = "Velero"
description = "Created by Terraform"
}

resource "google_storage_bucket" "velero" {
name = local.service_name
location = var.bucket_location
storage_class = var.bucket_storage_class
labels = var.bucket_labels
module "service_account" {
source = "terraform-google-modules/service-accounts/google"
version = "4.0.3"

encryption {
default_kms_key_name = google_kms_crypto_key.velero.id
}
project_id = var.project

# Ensure the KMS crypto-key IAM binding for the service account exists prior to the
# bucket attempting to utilise the crypto-key.
depends_on = [google_kms_crypto_key_iam_binding.binding]
names = [
local.service
]
}

resource "google_project_iam_custom_role" "velero" {
module "custom_role" {
source = "terraform-google-modules/iam/google//modules/custom_role_iam"
version = "7.3.0"

target_level = "project"
target_id = var.project
role_id = local.service
title = title(local.service)
description = format("Role for %s", local.service)
base_roles = []

permissions = [
"compute.disks.get",
"compute.disks.create",
Expand All @@ -46,25 +46,64 @@ resource "google_project_iam_custom_role" "velero" {
"compute.snapshots.delete",
"compute.zones.get"
]
role_id = "velero"
title = "Velero"
}

resource "google_project_iam_binding" "velero" {
role = google_project_iam_custom_role.velero.id
excluded_permissions = []

members = [
format("serviceAccount:%s", google_service_account.velero.email)
format("serviceAccount:%s", module.service_account.email),
]
}

resource "google_storage_bucket_iam_member" "velero" {
bucket = google_storage_bucket.velero.name
role = "roles/storage.objectAdmin"
member = format("serviceAccount:%s", google_service_account.velero.email)
module "iam_service_accounts" {
source = "terraform-google-modules/iam/google//modules/service_accounts_iam"
version = "7.3.0"

project = var.project
mode = "authoritative"

service_accounts = [
module.service_account.email
]

bindings = {
"roles/iam.workloadIdentityUser" = [
format("serviceAccount:%s.svc.id.goog[%s/%s]", var.project, var.namespace, var.service_account)
]
}
}

module "bucket" {
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "3.0.0"

name = format("%s-%s", var.project, local.service)
project_id = var.project
location = var.bucket_location
storage_class = var.bucket_storage_class
labels = var.bucket_labels
lifecycle_rules = var.lifecycle_rules

encryption = var.enable_kms ? {
default_kms_key_name = google_kms_crypto_key.velero[0].name
} : null

# https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/142
# iam_members = [{
# role = "roles/storage.objectAdmin"
# member = format("serviceAccount:%s", module.service_account.email)
# }]
}

resource "google_service_account_iam_member" "velero" {
role = "roles/iam.workloadIdentityUser"
service_account_id = google_service_account.velero.name
member = format("serviceAccount:%s.svc.id.goog[%s/%s]", var.project, var.namespace, var.service_account)
module "iam_storage_buckets" {
source = "terraform-google-modules/iam/google//modules/storage_buckets_iam"
version = "7.3.0"

storage_buckets = [module.bucket.bucket.name]
mode = "authoritative"

bindings = {
"roles/storage.objectAdmin" = [
format("serviceAccount:%s", module.service_account.email)
]
}
}

0 comments on commit b4f5f42

Please sign in to comment.