Integrate Cloud Secrets with Kubernetes Secrets using External Secrets Through Terraform
Tags: cloud, kubernetes, security, devops
Published: 2024-05-19 05:52:48

In the dynamic landscape of cloud-native applications, managing secrets securely is paramount. Secrets such as API keys, database credentials, and other sensitive configuration details need to be handled with care to prevent unauthorized access. Kubernetes, being a leading orchestration platform, offers mechanisms to manage these secrets internally. However, leveraging external secret managers adds an extra layer of security and flexibility, enabling centralized management and seamless integration across multiple environments.

This blog will guide you through the process of fetching cloud secrets to Kubernetes secrets using an External Secret Manager (ESM) with Terraform. External Secret Managers like AWS Secrets Manager, HashiCorp Vault, and Google Cloud Secret Manager provide robust solutions for storing and managing secrets securely outside of your Kubernetes cluster. By using Terraform, an infrastructure-as-code (IaC) tool, we can automate the provisioning and management of these secrets, ensuring consistency and reproducibility.

By the end of this tutorial, you'll have a clear understanding of how to securely manage your secrets using external secret managers and Terraform, enhancing the security and maintainability of your Kubernetes-based applications.

Steps:4
1. Install External Secret Manager via helm.
2. Authenticate K8s(Kubernetes) with CSP(Cloud Service Provider).
3. Store the Secrets in the CSP Secrets Service like AWS Secret Manager, GCP Secret Store, and Azure Key Vault.
4. Create an External Secret Store that synced with Cloud Secrets.
5. Create K8s Secret which refers the value from External Secrets Manager.

Diagram:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/12qjipq7jwnysq0e3p80.jpg)

## 1. Install External Secret Manager via helm.

First we will install an External Secret Manager in the K8s cluster using Helm.

```
resource "helm_release" "external_secret_operator" {
  name = "external-secret-operator"
  repository = "https://charts.external-secrets.io"
  chart = "external-secrets"
  namespace = "default"
}
```

## 2. Authenticate K8s(Kubernetes) with CSP(Cloud Service Provider).

For the Example let's take GCP as a CSP, and create a Service Account in the GCP that has GCP Secret Accessor permission.
Now create a terraform Script that will authenticate K8s with CSP in our case it's GCP.

```
resource "kubernetes_manifest" "service-account-secret-authenticator" {
  computed_fields = [ "stringData" ]
  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Secret"
    "metadata" = {
      "name"      = ""   # K8s secret to authenticate gsm with k8s
      "namespace" = "default"
      "labels"    = {
        "type" = "gcpsm"
      }
    }
    "type" = "Opaque"
    "stringData" = {
      "secret-access-credentials" = "" #Service Account Token value.
    }
  }
}
```
## 3. Store the Secrets in the CSP Secrets Service like AWS Secret Manager, GCP Secret Store, and Azure Key Vault.

Now create a secret on CSP which we are going to use in the k8s Secrets.

## 4. Create an External Secret Store that synced with Cloud Secrets.

To create a secret in the K8s first, we have to create an External Secret Store which will fetch secret from CSP.

```
resource "kubernetes_manifest" "clustersecretstore" {
  depends_on = [ kubernetes_manifest.service-account-secret-authenticator ]
  manifest = {
    "apiVersion" = "external-secrets.io/v1beta1"
    "kind"       = "ClusterSecretStore"
    "metadata" = {
      "name"      = "gcp-store"
    }
    "spec" = {
      "provider" = {
        "gcpsm" = {
            "projectID" ="" # Based on GCP we have to pass projectID
            "auth" = {
                "secretRef" = {
                    "secretAccessKeySecretRef" = {
                        "name" = "" #k8s secret service account name
                        "key"  = "secret-access-credentials"   # K8s secret service acount token
                    }
                }
            }
        }
      }
    }
  }
}
```
Here we have one field named "depends on" which indicates that first, we have to authenticate K8s cluster with CSP then we can create an External Secret Store.

## 5. Create K8s Secret which refers to the value from External Secrets Manager.

Now we will create an External Secret which will create a K8s secret and we can get our value in the K8s cluster.

```
resource "kubernetes_manifest" "external-secrets" {
  depends_on = [ kubernetes_manifest.clustersecretstore ]

  manifest = {
    "apiVersion" = "external-secrets.io/v1beta1"
    "kind"       = "ExternalSecret"
    "metadata" = {
      "name"      = ""   # external secret name
      "namespace" = "default"
    }
    "spec" = {
      "refreshInterval" = "5m"
      "secretStoreRef" = {
        "kind" = "ClusterSecretStore"
        "name" = "gcp-store"
      }
      "target" = {
        "name" = ""    # K8s secret name
        "creationPolicy" = "Owner"
      }
      "data" = [
        {
            "secretKey" = ""  # K8s secrent file name
            "remoteRef" = {
                "key" = ""   # GSM secret name
            }
        }
      ]
    }
  }
}
```
Here is one field which is "refreshInterval" this field indicates that an External Secret Store will refresh in each 5-minute period to sync with Cloud Secrets.

Through this, we can securely fetch our Cloud Secrets in the K8s Secrets.

Thank you for reading the blog!
Content Copyright reserved by Author Harsh Viradia.