<p>I'm contemplating using Hashicorp vault in my Kubernetes, to store some dynamic secrets. I did find out that I can set the sidecar injector to periodically retrieve the secret and app can look for file changes etc... all fine.</p>
<p>But after solid research, I could not find out how to update the key/pair from scheduled job in Kubernetes. Basically I need to run container than do some magic and retrieve new token, and then updates the vault pair. With kv commands, or somehow... bonus point if I do not have to use any API keys, just service account same like for reading the values.</p>
<p>Assuming the vault is running on Kubernetes where the pods will be.</p>

<p>You can use the <a href="https://www.vaultproject.io/api-docs/secret/kv/kv-v2#patch-secret" rel="nofollow noreferrer">http API</a> to interact with the vault.</p>
<p>Given the assumption that your service account has permission to update the secret, you could run a container with a small script.</p>
<pre class="lang-bash prettyprint-override"><code>#!/bin/sh

set -eu

# get the mounted service account token
token=&quot;$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&quot;

# update the secret using curl
curl \
    --header &quot;X-Vault-Token: $token&quot; \
    --header &quot;Content-Type: application/merge-patch+json&quot; \
    --request PATCH \
    --data @/path/to/payload.json \
    &quot;$VAULT_ADDR/v1/secret/data/my-secret&quot;
</code></pre>
<p>You need to tell your cronjob it should use the service account with the permissions, of course.</p>
<p>This could look roughly like this. It's probably better practice to build a custom image. I am mounting the script just for demo purposes.</p>
<pre><code>---
apiVersion: batch/v1
kind: Job
metadata:
  name: patch-secret
spec:
  ttlSecondsAfterFinished: 100
  template:
    spec:
      serviceAccount: my-service-account
      restartPolicy: Never
      containers:
        - name: patcher
          image: index.docker.io/bluebrown/netutils
          command: [sh, &quot;-e&quot;, &quot;/opt/my-org/update-secret.sh&quot;]
          volumeMounts:
            - name: scripts
              mountPath: /opt/my-org
      volumes:
        - name: scripts
          configMap:
            name: patch-secret-scripts
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: patch-secret-scripts
data:
  update-secret.sh: |
    token=&quot;$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&quot;
    curl \
        --header &quot;X-Vault-Token: $token&quot; \
        --header &quot;Content-Type: application/merge-patch+json&quot; \
        --request PATCH \
        --data @/path/to/payload.json \
        &quot;$VAULT_ADDR/v1/secret/data/my-secret&quot;
</code></pre>
<p>You need to know where the payload is coming from. I left that part out in the example.</p>
