unfriendlygrinch.info
Open in
urlscan Pro
176.118.186.121
Public Scan
Submitted URL: https://view.hashicorp.com/ODQ1LVpMRi0xOTEAAAGP_TR7d0Xw401KNmid7lUeTzwxW2WUYNk1Qx4xj_vnV1colpwaNhSOzYcAGRL8KPwUjKd3b18ZEJcn...
Effective URL: https://unfriendlygrinch.info/posts/vault-csi-provider/?mkt_tok=ODQ1LVpMRi0xOTEAAAGP_TR7d28x9xvBwl4kC_9YWbSSG8h_lpZ1tcAtqcV1Kk...
Submission: On December 13 via api from US — Scanned from DE
Effective URL: https://unfriendlygrinch.info/posts/vault-csi-provider/?mkt_tok=ODQ1LVpMRi0xOTEAAAGP_TR7d28x9xvBwl4kC_9YWbSSG8h_lpZ1tcAtqcV1Kk...
Submission: On December 13 via api from US — Scanned from DE
Form analysis
0 forms found in the DOMText Content
Unfriendly Grinch Posts Authors Tags VAULT CSI PROVIDER Posted on Sep 8, 2023 | By Elif Samedin | 15 minutes read * Kubernetes * Secrets * Hashicorp * Vault * Container Storage Interface (CSI) Secrets Store Driver * Vault CSI Driver * Hands-on Time * Prerequisites * Vault Helm Chart * Vault kvv2 Secrets Engine * Kubernetes Auth Method * Secrets Store CSI Driver * The SecretProviderClass Resource * Secrets Store CSI Driver: Sync as Kubernetes secret * Conclusions CONTAINER STORAGE INTERFACE (CSI) SECRETS STORE DRIVER Prior to the introduction of the Container Storage Interface (CSI), Kubernetes included a powerful volume plugin mechanism. It did, however, provide certain challenges. These “in-tree” plugins were integrated into the main Kubernetes source, thus making it cumbersome for vendors to add or amend storage plugins without adhering to the Kubernetes release schedule. This not only restricted flexibility, but also raised concerns regarding the core Kubernetes system’s reliability and security. Additionally, maintaining this “in-tree” code was often a challenging endeavor for Kubernetes maintainers. The Container Storage Interface (CSI) was developed as a response to these challenges. This standard provides a consistent method to integrate arbitrary block and file storage systems with containerized workloads across various Container Orchestration Systems, including Kubernetes, Mesos, and Cloud Foundry. The beauty of CSI lies in its extensibility. Vendors are now able to seamlessly integrate their systems with Kubernetes without tampering with its core code. This enhancement conveys end users with a wider array of storage choices while boosting the overall reliability and security of the system. By the time Kubernetes version v1.13 was released, the CSI implementation was upgraded to General Availability (GA). For anyone interested in further exploring these, a comprehensive list of CSI drivers is accessible here. Furthermore, this separation enables storage vendors to maintain jurisdiction over their release and feature cycles. They may focus on API development without having to worry about backward incompatibility issues. Supporting their plugin is as simple as deploying a few pods. VAULT CSI DRIVER The Secrets Store CSI Driver project for Vault Provider began with a simple discussion on GitHub to determine how much interest there was in utilizing CSI to reveal secrets in a Kubernetes pod’s volume. The Secrets Store CSI driver interacts with the Vault CSI provider via gRPC to retrieve secret data. This driver enables us to integrate numerous secrets, keys, and certificates from Vault, making them available as a volume in our pods. It makes use of a custom resource definition (CRD) named SecretProviderClass, which identifies Vault as the source and provides configuration settings for both Vault and the paths to your secrets. When a pod is started, it uses the Kubernetes Auth Method for authentication against the service account identity specified in the pod blueprint. Once authenticated, the secret paths defined in the SecretProviderClass are retrieved and written to a tmpfs volume, and subsequently mounted to the pod. This configuration makes it possible for the applications to access and use the secrets from the attached volume as needed. HANDS-ON TIME PREREQUISITES VAULT HELM CHART Installing the Vault Helm chart with the injector service disabled and CSI enabled: $ helm -n vault get values vault | grep -A1 -E '^(csi|injector)' csi: enabled: true -- injector: enabled: false VAULT KVV2 SECRETS ENGINE We’ve already enabled a kvv2 Secrets Engine at the unfriendlygrinch path in the previous blog entry and created a secret: $ vault kv get unfriendlygrinch/app/config ========== Secret Path ========== unfriendlygrinch/data/app/config ======= Metadata ======= Key Value --- ----- created_time 2023-07-31T14:57:00.611356951Z custom_metadata <nil> deletion_time n/a destroyed false version 1 ====== Data ====== Key Value --- ----- password dretda1rus KUBERNETES AUTH METHOD SECRETS STORE CSI DRIVER Installing the Secrets Store CSI Driver secrets-store.csi.k8s.io using Helm: $ helm -n vault ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION secrets-store-csi-driver vault 1 2023-08-15 18:55:39.838682762 +0300 EEST deployed secrets-store-csi-driver-1.3.3 1.3.3 For the moment, the installation uses the default values: $ helm -n vault get values secrets-store-csi-driver USER-SUPPLIED VALUES: null THE SECRETPROVIDERCLASS RESOURCE The SecretProviderClass is a Kubernetes custom resource that is used to provide driver configurations and provider-specific parameters to the CSI driver. A SecretProviderClass resource for the Vault provider would typically look like this: kind: SecretProviderClass metadata: name: vault namespace: unfriendlygrinch spec: provider: vault parameters: roleName: "unfriendlygrinch" vaultAddress: "http://<MY_VAULT_ADDR>" objects: | - objectName: "password" secretPath: "unfriendlygrinch/data/app/config" secretKey: "password" Whereas: * provider: the name of the secrets store. For HashiCorp Vault, this is vault. * vaultAddress: the URL of the Vault server. * roleName: The Vault role the driver will use. * objects: An array of secrets to retrieve from Vault. Each object has: * objectName: An alias used within the SecretProviderClass to refer to a specific secret. The name of the file (inside the pod) that contains the secret. * secretPath: The path in Vault where that secret is stored. * secretKey: The secret key to extract the value from. After creating the SecretProviderClass, we can reference it the pod’s definition using a volume of csi type. When the pod starts, the driver ensures that the secrets defined by the SecretProviderClass are retrieved from Vault and written to the pod’s filesystem. apiVersion: v1 kind: Pod metadata: labels: run: nginx name: nginx namespace: unfriendlygrinch spec: containers: - name: nginx image: nginx volumeMounts: - name: secrets-store mountPath: "/mnt/secrets-store" readOnly: true dnsPolicy: ClusterFirst restartPolicy: Always serviceAccountName: unfriendlygrinch volumes: - name: secrets-store csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: vault $ k -n unfriendlygrinch exec -it nginx -- cat /mnt/secrets-store/password && echo dretda1rus SECRETS STORE CSI DRIVER: SYNC AS KUBERNETES SECRET The Secrets Store CSI Driver also provides the option to sync these secrets to native Kubernetes secrets, allowing them to be managed and accessed using Kubernetes-native methods. This is not enabled by default, thus we need to explicitly do so: $ helm -n vault get values secrets-store-csi-driver USER-SUPPLIED VALUES: syncSecret: enabled: "true" Let’s now adjust the previous example in order to further explore the Sync as Kubernetes secret functionality. The updated SecretProviderClass resource would look like: kind: SecretProviderClass metadata: name: vault namespace: unfriendlygrinch spec: provider: vault parameters: roleName: "unfriendlygrinch" vaultAddress: "http://<MY_VAULT_ADDR>" objects: | - objectName: "password" secretPath: "unfriendlygrinch/data/app/config" secretKey: "password" secretObjects: - data: - key: password objectName: password secretName: my-password type: Opaque As you may notice in the above example, we employed the optional secretObjects parameter to specify the intended state of the synchronized Kubernetes secret objects: * data is an array consisting of key, namely the data field to populate, and objectName, the name of the object to sync. * secretName: the name of the Kubernetes secret object. * type: the type of Kubernetes secret object. As such, we are able to create Kubernetes Secrets to mirror the mounted content. It’s worth noting that secrets will only sync after we start a pod mounting them. Thus, relying solely on the synchronization with Kubernetes secrets functionality does not work. When all of the pods that consume the secret are deleted, the Kubernetes secret is also removed. Next we only need to use the Kubernetes secret in an environment variable in the pod. Well, that’s noting fancy, right? $ k -n unfriendlygrinch exec -it nginx -- env | grep ^MY MY_PASSWORD=dretda1rus CONCLUSIONS The Vault CSI Driver is deployed as a daemonset and uses the Secret Provider Class specified and the pod’s service account to retrieve the secrets from Vault and mount them into the pod’s CSI volume. It’s compatible solely with the Kubernetes auth method. The Vault CSI driver offers the capability to render Vault secrets into Kubernetes secrets as well as environment variables. However, if Secret synchronization is not absolutely necessary, it’s recommended to disable it. Having secrets accessible both in Vault and within etcd defeats the purpose of using Vault in the first place, as secrets are still stored as base64 encoded data in etcd. Given this scenario, it’s wise to think about encrypting the stored data using one of the various available service providers. It’s important to note, however, that doing so may introduce additional overhead. -------------------------------------------------------------------------------- | Copyright © Unfriendly Grinch 2023 | Archie Theme | Rendered by Hugo