Repository: provectus/kafka-ui
Issue: Let environment variable values be injected from Secrets
Labels: type/enhancement
status/accepted
scope/k8s

### Is your proposal related to a problem?

The issue is that the `KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG` environment variable needs to be populated in plaintext.

### Describe the solution you'd like

I would like to see the Helm chart support referencing values for the environment variables from a Kubernetes `Secret`.

For example:

```
 values:
      - envs:
         config:
             KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG:
                 valueFrom:
                     secretKeyRef:
                         name: "kafka-ui-user"
                         key: "sasl.jaas.config"
```

However, my `helmfile diff` complains since the parameter `KAFKA_CLUSTERS_X_...` only supports values of type string, implying that these type of injections are not supported by the Chart yet.

### Describe alternatives you've considered

In this case, my `kafka-ui-user` Kubernetes `Secret` is created with a `CRD` of kind `KafkaUser`. I do not want to change how I create a `KafkaUser` (ie maintaining Kafka configuration as CRDs) since the current setup works well from a CI/CD perspective, and since the `KafkaUser` allows me to manage ACLs to Kafka resources.

Still, this `KafkaUser` and its associated `Secret` autogenerates the `.sasl.jaas.config`, including the `password` (referenced from the `Secret` with `kafka-ui-user.password`) for me. I would like to be able to inject the values associated with those two keys to the `kafka-ui` Chart's environment variables as a consequence.

I have tried with the following:

```
values:
  - existingSecret: "kafka-ui-user"`
```

But this simply gives me two environment variables:
- `password`
- `sasl.jaas.config` 

with the values of the environment variables coming from the data parameter of the `Secret`. There is therefore no way to inject these into the `KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG` AFAIK, which is what is required for the `kube-ui` `Pod` to authenticate to my Kafka environment.

Issue comments:
Hi @mattia-crypto thank you for opening the issue.

Have you tried referencing these env variables like: 
`KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: "org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="$PASSWORD";" ?`

Where `$PASSWORD` is the name of env var provided by the existing secret.
Have not tried this yet, no! Good advice which by the looks of it should work. I will test it out :-) 
Hey @5hin0bi ! 

That solved this Issue indeed, many thanks. However, it only fixes the problem when `SASL_PLAINTEXT` is used.

In my case I do use `SASL_SSL`, and the above solution gave me the idea to use the `existingSecret` parameter as a way to inject the certs. However, these are not in `.jks` format by default...

Are you working on converting Kubernetes secrets to `.jks` with `kube-ui`, or are you expecting end-users to manage this in adance?


For your information I also tried this:
```
values:
      - existingSecret: "kafka-ui-user" 
      - existingSecret: "kafka-client-cert"
```
But that only stored the latter `Secret` as environment variables, leaving the `KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG:` environment variable undefined which crashed my `Pod`.
Is there a way to inject multiple existing secrets? 

Thanks.

Hi @mattia-crypto glad it helped at least with the simple case.

If you wish to store certificates as files in the container, I believe the best option will be to use volumeMounts: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod

It's not yet supported by the existing state of the helm chart we maintain but I see it's a required thing to have. We will implement the support for mounting secrets in future. **The work will be done within this issue.**

Meanwhile, you can make required changes basing on the link I've provided to store certificates as files in the container and reference them in the kafka-ui config.
Setting multiple existing secrets is not supported either, but you can include cert to the same kafka-ui-user secret and reference it as env variable. So that you will need to specify only one existing secret.
Thank you @5hin0bi. I would like to add that the Strimzi Kafka operator generates the following content for the secret related to a particular KafkaUser CRD:
- `ca.crt`
- `user.crt`
- `user.key`
- `user.p12`
- `user.password`

This is one of the most highly used Kafka operators so I would recommend a solution that can integrate neatly with this `Secret` generated for the CRD. 
OK @mattia-crypto , we will consider these when implementing the feature.
@mattia-crypto, @5hin0bi ,

I just follow the above answer but no luck
```
22-05-20 11:21:24,265 WARN  [kafka-admin-client-thread | adminclient-3] o.a.k.c.a.i.AdminMetadataManager: [AdminClient clientId=adminclient-3] Metadata update failed due to authentication error
org.apache.kafka.common.errors.SaslAuthenticationException: Authentication failed during authentication due to invalid credentials with SASL mechanism SCRAM-SHA-512
```
Can you guys help me check? What is wrong

```
  replicaCount: 1
  fullnameOverride: "kafka-ui"

  existingConfigMap: ""
  existingSecret: ""
  envs:
    secret:
      PASSWORD: cGFzc3dvcmQ=
    config:
      KAFKA_CLUSTERS_0_NAME: test-msk
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: b-1.my-msk.xxxxxx.c5.kafka.ap-southeast-1.amazonaws.com:9096
      KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_SSL
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: SCRAM-SHA-512
      KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="mskadm" password="$(PASSWORD)";'

```

But when I specify my password in envs.config it works perfectly
> @mattia-crypto, @5hin0bi ,
> 
> I just follow the above answer but no luck
> 
> ```
> 22-05-20 11:21:24,265 WARN  [kafka-admin-client-thread | adminclient-3] o.a.k.c.a.i.AdminMetadataManager: [AdminClient clientId=adminclient-3] Metadata update failed due to authentication error
> org.apache.kafka.common.errors.SaslAuthenticationException: Authentication failed during authentication due to invalid credentials with SASL mechanism SCRAM-SHA-512
> ```
> 
> Can you guys help me check? What is wrong
> 
> ```
>   replicaCount: 1
>   fullnameOverride: "kafka-ui"
> 
>   existingConfigMap: ""
>   existingSecret: ""
>   envs:
>     secret:
>       PASSWORD: cGFzc3dvcmQ=
>     config:
>       KAFKA_CLUSTERS_0_NAME: test-msk
>       KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: b-1.my-msk.xxxxxx.c5.kafka.ap-southeast-1.amazonaws.com:9096
>       KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_SSL
>       KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: SCRAM-SHA-512
>       KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="mskadm" password="$(PASSWORD)";'
> ```
> 
> But when I specify my password in envs.config it works perfectly

@azatsafin any ideas?
> @mattia-crypto, @5hin0bi ,
> 
> I just follow the above answer but no luck
> 
> ```
> 22-05-20 11:21:24,265 WARN  [kafka-admin-client-thread | adminclient-3] o.a.k.c.a.i.AdminMetadataManager: [AdminClient clientId=adminclient-3] Metadata update failed due to authentication error
> org.apache.kafka.common.errors.SaslAuthenticationException: Authentication failed during authentication due to invalid credentials with SASL mechanism SCRAM-SHA-512
> ```
> 
> Can you guys help me check? What is wrong
> 
> ```
>   replicaCount: 1
>   fullnameOverride: "kafka-ui"
> 
>   existingConfigMap: ""
>   existingSecret: ""
>   envs:
>     secret:
>       PASSWORD: cGFzc3dvcmQ=
>     config:
>       KAFKA_CLUSTERS_0_NAME: test-msk
>       KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: b-1.my-msk.xxxxxx.c5.kafka.ap-southeast-1.amazonaws.com:9096
>       KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_SSL
>       KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: SCRAM-SHA-512
>       KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="mskadm" password="$(PASSWORD)";'
> ```
> 
> But when I specify my password in envs.config it works perfectly

@lllsJllsJ do you have any special characters in a password by any chance? if yes, please comment on #2116
was there ever a solution to this?
@SuitableProduce please follow #3142
Thank you!

I know that this issue is closed, but I am having an issue being able to reference environment variables in environment yamlApplicationConfig or envs config.

The configuration provided below does not work.  It throws a Java stack trace with `Caused by: java.lang.IllegalArgumentException: Login module control flag not specified in JAAS config` seeming to be the root cause. 
 Where the `user-auth-jaas` secret contains the JAAS config.  If I replace `$JAAS` with the contents of the secret it works fine.  Additionally if I shell into the pod `echo $JAAS` provides the expected value.

```yaml
existingSecret: "user-auth-jaas"
envs:
  secret: {}
  config:
    KAFKA_CLUSTERS_0_NAME: cluster
    KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka.confluent.svc.cluster.local:9071
    KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: SASL_PLAINTEXT
    KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM: PLAIN
    KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: "$JAAS"
```
@blacklobo Hey. Were you able to solve it? Have the same problem, passing the variable from the env variable seems not working.
@mattia-crypto Hey. Do you remember how you did that? Probably you still have it in your configuration.
Had the same problem but was able to work around it as follows:

Base64 encode your `sasl_jaas_config` or what ever config-value you want to set:
```sh
echo  'org.apache.kafka.common.security.scram.ScramLoginModule required username="<user>" password="<password>' | base64
```

Create a Kubernetes-Secret:
```yaml
apiVersion: v1
data:
 KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG: >-
    <base64-string>
kind: Secret
metadata:
  name: kafka-ui-sasl-config
  namespace: <namespace>
```

In your values.yaml reference the secret:
```yaml
existingSecret: "kafka-ui-sasl-config"
```
All values set in the Secret get set as env-vars in the container.

Helm-chart-version: `kafka-ui:0.7.5`

Pull request review comments:

Patch that resolved the issue:
diff --git a/charts/kafka-ui/templates/deployment.yaml b/charts/kafka-ui/templates/deployment.yaml
index 0f995b837d8..630d93c8329 100644
--- a/charts/kafka-ui/templates/deployment.yaml
+++ b/charts/kafka-ui/templates/deployment.yaml
@@ -29,6 +29,10 @@ spec:
       imagePullSecrets:
         {{- toYaml . | nindent 8 }}
       {{- end }}
+      {{- with .Values.initContainers }}
+      initContainers:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
       serviceAccountName: {{ include "kafka-ui.serviceAccountName" . }}
       securityContext:
         {{- toYaml .Values.podSecurityContext | nindent 8 }}
@@ -38,6 +42,10 @@ spec:
             {{- toYaml .Values.securityContext | nindent 12 }}
           image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
           imagePullPolicy: {{ .Values.image.pullPolicy }}
+          {{- with .Values.env }}
+          env:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
           envFrom:
             {{- if .Values.existingConfigMap }}
             - configMapRef:
@@ -73,6 +81,14 @@ spec:
             timeoutSeconds: 10
           resources:
             {{- toYaml .Values.resources | nindent 12 }}
+          {{- with .Values.volumeMounts }}
+          volumeMounts:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+      {{- with .Values.volumes }}
+      volumes:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
       {{- with .Values.nodeSelector }}
       nodeSelector:
         {{- toYaml . | nindent 8 }}
diff --git a/charts/kafka-ui/values.yaml b/charts/kafka-ui/values.yaml
index 43cbf869f6b..33dcfb0b300 100644
--- a/charts/kafka-ui/values.yaml
+++ b/charts/kafka-ui/values.yaml
@@ -117,3 +117,11 @@ nodeSelector: {}
 tolerations: []
 
 affinity: {}
+
+env: {}
+
+initContainers: {}
+
+volumeMounts: {}
+
+volumes: {}


Test patch: