<p>I would like to provide secrets from a Hashicorp Vault for the Apache Flink jobs running in a Kubernetes cluster.
These credits will be used to access a state-backend for checkpointing and savepoints. The state-backend could be for example Minio S3 storage.
Could someone provide a working example for a <a href="https://github.com/lyft/flinkk8soperator/blob/master/docs/crd.md" rel="nofollow noreferrer">FlinkApplication operator</a> please given the following setup?</p>
<p>Vault secrets for username and password (or an access key):</p>
<pre><code>vault kv put vvp/storage/config username=user password=secret
vault kv put vvp/storage/config access-key=minio secret-key=minio123
</code></pre>
<p>k8s manifest of the Flink application custom resource:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: flink.k8s.io/v1beta1
kind: FlinkApplication
metadata:
  name: processor
  namespace: default
spec:
  image: stream-processor:0.1.0
  deleteMode: None

  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: &quot;true&quot;
        vault.hashicorp.com/role: vvp-flink-job
        vault.hashicorp.com/agent-inject-secret-storage-config.txt: vvp/data/storage/config

  flinkConfig:
    taskmanager.memory.flink.size: 1024mb
    taskmanager.heap.size: 200
    taskmanager.network.memory.fraction: 0.1
    taskmanager.network.memory.min: 10mb
    web.upload.dir: /opt/flink
  jobManagerConfig:
    resources:
      requests:
        memory: &quot;1280Mi&quot;
        cpu: &quot;0.1&quot;
    replicas: 1
  taskManagerConfig:
    taskSlots: 2
    resources:
      requests:
        memory: &quot;1280Mi&quot;
        cpu: &quot;0.1&quot;
  flinkVersion: &quot;1.14.2&quot;
  jarName: &quot;stream-processor-1.0-SNAPSHOT.jar&quot;
  parallelism: 3
  entryClass: &quot;org.StreamingJob&quot;
  programArgs: &gt;
    --name value
</code></pre>
<p>Docker file of the flink application:</p>
<pre><code>FROM maven:3.8.4-jdk-11 AS build
ARG revision

WORKDIR /
COPY    src /src
COPY    pom.xml /

RUN mvn -B -Drevision=${revision} package

# runtime
FROM flink:1.14.2-scala_2.12-java11

ENV FLINK_HOME=/opt/flink

ENTRYPOINT [&quot;/docker-entrypoint.sh&quot;]
EXPOSE 6123 8081
CMD [&quot;help&quot;]
</code></pre>
<p>The flink-config.yaml contains the following examples:</p>
<pre class="lang-yaml prettyprint-override"><code># state.backend: filesystem

# Directory for checkpoints filesystem, when using any of the default bundled
# state backends.
#
# state.checkpoints.dir: hdfs://namenode-host:port/flink-checkpoints

# Default target directory for savepoints, optional.
#
# state.savepoints.dir: hdfs://namenode-host:port/flink-savepoints
</code></pre>
<p>The end goal is to replace the hardcoded secrets or set them somehow from the vault:</p>
<pre class="lang-yaml prettyprint-override"><code>state.backend: filesystem
s3.endpoint: http://minio:9000
s3.path.style.access: true
s3.access-key: minio
s3.secret-key: minio123
</code></pre>
<p>Thank you.</p>

<p>Once you have vault variables set</p>
<p>You can add the annotation in deployment to get variables out of the vault to deployment</p>
<pre><code>annotations:
        vault.hashicorp.com/agent-image: &lt;Agent image&gt;
        vault.hashicorp.com/agent-inject: &quot;true&quot;
        vault.hashicorp.com/agent-inject-secret-secrets: kv/&lt;Path-of-secret&gt;
        vault.hashicorp.com/agent-inject-template-secrets: |2

          {{- with secret &quot;kv/&lt;Path-of-secret&gt;&quot; -}}

          #!/bin/sh
          set -e

          {{- range $key, $value := .Data.data }}
          export {{ $key }}={{ $value }}
          {{- end }}

          exec &quot;$@&quot;
          {{- end }}
        vault.hashicorp.com/auth-path: auth/&lt;K8s cluster for auth&gt;
        vault.hashicorp.com/role: app
</code></pre>
<p>this will create the file inside your POD.</p>
<p>When you application run it should execute this file first and the environment variable will get injected to POD.</p>
<p>So vault annotation will create one file the same as you are getting as <strong>txt</strong> but instead, we will be doing it like</p>
<pre><code>{{- range $key, $value := .Data.data }}
       export {{ $key }}={{ $value }}
{{- end }}
</code></pre>
<p>it will keep and inject the <strong>export</strong> before key &amp; value. Now the file is a kind of shell script and once it will get executed on the startup of the application it will inject variables to the <strong>OS</strong> level.</p>
<p>Keep this file in reop and add it in Docker <strong>./bin/runapp</strong></p>
<pre><code>#!/bin/bash
if [ -f '/vault/secrets/secrets' ]; then
  source '/vault/secrets/secrets'
fi
node &lt;path-insnide-docker&gt;/index.js #Sorry dont know scala or Java
</code></pre>
<p><strong>package.json</strong></p>
<pre><code>&quot;start&quot;: &quot;./bin/runapp&quot;,
</code></pre>
<p><strong>Dockerfile</strong></p>
<pre><code>ADD ./bin/runapp ./
EXPOSE 4444
CMD [&quot;npm&quot;, &quot;start&quot;]
</code></pre>
<p>Your vault injected file will be something like inside pod at <code>/vault/secrets/secrets</code> or your configured path.</p>
<pre><code>#!/bin/sh
set -e
export development=false
export production=true
exec &quot;$@&quot;
</code></pre>
