From 76f022a97d0274d64bb0b693f6abb6507cdb99d2 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 13:04:04 +0100 Subject: [PATCH 01/18] new bindplane on gke secops blueprint --- blueprints/secops/bindplane-gke/OWNERS | 1 + blueprints/secops/bindplane-gke/README.md | 155 +++++++++++++ .../bindplane-deployment/main.tf | 60 +++++ .../bindplane-deployment/variables.tf | 34 +++ .../bindplane-deployment/versions_override.tf | 25 ++ .../bindplane-gke/config/values.yaml.tpl | 89 +++++++ .../images/cloud-shell-button.png | Bin 0 -> 10762 bytes .../secops/bindplane-gke/images/diagram.png | Bin 0 -> 47434 bytes .../secops/bindplane-gke/images/login.png | Bin 0 -> 48397 bytes blueprints/secops/bindplane-gke/main.tf | 217 ++++++++++++++++++ blueprints/secops/bindplane-gke/outputs.tf | 40 ++++ blueprints/secops/bindplane-gke/ssl.tf | 107 +++++++++ blueprints/secops/bindplane-gke/variables.tf | 107 +++++++++ blueprints/secops/bindplane-gke/versions.tf | 29 +++ 14 files changed, 864 insertions(+) create mode 100644 blueprints/secops/bindplane-gke/OWNERS create mode 100644 blueprints/secops/bindplane-gke/README.md create mode 100644 blueprints/secops/bindplane-gke/bindplane-deployment/main.tf create mode 100644 blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf create mode 100644 blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf create mode 100644 blueprints/secops/bindplane-gke/config/values.yaml.tpl create mode 100644 blueprints/secops/bindplane-gke/images/cloud-shell-button.png create mode 100644 blueprints/secops/bindplane-gke/images/diagram.png create mode 100644 blueprints/secops/bindplane-gke/images/login.png create mode 100644 blueprints/secops/bindplane-gke/main.tf create mode 100644 blueprints/secops/bindplane-gke/outputs.tf create mode 100644 blueprints/secops/bindplane-gke/ssl.tf create mode 100644 blueprints/secops/bindplane-gke/variables.tf create mode 100644 blueprints/secops/bindplane-gke/versions.tf diff --git a/blueprints/secops/bindplane-gke/OWNERS b/blueprints/secops/bindplane-gke/OWNERS new file mode 100644 index 0000000000..65c8fc162f --- /dev/null +++ b/blueprints/secops/bindplane-gke/OWNERS @@ -0,0 +1 @@ +simonebruzzechesse diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md new file mode 100644 index 0000000000..4de357926e --- /dev/null +++ b/blueprints/secops/bindplane-gke/README.md @@ -0,0 +1,155 @@ +# BindPlane OP Management console on GKE + +This Terraform module simplifies the deployment of the BindPlane OP Management Console within a Google Kubernetes Engine (GKE) environment. It's specifically engineered for organizations seeking a scalable and highly available solution, capitalizing on the strengths of containerization and managed platform services like Cloud SQL for PostgreSQL. + +This module streamlines the process of deploying BindPlane OP, by leveraging GKE, PubSub and Cloud SQL, this module provides: + +- **Simplified Deployment**: Deploy a production-ready BindPlane OP environment with minimal manual configuration. +- **Enhanced Scalability**: Easily adapt to increasing demands and data volumes as your needs evolve. +- **Increased Resilience**: Benefit from the high availability and fault tolerance offered by GKE and Cloud SQL. +- **Operational Efficiency**: Reduce operational overhead by utilizing managed Kubernetes and database services. + +This module encapsulates best practices for deploying BindPlane OP in a cloud-native environment, ensuring a robust and reliable foundation for your observability platform. + +### High level architecture + +The following diagram illustrates the high-level design of created resources, which can be adapted to specific requirements via variables: + +![Bindplane OP Management console on GKE](./images/diagram.png) + +BindPlane OP Management console will be exposed via Internal HTTPS Load Balancer, this module assume a private connection to GCP environment is in place to reach the BindPlane management console over private IPs. +In case no private connection is in place it should be pretty straightforward to setup a proxy VM to proxy the connection towards the bindplane console. Of course such a deployment can only deal with agents running on the same GCP infrastructure. + +### Deployment + +#### Step 0: Cloning the repository + +If you want to deploy from your Cloud Shell, click on the image below, sign in +if required and when the prompt appears, click on “confirm”. + +[![Open Cloudshell](./images/cloud-shell-button.png)](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fcloud-foundation-fabric&cloudshell_workspace=blueprints%2Fthird-party-solutions%2Fwordpress%2Fcloudrun) + +Otherwise, in your console of choice: + +```bash +git clone https://github.com/GoogleCloudPlatform/cloud-foundation-fabric.git +``` + +Before you deploy the architecture, you will need at least the following +information/configurations in place (for more precise configuration see the Variables section): + +* The project ID +* The VPC host project +* VPC and subnets should already exist +* Subnet must be configured with pods and services secondary ranges (default names for secondary ranges is "pod" and "services") + +#### Step 2: Prepare the variables + +Once you have the required information, head back to your cloned repository. +Make sure you’re in the directory of this tutorial (where this README is in). + +Configure the Terraform variables in your `terraform.tfvars` file. +See the example test at the end of this README.md as starting point - just +copy it to `terraform.tfvars` and edit the latter. See the variables +documentation below. + +#### Step 3: Prepare the providers in the root module + +Setup terraform providers in the root module to deal with kubernetes resources as follows: + +```terraform +data "google_client_config" "identity" { + count = module.chronicle-forwarder.fleet_host != null ? 1 : 0 +} + +provider "kubernetes" { + host = module.chronicle-forwarder.fleet_host + token = try(data.google_client_config.identity.0.access_token, null) +} + +provider "kubectl" { + host = module.chronicle-forwarder.fleet_host + token = try(data.google_client_config.identity.0.access_token, null) +} +``` + +#### Step 4: Deploy resources + +Initialize your Terraform environment and deploy the resources: + +```shell +terraform init +terraform apply +``` + +Get kubeconfig to connect to the cluster using the command below: + +```shell +gcloud container fleet memberships get-credentials CLUSTER_NAME --project PROJECT +``` + +Then running the command `kubectl get pods` you should receive the following message: + +``` +"No resources found in default namespace." +``` + +In case private connection is available and DNS configuration is properly in place you should be able to reach the BindPlane OP Management console navigating the url (e.g. https://bindplane.example.com/), the following login page should show up. + +![Bindplane OP Management console login page](./images/login.png) + +Access the management console leveraging credentials bootstrapped via terraform (user and password in `bindplane_secrets` variable). + +## Variables + +| name | description | type | required | default | +|---|---|:---:|:---:|:---:| +| [bindplane_secrets](variables.tf#L26) | Bindplane secrets. | object({…}) | ✓ | | +| [network_config](variables.tf#L58) | Shared VPC network configurations to use for GKE cluster. | object({…}) | ✓ | | +| [prefix](variables.tf#L80) | Prefix used for resource names. | string | ✓ | | +| [project_id](variables.tf#L99) | Project id, references existing project if `project_create` is null. | string | ✓ | | +| [region](variables.tf#L104) | GCP region. | string | ✓ | | +| [bindplane_config](variables.tf#L17) | Bindplane config. | object({…}) | | {} | +| [cluster_config](variables.tf#L37) | GKE cluster configuration. | object({…}) | | {} | +| [dns_config](variables.tf#L48) | DNS config. | object({…}) | | {} | +| [postgresql_config](variables.tf#L70) | Cloud SQL postgresql config. | object({…}) | | {} | +| [project_create](variables.tf#L90) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| [bindplane_hostname](outputs.tf#L17) | BindPlane OP Management console hostname. | | +| [ca_cert](outputs.tf#L22) | TLS CA certificate. | | +| [cluster_ca_certificate](outputs.tf#L27) | GKE CA Certificate. | | +| [fleet_host](outputs.tf#L32) | GKE Fleet host. | | +| [lb_ip_address](outputs.tf#L37) | Ingress LB address. | | + +## Test + +```hcl +module "bindplane-gke" { + source = "./fabric/blueprints/secops/bindplane-gke" + project_id = "bindplane" + bindplane_secrets = { + user = "admin" + password = "thisisnotasecret" + secret_key = "xxxxxx-xxxxxxx-xxxxxx" + sessions_secret = "xxxxxx-xxxxxxx-xxxxxx" + license = "XXXXXXXXXXXXXXXXXXXXXX" + } + dns_config = { + bootstrap_private_zone = true + domain = "example.com" + hostname = "bindplane" + } + network_config = { + network_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/global/networks/prod-landing-0" + subnet_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/regions/europe-west1/subnetworks/gke" + ip_range_gke_master = "192.168.0.0/28" + } + region = "europe-west8" + prefix = "tmp" +} +# tftest modules=5 resources=34 files=credentials,config +``` diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf new file mode 100644 index 0000000000..41b59b2b5e --- /dev/null +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf @@ -0,0 +1,60 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +locals { + bindplane_password = coalesce(var.bindplane_secrets.password, try(random_password.password.0.result,null)) +} + +resource "random_password" "password" { + count = var.bindplane_secrets.password == null ? 1 : 0 + length = 16 + special = true + override_special = "_!%^" +} + +resource "kubernetes_namespace" "namespace" { + metadata { + name = "bindplane" + } +} + +resource "kubernetes_secret" "bindplane_secret" { + metadata { + name = "bindplane" + namespace = kubernetes_namespace.namespace.metadata[0].name + } + + data = { + username = var.bindplane_secrets.user + password = local.bindplane_password + secret_key = var.bindplane_secrets.secret_key + sessions_secret = var.bindplane_secrets.sessions_secret + license = var.bindplane_secrets.license + } + type = "Opaque" +} + +resource "kubernetes_secret" "tls" { + metadata { + name = "bindplane-tls" + namespace = kubernetes_namespace.namespace.metadata[0].name + } + data = { + "tls.crt" = var.bindplane_tls.cer + "tls.key" = var.bindplane_tls.key + } + type = "kubernetes.io/tls" +} \ No newline at end of file diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf new file mode 100644 index 0000000000..8c6a8ab361 --- /dev/null +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf @@ -0,0 +1,34 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +variable "bindplane_secrets" { + description = "Bindplane configuration." + type = object({ + license = string + user = optional(string, "admin") + password = optional(string, null) + secret_key = string + sessions_secret = string + }) +} + +variable "bindplane_tls" { + description = "Bindplane TLS certificates." + type = object({ + cer = string + key = string + }) +} diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf new file mode 100644 index 0000000000..75d041486f --- /dev/null +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf @@ -0,0 +1,25 @@ +# Copyright 2024 Google LLC +# +# 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 +# +# https://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. + +terraform { + required_providers { + restful = { + source = "magodo/restful" + } + kubectl = { + source = "gavinbunney/kubectl" + version = ">= 1.7.0" + } + } +} diff --git a/blueprints/secops/bindplane-gke/config/values.yaml.tpl b/blueprints/secops/bindplane-gke/config/values.yaml.tpl new file mode 100644 index 0000000000..4f7d8398dc --- /dev/null +++ b/blueprints/secops/bindplane-gke/config/values.yaml.tpl @@ -0,0 +1,89 @@ +# This ingress example uses Ingress NGINX and Cert Manager +# for creating Lets Encrypt signed certificates. +# +# - https://kubernetes.github.io/ingress-nginx/deploy/#gce-gke +# - https://cert-manager.io/docs/tutorials/getting-started-with-cert-manager-on-google-kubernetes-engine-using-lets-encrypt-for-ingress-ssl/ +# +ingress: + enable: true + host: ${hostname} + class: "gce-internal" + tls: + enable: true + secret: bindplane-tls + annotations: + # cert-manager.io/issuer: letsencrypt + kubernetes.io/ingress.regional-static-ip-name: ${address} + +config: + # Use the secret named "bindplane", which contains + # the license, username, password, secret_key, and sessions_secret. + # If you do not want to use a secret, see the comment below and + # disable this option. + licenseUseSecret: true + + # Defaults to wss://bindplane.bindplane.svc.cluster.local:3001/v1/opamp, + # which is the bindplane namespace's bindplane service. This is suitable + # for connecting agents within the same cluster. We are using ingress + # so server_url needs to be updated to the ingress host. + # NOTE: server_url maps to bindplane's network.remoteURL option. + server_url: https://${hostname} + + +# Enables mutli account, allowing you to create +# multiple Tenants within the same BindPlane instance. +multiAccount: true + +# Fixed number of pods. BindPlane CPU usage is bursty, using +# a pod autoscaler can be tricky. Generally a fixed number +# of pods is recommended. +replicas: 2 + +resources: + # Allow cpu bursting by leaving limits.cpu unset + requests: + cpu: '1000m' + memory: '4096Mi' + limits: + memory: '4096Mi' + +# Node pools must be authenticated to Pub/Sub with one of the following options +# - Pub/Sub scope enabled +# - GKE Service Account with Pub/Sub permissions +# - Service Account key file and the GOOGLE_APPLICATION_CREDENTIALS environment variable set +# to the path of the key file. You can use extraVolumes, extraVolumeMounts, extraEnv to +# mount a configMap or secret containing the key file. +eventbus: + type: 'pubsub' + pubsub: + projectid: '${gcp_project_id}' + topic: 'bindplane' + +backend: + type: postgres + postgres: + host: '${postgresql_ip}' + port: 5432 + database: 'bindplane' + username: '${postgresql_username}' + password: '${postgresql_password}' + # Replicas * max connections should not exceed + # your Postgres instance's max connections. + # This option defaults to 100, which is too high + # for an environment with 7 replicas. + maxConnections: 20 + +transform_agent: + replicas: 2 + +# Prometheus is deployed and managed by the Helm chart. At scale +# it will require additional resources which can be set here. +prometheus: + resources: + requests: + cpu: '2000m' + memory: '8192Mi' + limits: + memory: '8192Mi' + storage: + volumeSize: '120Gi' \ No newline at end of file diff --git a/blueprints/secops/bindplane-gke/images/cloud-shell-button.png b/blueprints/secops/bindplane-gke/images/cloud-shell-button.png new file mode 100644 index 0000000000000000000000000000000000000000..21a3f3de9d130679049a1085476073e5bf54a43d GIT binary patch literal 10762 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

S%MqqP?}BTT3JYV$QAA08fF2&yR#=lPaYL8Mt1 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 literal 0 HcmV?d00001 diff --git a/blueprints/secops/bindplane-gke/images/login.png b/blueprints/secops/bindplane-gke/images/login.png new file mode 100644 index 0000000000000000000000000000000000000000..2681ce887a9a20c7af1dca2e8ef0e3fb5a87c86d GIT binary patch literal 48397 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 P13nNvm~QEH`-lGz?~NJZ literal 0 HcmV?d00001 diff --git a/blueprints/secops/bindplane-gke/main.tf b/blueprints/secops/bindplane-gke/main.tf new file mode 100644 index 0000000000..3b260f07d2 --- /dev/null +++ b/blueprints/secops/bindplane-gke/main.tf @@ -0,0 +1,217 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +locals { + fleet_host = join("", [ + "https://connectgateway.googleapis.com/v1/", + "projects/${module.project.number}/", + "locations/global/gkeMemberships/bindplane" + ]) +} + +module "project" { + source = "../../../modules/project" + billing_account = (var.project_create != null + ? var.project_create.billing_account_id + : null + ) + parent = (var.project_create != null + ? var.project_create.parent + : null + ) + prefix = var.prefix + project_create = var.project_create != null + name = var.project_id + services = concat([ + "compute.googleapis.com", + "iap.googleapis.com", + "stackdriver.googleapis.com", + "chronicle.googleapis.com", + "container.googleapis.com", + "gkehub.googleapis.com", + "connectgateway.googleapis.com", + "gkeconnect.googleapis.com" + ]) + iam = { + "roles/pubsub.editor" = ["principal://iam.googleapis.com/projects/${module.project.number}/locations/global/workloadIdentityPools/${module.project.project_id}.svc.id.goog/subject/ns/bindplane/sa/bindplane"] + } +} + +module "fleet" { + source = "../../../modules/gke-hub" + project_id = module.project.project_id + clusters = { + "bindplane" = module.bindplane-cluster.id + } +} + +module "bindplane-cluster" { + source = "../../../modules/gke-cluster-autopilot" + project_id = module.project.project_id + name = var.cluster_config.cluster_name + location = var.region + deletion_protection = false + vpc_config = { + network = var.network_config.network_self_link + subnetwork = var.network_config.subnet_self_link + secondary_range_names = { + pods = var.network_config.secondary_pod_range_name + services = var.network_config.secondary_services_range_name + } + master_ipv4_cidr_block = var.network_config.ip_range_gke_master + master_authorized_ranges = var.cluster_config.master_authorized_ranges + } + private_cluster_config = { + enable_private_endpoint = true + master_global_access = true + } + enable_features = { + gateway_api = true + } + logging_config = { + enable_api_server_logs = true + enable_scheduler_logs = true + enable_controller_manager_logs = true + } + monitoring_config = { + enable_daemonset_metrics = true + enable_deployment_metrics = true + enable_hpa_metrics = true + enable_pod_metrics = true + enable_statefulset_metrics = true + enable_storage_metrics = true + enable_api_server_metrics = true + enable_controller_manager_metrics = true + enable_scheduler_metrics = true + } +} + +module "db" { + source = "../../../modules/cloudsql-instance" + project_id = module.project.project_id + databases = ["bindplane"] + network_config = { + connectivity = { + psc_allowed_consumer_projects = [module.project.project_id] + } + } + prefix = var.prefix + name = "bindplane" + region = var.region + availability_type = var.postgresql_config.availability_type + database_version = var.postgresql_config.database_version + tier = var.postgresql_config.tier + + users = { + bindplane = { + password = null + type = "BUILT_IN" + } + } + + gcp_deletion_protection = false + terraform_deletion_protection = false +} + +module "addresses" { + source = "../../../modules/net-address" + project_id = module.project.project_id + internal_addresses = { + ingress = { + purpose = "SHARED_LOADBALANCER_VIP" + region = var.region + subnetwork = var.network_config.subnet_self_link + } + } + psc_addresses = { + postgresql = { + address = "" + region = var.region + subnet_self_link = var.network_config.subnet_self_link + service_attachment = { + psc_service_attachment_link = module.db.psc_service_attachment_link + global_access = true + } + } + } +} + +module "dns" { + source = "../../../modules/dns" + count = var.dns_config.bootstrap_private_zone ? 1 : 0 + project_id = module.project.project_id + name = "bindplane" + zone_config = { + domain = "${var.dns_config.domain}." + private = { + client_networks = [var.network_config.network_self_link] + } + } + recordsets = { + "A ${var.dns_config.hostname}" = { ttl = 600, records = [module.addresses.internal_addresses["ingress"].address] } + } +} + +module "pubsub" { + source = "../../../modules/pubsub" + project_id = module.project.project_id + name = "bindplane" +} + +module "bindplane-sa" { + source = "../../../modules/iam-service-account" + project_id = module.project.project_id + name = "bindplane" + iam = { + "roles/iam.workloadIdentityUser" = ["serviceAccount:${module.project.project_id}.svc.id.goog[bindplane/bindplane]"] + } + iam_project_roles = { + "${module.project.project_id}" = [ + "roles/pubsub.editor" + ] + } +} + +module "bindplane-deployment" { + source = "./bindplane-deployment" + depends_on = [module.bindplane-cluster] + bindplane_secrets = var.bindplane_secrets + bindplane_tls = { + cer = coalesce(var.bindplane_config.tls_certificate_cer, try(tls_locally_signed_cert.server_singed_cert.0.cert_pem,null)) + key = coalesce(var.bindplane_config.tls_certificate_key, try(tls_private_key.server_key.0.private_key_pem,null)) + } +} + +resource "helm_release" "bindplane" { + name = "bindplane" + repository = "https://observiq.github.io/bindplane-op-helm" + chart = "bindplane" + namespace = "bindplane" + create_namespace = false + values = [templatefile("${path.module}/config/values.yaml.tpl", { + postgresql_ip = module.addresses.psc_addresses["postgresql"].address + postgresql_username = "bindplane" + postgresql_password = module.db.user_passwords["bindplane"] + gcp_project_id = module.project.project_id + hostname = "${var.dns_config.hostname}.${var.dns_config.domain}" + address = "ingress" + })] + + depends_on = [ + module.bindplane-deployment, + module.addresses + ] +} diff --git a/blueprints/secops/bindplane-gke/outputs.tf b/blueprints/secops/bindplane-gke/outputs.tf new file mode 100644 index 0000000000..e25ad7085b --- /dev/null +++ b/blueprints/secops/bindplane-gke/outputs.tf @@ -0,0 +1,40 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +output "bindplane_hostname" { + description = "BindPlane OP Management console hostname." + value = "https://${var.dns_config.hostname}.${var.dns_config.domain}" +} + +output "ca_cert" { + description = "TLS CA certificate." + value = try(tls_self_signed_cert.ca_cert.0.cert_pem, null) +} + +output "cluster_ca_certificate" { + description = "GKE CA Certificate." + value = module.bindplane-cluster.ca_certificate +} + +output "fleet_host" { + description = "GKE Fleet host." + value = local.fleet_host +} + +output "lb_ip_address" { + description = "Ingress LB address." + value = module.addresses.internal_addresses["ingress"].address +} diff --git a/blueprints/secops/bindplane-gke/ssl.tf b/blueprints/secops/bindplane-gke/ssl.tf new file mode 100644 index 0000000000..76d87f7340 --- /dev/null +++ b/blueprints/secops/bindplane-gke/ssl.tf @@ -0,0 +1,107 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +locals { + bootstrap_self_signed_cert = var.bindplane_config.tls_certificate_cer == null || var.bindplane_config.tls_certificate_key == null + cert_subjects = [ + { + country = "IT" + province = "Lombardy" + locality = "Milan" + organization = "Example" + organizational_unit = "Example" + } + ] +} + +####################################################################### +# CA PRIVATE KEY # +####################################################################### + +resource "tls_private_key" "ca_private_key" { + count = local.bootstrap_self_signed_cert ? 1 : 0 + algorithm = "RSA" +} + +####################################################################### +# CA CERT # +####################################################################### + +resource "tls_self_signed_cert" "ca_cert" { + count = local.bootstrap_self_signed_cert ? 1 : 0 + private_key_pem = tls_private_key.ca_private_key.0.private_key_pem + is_ca_certificate = true + dynamic "subject" { + for_each = toset(local.cert_subjects) + content { + country = subject.value.country + province = subject.value.province + locality = subject.value.locality + common_name = "Bindplane" + organization = subject.value.organization + organizational_unit = subject.value.organization + } + } + validity_period_hours = 87600 // 3650 days or 10 years + allowed_uses = [ + "digital_signature", + "cert_signing", + "crl_signing", + ] +} + +####################################################################### +# SERVER CERT SIGNED BY CA # +####################################################################### + +resource "tls_private_key" "server_key" { + count = local.bootstrap_self_signed_cert ? 1 : 0 + algorithm = "RSA" +} + +resource "tls_cert_request" "server_csr" { + count = local.bootstrap_self_signed_cert ? 1 : 0 + private_key_pem = tls_private_key.server_key.0.private_key_pem + dns_names = ["bindplane.${var.hostname}"] + + dynamic "subject" { + for_each = toset(local.cert_subjects) + content { + country = subject.value.country + province = subject.value.province + locality = subject.value.locality + common_name = "Gitlab" + organization = subject.value.organization + organizational_unit = subject.value.organization + } + } +} + +resource "tls_locally_signed_cert" "server_singed_cert" { + count = local.bootstrap_self_signed_cert ? 1 : 0 + cert_request_pem = tls_cert_request.server_csr.0.cert_request_pem + ca_private_key_pem = tls_private_key.ca_private_key.0.private_key_pem + ca_cert_pem = tls_self_signed_cert.ca_cert.0.cert_pem + + validity_period_hours = 87600 // 3650 days or 10 years + + allowed_uses = [ + "digital_signature", + "key_encipherment", + "server_auth", + "client_auth", + ] +} diff --git a/blueprints/secops/bindplane-gke/variables.tf b/blueprints/secops/bindplane-gke/variables.tf new file mode 100644 index 0000000000..95b6016cb6 --- /dev/null +++ b/blueprints/secops/bindplane-gke/variables.tf @@ -0,0 +1,107 @@ +/** + * Copyright 2024 Google LLC + * + * 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. + */ + +variable "bindplane_config" { + description = "Bindplane config." + type = object({ + tls_certificate_cer = optional(string, null) + tls_certificate_key = optional(string, null) + }) + default = {} +} + +variable "bindplane_secrets" { + description = "Bindplane secrets." + type = object({ + license = string + user = optional(string, "admin") + password = optional(string, null) + secret_key = string + sessions_secret = string + }) +} + +variable "cluster_config" { + description = "GKE cluster configuration." + type = object({ + cluster_name = optional(string, "bindplane-op") + master_authorized_ranges = optional(map(string), { + rfc-1918-10-8 = "10.0.0.0/8" + }) + }) + default = {} +} + +variable "dns_config" { + description = "DNS config." + type = object({ + bootstrap_private_zone = optional(bool, false) + domain = optional(string, "example.com") + hostname = optional(string, "bindplane") + }) + default = {} +} + +variable "network_config" { + description = "Shared VPC network configurations to use for GKE cluster." + type = object({ + host_project = optional(string) + network_self_link = string + subnet_self_link = string + ip_range_gke_master = string + secondary_pod_range_name = optional(string, "pods") + secondary_services_range_name = optional(string, "services") + }) +} + +variable "postgresql_config" { + description = "Cloud SQL postgresql config." + type = object({ + availability_type = optional(string, "REGIONAL") + database_version = optional(string, "POSTGRES_13") + tier = optional(string, "db-g1-small") + }) + default = {} +} + +variable "prefix" { + description = "Prefix used for resource names." + type = string + nullable = false + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty." + } +} + +variable "project_create" { + description = "Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format." + type = object({ + billing_account_id = string + parent = string + }) + default = null +} + +variable "project_id" { + description = "Project id, references existing project if `project_create` is null." + type = string +} + +variable "region" { + description = "GCP region." + type = string +} diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf new file mode 100644 index 0000000000..f569ce5af2 --- /dev/null +++ b/blueprints/secops/bindplane-gke/versions.tf @@ -0,0 +1,29 @@ +# Copyright 2024 Google LLC +# +# 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 +# +# https://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. + +# Fabric release: v35.0.0 + +terraform { + required_version = ">= 1.7.4" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 6.1.0, < 7.0.0" # tftest + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 6.1.0, < 7.0.0" # tftest + } + } +} From bf40cbdae421b303a29fce2bbe8527fa93abce09 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 13:06:08 +0100 Subject: [PATCH 02/18] format --- .../bindplane-gke/bindplane-deployment/main.tf | 4 ++-- .../bindplane-deployment/variables.tf | 2 +- blueprints/secops/bindplane-gke/main.tf | 8 ++++---- blueprints/secops/bindplane-gke/outputs.tf | 6 +++--- blueprints/secops/bindplane-gke/ssl.tf | 10 +++++----- blueprints/secops/bindplane-gke/variables.tf | 18 +++++++++--------- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf index 41b59b2b5e..56f7306e30 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf @@ -15,7 +15,7 @@ */ locals { - bindplane_password = coalesce(var.bindplane_secrets.password, try(random_password.password.0.result,null)) + bindplane_password = coalesce(var.bindplane_secrets.password, try(random_password.password.0.result, null)) } resource "random_password" "password" { @@ -57,4 +57,4 @@ resource "kubernetes_secret" "tls" { "tls.key" = var.bindplane_tls.key } type = "kubernetes.io/tls" -} \ No newline at end of file +} diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf index 8c6a8ab361..215ac9b6e0 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf @@ -27,7 +27,7 @@ variable "bindplane_secrets" { variable "bindplane_tls" { description = "Bindplane TLS certificates." - type = object({ + type = object({ cer = string key = string }) diff --git a/blueprints/secops/bindplane-gke/main.tf b/blueprints/secops/bindplane-gke/main.tf index 3b260f07d2..3c6f0627f2 100644 --- a/blueprints/secops/bindplane-gke/main.tf +++ b/blueprints/secops/bindplane-gke/main.tf @@ -143,7 +143,7 @@ module "addresses" { subnet_self_link = var.network_config.subnet_self_link service_attachment = { psc_service_attachment_link = module.db.psc_service_attachment_link - global_access = true + global_access = true } } } @@ -175,7 +175,7 @@ module "bindplane-sa" { source = "../../../modules/iam-service-account" project_id = module.project.project_id name = "bindplane" - iam = { + iam = { "roles/iam.workloadIdentityUser" = ["serviceAccount:${module.project.project_id}.svc.id.goog[bindplane/bindplane]"] } iam_project_roles = { @@ -190,8 +190,8 @@ module "bindplane-deployment" { depends_on = [module.bindplane-cluster] bindplane_secrets = var.bindplane_secrets bindplane_tls = { - cer = coalesce(var.bindplane_config.tls_certificate_cer, try(tls_locally_signed_cert.server_singed_cert.0.cert_pem,null)) - key = coalesce(var.bindplane_config.tls_certificate_key, try(tls_private_key.server_key.0.private_key_pem,null)) + cer = coalesce(var.bindplane_config.tls_certificate_cer, try(tls_locally_signed_cert.server_singed_cert.0.cert_pem, null)) + key = coalesce(var.bindplane_config.tls_certificate_key, try(tls_private_key.server_key.0.private_key_pem, null)) } } diff --git a/blueprints/secops/bindplane-gke/outputs.tf b/blueprints/secops/bindplane-gke/outputs.tf index e25ad7085b..a8ee465c33 100644 --- a/blueprints/secops/bindplane-gke/outputs.tf +++ b/blueprints/secops/bindplane-gke/outputs.tf @@ -16,12 +16,12 @@ output "bindplane_hostname" { description = "BindPlane OP Management console hostname." - value = "https://${var.dns_config.hostname}.${var.dns_config.domain}" + value = "https://${var.dns_config.hostname}.${var.dns_config.domain}" } output "ca_cert" { description = "TLS CA certificate." - value = try(tls_self_signed_cert.ca_cert.0.cert_pem, null) + value = try(tls_self_signed_cert.ca_cert.0.cert_pem, null) } output "cluster_ca_certificate" { @@ -36,5 +36,5 @@ output "fleet_host" { output "lb_ip_address" { description = "Ingress LB address." - value = module.addresses.internal_addresses["ingress"].address + value = module.addresses.internal_addresses["ingress"].address } diff --git a/blueprints/secops/bindplane-gke/ssl.tf b/blueprints/secops/bindplane-gke/ssl.tf index 76d87f7340..87e3645b07 100644 --- a/blueprints/secops/bindplane-gke/ssl.tf +++ b/blueprints/secops/bindplane-gke/ssl.tf @@ -32,7 +32,7 @@ locals { ####################################################################### resource "tls_private_key" "ca_private_key" { - count = local.bootstrap_self_signed_cert ? 1 : 0 + count = local.bootstrap_self_signed_cert ? 1 : 0 algorithm = "RSA" } @@ -41,7 +41,7 @@ resource "tls_private_key" "ca_private_key" { ####################################################################### resource "tls_self_signed_cert" "ca_cert" { - count = local.bootstrap_self_signed_cert ? 1 : 0 + count = local.bootstrap_self_signed_cert ? 1 : 0 private_key_pem = tls_private_key.ca_private_key.0.private_key_pem is_ca_certificate = true dynamic "subject" { @@ -68,12 +68,12 @@ resource "tls_self_signed_cert" "ca_cert" { ####################################################################### resource "tls_private_key" "server_key" { - count = local.bootstrap_self_signed_cert ? 1 : 0 + count = local.bootstrap_self_signed_cert ? 1 : 0 algorithm = "RSA" } resource "tls_cert_request" "server_csr" { - count = local.bootstrap_self_signed_cert ? 1 : 0 + count = local.bootstrap_self_signed_cert ? 1 : 0 private_key_pem = tls_private_key.server_key.0.private_key_pem dns_names = ["bindplane.${var.hostname}"] @@ -91,7 +91,7 @@ resource "tls_cert_request" "server_csr" { } resource "tls_locally_signed_cert" "server_singed_cert" { - count = local.bootstrap_self_signed_cert ? 1 : 0 + count = local.bootstrap_self_signed_cert ? 1 : 0 cert_request_pem = tls_cert_request.server_csr.0.cert_request_pem ca_private_key_pem = tls_private_key.ca_private_key.0.private_key_pem ca_cert_pem = tls_self_signed_cert.ca_cert.0.cert_pem diff --git a/blueprints/secops/bindplane-gke/variables.tf b/blueprints/secops/bindplane-gke/variables.tf index 95b6016cb6..ff2ceedc90 100644 --- a/blueprints/secops/bindplane-gke/variables.tf +++ b/blueprints/secops/bindplane-gke/variables.tf @@ -49,8 +49,8 @@ variable "dns_config" { description = "DNS config." type = object({ bootstrap_private_zone = optional(bool, false) - domain = optional(string, "example.com") - hostname = optional(string, "bindplane") + domain = optional(string, "example.com") + hostname = optional(string, "bindplane") }) default = {} } @@ -58,11 +58,11 @@ variable "dns_config" { variable "network_config" { description = "Shared VPC network configurations to use for GKE cluster." type = object({ - host_project = optional(string) - network_self_link = string - subnet_self_link = string - ip_range_gke_master = string - secondary_pod_range_name = optional(string, "pods") + host_project = optional(string) + network_self_link = string + subnet_self_link = string + ip_range_gke_master = string + secondary_pod_range_name = optional(string, "pods") secondary_services_range_name = optional(string, "services") }) } @@ -71,8 +71,8 @@ variable "postgresql_config" { description = "Cloud SQL postgresql config." type = object({ availability_type = optional(string, "REGIONAL") - database_version = optional(string, "POSTGRES_13") - tier = optional(string, "db-g1-small") + database_version = optional(string, "POSTGRES_13") + tier = optional(string, "db-g1-small") }) default = {} } From 84ab8a47506c3783802d107bd41872eeb4de4003 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 13:08:33 +0100 Subject: [PATCH 03/18] format --- blueprints/secops/bindplane-gke/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index 4de357926e..2ee481063d 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -18,7 +18,7 @@ The following diagram illustrates the high-level design of created resources, wh ![Bindplane OP Management console on GKE](./images/diagram.png) BindPlane OP Management console will be exposed via Internal HTTPS Load Balancer, this module assume a private connection to GCP environment is in place to reach the BindPlane management console over private IPs. -In case no private connection is in place it should be pretty straightforward to setup a proxy VM to proxy the connection towards the bindplane console. Of course such a deployment can only deal with agents running on the same GCP infrastructure. +In case no private connection is in place it should be pretty straightforward to setup a proxy VM to proxy the connection towards the bindplane console. Of course such a deployment can only deal with agents running on the same GCP infrastructure. ### Deployment @@ -105,14 +105,14 @@ Access the management console leveraging credentials bootstrapped via terraform | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [bindplane_secrets](variables.tf#L26) | Bindplane secrets. | object({…}) | ✓ | | -| [network_config](variables.tf#L58) | Shared VPC network configurations to use for GKE cluster. | object({…}) | ✓ | | +| [network_config](variables.tf#L58) | Shared VPC network configurations to use for GKE cluster. | object({…}) | ✓ | | | [prefix](variables.tf#L80) | Prefix used for resource names. | string | ✓ | | | [project_id](variables.tf#L99) | Project id, references existing project if `project_create` is null. | string | ✓ | | | [region](variables.tf#L104) | GCP region. | string | ✓ | | | [bindplane_config](variables.tf#L17) | Bindplane config. | object({…}) | | {} | | [cluster_config](variables.tf#L37) | GKE cluster configuration. | object({…}) | | {} | -| [dns_config](variables.tf#L48) | DNS config. | object({…}) | | {} | -| [postgresql_config](variables.tf#L70) | Cloud SQL postgresql config. | object({…}) | | {} | +| [dns_config](variables.tf#L48) | DNS config. | object({…}) | | {} | +| [postgresql_config](variables.tf#L70) | Cloud SQL postgresql config. | object({…}) | | {} | | [project_create](variables.tf#L90) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | | null | ## Outputs From d8e3fd12d6ab5f3bcb405433dd94ae5d9730547c Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 14:13:10 +0100 Subject: [PATCH 04/18] fixes --- blueprints/secops/bindplane-gke/README.md | 2 +- blueprints/secops/bindplane-gke/ssl.tf | 2 +- blueprints/secops/bindplane-gke/versions.tf | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index 2ee481063d..4e229718c7 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -151,5 +151,5 @@ module "bindplane-gke" { region = "europe-west8" prefix = "tmp" } -# tftest modules=5 resources=34 files=credentials,config +# tftest modules=9 resources=50 ``` diff --git a/blueprints/secops/bindplane-gke/ssl.tf b/blueprints/secops/bindplane-gke/ssl.tf index 87e3645b07..7fd460f3ed 100644 --- a/blueprints/secops/bindplane-gke/ssl.tf +++ b/blueprints/secops/bindplane-gke/ssl.tf @@ -75,7 +75,7 @@ resource "tls_private_key" "server_key" { resource "tls_cert_request" "server_csr" { count = local.bootstrap_self_signed_cert ? 1 : 0 private_key_pem = tls_private_key.server_key.0.private_key_pem - dns_names = ["bindplane.${var.hostname}"] + dns_names = ["${var.dns_config.hostname}.${var.dns_config.domain}"] dynamic "subject" { for_each = toset(local.cert_subjects) diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf index f569ce5af2..0d64211e9a 100644 --- a/blueprints/secops/bindplane-gke/versions.tf +++ b/blueprints/secops/bindplane-gke/versions.tf @@ -19,11 +19,11 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 6.1.0, < 7.0.0" # tftest + version = ">= 6.11.2, < 7.0.0" # tftest } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.1.0, < 7.0.0" # tftest + version = ">= 6.11.2, < 7.0.0" # tftest } } } From da8fe22cdde3c6df669d4608431b9ec2e8d81ad3 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 14:21:01 +0100 Subject: [PATCH 05/18] README.md --- blueprints/secops/README.md | 7 +++++++ blueprints/secops/bindplane-gke/README.md | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/blueprints/secops/README.md b/blueprints/secops/README.md index 0d42455f68..04082de5d8 100644 --- a/blueprints/secops/README.md +++ b/blueprints/secops/README.md @@ -2,6 +2,13 @@ This repository provides a collection of Terraform blueprints designed to automate the implementation of custom integrations, agents and configurations for Google Cloud Security and Operations SecOps (aka Chronicle). +## BindPlane OP Management on GKE + + This [blueprint](./bindplane-gke/) is a modular and scalable solution for deployment of the BindPlane OP Management Console within a Google Kubernetes Engine (GKE) environment. + +
+ + ## SecOps GKE Forwarder This [blueprint](./secops-gke-forwarder/) is a modular and scalable solution for setting up a SecOps forwarder on Google Kubernetes Engine (GKE). This forwarder is designed to handle multi-tenant data ingestion, ensuring secure and efficient log forwarding to your SecOps SIEM instances. diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index 4e229718c7..fbd17ff98e 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -59,16 +59,16 @@ Setup terraform providers in the root module to deal with kubernetes resources a ```terraform data "google_client_config" "identity" { - count = module.chronicle-forwarder.fleet_host != null ? 1 : 0 + count = module.bindplane-gke.fleet_host != null ? 1 : 0 } provider "kubernetes" { - host = module.chronicle-forwarder.fleet_host + host = module.bindplane-gke.fleet_host token = try(data.google_client_config.identity.0.access_token, null) } provider "kubectl" { - host = module.chronicle-forwarder.fleet_host + host = module.bindplane-gke.fleet_host token = try(data.google_client_config.identity.0.access_token, null) } ``` @@ -130,7 +130,7 @@ Access the management console leveraging credentials bootstrapped via terraform ```hcl module "bindplane-gke" { source = "./fabric/blueprints/secops/bindplane-gke" - project_id = "bindplane" + project_id = "test" bindplane_secrets = { user = "admin" password = "thisisnotasecret" From f3c9554ddd98de197c8d1dd8fd301763eda8522a Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 19 Nov 2024 14:45:05 +0100 Subject: [PATCH 06/18] README.md --- blueprints/secops/bindplane-gke/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index fbd17ff98e..55f4b8a0b6 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -131,6 +131,10 @@ Access the management console leveraging credentials bootstrapped via terraform module "bindplane-gke" { source = "./fabric/blueprints/secops/bindplane-gke" project_id = "test" + project_create = { + billing_account_id = "12345-ABCDEF-12345" + parent = "folders/2345678901" + } bindplane_secrets = { user = "admin" password = "thisisnotasecret" @@ -148,8 +152,8 @@ module "bindplane-gke" { subnet_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/regions/europe-west1/subnetworks/gke" ip_range_gke_master = "192.168.0.0/28" } - region = "europe-west8" - prefix = "tmp" + region = "europe-west8" + prefix = "tmp" } -# tftest modules=9 resources=50 +# tftest modules=10 resources=45 ``` From b5722de49b5ae901218217f6efbcbdec5a6bcaae Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 22 Nov 2024 10:19:36 +0100 Subject: [PATCH 07/18] fews changes based on feedbacks --- blueprints/secops/bindplane-gke/README.md | 1 - .../secops/bindplane-gke/bindplane-deployment/main.tf | 1 - .../secops/bindplane-gke/bindplane-deployment/variables.tf | 1 - .../bindplane-deployment/versions_override.tf | 3 --- blueprints/secops/bindplane-gke/config/values.yaml.tpl | 7 +------ blueprints/secops/bindplane-gke/variables.tf | 1 - 6 files changed, 1 insertion(+), 13 deletions(-) diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index 55f4b8a0b6..b90ca74bd6 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -138,7 +138,6 @@ module "bindplane-gke" { bindplane_secrets = { user = "admin" password = "thisisnotasecret" - secret_key = "xxxxxx-xxxxxxx-xxxxxx" sessions_secret = "xxxxxx-xxxxxxx-xxxxxx" license = "XXXXXXXXXXXXXXXXXXXXXX" } diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf index 56f7306e30..abdeb4de1c 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/main.tf @@ -40,7 +40,6 @@ resource "kubernetes_secret" "bindplane_secret" { data = { username = var.bindplane_secrets.user password = local.bindplane_password - secret_key = var.bindplane_secrets.secret_key sessions_secret = var.bindplane_secrets.sessions_secret license = var.bindplane_secrets.license } diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf index 215ac9b6e0..4d15bfacf7 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/variables.tf @@ -20,7 +20,6 @@ variable "bindplane_secrets" { license = string user = optional(string, "admin") password = optional(string, null) - secret_key = string sessions_secret = string }) } diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf index 75d041486f..67a5f0d290 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf @@ -14,9 +14,6 @@ terraform { required_providers { - restful = { - source = "magodo/restful" - } kubectl = { source = "gavinbunney/kubectl" version = ">= 1.7.0" diff --git a/blueprints/secops/bindplane-gke/config/values.yaml.tpl b/blueprints/secops/bindplane-gke/config/values.yaml.tpl index 4f7d8398dc..a6098a9355 100644 --- a/blueprints/secops/bindplane-gke/config/values.yaml.tpl +++ b/blueprints/secops/bindplane-gke/config/values.yaml.tpl @@ -29,11 +29,6 @@ config: # NOTE: server_url maps to bindplane's network.remoteURL option. server_url: https://${hostname} - -# Enables mutli account, allowing you to create -# multiple Tenants within the same BindPlane instance. -multiAccount: true - # Fixed number of pods. BindPlane CPU usage is bursty, using # a pod autoscaler can be tricky. Generally a fixed number # of pods is recommended. @@ -86,4 +81,4 @@ prometheus: limits: memory: '8192Mi' storage: - volumeSize: '120Gi' \ No newline at end of file + volumeSize: '120Gi' diff --git a/blueprints/secops/bindplane-gke/variables.tf b/blueprints/secops/bindplane-gke/variables.tf index ff2ceedc90..973c5db189 100644 --- a/blueprints/secops/bindplane-gke/variables.tf +++ b/blueprints/secops/bindplane-gke/variables.tf @@ -29,7 +29,6 @@ variable "bindplane_secrets" { license = string user = optional(string, "admin") password = optional(string, null) - secret_key = string sessions_secret = string }) } From b36ed744ca7b1fe1015e6ae66090e46f4b5ce0ab Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 22 Nov 2024 10:55:01 +0100 Subject: [PATCH 08/18] update README.md --- blueprints/secops/bindplane-gke/README.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/blueprints/secops/bindplane-gke/README.md b/blueprints/secops/bindplane-gke/README.md index b90ca74bd6..85de48b36d 100644 --- a/blueprints/secops/bindplane-gke/README.md +++ b/blueprints/secops/bindplane-gke/README.md @@ -53,6 +53,10 @@ See the example test at the end of this README.md as starting point - just copy it to `terraform.tfvars` and edit the latter. See the variables documentation below. +> **Warning** +> +> BindPlane secrets (such as license and admin password) specified as variables within this Terraform configuration will be stored in plain text within the Terraform state file. + #### Step 3: Prepare the providers in the root module Setup terraform providers in the root module to deal with kubernetes resources as follows: @@ -104,16 +108,16 @@ Access the management console leveraging credentials bootstrapped via terraform | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [bindplane_secrets](variables.tf#L26) | Bindplane secrets. | object({…}) | ✓ | | -| [network_config](variables.tf#L58) | Shared VPC network configurations to use for GKE cluster. | object({…}) | ✓ | | -| [prefix](variables.tf#L80) | Prefix used for resource names. | string | ✓ | | -| [project_id](variables.tf#L99) | Project id, references existing project if `project_create` is null. | string | ✓ | | -| [region](variables.tf#L104) | GCP region. | string | ✓ | | +| [bindplane_secrets](variables.tf#L26) | Bindplane secrets. | object({…}) | ✓ | | +| [network_config](variables.tf#L57) | Shared VPC network configurations to use for GKE cluster. | object({…}) | ✓ | | +| [prefix](variables.tf#L79) | Prefix used for resource names. | string | ✓ | | +| [project_id](variables.tf#L98) | Project id, references existing project if `project_create` is null. | string | ✓ | | +| [region](variables.tf#L103) | GCP region. | string | ✓ | | | [bindplane_config](variables.tf#L17) | Bindplane config. | object({…}) | | {} | -| [cluster_config](variables.tf#L37) | GKE cluster configuration. | object({…}) | | {} | -| [dns_config](variables.tf#L48) | DNS config. | object({…}) | | {} | -| [postgresql_config](variables.tf#L70) | Cloud SQL postgresql config. | object({…}) | | {} | -| [project_create](variables.tf#L90) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | | null | +| [cluster_config](variables.tf#L36) | GKE cluster configuration. | object({…}) | | {} | +| [dns_config](variables.tf#L47) | DNS config. | object({…}) | | {} | +| [postgresql_config](variables.tf#L69) | Cloud SQL postgresql config. | object({…}) | | {} | +| [project_create](variables.tf#L89) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | | null | ## Outputs From 2a104fcc0a09f480d78a3edc3fa3f50ab9551d64 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Sun, 24 Nov 2024 16:11:18 +0100 Subject: [PATCH 09/18] update README.md --- blueprints/secops/bindplane-gke/versions.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf index 0d64211e9a..3018c9bf93 100644 --- a/blueprints/secops/bindplane-gke/versions.tf +++ b/blueprints/secops/bindplane-gke/versions.tf @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Fabric release: v35.0.0 +# Fabric release: v36.0.0 terraform { required_version = ">= 1.7.4" From 4f8057ba1cab885dbd3328e459f44881368237a4 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Mon, 25 Nov 2024 08:52:56 +0100 Subject: [PATCH 10/18] update versions.tf --- blueprints/secops/bindplane-gke/versions.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf index 3018c9bf93..e1f0b14270 100644 --- a/blueprints/secops/bindplane-gke/versions.tf +++ b/blueprints/secops/bindplane-gke/versions.tf @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Fabric release: v36.0.0 +# Fabric release: v36.0.1 terraform { required_version = ">= 1.7.4" From e7e21b540368441db8a0e62f2d45756628d4171c Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Wed, 27 Nov 2024 21:38:30 +0100 Subject: [PATCH 11/18] upgrade kubectl --- .../bindplane-gke/bindplane-deployment/versions_override.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf index 67a5f0d290..c68b307c38 100644 --- a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf +++ b/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf @@ -16,7 +16,7 @@ terraform { required_providers { kubectl = { source = "gavinbunney/kubectl" - version = ">= 1.7.0" + version = ">= 1.16.0" } } } From e37b33fcc3043291e34495feb6b03d1acfb96d46 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Thu, 28 Nov 2024 15:28:27 +0100 Subject: [PATCH 12/18] move versions_override.tf in the root folder for blueprint --- .../bindplane-gke/{bindplane-deployment => }/versions_override.tf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename blueprints/secops/bindplane-gke/{bindplane-deployment => }/versions_override.tf (100%) diff --git a/blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf b/blueprints/secops/bindplane-gke/versions_override.tf similarity index 100% rename from blueprints/secops/bindplane-gke/bindplane-deployment/versions_override.tf rename to blueprints/secops/bindplane-gke/versions_override.tf From 561c22eed3d2163114a72457f4a594d957d652e1 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Thu, 28 Nov 2024 17:44:09 +0100 Subject: [PATCH 13/18] remove versions_override.tf --- .../secops/bindplane-gke/versions_override.tf | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 blueprints/secops/bindplane-gke/versions_override.tf diff --git a/blueprints/secops/bindplane-gke/versions_override.tf b/blueprints/secops/bindplane-gke/versions_override.tf deleted file mode 100644 index c68b307c38..0000000000 --- a/blueprints/secops/bindplane-gke/versions_override.tf +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2024 Google LLC -# -# 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 -# -# https://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. - -terraform { - required_providers { - kubectl = { - source = "gavinbunney/kubectl" - version = ">= 1.16.0" - } - } -} From 99faf72fc0d90d64195f8ce85b5726c00a1f7e6a Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 13 Dec 2024 11:50:13 +0100 Subject: [PATCH 14/18] update versions.tf --- blueprints/secops/bindplane-gke/versions.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf index e1f0b14270..057082a242 100644 --- a/blueprints/secops/bindplane-gke/versions.tf +++ b/blueprints/secops/bindplane-gke/versions.tf @@ -19,11 +19,11 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = ">= 6.11.2, < 7.0.0" # tftest + version = ">= 6.13.0, < 7.0.0" # tftest } google-beta = { source = "hashicorp/google-beta" - version = ">= 6.11.2, < 7.0.0" # tftest + version = ">= 6.13.0, < 7.0.0" # tftest } } } From b9496bef1be8fa865589ddbaf6507ffcb52333cf Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 13 Dec 2024 15:56:23 +0100 Subject: [PATCH 15/18] fix --- blueprints/secops/bindplane-gke/versions.tf | 29 ------------------- .../bindplane/variables.tf | 5 ++++ 2 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 blueprints/secops/bindplane-gke/versions.tf diff --git a/blueprints/secops/bindplane-gke/versions.tf b/blueprints/secops/bindplane-gke/versions.tf deleted file mode 100644 index 057082a242..0000000000 --- a/blueprints/secops/bindplane-gke/versions.tf +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2024 Google LLC -# -# 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 -# -# https://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. - -# Fabric release: v36.0.1 - -terraform { - required_version = ">= 1.7.4" - required_providers { - google = { - source = "hashicorp/google" - version = ">= 6.13.0, < 7.0.0" # tftest - } - google-beta = { - source = "hashicorp/google-beta" - version = ">= 6.13.0, < 7.0.0" # tftest - } - } -} diff --git a/modules/cloud-config-container/bindplane/variables.tf b/modules/cloud-config-container/bindplane/variables.tf index 39856f4585..07139a75ee 100644 --- a/modules/cloud-config-container/bindplane/variables.tf +++ b/modules/cloud-config-container/bindplane/variables.tf @@ -26,6 +26,11 @@ variable "bindplane_config" { nullable = false } +variable "bindplane_license" { + description = "BindPlane License." + type = string +} + variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string From a42ef392ae600af0e0fbfd425b5ca9dcb2fadd01 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 13 Dec 2024 15:56:38 +0100 Subject: [PATCH 16/18] fix --- blueprints/secops/bindplane-gke/main.tf | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/blueprints/secops/bindplane-gke/main.tf b/blueprints/secops/bindplane-gke/main.tf index 3c6f0627f2..4e0b12c342 100644 --- a/blueprints/secops/bindplane-gke/main.tf +++ b/blueprints/secops/bindplane-gke/main.tf @@ -74,9 +74,16 @@ module "bindplane-cluster" { master_ipv4_cidr_block = var.network_config.ip_range_gke_master master_authorized_ranges = var.cluster_config.master_authorized_ranges } - private_cluster_config = { - enable_private_endpoint = true - master_global_access = true + access_config = { + dns_access = false + ip_access = { + authorized_ranges = { + "rfc-1918-10-8" = "10.0.0.0/8" + } + private_endpoint_config = { + global_access = true + } + } } enable_features = { gateway_api = true From 0a4bd169507380d915c13c59334d47d08f0bb057 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Fri, 13 Dec 2024 16:01:10 +0100 Subject: [PATCH 17/18] fix --- modules/cloud-config-container/bindplane/variables.tf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/cloud-config-container/bindplane/variables.tf b/modules/cloud-config-container/bindplane/variables.tf index 07139a75ee..39856f4585 100644 --- a/modules/cloud-config-container/bindplane/variables.tf +++ b/modules/cloud-config-container/bindplane/variables.tf @@ -26,11 +26,6 @@ variable "bindplane_config" { nullable = false } -variable "bindplane_license" { - description = "BindPlane License." - type = string -} - variable "cloud_config" { description = "Cloud config template path. If null default will be used." type = string From 489ddbbcc32090309b962d627a001362002ae374 Mon Sep 17 00:00:00 2001 From: bruzzechesse Date: Tue, 17 Dec 2024 22:01:33 +0100 Subject: [PATCH 18/18] add empty resource --- tools/lockfile/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/lockfile/main.tf b/tools/lockfile/main.tf index 9c8a3e7047..6670ff63ce 100644 --- a/tools/lockfile/main.tf +++ b/tools/lockfile/main.tf @@ -23,3 +23,4 @@ resource "random_pet" "default" {} resource "time_static" "default" {} resource "tls_private_key" "default" {} resource "vsphere_role" "default" {} +resource "kubernetes_secret" "default" {}