From cade2430693d0b7760f3d6794ab2999602819952 Mon Sep 17 00:00:00 2001 From: Fabrizio Cafolla Date: Thu, 19 Dec 2024 19:48:04 +0100 Subject: [PATCH] refs board#3052: create network-policy (#48) --- CHANGELOG.md | 6 ++++++ README.md | 14 ++++++++------ main.tf | 36 ++++++++++++++++++++++++++++++++++++ outputs.tf | 9 +++++++++ variables.tf | 7 ++++++- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd92bd..5322c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.20.0] - 2024-12-19 + +[Compare with previous version](https://github.com/sparkfabrik/terraform-google-gcp-cloud-native-drupal-resources/compare/0.19.0...0.20.0) + +- Add feature to enable network policy between `isolated` and `restricted` at namespace level. + ## [0.19.0] - 2024-12-3 [Compare with previous version](https://github.com/sparkfabrik/terraform-google-gcp-cloud-native-drupal-resources/compare/0.18.0...0.19.0) diff --git a/README.md b/README.md index 2429c90..ddbfc21 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ the random suffix `bucket_append_random_suffix` for the bucket name. | [create\_clousql\_dumps\_bucket](#input\_create\_clousql\_dumps\_bucket) | If true, the module will create a Google Storage bucket that can be used as a destination for CloudSQL dumps. The bucket will also be tagged with the global tags. | `bool` | `false` | no | | [create\_databases\_and\_users](#input\_create\_databases\_and\_users) | If true, the module will create a user and a database for each project. | `bool` | `true` | no | | [default\_k8s\_labels](#input\_default\_k8s\_labels) | A map of labels to be applied to all the kubernetes resources created by this module. If a resource specify a map of labels, the default labels will merged with those specified in the resource. | `map(string)` |
{
"managed-by": "terraform"
}
| no | -| [drupal\_projects\_list](#input\_drupal\_projects\_list) | The list of Drupal projects, add a project name and this will create all infrastructure resources needed to run your project (bucket, database, user with relative credentials). Database resources are created in the CloudSQL instance you specified. Please not that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. The default values are thought for a production environment, they will need to be adjusted accordingly for a stage environment. |
list(object({
project_name = string
gitlab_project_id = number
release_branch_name = optional(string, "main")
kubernetes_namespace = optional(string, null)
kubernetes_namespace_labels = optional(map(string), {})
helm_release_name = optional(string, null)
database_name = optional(string, null)
database_user_name = optional(string, null)
database_host = optional(string, null)
database_port = optional(number, 3306)
bucket_name = optional(string, null)
bucket_host = optional(string, "storage.googleapis.com")
bucket_append_random_suffix = optional(bool, true)
bucket_location = optional(string, null)
bucket_storage_class = optional(string, "STANDARD")
bucket_enable_versioning = optional(bool, true)
bucket_enable_disaster_recovery = optional(bool, true)
bucket_force_destroy = optional(bool, false)
bucket_legacy_public_files_path = optional(string, "/public")
bucket_set_all_users_as_viewer = optional(bool, false)
bucket_labels = optional(map(string), {})
bucket_tag_list = optional(list(string), [])
bucket_obj_adm = optional(list(string), [])
bucket_obj_vwr = optional(list(string), [])
bucket_soft_delete_retention_seconds = optional(number, 0)
}))
| n/a | yes | +| [drupal\_projects\_list](#input\_drupal\_projects\_list) | The list of Drupal projects, add a project name and this will create all infrastructure resources needed to run your project (bucket, database, user with relative credentials). Database resources are created in the CloudSQL instance you specified. Please not that you can assign only a database to a single user, the same user cannot be assigned to multiple databases. The default values are thought for a production environment, they will need to be adjusted accordingly for a stage environment. |
list(object({
project_name = string
gitlab_project_id = number
release_branch_name = optional(string, "main")
kubernetes_namespace = optional(string, null)
kubernetes_namespace_labels = optional(map(string), {})
helm_release_name = optional(string, null)
database_name = optional(string, null)
database_user_name = optional(string, null)
database_host = optional(string, null)
database_port = optional(number, 3306)
bucket_name = optional(string, null)
bucket_host = optional(string, "storage.googleapis.com")
bucket_append_random_suffix = optional(bool, true)
bucket_location = optional(string, null)
bucket_storage_class = optional(string, "STANDARD")
bucket_enable_versioning = optional(bool, true)
bucket_enable_disaster_recovery = optional(bool, true)
bucket_force_destroy = optional(bool, false)
bucket_legacy_public_files_path = optional(string, "/public")
bucket_set_all_users_as_viewer = optional(bool, false)
bucket_labels = optional(map(string), {})
bucket_tag_list = optional(list(string), [])
bucket_obj_adm = optional(list(string), [])
bucket_obj_vwr = optional(list(string), [])
bucket_soft_delete_retention_seconds = optional(number, 0)
network_policy = optional(string, "")
}))
| n/a | yes | | [global\_tags](#input\_global\_tags) | A list of tags to be applied to all the drupal buckets, in the form /. If a resource specify a list of tags, the global tags will be overridden and replaced by those specified in the resource. Please note that actually only the buckets are tagged by this module. | `list(string)` | `[]` | no | | [logging\_bucket\_name](#input\_logging\_bucket\_name) | The name of the logging bucket. If empty, no logging bucket will be added and bucket logs will be disabled. | `string` | `""` | no | | [project\_id](#input\_project\_id) | The ID of the project in which the resource belongs. | `string` | n/a | yes | @@ -145,15 +145,16 @@ the random suffix `bucket_append_random_suffix` for the bucket name. | [cloudsql\_dumps\_bucket\_name](#output\_cloudsql\_dumps\_bucket\_name) | CloudSQL dumps bucket name. | | [details\_of\_used\_tag\_keys](#output\_details\_of\_used\_tag\_keys) | Details of the tag keys passed to this module. | | [details\_of\_used\_tag\_values](#output\_details\_of\_used\_tag\_values) | Details of the tag values passed to this module. | -| [drupal\_apps\_all\_bucket\_credentials](#output\_drupal\_apps\_all\_bucket\_credentials) | Bucket credentials for each Drupal project | -| [drupal\_apps\_all\_bucket\_secrets](#output\_drupal\_apps\_all\_bucket\_secrets) | Bucket kubernetes secrets for each Drupal project | +| [drupal\_apps\_all\_bucket\_credentials](#output\_drupal\_apps\_all\_bucket\_credentials) | Bucket credentials for each Drupal project, indexed same as all\_data | +| [drupal\_apps\_all\_bucket\_secrets](#output\_drupal\_apps\_all\_bucket\_secrets) | Bucket kubernetes secrets for each Drupal project, indexed same as all\_data | | [drupal\_apps\_all\_data](#output\_drupal\_apps\_all\_data) | All data for each Drupal project. | -| [drupal\_apps\_all\_database\_credentials](#output\_drupal\_apps\_all\_database\_credentials) | Database credentials for each Drupal project | -| [drupal\_apps\_all\_database\_secrets](#output\_drupal\_apps\_all\_database\_secrets) | Database kubernetes secrets for each Drupal project | -| [drupal\_apps\_all\_namespaces](#output\_drupal\_apps\_all\_namespaces) | Namespace for each Drupal project | +| [drupal\_apps\_all\_database\_credentials](#output\_drupal\_apps\_all\_database\_credentials) | Database credentials for each Drupal project, indexed same as all\_data | +| [drupal\_apps\_all\_database\_secrets](#output\_drupal\_apps\_all\_database\_secrets) | Database kubernetes secrets for each Drupal project, indexed same as all\_data | +| [drupal\_apps\_all\_namespaces](#output\_drupal\_apps\_all\_namespaces) | Map of all Kubernetes namespaces used by Drupal apps, indexed same as all\_data | | [drupal\_apps\_bucket\_credentials](#output\_drupal\_apps\_bucket\_credentials) | Drupal apps bucket credentials for each Drupal project. | | [drupal\_apps\_database\_credentials](#output\_drupal\_apps\_database\_credentials) | Drupal apps database credentials for each Drupal project. | | [drupal\_buckets\_names\_list](#output\_drupal\_buckets\_names\_list) | The list with the names of the Drupal buckets managed by this module. | +| [namespaces\_network\_policy](#output\_namespaces\_network\_policy) | Namespaces with network policy enabled. | ## Resources | Name | Type | @@ -162,6 +163,7 @@ the random suffix `bucket_append_random_suffix` for the bucket name. | [google_storage_bucket_iam_member.cloudsql_dumps_bucket_writer](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam_member) | resource | | [google_tags_location_tag_binding.binding](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/tags_location_tag_binding) | resource | | [kubernetes_namespace.namespace](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [kubernetes_network_policy_v1.this](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/network_policy_v1) | resource | | [kubernetes_secret.bucket_secret_name](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource | | [kubernetes_secret.database_secret_name](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource | | [random_id.cloudsql_dumps_bucket_name_suffix](https://registry.terraform.io/providers/hashicorp/random/3.6.2/docs/resources/id) | resource | diff --git a/main.tf b/main.tf index 8f165ed..a3e7216 100644 --- a/main.tf +++ b/main.tf @@ -51,6 +51,8 @@ locals { p.kubernetes_namespace_labels, var.default_k8s_labels ) + project_name = p.project_name + network_policy = p.network_policy } ] } @@ -92,3 +94,37 @@ resource "kubernetes_namespace" "namespace" { labels = each.value.labels } } + +locals { + unique_namespaces = toset([for p in local.namespace_list : p.namespace if p.network_policy != ""]) +} + +resource "kubernetes_network_policy_v1" "this" { + for_each = { + for p in local.namespace_list : p.namespace => p.network_policy if contains(local.unique_namespaces, p.namespace) + } + + metadata { + name = "network-policy-${each.value}" + namespace = kubernetes_namespace.namespace[each.key].metadata[0].name + } + + spec { + pod_selector {} + + policy_types = ["Ingress"] + + ingress { + dynamic "from" { + for_each = each.value == "isolated" ? { "isolated" : true } : {} + content { + pod_selector {} + } + } + dynamic "from" { + for_each = each.value == "restricted" ? { "restricted" : true } : {} + content {} + } + } + } +} diff --git a/outputs.tf b/outputs.tf index 1d84b6b..72aeaa1 100644 --- a/outputs.tf +++ b/outputs.tf @@ -137,3 +137,12 @@ output "cloudsql_dumps_bucket_name" { description = "CloudSQL dumps bucket name." value = local.cloudsql_dumps_bucket_name } + +output "namespaces_network_policy" { + description = "Namespaces with network policy enabled." + value = { + "isolated" : { for obj in local.namespace_list : obj.namespace => obj.project_name if obj.network_policy == "isolated" }, + "restricted" : { for obj in local.namespace_list : obj.namespace => obj.project_name if obj.network_policy == "restricted" }, + "none" : { for obj in local.namespace_list : obj.namespace => obj.project_name if obj.network_policy == "" } + } +} diff --git a/variables.tf b/variables.tf index 3a0d396..314b154 100644 --- a/variables.tf +++ b/variables.tf @@ -74,6 +74,7 @@ variable "drupal_projects_list" { bucket_obj_adm = optional(list(string), []) bucket_obj_vwr = optional(list(string), []) bucket_soft_delete_retention_seconds = optional(number, 0) + network_policy = optional(string, "") })) validation { @@ -91,9 +92,13 @@ variable "drupal_projects_list" { (p.database_host != null && p.database_name == null && p.database_user_name == null && length(p.project_name) <= 16) || (p.database_host != null && p.database_name != null && p.database_user_name != null && length(p.project_name) <= 23) || (p.database_host == null && length(p.project_name) <= 23) + ) && + ( + (p.network_policy != "" && contains(["isolated", "restricted"], p.network_policy)) || + (p.network_policy == "") ) ]) - error_message = "The project name is invalid. Must be 6 to 16 characters long, with only lowercase letters, numbers, hyphens and underscores if the database must be created by the module or 6 to 23 characters long if we pass database_host database_user_name and database_name to the module." + error_message = "The project name is invalid. Must be 6 to 16 characters long, with only lowercase letters, numbers, hyphens and underscores if the database must be created by the module or 6 to 23 characters long if we pass database_host database_user_name and database_name to the module. If a network policy is specified, it must be 'isolated' or 'restricted'." } validation {