diff --git a/infrastructure/main.tf b/infrastructure/main.tf
index e4b8e3a..7cb3cfe 100644
--- a/infrastructure/main.tf
+++ b/infrastructure/main.tf
@@ -35,7 +35,7 @@ module "observability" {
# OpenBao Secrets Management Solution deployment
module "openbao" {
- source = "git::https://github.com/necro-cloud/modules//modules/openbao?ref=main"
+ source = "git::https://github.com/necro-cloud/modules//modules/openbao?ref=task/118/ferret-secrets"
// Certificates Details
cluster_issuer_name = module.cluster-issuer.cluster-issuer-name
@@ -132,7 +132,7 @@ module "cnpg" {
# FerretDB Deployment for MongoDB Database Solution
module "ferretdb" {
- source = "git::https://github.com/necro-cloud/modules//modules/ferretdb?ref=main"
+ source = "git::https://github.com/necro-cloud/modules//modules/ferretdb?ref=task/118/ferret-secrets"
// Cluster Secret Store Details
cluster_secret_store_name = module.openbao.cluster_secret_store_name
diff --git a/modules/ferretdb/README.md b/modules/ferretdb/README.md
index 79e77c8..c7d904f 100644
--- a/modules/ferretdb/README.md
+++ b/modules/ferretdb/README.md
@@ -7,6 +7,7 @@ Required Modules to deploy FerretDB Database:
2. [Cluster Issuer](../cluster-issuer)
3. [Garage](../garage)
4. [Observability](../observability)
+5. [OpenBao](../openbao)
## Providers
@@ -24,13 +25,22 @@ Required Modules to deploy FerretDB Database:
| [kubernetes_ingress_v1.mongo_express_ingress](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/ingress_v1) | resource |
| [kubernetes_manifest.barman_object_store](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.client_certificate_authority](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.client_database_credentials_sync](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.client_issuer](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.client_streaming_replica_certificate](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.cluster](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.ferret_cluster_image_catalog](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.ferret_database_credentials_sync](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.garage_certificate_authority_sync](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.garage_configuration_sync](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.ingress_certificate](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.mongo_express_credentials_sync](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.mongo_express_internal_certificate](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.password_generator](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.public_issuer](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.push_client_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.push_ferret_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_manifest.push_mongo_express_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.server_certificate](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.server_certificate_authority](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
| [kubernetes_manifest.server_issuer](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
@@ -39,17 +49,9 @@ Required Modules to deploy FerretDB Database:
| [kubernetes_network_policy.ferret_network_policy](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/network_policy) | resource |
| [kubernetes_pod_disruption_budget_v1.cnpg_pdb](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/pod_disruption_budget_v1) | resource |
| [kubernetes_pod_disruption_budget_v1.ferret_pdb](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/pod_disruption_budget_v1) | resource |
-| [kubernetes_secret.client_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [kubernetes_secret.cloudflare_token](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
-| [kubernetes_secret.ferret_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
-| [kubernetes_secret.garage_certificate_authority](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
-| [kubernetes_secret.garage_configuration](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
-| [kubernetes_secret.ui_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [kubernetes_service.ferret_service](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
| [kubernetes_service.mongo_express](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
-| [random_password.client_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
-| [random_password.ferret_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
-| [random_password.ui_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
## Inputs
@@ -68,6 +70,7 @@ Required Modules to deploy FerretDB Database:
| [cluster\_issuer\_name](#input\_cluster\_issuer\_name) | Name for the Cluster Issuer to be used to generate internal self signed certificates | `string` | n/a | yes |
| [cluster\_name](#input\_cluster\_name) | Name of the Ferret Database Cluster to be created | `string` | `"ferret-postgresql-cluster"` | no |
| [cluster\_postgresql\_version](#input\_cluster\_postgresql\_version) | Version of Ferret Database to use and deploy | `number` | `17` | no |
+| [cluster\_secret\_store\_name](#input\_cluster\_secret\_store\_name) | Name of the cluster secret store to be used for pulling and pushing secrets to OpenBao | `string` | n/a | yes |
| [cluster\_size](#input\_cluster\_size) | Number of pods to deploy for the Ferret Cluster | `number` | `2` | no |
| [country\_name](#input\_country\_name) | Country name for deploying Ferret Database | `string` | `"India"` | no |
| [domain](#input\_domain) | Domain for which Ingress Certificate is to be generated for | `string` | n/a | yes |
diff --git a/modules/ferretdb/cluster.tf b/modules/ferretdb/cluster.tf
index 629d22b..9b97310 100644
--- a/modules/ferretdb/cluster.tf
+++ b/modules/ferretdb/cluster.tf
@@ -82,7 +82,7 @@ resource "kubernetes_manifest" "cluster" {
"login" = true
"name" = "ferret"
"passwordSecret" = {
- "name" = kubernetes_secret.ferret_database_credentials.metadata[0].name
+ "name" = kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name
}
"replication" = false
"superuser" = false
diff --git a/modules/ferretdb/locals.tf b/modules/ferretdb/locals.tf
index 560de2b..23416a2 100644
--- a/modules/ferretdb/locals.tf
+++ b/modules/ferretdb/locals.tf
@@ -1,17 +1,17 @@
locals {
access_namespaces = [for config in var.clients : config.namespace]
- managed_roles = [for secret in kubernetes_secret.client_database_credentials : {
+ managed_roles = [for index, client in var.clients : {
"bypassrls" = false
- "comment" = "${secret.data.username} user for postgresql"
+ "comment" = "${client.user} user for postgresql"
"connectionLimit" = -1
"createdb" = true
"createrole" = true
"ensure" = "present"
"inherit" = true
"login" = true
- "name" = secret.data.username
+ "name" = client.user
"passwordSecret" = {
- "name" = secret.metadata[0].name
+ "name" = kubernetes_manifest.client_database_credentials_sync[index].object.spec.target.name
}
"replication" = false
"superuser" = false
diff --git a/modules/ferretdb/mongo-express.tf b/modules/ferretdb/mongo-express.tf
index 75e0301..9d678c9 100644
--- a/modules/ferretdb/mongo-express.tf
+++ b/modules/ferretdb/mongo-express.tf
@@ -63,7 +63,7 @@ resource "kubernetes_deployment" "mongo_express" {
name = "DB_USERNAME"
value_from {
secret_key_ref {
- name = kubernetes_secret.ferret_database_credentials.metadata[0].name
+ name = kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name
key = "username"
}
}
@@ -73,7 +73,7 @@ resource "kubernetes_deployment" "mongo_express" {
name = "DB_PASSWORD"
value_from {
secret_key_ref {
- name = kubernetes_secret.ferret_database_credentials.metadata[0].name
+ name = kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name
key = "password"
}
}
@@ -99,7 +99,7 @@ resource "kubernetes_deployment" "mongo_express" {
name = "ME_CONFIG_BASICAUTH_USERNAME"
value_from {
secret_key_ref {
- name = kubernetes_secret.ui_credentials.metadata[0].name
+ name = kubernetes_manifest.mongo_express_credentials_sync.object.spec.target.name
key = "username"
}
}
@@ -109,7 +109,7 @@ resource "kubernetes_deployment" "mongo_express" {
name = "ME_CONFIG_BASICAUTH_PASSWORD"
value_from {
secret_key_ref {
- name = kubernetes_secret.ui_credentials.metadata[0].name
+ name = kubernetes_manifest.mongo_express_credentials_sync.object.spec.target.name
key = "password"
}
}
diff --git a/modules/ferretdb/secrets.tf b/modules/ferretdb/secrets.tf
index 1b81ab1..6eb7b40 100644
--- a/modules/ferretdb/secrets.tf
+++ b/modules/ferretdb/secrets.tf
@@ -38,90 +38,226 @@ resource "kubernetes_manifest" "garage_configuration_sync" {
}
}
-// Database credentials configuration for Ferret
-resource "random_password" "ferret_password" {
- length = 20
- lower = true
- numeric = true
- special = false
+// Password Generator for generating random passwords
+resource "kubernetes_manifest" "password_generator" {
+ manifest = {
+ apiVersion = "generators.external-secrets.io/v1alpha1"
+ kind = "Password"
+ metadata = {
+ name = "password-generator"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ length = 20
+ digits = 5
+ symbols = 0
+ noUpper = true
+ }
+ }
}
-resource "kubernetes_secret" "ferret_database_credentials" {
- metadata {
- name = "credentials-ferret"
- namespace = kubernetes_namespace.namespace.metadata[0].name
-
- labels = {
- app = var.app_name
- component = "secret"
+// Database credentials configuration for Ferret
+resource "kubernetes_manifest" "ferret_database_credentials_sync" {
+ manifest = {
+ apiVersion = "external-secrets.io/v1"
+ kind = "ExternalSecret"
+ metadata = {
+ name = "credentials-ferret"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ refreshInterval = "0"
+ target = {
+ name = "credentials-ferret"
+ template = {
+ type = "kubernetes.io/basic-auth"
+ data = {
+ username = "ferret"
+ password = "{{ .password }}"
+ }
+ }
+ }
+ dataFrom = [{
+ sourceRef = {
+ generatorRef = {
+ apiVersion = "generators.external-secrets.io/v1alpha1"
+ kind = "Password"
+ name = kubernetes_manifest.password_generator.object.metadata.name
+ }
+ }
+ }]
}
}
+}
- data = {
- "username" = "ferret"
- "password" = random_password.ferret_password.result
+resource "kubernetes_manifest" "push_ferret_database_credentials" {
+ manifest = {
+ apiVersion = "external-secrets.io/v1alpha1"
+ kind = "PushSecret"
+ metadata = {
+ name = "push-${kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name}"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ refreshInterval = "1h"
+ deletionPolicy = "None"
+ secretStoreRefs = [{
+ name = var.cluster_secret_store_name
+ kind = "ClusterSecretStore"
+ }]
+ selector = {
+ secret = {
+ name = kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name
+ }
+ }
+ data = [
+ {
+ match = {
+ remoteRef = {
+ remoteKey = "${kubernetes_namespace.namespace.metadata[0].name}/credentials/${kubernetes_manifest.ferret_database_credentials_sync.object.spec.target.name}"
+ }
+ }
+ }
+ ]
+ }
}
-
- type = "kubernetes.io/basic-auth"
+ depends_on = [kubernetes_manifest.ferret_database_credentials_sync]
}
+
// Database credentials configuration for all clients
-resource "random_password" "client_password" {
+resource "kubernetes_manifest" "client_database_credentials_sync" {
count = length(var.clients)
- length = 20
- lower = true
- numeric = true
- special = false
-}
-
-resource "kubernetes_secret" "client_database_credentials" {
- count = length(var.clients)
- metadata {
- name = "credentials-${var.clients[count.index].user}"
- namespace = kubernetes_namespace.namespace.metadata[0].name
-
- labels = {
- app = var.app_name
- component = "secret"
+ manifest = {
+ apiVersion = "external-secrets.io/v1"
+ kind = "ExternalSecret"
+ metadata = {
+ name = "credentials-${var.clients[count.index].user}"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
}
-
- annotations = {
- "reflector.v1.k8s.emberstack.com/reflection-allowed" = "true"
- "reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces" = var.clients[count.index].namespace
+ spec = {
+ refreshInterval = "0"
+ target = {
+ name = "credentials-${var.clients[count.index].user}"
+ template = {
+ type = "kubernetes.io/basic-auth"
+ data = {
+ username = var.clients[count.index].user
+ password = "{{ .password }}"
+ }
+ }
+ }
+ dataFrom = [{
+ sourceRef = {
+ generatorRef = {
+ apiVersion = "generators.external-secrets.io/v1alpha1"
+ kind = "Password"
+ name = kubernetes_manifest.password_generator.object.metadata.name
+ }
+ }
+ }]
}
}
+}
- data = {
- "username" = var.clients[count.index].user
- "password" = random_password.client_password[count.index].result
+resource "kubernetes_manifest" "push_client_database_credentials" {
+ count = length(var.clients)
+ manifest = {
+ apiVersion = "external-secrets.io/v1alpha1"
+ kind = "PushSecret"
+ metadata = {
+ name = "push-${kubernetes_manifest.client_database_credentials_sync[count.index].object.spec.target.name}"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ refreshInterval = "1h"
+ deletionPolicy = "None"
+ secretStoreRefs = [{
+ name = var.cluster_secret_store_name
+ kind = "ClusterSecretStore"
+ }]
+ selector = {
+ secret = {
+ name = kubernetes_manifest.client_database_credentials_sync[count.index].object.spec.target.name
+ }
+ }
+ data = [
+ {
+ match = {
+ remoteRef = {
+ remoteKey = "${kubernetes_namespace.namespace.metadata[0].name}/credentials/${kubernetes_manifest.client_database_credentials_sync[count.index].object.spec.target.name}"
+ }
+ }
+ }
+ ]
+ }
}
-
- type = "kubernetes.io/basic-auth"
+ depends_on = [kubernetes_manifest.client_database_credentials_sync]
}
// UI credentials configuration for MongoExpress
-resource "random_password" "ui_password" {
- length = 20
- lower = true
- numeric = true
- special = false
-}
-
-resource "kubernetes_secret" "ui_credentials" {
- metadata {
- name = "ui-ferret"
- namespace = kubernetes_namespace.namespace.metadata[0].name
-
- labels = {
- app = var.app_name
- component = "secret"
+resource "kubernetes_manifest" "mongo_express_credentials_sync" {
+ manifest = {
+ apiVersion = "external-secrets.io/v1"
+ kind = "ExternalSecret"
+ metadata = {
+ name = "mongo-express-credentials"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ refreshInterval = "0"
+ target = {
+ name = "mongo-express-credentials"
+ template = {
+ data = {
+ username = "ferret"
+ password = "{{ .password }}"
+ }
+ }
+ }
+ dataFrom = [{
+ sourceRef = {
+ generatorRef = {
+ apiVersion = "generators.external-secrets.io/v1alpha1"
+ kind = "Password"
+ name = kubernetes_manifest.password_generator.object.metadata.name
+ }
+ }
+ }]
}
}
+}
- data = {
- "username" = "ferret"
- "password" = random_password.ferret_password.result
+resource "kubernetes_manifest" "push_mongo_express_credentials" {
+ manifest = {
+ apiVersion = "external-secrets.io/v1alpha1"
+ kind = "PushSecret"
+ metadata = {
+ name = "push-${kubernetes_manifest.mongo_express_credentials_sync.object.spec.target.name}"
+ namespace = kubernetes_namespace.namespace.metadata[0].name
+ }
+ spec = {
+ refreshInterval = "1h"
+ deletionPolicy = "None"
+ secretStoreRefs = [{
+ name = var.cluster_secret_store_name
+ kind = "ClusterSecretStore"
+ }]
+ selector = {
+ secret = {
+ name = kubernetes_manifest.mongo_express_credentials_sync.object.spec.target.name
+ }
+ }
+ data = [
+ {
+ match = {
+ remoteRef = {
+ remoteKey = "${kubernetes_namespace.namespace.metadata[0].name}/credentials/ui/${kubernetes_manifest.mongo_express_credentials_sync.object.spec.target.name}"
+ }
+ }
+ }
+ ]
+ }
}
-
- type = "kubernetes.io/basic-auth"
+ depends_on = [kubernetes_manifest.mongo_express_credentials_sync]
}
diff --git a/modules/openbao/job.tf b/modules/openbao/job.tf
index c41a6ac..93e116b 100644
--- a/modules/openbao/job.tf
+++ b/modules/openbao/job.tf
@@ -65,4 +65,10 @@ resource "kubernetes_job" "configurator" {
# Ensure OpenBao is fully up before running
depends_on = [helm_release.openbao, kubernetes_manifest.internal_certificate]
+
+ timeouts {
+ create = "10m"
+ update = "10m"
+ delete = "10m"
+ }
}