<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nikhil Purva</title>
    <description>The latest articles on Forem by Nikhil Purva (@nikhilpurva).</description>
    <link>https://forem.com/nikhilpurva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F879806%2F96e04dfa-bdde-488c-809c-a38b93900825.jpeg</url>
      <title>Forem: Nikhil Purva</title>
      <link>https://forem.com/nikhilpurva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nikhilpurva"/>
    <language>en</language>
    <item>
      <title>Securing Kubernetes Secrets with HashiCorp Vault</title>
      <dc:creator>Nikhil Purva</dc:creator>
      <pubDate>Wed, 22 Jun 2022 05:55:04 +0000</pubDate>
      <link>https://forem.com/infracloud/securing-kubernetes-secrets-with-hashicorp-vault-521e</link>
      <guid>https://forem.com/infracloud/securing-kubernetes-secrets-with-hashicorp-vault-521e</guid>
      <description>&lt;p&gt;As more and more organizations making the shift to cloud native technologies, Kubernetes has become the de facto choice to orchestrate container based applications. As applications grow in size, the number of microservices increases and so does the data they process. Hence, handling data, especially sensitive data becomes critical. Out of the box, Kubernetes supports 'Secrets' objects to store sensitive information like passwords, tokens, ssh keys, etc. securely.&lt;/p&gt;

&lt;p&gt;Kubernetes secret eliminates the need of hard-coding sensitive data in the application code. Secrets provide this sensitive information as data mount or expose them as environment variables. &lt;/p&gt;

&lt;p&gt;Let’s take a quick example of how this secret object is getting used within the Kubernetes cluster. &lt;/p&gt;

&lt;p&gt;Create a secret object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
 &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Opaque&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;RABBITMQ_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cmFiYml0bXE=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's understand how to Inject this secret object inside a pod using an environment variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RABBITMQ_PASSWORD&lt;/span&gt;
        &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;secretKeyRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
            &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RABBITMQ_PASSWORD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s how we can easily inject a secret inside a pod and secure sensitive information. However, there is a challenge with this approach. Our sensitive information is still not fully secure because the yaml definition of secrets are base64 encoded, and anyone can easily decode base64 encoded secrets.&lt;/p&gt;

&lt;p&gt;To overcome this challenge with managing secrets within Kubernetes cluster, we need a better secret management system that provides a single source of credentials, secrets, security policies, etc. There are many solutions already available in the open source world like Bank-Vaults, AWS Secrets Manager, and Cloud KMS, but in this article, we will be focusing on HashiCorp Vault as it is currently widely adopted within the cloud native ecosystem. In this blog post, we will discuss how you can create a production grade secret management system using Hashicorp Vault.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HashiCorp Vault?
&lt;/h2&gt;

&lt;p&gt;HashiCorp Vault is a secret management tool that is used to store sensitive values and access it securely. A secret can be anything, such as API encryption keys, passwords, or certificates. Vault provides encryption services and supports authentication and authorization.&lt;/p&gt;

&lt;p&gt;We can run Vault in high-availability (HA) mode and standalone mode. The standalone mode runs a single Vault server which is less secure and less resilient that is not recommended for production grade setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefit of using HashiCorp Vault in HA using Raft
&lt;/h3&gt;

&lt;p&gt;Vault can run in the multi-server mode for high availability to protect against outages. To persist the encrypted data, Vault supports many storage backends like Consul, MySQL, DynamoDB, etc.&lt;/p&gt;

&lt;p&gt;But there are some challenges using these standard backend storages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Increased complexity with addition of storage backends.&lt;/li&gt;
&lt;li&gt;Additional configuration needed to allow Vault to operate as a client.&lt;/li&gt;
&lt;li&gt;Vault configuration to connect to the provider as a client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we need a solution which minimizes these challenges and at the same time, allows us to &lt;a href="https://dev.to/cloud-native-security-services/"&gt;implement and manage security&lt;/a&gt; efficiently. &lt;/p&gt;

&lt;p&gt;In this article we are focusing on Integrated storage to persist the data which has below benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrated into Vault (reducing the total administration).&lt;/li&gt;
&lt;li&gt;All configuration stays within Vault.&lt;/li&gt;
&lt;li&gt;Supports failover and multi-cluster replication.&lt;/li&gt;
&lt;li&gt;Get rid of additional network requests to backe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a Kubernetes cluster, to deploy Vault in high availability mode, it would be deployed as a cluster of pods. When deploying Vault in HA mode, all the nodes in a Vault cluster will have a replicated copy of Vault's data. Under the hood, &lt;a href="https://raft.github.io/"&gt;Raft Consensus Algorithm&lt;/a&gt; is used to replicate the data across all the nodes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bKzVqjBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7p5ia1eqjf07vhx8vl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bKzVqjBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7p5ia1eqjf07vhx8vl8.png" alt="Image description" width="880" height="280"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
 &lt;a href="https://learn.hashicorp.com/tutorials/vault/raft-storage"&gt;Image Source&lt;/a&gt; &lt;br&gt;
&lt;/center&gt;
&lt;h3&gt;
  
  
  Deploy Vault in HA and Vault Auto Unseal
&lt;/h3&gt;

&lt;p&gt;Before we jump into deploying Vault, it is important to understand what happens when we deploy a Vault pod. After deployment, the Vault pods start in a sealed state. That means until we unseal the Vault server, almost no operations are allowed. Here, unsealing is the process of decrypting the data inside Vault and allowing other services to access it.&lt;/p&gt;

&lt;p&gt;The data that is generally stored in Vault is encrypted and it needs an encryption key to decrypt the data. As we see in the below diagram, to decrypt the data, Vault must decrypt the encryption key first, which requires the master key. Unsealing is the process of getting access to this master key. The master key is also stored alongside all other Vault data, but it is encrypted by another mechanism: &lt;strong&gt;the unseal key&lt;/strong&gt;. By default the Vault config uses &lt;a href="https://www.vaultproject.io/docs/concepts/seal"&gt;Shamir seals&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mqdd9GfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xusv87ojobleeg8okzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mqdd9GfE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xusv87ojobleeg8okzu.png" alt="Image description" width="572" height="247"&gt;&lt;/a&gt; &lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
 &lt;a href="https://www.hashicorp.com/resources/vault-auto-unseal-using-aws-key-management-service"&gt;Image Source&lt;/a&gt; &lt;br&gt;
&lt;/center&gt;
&lt;h3&gt;
  
  
  Vault Auto Unseal
&lt;/h3&gt;

&lt;p&gt;To make the Vault server secure, there is also an API that seals it. This process puts away the master key in memory and requires another unseal process to restore it. So in case a pod gets restarted, every time someone has to manually unseal the Vault using &lt;strong&gt;vault operator unseal&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;To avoid the manual step of unsealing, Vault supports automatic unsealing via cloud based key management services like Azure Key Vault, Amazon KMS, AliCloud KMS, and Google Cloud KMS which enables us to let trusted cloud providers take care of the unsealing process, as seen in the below diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MHhzYmnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fd6g3nubarvn4tjxhl5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MHhzYmnQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fd6g3nubarvn4tjxhl5m.png" alt="Image description" width="810" height="257"&gt;&lt;/a&gt; &lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
 &lt;a href="https://www.hashicorp.com/resources/vault-auto-unseal-using-aws-key-management-service"&gt;Image Source&lt;/a&gt; &lt;br&gt;
&lt;/center&gt;

&lt;p&gt;We are going to set up an auto-unsealing Vault on Kubernetes with Azure Key Vault. Let’s start by setting up the required Azure Services:\&lt;br&gt;
Prerequisite: You need to have an Azure cloud account. If not, you can &lt;a href="https://azure.microsoft.com/en-in/free/"&gt;create trial account&lt;/a&gt; for free.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an Azure Key Vault &lt;a href="https://docs.microsoft.com/en-us/azure/key-vault/general/quick-create-portal"&gt;by following official documentation&lt;/a&gt; and note down the &lt;strong&gt;Subscription ID&lt;/strong&gt; and &lt;strong&gt;Directory ID&lt;/strong&gt;, which will be required in later steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a_FI-hFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4u10bx5l2l32pe12xqzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a_FI-hFD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4u10bx5l2l32pe12xqzb.png" alt="Image description" width="880" height="195"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next step is to register an App by &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app"&gt;following official documentation&lt;/a&gt; which &lt;strong&gt;establishes a trust relationship between our app and the Microsoft identity platform&lt;/strong&gt;. This trust is unidirectional: your app trusts the Microsoft identity platform, and not the other way around. Here we will create a Service Principal which will work as our access layer to the Azure Key Vault.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;It is very important to copy the value of Application (client ID) and client secret from register an App section mentioned above.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once this is done, let's switch back to Azure Key Vault, and under IAM add a new Role Assignment as Key Vault Contributor for our newly created Service Principal:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KP4C4n_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pg9siddfigt1rjayzlvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KP4C4n_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pg9siddfigt1rjayzlvu.png" alt="Image description" width="428" height="647"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once the Service Principal is assigned to the Azure Key Vault, we need to provide specific access permissions to it. Vault needs &lt;strong&gt;Get&lt;/strong&gt; permissions at key level and Unwrap Key and Wrap Key at Cryptographic level, so under access policy, create a new one with those selected:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Q9HS1i9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xspg8tz9cb2ht0rkbfrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Q9HS1i9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xspg8tz9cb2ht0rkbfrd.png" alt="Image description" width="506" height="667"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the Service Principal in the list, Click on Add and Save the configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KkAo3t5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntnw5hae6nswhw14qw0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KkAo3t5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntnw5hae6nswhw14qw0x.png" alt="Image description" width="799" height="443"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The last step on Azure portal is to create a key on Key Vault, which will be the unsealing key for Vault:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V2tpZsDq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pk9iivrxyqqw4hijot3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2tpZsDq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pk9iivrxyqqw4hijot3w.png" alt="Image description" width="505" height="507"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once the above steps are done, it's time to install the HashiCorp Vault. The recommended way to deploy a Vault in the Kubernetes cluster is using the Vault’s &lt;a href="https://github.com/hashicorp/vault-helm"&gt;official Helm chart&lt;/a&gt;. To deploy Vault in HA with auto unsealing use the below-mentioned &lt;code&gt;values.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;injector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hashicorp/vault"&lt;/span&gt;
    &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.9.0"&lt;/span&gt;
    &lt;span class="c1"&gt;# Overrides the default Image Pull Policy&lt;/span&gt;
    &lt;span class="na"&gt;pullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IfNotPresent&lt;/span&gt;

  &lt;span class="c1"&gt;# Configure the Update Strategy Type for the StatefulSet&lt;/span&gt;
  &lt;span class="na"&gt;updateStrategyType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OnDelete"&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;250m&lt;/span&gt;
    &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256Mi&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;250m&lt;/span&gt;
  &lt;span class="na"&gt;ha&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="na"&gt;raft&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;ui = true&lt;/span&gt;
        &lt;span class="s"&gt;listener "tcp" {&lt;/span&gt;
          &lt;span class="s"&gt;tls_disable = 1&lt;/span&gt;
          &lt;span class="s"&gt;address = "[::]:8200"&lt;/span&gt;
          &lt;span class="s"&gt;cluster_address = "[::]:8201"&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;seal "azurekeyvault" {&lt;/span&gt;
          &lt;span class="s"&gt;tenant_id       = "0fd16XXX-xxxx-xxxx-xxxx-xxxx"&lt;/span&gt;
          &lt;span class="s"&gt;client_id       = "ab509eca-xxxx-xxxx-xxxx-xxxxxxxxxxxx"&lt;/span&gt;
          &lt;span class="s"&gt;client_secret   = "UTb7Q~xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"&lt;/span&gt;
          &lt;span class="s"&gt;vault_name      = "vault-k8s-data"&lt;/span&gt;
          &lt;span class="s"&gt;key_name        = "vault-k8s-unsealer-key"&lt;/span&gt;
          &lt;span class="s"&gt;subscription_id = "c83a96b1-xxxx-xxxx-xxxx-xxxxxxxxxxxx"&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;storage "raft" {&lt;/span&gt;
          &lt;span class="s"&gt;path = "/vault/data"&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;service_registration "kubernetes" {}&lt;/span&gt;
  &lt;span class="na"&gt;dataStorage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500Mi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values mentioned under seal “azurekeyvault” in the above configuration are derived from Azure portal while setting up azure services.&lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Config&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tenant_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Key Vault's Directory ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service Principal's Application ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;client_secret&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service Principal's generated secret (the one that is not retrievable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vault_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of Azure Key Vault instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Name of generated key on Azure Key Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subscription_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ID of the Azure Subscription&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Proceed with the installation following the steps mentioned below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;helm repo add hashicorp https://helm.releases.hashicorp.com
&lt;span class="s2"&gt;"hashicorp"&lt;/span&gt; has been added to your repositories

&lt;span class="nv"&gt;$ &lt;/span&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;vault hashicorp/vault &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
NAME: vault
LAST DEPLOYED: Sat Mar  5 22:14:51 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
Thank you &lt;span class="k"&gt;for &lt;/span&gt;installing HashiCorp Vault!

Now that you have deployed Vault, you should look over the docs on using
Vault with Kubernetes available here:

https://www.vaultproject.io/docs/


Your release is named vault. To learn more about the release, try:

&lt;span class="nv"&gt;$ &lt;/span&gt;helm status vault
&lt;span class="nv"&gt;$ &lt;/span&gt;helm get manifest vault
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s verify the installation by running below-mentioned command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; vault
NAME                                           READY   STATUS    RESTARTS 
vault-0                                        0/1     Running   0      
vault-1                                        0/1     Running   0     
vault-2                                        0/1     Running   0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As discussed earlier, Vault starts in a sealed state, and that’s why all the Vault pods are in running status but none of the Vault pods are "ready". To unseal Vault, we need to initialize it. Just exec into pod vault-0 and initialize your Vault instance (and keep your generated keys safe) as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-0 vault operator init

Recovery Key 1: FKjt5wkzN5bUBIuR52KrPP1c2Il/f7RZdn5E+ipfNF8s
Recovery Key 2: FCzUyduESPyavh6QtqWZpdnUDKa3bEEpBHbX3NgTrCiU
Recovery Key 3: Tf7FVEpj5tdJLqQqNw/Jt0OytRI5FAZYig/yafSVz3Xg
Recovery Key 4: duLpa/6IozTOR0mkO7sp0CwmnI+1DsC6d2+oZG/A1CIZ
Recovery Key 5: pyVFs/rRFEk9rSn57Ru+KeuAQzW6eurl3j0/pS/JRpXD
Initial Root Token: s.d0LAlSnAerb4a7d6ibkfxrZy
Success! Vault is initialized
Recovery key initialized with 5 key shares and a key threshold of 3. Please
securely distribute the key shares printed above.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we see the Vault unsealer in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; vault
NAME                                           READY   STATUS    RESTARTS
vault-0                                        1/1     Running   0      
vault-1                                        0/1     Running   0     
vault-2                                        0/1     Running   0         
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, our replica &lt;code&gt;vault-1&lt;/code&gt; and &lt;code&gt;vault-2&lt;/code&gt; are still not ready. They are follower pods of the leader &lt;code&gt;vault-0&lt;/code&gt;. In order to make vault-0 visible, we need to login using our &lt;code&gt;Initial Root Token&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-0 &lt;span class="nt"&gt;--&lt;/span&gt; vault login s.d0LAlSnAerb4a7d6ibkfxrZy

Success! You are now authenticated. The token information displayed below
is already stored &lt;span class="k"&gt;in &lt;/span&gt;the token helper. You &lt;span class="k"&gt;do &lt;/span&gt;NOT need to run &lt;span class="s2"&gt;"vault login"&lt;/span&gt;
again. Future Vault requests will automatically use this token.
Key                  Value
&lt;span class="nt"&gt;---&lt;/span&gt;                  &lt;span class="nt"&gt;-----&lt;/span&gt;
token                s.d0LAlSnAerb4a7d6ibkfxrZy
token_accessor       hJEFibLTbUP4sgA8X4tMBqZ8
token_duration       ∞
token_renewable      &lt;span class="nb"&gt;false
&lt;/span&gt;token_policies       &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
identity_policies    &lt;span class="o"&gt;[]&lt;/span&gt;
policies             &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next,  let’s join vault-1 and vault-2 to Vault-0 to make the Vault setup Highly available by running commands as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-1 &lt;span class="nt"&gt;--&lt;/span&gt; vault operator raft &lt;span class="nb"&gt;join &lt;/span&gt;http://vault-0.vault-internal:8200

Key       Value
&lt;span class="nt"&gt;---&lt;/span&gt;       &lt;span class="nt"&gt;-----&lt;/span&gt;
Joined    &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-2 &lt;span class="nt"&gt;--&lt;/span&gt; vault operator raft &lt;span class="nb"&gt;join &lt;/span&gt;http://vault-0.vault-internal:8200

Key       Value
&lt;span class="nt"&gt;---&lt;/span&gt;       &lt;span class="nt"&gt;-----&lt;/span&gt;
Joined    &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s check the pod status and this time you would be able to see them in running as well as Ready mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; vault
NAME                                           READY   STATUS    RESTARTS   
vault-0                                        1/1     Running   0     
vault-1                                        1/1     Running   0     
vault-2                                        1/1     Running   0     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last but important step is to verify whether the HA setup is correct or not, is by running the below command against each Vault pod and making sure that the value of HA Enabled parameters is true.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; vault vault-0 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
Key                      Value
&lt;span class="nt"&gt;---&lt;/span&gt;                      &lt;span class="nt"&gt;-----&lt;/span&gt;
Recovery Seal Type       shamir
Initialized              &lt;span class="nb"&gt;true
&lt;/span&gt;Sealed                   &lt;span class="nb"&gt;false
&lt;/span&gt;Total Recovery Shares    5
Threshold                3
Version                  1.9.0
Storage Type             raft
Cluster Name             vault-cluster-30882e80
Cluster ID               1afbe13a-e951-482d-266b-e31693d17e20
HA Enabled               &lt;span class="nb"&gt;true
&lt;/span&gt;HA Cluster               https://vault-0.vault-internal:8201
HA Mode                  active
Active Since             2022-01-19T04:39:37.586622342Z
Raft Committed Index     61
Raft Applied Index       61

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; vault vault-1 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
Key                      Value
&lt;span class="nt"&gt;---&lt;/span&gt;                      &lt;span class="nt"&gt;-----&lt;/span&gt;
…
HA Enabled               &lt;span class="nb"&gt;true
&lt;/span&gt;HA Cluster               https://vault-0.vault-internal:8201
HA Mode                  standby
Active Node Address      http://10.244.0.17:8200
Raft Committed Index     61
Raft Applied Index       61

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; vault vault-2 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
Key                      Value
&lt;span class="nt"&gt;---&lt;/span&gt;                      &lt;span class="nt"&gt;-----&lt;/span&gt;
HA Enabled               &lt;span class="nb"&gt;true
&lt;/span&gt;HA Cluster               https://vault-0.vault-internal:8201
HA Mode                  standby
Active Node Address      http://10.244.0.17:8200
Raft Committed Index     61
Raft Applied Index       61
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see &lt;code&gt;vault-0&lt;/code&gt; is &lt;code&gt;active&lt;/code&gt; and &lt;code&gt;vault-1&lt;/code&gt; and &lt;code&gt;vault-2&lt;/code&gt; is &lt;code&gt;standby&lt;/code&gt;. Now, Let’s try deleting vault-0 and run the same command, you will notice that vault-1 has become active and vault-0 becomes standby.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; vault delete pod vault-0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; vault vault-1 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
Key                      Value
&lt;span class="nt"&gt;---&lt;/span&gt;                      &lt;span class="nt"&gt;-----&lt;/span&gt;
…
HA Enabled               &lt;span class="nb"&gt;true
&lt;/span&gt;HA Cluster               https://vault-1.vault-internal:8201
HA Mode                  active
Active Node Address      http://10.244.0.18:8200
Raft Committed Index     61
Raft Applied Index       61

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; vault vault-0 &lt;span class="nt"&gt;--&lt;/span&gt; vault status
Key                      Value
&lt;span class="nt"&gt;---&lt;/span&gt;                      &lt;span class="nt"&gt;-----&lt;/span&gt;
…
HA Enabled               &lt;span class="nb"&gt;true
&lt;/span&gt;HA Cluster               https://vault-1.vault-internal:8201
HA Mode                  standby
Active Since             2022-01-19T04:39:37.586622342Z
Raft Committed Index     61
Raft Applied Index       61
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vault Web UI
&lt;/h3&gt;

&lt;p&gt;Finally to be able to access the Vault web interface; let’s port-forward the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl port-forward &lt;span class="nt"&gt;-n&lt;/span&gt; vault svc/vault 8200:8200&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vault UI will be accessible on &lt;code&gt;http://localhost:8200&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GPMfzKAf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nipja0bkb10ri0838v23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GPMfzKAf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nipja0bkb10ri0838v23.png" alt="Image description" width="880" height="535"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To login in Vault, enter the token that we generated when we initialized Vault for the first time (&lt;code&gt;Initial Root Token&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AS8EGSl4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5i680r6tqgf22ib21g34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AS8EGSl4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5i680r6tqgf22ib21g34.png" alt="Image description" width="880" height="240"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Secrets Engine is a Vault component that stores or generates a secret. Vault supports different types of Secrets Engines like key-value, ssh keys, certificates, etc.&lt;/p&gt;

&lt;p&gt;To start with, let's use a KV secrets engine, click on the &lt;strong&gt;Enable New Engine+&lt;/strong&gt; button, select the KV engine and click on &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AW_7z0EW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/raiajbzwg6pepcpr4eul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AW_7z0EW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/raiajbzwg6pepcpr4eul.png" alt="Image description" width="777" height="603"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Give a path name and click on &lt;strong&gt;Enable Engine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d5biw2PV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uiza3nekcwxt760rylba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d5biw2PV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uiza3nekcwxt760rylba.png" alt="Image description" width="880" height="422"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rHj-xi0t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jq7th3lnhmznfazpx52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rHj-xi0t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9jq7th3lnhmznfazpx52.png" alt="Image description" width="880" height="291"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, let’s create a secret, click on Create secret and enter the details as shown in the below figure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JdGVEF6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqurhawy148ej50ay3ky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JdGVEF6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqurhawy148ej50ay3ky.png" alt="Image description" width="880" height="306"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Once we click on save, we should be able to see that the secret has been successfully created and stored in a Vault.&lt;/p&gt;

&lt;p&gt;Since Vault centrally stores, secures and controls access to the secrets, it is important to control the permissions before anyone can gain access. Vault supports Role Based Access Control to limit the access. Refer to the &lt;a href="https://learn.hashicorp.com/tutorials/vault/policies"&gt;official Vault documentation on policies&lt;/a&gt; to understand more about the policies and roles.&lt;/p&gt;

&lt;p&gt;Until this point, we have successfully deployed Vault in HA using Helm, learnt about configuring role based access and created a secret object. Let’s now inject this secret inside a pod.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inject Vault secrets into pod
&lt;/h3&gt;

&lt;p&gt;Since Vault has been deployed successfully let’s now jump into injecting the Vault secrets into the pods/application. Mainly there are two ways for a pod to use Secret object: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a file mounted in volume.&lt;/li&gt;
&lt;li&gt;As a container environment variable.
Secrets can be injected into the application with the Vault agent and this introduces a new requirement that deployments install and configure Vault Agent alongside the application as a sidecar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we will be focusing on injecting a Vault secret into an application using &lt;strong&gt;External Secrets&lt;/strong&gt;. The benefit of Kubernetes External Secrets is that it can be used with Vault, external secret management systems like AWS Secret Manager, Azure Key Vault to securely add secrets. Kubernetes External Secrets extends the Kubernetes API by adding an ExternalSecrets object using Custom Resource Definition.&lt;/p&gt;

&lt;p&gt;An ExternalSecret object declares how to fetch the secret data, while the controller converts all ExternalSecrets to Secrets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dTr9f3KN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tiw63joth3vuh9s633y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dTr9f3KN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tiw63joth3vuh9s633y.png" alt="Image description" width="880" height="381"&gt;&lt;/a&gt; &lt;br&gt;
&lt;/p&gt;
&lt;center&gt;
&lt;br&gt;
 &lt;a href="https://github.com/external-secrets/kubernetes-external-secrets"&gt;Image Source&lt;/a&gt; &lt;br&gt;
&lt;/center&gt;

&lt;p&gt;Just like the Hashicorp Vault, the recommended way to deploy Kubernetes-External-Secrets is using the official helm chart and use the below-mentioned values.yaml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://vault:8200&lt;/span&gt;
  &lt;span class="na"&gt;METRICS_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;
  &lt;span class="na"&gt;POLLER_INTERVAL_MILLISECONDS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10000&lt;/span&gt;  
  &lt;span class="na"&gt;WATCH_TIMEOUT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60000&lt;/span&gt;
  &lt;span class="na"&gt;WATCHED_NAMESPACES&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Comma separated list of namespaces, empty or unset means ALL namespaces.&lt;/span&gt;
  &lt;span class="na"&gt;LOG_LEVEL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;info&lt;/span&gt;
  &lt;span class="na"&gt;LOG_MESSAGE_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;msg"&lt;/span&gt;
&lt;span class="na"&gt;rbac&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Specifies whether RBAC resources should be created&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;serviceAccount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Specifies whether a service account should be created&lt;/span&gt;
  &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="c1"&gt;# Specifies annotations for this service account&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="c1"&gt;# The name of the service account to use.&lt;/span&gt;
  &lt;span class="c1"&gt;# If not set and create is true, a name is generated using the fullname template&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes-external-secrets&lt;/span&gt;
&lt;span class="na"&gt;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/external-secrets/kubernetes-external-secrets&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8.5.1&lt;/span&gt;
  &lt;span class="na"&gt;pullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IfNotPresent&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to deploy the external secrets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;helm repo add external-secrets 
https://external-secrets.github.io/kubernetes-external-secrets/
&lt;span class="s2"&gt;"external-secrets"&lt;/span&gt; has been added to your repositories

&lt;span class="nv"&gt;$ &lt;/span&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;k8s-external-secrets external-secrets/kubernetes-external-secrets &lt;span class="nt"&gt;-f&lt;/span&gt; values.yaml
NAME: k8s-external-secrets
LAST DEPLOYED: Wed Mar 23 22:50:35 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The kubernetes external secrets has been installed. Check its status by running:
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;--namespace&lt;/span&gt; default get pods &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"app.kubernetes.io/name=kubernetes-external-secrets,app.kubernetes.io/instance=k8s-external-secrets"&lt;/span&gt;

Visit https://github.com/external-secrets/kubernetes-external-secrets &lt;span class="k"&gt;for &lt;/span&gt;instructions on how to use kubernetes external secrets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the kubernetes-external-secret has been deployed successfully and with the help of the ExternalSecrets object, now we can inject secrets inside the pods that are stored in Vault.&lt;/p&gt;

&lt;p&gt;But the external-secrets controller needs to be authenticated with Vault before making any request to retrieve the secrets, so we need to enable the Kubernetes authentication method and attach a policy to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable Kubernetes Auth Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's access the Vault pod's terminal and enable kubernetes auth method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; vault-0 sh
&lt;span class="nv"&gt;$ &lt;/span&gt;vault login s.d0LAlSnAerb4a7d6ibkfxrZy
&lt;span class="nv"&gt;$ &lt;/span&gt;vault auth &lt;span class="nb"&gt;enable &lt;/span&gt;kubernetes

Success! Enabled kubernetes auth method at: kubernetes/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Kubernetes Auth Method can be used to authenticate with Vault using Kubernetes Service Account Token, as Vault accepts this token by any client within the Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;Configure the kubernetes authentication method by running below command from inside the active Vault pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vault write auth/kubernetes/config &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;token_reviewer_jwt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;kubernetes_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KUBERNETES_PORT_443_TCP_ADDR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:443 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;kubernetes_ca_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

Success! Data written to: auth/kubernetes/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The token_reviewer_jwt and kubernetes_ca_cert are created for a pod  by Kubernetes when it is started. The env variable KUBERNETES_PORT_443_TCP_ADDR is defined and references the internal Kubernetes API Server network address. When an application tries to authenticate with Vault using its Service Account Token, Vault uses the above configuration to verify the client application’s identity with Kubernetes API Server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attach a policy to Kubernetes auth method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since we have already created a &lt;strong&gt;readonly&lt;/strong&gt; policy, let’s create a role for kubernetes and attach this policy. In the below mentioned role all the service accounts in any namespaces are allowed to authenticate. We can also limit authentication to specific service accounts and namespaces as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wUnYObrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryftl2emt6npagdsegz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wUnYObrZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryftl2emt6npagdsegz9.png" alt="Image description" width="880" height="532"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vault write auth/kubernetes/role/k8s-role &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;bound_service_account_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;bound_service_account_namespaces&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;policies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1h

Success! Data written to: auth/kubernetes/role/k8s-role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s now inject vault secrets inside a pod. We will be using the same example which we used at the start of this blog post. As discussed earlier, we just need to create an ExternalSecret object and the controller will convert it to a Secret object. Delete the secret object we created earlier and apply the below file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;kubernetes-client.io/v1'&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ExternalSecret&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rabbitmq&lt;/span&gt;
 &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;kvVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
 &lt;span class="na"&gt;backendType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault&lt;/span&gt;
 &lt;span class="na"&gt;vaultMountPoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes&lt;/span&gt;
 &lt;span class="na"&gt;vaultRole&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;k8s-role&lt;/span&gt;
 &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RABBITMQ_USERNAME&lt;/span&gt;
   &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secret/Rabbitmq&lt;/span&gt;
   &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;username&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this file by name rabbitmq-external-secret.yaml and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl delete secret rabbitmq
secret &lt;span class="s2"&gt;"rabbitmq"&lt;/span&gt; deleted

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; rabbitmq-external-secret.yaml 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s run the below command to check the status of external-secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get externalsecrets.kubernetes-client.io
NAME       LAST SYNC   STATUS    AGE
rabbitmq   10s         SUCCESS   15s

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get secrets
NAME       TYPE     DATA    AGE
rabbitmq   Opaque   1       15s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here, External Secret has been created successfully and the External Secrets fetched the correct value from Vault, and created the Secret object for us. This Secret object is used by our application as we saw in the beginning of the post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Since Kubernetes is widely used and to make a Kubernetes cluster production-grade, it is very important to make sure the secret objects are handled carefully. In this article, we learned why it is important not to use native secret objects due to their limitations and the importance of using a secret management tool like HashiCorp Vault.&lt;/p&gt;

&lt;p&gt;We also learned about External Secrets, which help us to inject secrets inside a pod. With the help of external secrets, we can easily replace the Kubernetes secrets with Vault secrets inside any existing deployments.&lt;/p&gt;

&lt;p&gt;That’s it, folks !! I hope this article was informative and engaging. I am looking forward to hearing your thoughts on this post, so let’s connect and start a conversation on &lt;a href="https://www.linkedin.com/in/nikhil-purva-a1b1b320/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Looking for help with cloud native security? do check out our capabilities how we’re helping startups &amp;amp; enterprises as an &lt;a href="https://dev.to/cloud-native-security-services/"&gt;DevSecOps consulting services provider&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hashicorp</category>
      <category>vault</category>
      <category>kubernetes</category>
      <category>security</category>
    </item>
  </channel>
</rss>
