Sync Secrets from Vault#
To sync secrets from Vault using the External Secrets Operator, there are two steps needed:
- Vault configuration - we need to create a Vault role and policy that grants access to an application running in the cluster to access the desired secret(s)
- Kubernetes manifests - we need to define manifests for ExternalSecret, SecretStore, ServiceAccount, Role, and RoleBinding
Vault Configuration#
As of right now, all Vault config is done using Terraform in the es/Vault/config repo on code.vt.edu. To grant access to applications running in the platform, we've cre ated a Terraform module to minimize the amount of config you need to write.
-
After cloning the repo locally, create a file named
app-<org>-<app-name>.tf
in the root directory.- Replace
<org>
with your unit's name (eg,dit-es
,dit-middleware
,dit-platform
) - Replace
<app-name>
with the name of the app you're working with (e.g.,hello-world
)
- Replace
-
In that newly created file, place the following Terraform config:
module "app_<org>_<app_name>" { source = "./modules/platform-access" app_name = "<org>-<app-name>" tenant_identifier = "<your-tenant-identifier>" service_account_name = "vault-<app-name>" secret_paths = ["path/to/your/secret"] cluster_loc = "<cluster-location>" cluster_env = "<cluster-environment>" }
- Replace
<org>_<app_name>
with the same values you used in the filename, just with underscores to separate words (per TF naming conventions) - Replace
<org>-<app-name>
with the same values you used in the filename - Replace
<your-tenant-identifier>
with the name of your platform tenant, which is the same as the cluster namespace - Replace
<app-name>
with the same value you used in the filename - Replace
path/to/your/secret
with the path to your secret. Important note: the second segment should bedata
. If I were to use the Vault UI and navigate to a secret using the pathdit.platform/demo/registry-credential
, I would set the path todit.platform/data/demo/registry-credential
- Replace
<cluster-location>
witheksa
oraws
- Replace
<cluster-environment>
withdvlp
,pprd
, orprod
Example config:
module "app_dit_platform_hello_world" { source = "./modules/platform-access" app_name = "dit-platform-hello-world" tenant_identifier = "it-common-platform-hello-world" service_account_name = "vault-hello-world" secret_paths = ["dit.platform/data/demo/registry-credential"] cluster_loc = "eksa" cluster_env = "pprd" }
- Replace
-
Commit the change on a new branch, push the branch, and create a merge request. The Vault admin team will review it and it will be merged when approved.
Defining the Kubernetes manifests#
-
In your platform manifest repo, create a file named
external-secrets.yml
. In that file, place the following:apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: <module.app_name> spec: refreshInterval: "24h" secretStoreRef: name: vault-backend kind: SecretStore target: # Kubernetes Secret to be created name: <key-name> dataFrom: - extract: key: path/to/key --- apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: vault-backend spec: provider: vault: server: "https://vault.es.cloud.vt.edu:8200" path: "<secret-engine>" version: "v2" auth: # Authenticate against Vault using a Kubernetes ServiceAccount # token stored in a Secret. # https://www.vaultproject.io/docs/auth/kubernetes kubernetes: # Path where the Kubernetes authentication backend is mounted in Vault mountPath: "<platform-(cluster-location)-(cluster-environment)>" # A required field containing the Vault Role to assume. role: "it-platform-<module.app_name>" # Optional service account field containing the name # of a kubernetes ServiceAccount serviceAccountRef: name: "vault-<module.app_name>" --- apiVersion: v1 kind: ServiceAccount metadata: name: "vault-<module.app_name>" --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: "vault-<module.app_name>" rules: - apiGroups: [""] resources: ["secrets"] verbs: ["list", "get", "create", "delete", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: "vault-<module.app_name>" subjects: - kind: ServiceAccount name: "vault-<module.app_name>" roleRef: kind: Role name: "vault-<module.app_name>" apiGroup: rbac.authorization.k8s.io
- Replace
<module.app_name>
with the same value you put in the Vault Terraform config in theapp_name
field - Replace
<path/to/key>
with the path to the registry credential. Important note: this does not include the key name. - Replace
<secret-engine>
with your Vault secret engine - Replace
<platform-(cluster-location)-(cluster-environment)>
with one of- platform-eksa-pprd
- platform-eksa-prod
- platform-prod
- Replace
-
Commit the manifest and push it to your manifest repo. After a moment, you should see a Pod startup that runs and creates the secret!