DEV Community

Cover image for Setup a secure Apache NiFi cluster in Kubernetes

Setup a secure Apache NiFi cluster in Kubernetes

Jannik Rebmann on November 23, 2023

This article provides a detailed, step-by-step guide on setting up a secure Apache NiFi cluster with a NiFi Registry in Kubernetes, featuring the f...
Collapse
 
jrebmann profile image
Jannik Rebmann

Update

The restrictions for using Apache NiFi versions `>1.18.0´ (section 4.1) have been fixed:

This means that you can now also use the latest Apache NiFi versions.

Collapse
 
anmoln4 profile image
Anmol bansal

Hi Jannik Rebmann,

I am trying this configuration but i am facing some issue .
Using oidc nifi and nifi-registry redirect-uri is coming as below:

Nifi : https://:443/nifi-api/access/oidc/callback
Nifi-registry: http://:80/nifi-registry-api/access/oidc/callback

is there something i am missing. why nifi-registry oidc redirect uri is coming on http. but in logs it is running on https(18443).

Please help me out here.

Collapse
 
kamniphat01 profile image
kamniphat01

Hi @anmoln4

I had face this issue before you need add header x-proxyscheme: https and x-proxyport:443 in request-transformer for nifi to redirect https header instead of http

Name:         request-transformer
Namespace:    nifi-test
Labels:       <none>
Annotations:  kubernetes.io/ingress.class: xxxxx
API Version:  configuration.konghq.com/v1
Config:
  Add:
    Headers:
      X-ProxyScheme:https
      X-ProxyPort:443
Enter fullscreen mode Exit fullscreen mode

Hope its help you.

Collapse
 
jrebmann profile image
Jannik Rebmann

Hi @anmoln4

I think I need more information about your OIDC configuration.

The Callback URL must be set with your OIDC provider. This is the URL that sends back the OIDC authentication response to your NIFI service.

So maybe you have set http://:80/nifi-registry-api/access/oidc/callback as Callback URL on your OIDC server?

Collapse
 
kamniphat01 profile image
kamniphat01

Hi @jrebmann ,

I am following your configuration to enabled CertManager, but i am hitting some issue on unable to locate initial admin. Could you possible to share an example for authorizers.xml ?

Error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorizer': FactoryBean threw exception on object creation; nested exception is org.apache.nifi.authorization.exception.AuthorizerCreationException: org.apache.nifi.authorization.exception.AuthorizerCreationException: Unable to locate initial admin JoseAce@xxxx.com to seed policies

authorizers.xml

   {{- if .Values.auth.oidc.enabled}}
    <userGroupProvider>
        <identifier>file-user-group-provider</identifier>
        <class>org.apache.nifi.authorization.FileUserGroupProvider</class>
        <property name="Users File">./auth-conf/users.xml</property>
    </userGroupProvider>

    <userGroupProvider>
        <identifier>aad-user-group-provider</identifier>
        <class>org.apache.nifi.authorization.azure.AzureGraphUserGroupProvider</class>
        <property name="Refresh Delay">1 mins</property>
        <property name="Authority Endpoint">https://login.microsoftonline.com</property>
        <property name="Directory ID">{{.Values.auth.oidc.tenantId}}</property>
        <property name="Application ID">{{.Values.auth.oidc.clientId}}</property>
        <property name="Client Secret">{{.Values.auth.oidc.clientSecret}}</property>
        <property name="Group Filter Prefix">{{.Values.auth.oidc.groupPrefix}}</property>
        <property name="Page Size">100</property>
    </userGroupProvider>

    <userGroupProvider>
        <identifier>composite-configurable-user-group-provider</identifier>
        <class>org.apache.nifi.authorization.CompositeConfigurableUserGroupProvider</class>
        <property name="Configurable User Group Provider">file-user-group-provider</property>
        <property name="User Group Provider 1">aad-user-group-provider</property>
    </userGroupProvider>

    <accessPolicyProvider>
        <identifier>file-access-policy-provider</identifier>
        <class>org.apache.nifi.authorization.FileAccessPolicyProvider</class>
        <property name="User Group Provider">composite-configurable-user-group-provider</property>
        <property name="Authorizations File">./conf/authorizations.xml</property>
        <property name="Initial Admin Identity">{{.Values.auth.oidc.admin}}</property>
        <property name="Legacy Authorized Users File"></property>
        <property name="Node Identity 1"></property>
    </accessPolicyProvider>

    <authorizer>
        <identifier>managed-authorizer</identifier>
        <class>org.apache.nifi.authorization.StandardManagedAuthorizer</class>
        <property name="Access Policy Provider">file-access-policy-provider</property>
    </authorizer>
    {{- end}}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jrebmann profile image
Jannik Rebmann

Hi @kamniphat01,

thanks for your question.
I have never experienced this error.
Please make sure you also have the mail joseace@xxxx.com set in the security and oidc sections.

security:
  ...
  admin: <registered_email>
  ...
oidc:
  ...
  admin: <registered_email>
  ...
Enter fullscreen mode Exit fullscreen mode
Collapse
 
kamniphat01 profile image
kamniphat01

hi @jrebmann ,

Thanks for the article on how to setup a secure nifi cluster. Now i was able to successfully deploy nifi cluster with oidc method. Appreciate it

Thread Thread
 
jrebmann profile image
Jannik Rebmann

@kamniphat01 You're welcome! Thank you for reading. I hope you will like Apache NiFi ... it has solved so many problems for me.

Collapse
 
heni_nechi profile image
Heni Nechi • Edited

am deploying nifi and nifi-registry on aks and everything is working but the integration with git.
I try almost everything
change persistance from true to false, tried username and password auth.
this code is part of the values.yaml of nifi.

registry:
  ## If true, install the Nifi registry
  enabled: true
  url: ""
  port: 80
  # Default values for nifi-registry.
  # This is a YAML-formatted file.
  # Declare variables to be passed into your templates.

  replicaCount: 1

  image:
    repository: apache/nifi-registry
    pullPolicy: Always
    tag: "0.8.0"

  initContainers:
  git:
    image: alpine/git
    tag: v2.26.2
  # alpine:
  #   image: alpine
  #   tag: "3.6"
  # Additional environment variables to set for the initContainers
  extraEnvs: []
  # extraEnvs:
  #   - name: FOO
  #     value: bar

  service:
    type: LoadBalancer
    httpsport: 18080

  ingress:
    enabled: false
    annotations: {}
      # kubernetes.io/ingress.class: nginx
      # kubernetes.io/tls-acme: "true"
    hosts:
      - host: chart-example.local
        paths: []
    tls: []
    #  - secretName: chart-example-tls
    #    hosts:
    #      - chart-example.local

  ## Persist data to a persistent volume
  persistence:
    enabled: false
    database:
      # storageClass: "-"
      accessMode: ReadWriteOnce
      size: 1Gi
    flowStorage:
      # storageClass: "-"
      accessMode: ReadWriteOnce
      size: 1Gi

  resources: {}
    # We usually recommend not to specify default resources and to leave this as a conscious
    # choice for the user. This also increases chances charts run on environments with little
    # resources, such as Minikube. If you do want to specify resources, uncomment the following
    # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
    # limits:
    #   cpu: 100m
    #   memory: 128Mi
    # requests:
    #   cpu: 100m
    #   memory: 128Mi


  bundleProvider:
    file:
      enabled: true
      # -- the path in the running pod where the git repo will be cloned into
      # either absolute or relative to the container working directory, which is NIFI_REGISTRY_HOME
      # If you elect to use a non-default location, you must also update the property associated.
      storageDirectory: ./extension_bundles

  flowProvider:
    git:
      enabled: true
      # Repository to be cloned at pod startup
      url: 'git@github.com:N****ni/***.git'
      # Sets NIFI_REGISTRY_GIT_REMOTE for update_flow_provider.sh
      remote: 'origin'
      # Sets NIFI_REGISTRY_GIT_USER for update_flow_provider.sh
      user: 
      # Sets NIFI_REGISTRY_GIT_PASSWORD for update_flow_provider.sh
      password:
      # passwordSecret(Name|Key) is the name and key of the k8s secret holding the password (can be used instead of password)
      # passwordSecretName:
      # passwordSecretKey:
      # Global Git configuration See https://git-scm.com/docs/git-config for more details.
      config:
        enabled: false
        data: ""
        # data: |
        #   [credential "https://github.com"]
        #           username = foo
      ssh:
        # To use an SSH public/private keypair as a Kubernetes secret:
        # 1. Generate a SSH key named id_rsa:
        #      ssh-keygen -q -N "" -f ./id_rsa
        # 2. Create a Kubernetes secret:
        #      kubectl -n nifi-registry create secret generic nifi-registry-git-ssh --from-file=./id_rsa
        # 3. Don't check these key files into your Git repository! Once you've created
        #    the Kubernetes secret, Delete the private key:
        #      rm ./id_rsa
        # 4. Add ./id_rsa.pub as a deployment key with write access in your Git repo
        # 5. Set the secret name (e.g., nifi-registry-git-ssh) here:
        secretName: 'nifi-registry-git-ssh'
        # 6. Provide the public key(s) of the SSH server(s) for $HOME/.ssh/known_hosts
        knownHosts: |
         github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
        # 7. Set the GIT_SSH_COMMAND
        gitSshCommand: "ssh -v"
        # 8. specify the config which would go in $HOME/.ssh/config file, for e.g.
        # config: |
        #   Host github.com
        #   ProxyCommand socat STDIO PROXY:<proxyIP>:%h:%p,proxyport=<proxyPort>,proxyauth=<username:password>
        #   User git
        #   Hostname ssh.github.com
        #   Port 443
        #   IdentityFile /etc/fluxd/ssh/identity
        # or, if using an SSH public/private keypair:
        config: |
          StrictHostKeyChecking accept-new
    postgres:
      enabled: false
      driverURL: https://jdbc.postgresql.org/download/
      fileName: postgresql-42.2.6.jar
      driverClass: org.postgresql.Driver
      url: jdbc:postgresql://localhost/nifireg
      username: nifireg
      password: nifireg
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jrebmann profile image
Jannik Rebmann • Edited

Hi @heni_nechi,

first of all, I would recommend that you use at least version 1.18.0 of the Apache NIfi Registry. I had a similar problem with the Git integration. I finally solved the problem by using a ssh key.

registry:
   image:
     tag: 1.18.0
   enabled: true
   fullnameOverride: nifi-reg
   persistence:
     enabled: true
   flowProvider:
     git:
       enabled: true
       url: git@gitlab.com:group/repositry.git
       remote: origin
       user: nifi-registry-provider
       password: notUsed
       ssh:
         secretName: nifi-registry-ssh-secret
Enter fullscreen mode Exit fullscreen mode

The corresponding secret looks like following:

apiVersion: v1
kind: Secret
metadata:
 name: nifi-registry-ssh-secret
data:
 id_rsa: "<sshkeyasbase64>"
Enter fullscreen mode Exit fullscreen mode

I hope this helps you.

Collapse
 
heni_nechi profile image
Heni Nechi

Hello @jrebmann
Thanks for your quick response I tried using the integration with ssh key before, I'll give it a shot again with the code provided and I'll get back to you with a reply.

Thread Thread
 
heni_nechi profile image
Heni Nechi

Hey again @jrebmann
as I already told I have tried using the ssh key before and it didn't work same as now.
I really don't know what am doing worng, the secret is being set right by checking the logs it's always defaulting to FileSystemFlowPersistenceProvider and the providers.xml is not being configured :

<providers>

    <!-- NOTE: The providers in this file must be listed in the order defined in providers.xsd which is the following:
            1) Flow Persistence Provider (Must occur once and only once)
            2) Event Hook Providers (May occur 0 or more times)
            3) Bundle Persistence Provider (Must occur once and only once)
     -->

    <flowPersistenceProvider>
        <class>org.apache.nifi.registry.provider.flow.FileSystemFlowPersistenceProvider</class>
        <property name="Flow Storage Directory">./flow_storage</property>
    </flowPersistenceProvider>

    <!--
    <flowPersistenceProvider>
        <class>org.apache.nifi.registry.provider.flow.git.GitFlowPersistenceProvider</class>
        <property name="Flow Storage Directory">./flow_storage</property>
        <property name="Remote To Push"></property>
        <property name="Remote Access User"></property>
        <property name="Remote Access Password"></property>
        <property name="Remote Clone Repository"></property>
    </flowPersistenceProvider>
    -->

    <!--
    <flowPersistenceProvider>
        <class>org.apache.nifi.registry.provider.flow.DatabaseFlowPersistenceProvider</class>
    </flowPersistenceProvider>
    -->

    <!--
    <eventHookProvider>
        <class>org.apache.nifi.registry.provider.hook.ScriptEventHookProvider</class>
        <property name="Script Path"></property>
        <property name="Working Directory"></property>
        -->
        <!-- Optional Whitelist Event types
        <property name="Whitelisted Event Type 1">CREATE_FLOW</property>
        <property name="Whitelisted Event Type 2">DELETE_FLOW</property>
        -->
    <!--
    </eventHookProvider>
    -->

    <!-- This will log all events to a separate file specified by the EVENT_APPENDER in logback.xml -->
    <!--
    <eventHookProvider>
        <class>org.apache.nifi.registry.provider.hook.LoggingEventHookProvider</class>
    </eventHookProvider>
    -->

    <extensionBundlePersistenceProvider>
        <class>org.apache.nifi.registry.provider.extension.FileSystemBundlePersistenceProvider</class>
        <property name="Extension Bundle Storage Directory">./extension_bundles</property>
    </extensionBundlePersistenceProvider>

    <!-- Example S3 Bundle Persistence Provider
            - Requires nifi-registry-aws-assembly to be added to the classpath via a custom extension dir in nifi-registry.properties
                Example: nifi.registry.extension.dir.aws=./ext/aws/lib
                Where "./ext/aws/lib" contains the extracted contents of nifi-registry-aws-assembly
            - "Region" - The name of the S3 region where the bucket exists
            - "Bucket Name" - The name of an existing bucket to store extension bundles
            - "Key Prefix" - An optional prefix that if specified will be added to the beginning of all S3 keys
            - "Credentials Provider" - Indicates how credentials will be provided, must be a value of DEFAULT_CHAIN or STATIC
                - DEFAULT_CHAIN will consider in order: Java system properties, environment variables, credential profiles (~/.aws/credentials)
                - STATIC requires that "Access Key" and "Secret Access Key" be specified directly in this file
            - "Access Key" - The access key to use when using STATIC credentials provider
            - "Secret Access Key" - The secret access key to use when using STATIC credentials provider
            - "Endpoint URL" - An optional URL that overrides the default AWS S3 endpoint URL.
                 Set this when using an AWS S3 API compatible service hosted at a different URL.
     -->
    <!--
    <extensionBundlePersistenceProvider>
        <class>org.apache.nifi.registry.aws.S3BundlePersistenceProvider</class>
        <property name="Region">us-east-1</property>
        <property name="Bucket Name">my-bundles</property>
        <property name="Key Prefix"></property>
        <property name="Credentials Provider">DEFAULT_CHAIN</property>
        <property name="Access Key"></property>
        <property name="Secret Access Key"></property>
        <property name="Endpoint URL"></property>
    </extensionBundlePersistenceProvider>
    -->

Enter fullscreen mode Exit fullscreen mode
registry:
   image:
     tag: 1.18.0
   enabled: true
   fullnameOverride: nifi-reg
   initContainers:
   git:
    image: alpine/git
    tag: v2.26.2
   alpine:
    image: alpine
    tag: "3.6"
   service:
    type: LoadBalancer
    httpsport: 18080
   persistence:
     enabled: true
   flowProvider:
     git:
       enabled: true
       url: git@github.com:NechiHeni/flow.git
       remote: origin
       user: NechiHeni
       password: 
       ssh:
         secretName: nifi-registry-ssh-secret
Enter fullscreen mode Exit fullscreen mode