Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature to use commercial certs that are created and signed externally. #447

Open
aoinc13 opened this issue Aug 5, 2024 · 3 comments
Labels
community enhancement New feature or request

Comments

@aoinc13
Copy link
Contributor

aoinc13 commented Aug 5, 2024

Is your feature request related to a problem?

The object listenersConfig.sslSecrets.tlsSecretName is used to create and sign certs as needed. But there is no provision to bypass automated cert creation and configure pre-created certs.

Describe the solution you'd like to see

We would like the operator to use and configure pre-created, signed certs. For example, if you have a wildcard cert from Verisign and you want Nifi to use it. We aren't interested in using self-signed certs or Cert Manager Issuers to create new certs. We would like to plug in an existing cert.

Describe alternatives you've considered

We could create a secret that contains the pre-created cert, mount it in Nifi, and override Nifi properties to point to the mounted pre-created cert. This solution should be documented if adopted. If would be nice if the operator did this for us.

Additional context

No response

@aoinc13 aoinc13 added community enhancement New feature or request labels Aug 5, 2024
@juldrixx
Copy link
Contributor

juldrixx commented Aug 5, 2024

Hello, you can inject your cerficate in NiFi TrustStore using the initContainers and overring Bootstrap configuration to ask the JVM to use it instead of the default one. You can doing it with something like that:

  initContainers:
{{- if and .Values.nifiCluster.rootca.configmap.name .Values.nifiCluster.rootca.configmap.key }}
    - command:
      - sh
      - -c
      - |
        echo "$ROOT_CA_CERT" > /opt/nifi/nifi-current/conf/rootca.crt && \
        cp -f ${JAVA_HOME}/lib/security/cacerts /opt/nifi/nifi-current/conf/cacerts_updated.jks && \
        keytool -import -alias rootca -file /opt/nifi/nifi-current/conf/rootca.crt -storetype jks -keystore /opt/nifi/nifi-current/conf/cacerts_updated.jks -noprompt -storepass changeit
      image: {{ .Values.nifiCluster.image }}
      name: import-ca
      volumeMounts:
        - mountPath: /opt/nifi/nifi-current/conf
          name: conf
      env:
        - name: ROOT_CA_CERT
          valueFrom:
            configMapKeyRef:
              name: {{ .Values.nifiCluster.rootca.configmap.name }}
              key: {{ .Values.nifiCluster.rootca.configmap.key }}
...
    bootstrapProperties:
      overrideConfigs: |
        {{- if and .Values.nifiCluster.rootca.configmap.name .Values.nifiCluster.rootca.configmap.key }}
        java.arg.truststore=-Djavax.net.ssl.trustStore=/opt/nifi/nifi-current/conf/cacerts_updated.jks
        {{- end }}

Or you can just mount your certificates as volume to the main container and use a StandardSSLContextService.

You can mount a ConfigMap or a Secret, both ways work.

@lfreinag
Copy link

lfreinag commented Sep 6, 2024

Thanks for this posting this solution here. It did not work for me and I might be missing some experience and/or background.

Here are the challenges I encountered:

  1. I am missing how you declare the volume conf as I could not mount an emptyDir.
  2. The bootstrapProperties were correctly ingested but I could not read the new file. Possible solution: I think you need to restart all the nodes at the same time, otherwise the cluster will fail to connect. (I tried this later on with my solution).
  3. How do you mount the conf volume later on?

I share here what was my solution in case it can help others.

I added a job and a PVC to ingest the certificate authority. Then mounted that on top of the actual cacerts file. (I am aware that this might not be the best practice).

The job definition:

+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: ca-installer
+  namespace: nifi-cluster
+spec:
+  completions: 1
+  template:
+    spec:
+      containers:
+        - name: ca-installer
+          image: docker.io/library/bash:5
+          args:
+            - sh
+            - -c
+            - exit 0;
+          volumeMounts:
+            - name: shared-ca-file
+              mountPath: /artifact
+      initContainers:
+        - name: install-custom-ca
+          image: apache/nifi:1.25.0
+          command:
+            - sh
+            - -c
+            - |
+              echo "$ROOT_CA_CERT" > /opt/nifi/nifi-current/conf/rootca.crt && \
+              cp -fv ${JAVA_HOME}/lib/security/cacerts /opt/nifi/nifi-current/conf/ && \
+              keytool -import -alias rootca -file /opt/nifi/nifi-current/conf/rootca.crt -storetype jks -keystore /opt/nifi/nifi-current/conf/cacerts -noprompt -storepass changeit
+          volumeMounts:
+            - mountPath: /opt/nifi/nifi-current/conf
+              name: shared-ca-file
+          env:
+            - name: ROOT_CA_CERT
+              valueFrom:
+                configMapKeyRef:
+                  name: custom-ca-config
+                  key: custom-ca.pem
+      restartPolicy: Never
+      volumes:
+        - name: shared-ca-file
+          persistentVolumeClaim:
+            claimName: custom-ca-files
+        - name: custom-ca-config
+          configMap:
+            name: custom-ca-config
+  backoffLimit: 0

The PVC definition (example):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: custom-ca-files
  namespace: nifi-cluster
spec:
  storageClassName: "your-class-name"
  resources:
    requests:
      storage: 1Mi
    limits:
      storage: 2Mi
  accessModes:
    - ReadWriteMany

On the values.yaml files you will need to mount the volume like this:

externalVolumeConfigs:
+          - name: shared-custom-ca
+            mountPath: "/opt/java/openjdk/lib/security/cacerts"
+            subPath: cacerts
+            persistentVolumeClaim:
+              claimName: custom-ca-files

And of course you should have a configMap with your ca data (example):

apiVersion: v1
kind: ConfigMap
metadata:
  name: custom-ca-config
  namespace: nifi-cluster
data:
  custom-ca.pem: |
    -----BEGIN CERTIFICATE-----
    <Your cert info here>
    -----END CERTIFICATE-----

@juldrixx
Copy link
Contributor

juldrixx commented Sep 6, 2024

You can create the conf volume like that in NifiCluster resource.

...
nodeConfigGroups:
  default_group:
   ...
    storageConfigs:
      - mountPath: /opt/nifi/nifi-current/conf
        name: conf
        reclaimPolicy: Delete
        metadata:
          labels:
            my-label: my-value
          annotations:
            my-annotation: my-value
        pvcSpec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 5Gi
          storageClassName: ssd-wait

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants