Configuring Ranger authorization for NiFi

Delegate NiFi authorization to Apache Ranger so Cloudera Flow Management Operator for Kubernetes renders Ranger authorizer configuration instead of file-based access policies.

By default, NiFi manages access policies in a local authorizations.xml file through FileAccessPolicyProvider backed by StandardManagedAuthorizer. Cloudera Flow Management Operator for Kubernetes drives that model through its User and UserGroup controllers, which call the NiFi REST API to keep policy assignments in sync with the desired state declared in Kubernetes. If you run Cloudera on cloud, Cloudera on premises, or any deployment where Apache Ranger is the central policy engine, that file-based model is redundant and conflicts with Ranger.

When the ranger field is set on a Nifi resource's spec.security, Cloudera Flow Management Operator for Kubernetes switches to a fully Ranger-delegated authorization mode:

  • authorizers.xml is rendered with RangerNiFiAuthorizer instead of FileAccessPolicyProvider and StandardManagedAuthorizer.
  • nifi.properties sets nifi.security.user.authorizer=ranger-nifi-authorizer.
  • Two XML configuration files consumed by the Ranger NiFi plugin, ranger-nifi-security.xml and ranger-nifi-audit.xml, are generated and mounted into the NiFi pods at /opt/nifi/nifi-current/conf/.
  • The User and UserGroup controllers still create NiFi tenants (users and groups) so that Ranger-issued identities are recognized by NiFi, but they skip access policy management entirely.

Interaction with other security fields

Ranger authorization is separate from authentication and cannot be combined with a custom authorizer configuration.

spec.security.ranger is an authorizer configuration and is orthogonal to authentication configuration. You can combine it with any authentication method (Kerberos, LDAP, OIDC, SAML, certificate-based, or single user). The authorizer determines what an authenticated user may do; the authenticator determines who the user is.

Ranger authorization specification

The ranger block on a Nifi custom resource defines how the Ranger NiFi plugin connects to Ranger Admin and optional audit and TLS settings.

spec:
  security:
    ranger:
      serviceName: <string>           # required
      adminURL: <string>              # required
      adminIdentity: <string>         # required
      policyPollIntervalMs: <int>     # optional, default 30000
      audit:                          # optional
        solr:
          url: <string>               # optional
          zookeepersURL: <string>     # optional
          async: <bool>               # optional, default true
          maxQueueSize: <int>         # optional, default 10240
          maxFlushIntervalMs: <int>   # optional, default 30000
      tls:                            # optional
        secretName: <string>
      configSecretName: <string>      # optional escape hatch

This is a reference for each field under the Ranger authorization specification, including the Ranger plugin XML properties the operator generates from each value:

serviceName (string, required)

Specifies the name of the NiFi service as registered in Ranger Admin's service repository. Ranger uses this name to look up the applicable policies when a request arrives. It must exactly match the service name shown on the Ranger Admin Service Manager page under the NiFi service type.

Stored in ranger-nifi-security.xml as ranger.plugin.nifi.service.name.

Example: nifi-production

adminURL (string, required)

Specifies the base REST API URL of the Ranger Admin server. The Ranger NiFi plugin contacts this endpoint to download the policy set on startup and on each poll cycle. The URL must be reachable from inside the NiFi pods; include the port and scheme.

Stored in ranger-nifi-security.xml as ranger.plugin.nifi.policy.rest.url.

The plugin always uses the RangerAdminRESTClient implementation (ranger.plugin.nifi.policy.source.impl); that value is hardcoded by the operator and does not need to be set by you.

Example: https://ranger-admin.example.com:6182

adminIdentity (string, required)

Specifies the TLS distinguished name (DN) of the Ranger Admin server's certificate. NiFi's security model identifies all principals — including services — by their certificate DN. NiFi must recognize the Ranger Admin identity in order to trust policy download responses signed by that server.

This value is written into authorizers.xml as the Ranger Admin Identity property on the RangerNiFiAuthorizer block.

See the Authorizers.xml Setup in NiFi Administration Guide.

Example: CN=ranger-admin.example.com, OU=Security, O=Acme, L=San Jose, ST=CA, C=US

policyPollIntervalMs (integer, optional, default 30000)

Controls how frequently (in milliseconds) the Ranger NiFi plugin polls Ranger Admin for policy updates. Lower values reduce the lag between a policy change in Ranger and its effect in NiFi at the cost of more frequent HTTP calls to Ranger Admin. The default of 30 000 ms (30 seconds) is the Ranger plugin default and is appropriate for most deployments.

A local policy cache is written to /tmp/ranger-nifi-security-cache and is used as a fallback if Ranger Admin is temporarily unreachable.

Stored in ranger-nifi-security.xml as ranger.plugin.nifi.policy.pollIntervalMs.

Example: 15000 (poll every 15 seconds)

audit (object, optional)

Configures where the Ranger NiFi plugin writes access audit events. Audit records capture every authorization decision — allowed or denied — including the user identity, resource path, and action. When this section is omitted, Solr auditing is disabled (xasecure.audit.solr.enable=false).

Currently the only supported destination is Apache Solr.

audit.solr (object, optional)

Configures Apache Solr as the audit event destination.

Ranger's audit framework uses the xasecure.audit.* property namespace, inherited from the original XASecure project that became Ranger. For the full Solr audit configuration reference, see the Apache Ranger quick start guide.

audit.solr.url (string, optional)

Specifies a direct HTTP or HTTPS URL pointing to the Solr collection that receives audit events. This is the simplest connectivity option when Solr is accessible at a known stable address.

Stored in ranger-nifi-audit.xml as xasecure.audit.solr.url.

Mutually exclusive with zookeepersURL: set one or the other, not both.

Example: http://solr.example.com:6083/solr/ranger_audits

audit.solr.zookeepersURL (string, optional)

Specifies a ZooKeeper connection string used for Solr service discovery. When the Solr cluster uses SolrCloud mode with ZooKeeper-based routing, this is the preferred option because it accommodates Solr node additions and removals without reconfiguring NiFi.

Stored in ranger-nifi-audit.xml as xasecure.audit.solr.zookeepers.

Example: zk1.example.com:2181,zk2.example.com:2181/solr

audit.solr.async (bool, optional, default true)

When true, audit events are written to an in-memory queue and flushed to Solr in batches. Asynchronous mode prevents a slow or temporarily unavailable Solr from adding latency to NiFi request processing. When false, each audit write blocks until Solr acknowledges receipt, providing stronger durability guarantees at the cost of throughput.

Stored in ranger-nifi-audit.xml as xasecure.audit.solr.async.

audit.solr.maxQueueSize (integer, optional, default 10240)

Specifies the maximum number of audit events held in the asynchronous buffer before the oldest events are dropped to make room for new ones. Applies only when async is true. Increase this value if audit events are being dropped during bursty authorization activity (for example, large batch jobs that touch many NiFi resources rapidly).

Stored in ranger-nifi-audit.xml as xasecure.audit.solr.async.max.queue.size.

audit.solr.maxFlushIntervalMs (integer, optional, default 30000)

Specifies the maximum time in milliseconds between forced flushes of the asynchronous audit queue to Solr. Even if the queue has not reached maxQueueSize, a flush is triggered once this interval elapses. Lower values reduce audit event lag at the cost of more frequent Solr writes. Applies only when async is true.

Stored in ranger-nifi-audit.xml as xasecure.audit.solr.async.max.flush.interval.ms.

tls (object, optional)

Configures mutual TLS (mTLS) between the Ranger NiFi plugin running inside NiFi pods and the Ranger Admin server. When the Ranger Admin endpoint is TLS-protected — which is strongly recommended in production — both a keystore (client certificate for NiFi to authenticate to Ranger Admin) and a truststore (CA certificate to verify Ranger Admin's server certificate) are typically required.

If this section is omitted entirely, the plugin will use Java's default truststore and will not present a client certificate. This is acceptable when Ranger Admin is configured to not require mutual TLS and uses a publicly trusted certificate, but is not recommended for production environments.

The underlying XML property namespace is xasecure.policymgr.clientssl.*.

tls.secretName (string, optional)

Specifies the name of a Kubernetes Secret in the same namespace that contains the keystore and truststore NiFi uses to authenticate itself to Ranger Admin. The operator expects the Secret to contain the following keys:

Secret key Description
keystore.jks The JKS-format keystore file (binary)
keystore.password The plaintext password for the keystore
truststore.jks The JKS-format truststore file (binary)
truststore.password The plaintext password for the truststore

The keystore file is mounted read-only at /home/nifi/ranger-tls-keystore/keystore.jks inside the NiFi container. The password is injected at runtime; it does not appear in ranger-nifi-security.xml in cleartext — the placeholder ?RANGER_KEYSTORE_PASSWORD? is replaced by the plugin's credential provider mechanism.

Stored in ranger-nifi-security.xml as xasecure.policymgr.clientssl.keystore.

The truststore file is mounted read-only at /home/nifi/ranger-tls-truststore/truststore.jks.

Stored in ranger-nifi-security.xml as xasecure.policymgr.clientssl.truststore.

configSecretName (string, optional)

Provides an escape hatch for advanced Ranger configurations not expressible through the structured fields above. When set, the operator skips generating ranger-nifi-security.xml and ranger-nifi-audit.xml entirely and instead mounts the files from this Kubernetes Secret.

The Secret must be in the same namespace as the Nifi resource and must contain one or both of the following keys:

Secret key Mount path
ranger-nifi-security.xml /opt/nifi/nifi-current/conf/ranger-nifi-security.xml
ranger-nifi-audit.xml /opt/nifi/nifi-current/conf/ranger-nifi-audit.xml

Use cases include:

  • Properties not yet modeled in the operator schema (for example, Kafka or HDFS audit destinations).
  • Ranger plugin versions with non-standard property names.
  • Environments requiring credential provider integration (jceks:// URIs for passwords).

When configSecretName is set, all structured fields under audit and tls are still validated by the API server but their values are not used, the Secret contents take complete precedence.

Behavior under Ranger mode

When Ranger authorization is enabled, User and UserGroup resources still sync NiFi tenants but skip access policy management, and authorizer selection follows a fixed precedence.

User and UserGroup controllers

When ranger is configured, User and UserGroup resources still create and update NiFi tenant identities (users and groups) via the NiFi REST API. This is necessary so that NiFi can resolve identity strings returned from Ranger policy checks to internal user objects.

However, the controllers skip all access policy operations — they do not call CreateAccessPolicy, UpdateAccessPolicy, or add users to policy resource entries. The accessPolicies and accessPolicyProfileRef fields on User and UserGroup resources are accepted by the API server but have no effect when Ranger is enabled. Policy management is Ranger's responsibility.

For more information, see Configuring a user identity with access policies and Configuring user groups.

Authorizer selection

The nifi.security.user.authorizer property in nifi.properties is set based on the following precedence:

  1. single-user-authorizer — when Single User Auth is enabled.
  2. ranger-nifi-authorizer — when spec.security.ranger is set.
  3. managed-authorizer — the default file-based authorizer.

Consider the following three configuration scenarios:

  1. security.singleUserAuth and security.ranger
  2. security.ldap and security.ranger
  3. security.ldap

For case 1, single user authentication configures NiFi to ignore all authorizations because there is only the single super user.

For case 2, user authentication is handled by LDAP and authorization is handled by Ranger.

For case 3, user authentication is handled by LDAP and authorization is handled by managed-authorizer (file-based access policies).

Ranger authorization examples

Example Nifi custom resource configurations for Ranger authorization, from minimal setups to production deployments with mTLS, Solr audit, and custom XML overrides.

Minimal configuration (no TLS, no audit)

apiVersion: cfm.cloudera.com/v1alpha1
kind: Nifi
metadata:
  name: nifi-prod
  namespace: nifi
spec:
  security:
    ranger:
      serviceName: nifi-prod
      adminURL: https://ranger-admin.example.com:6182
      adminIdentity: "CN=ranger-admin.example.com, OU=Security, O=Acme, L=San Jose, ST=CA, C=US"

Production configuration (mTLS + Solr audit)

apiVersion: cfm.cloudera.com/v1alpha1
kind: Nifi
metadata:
  name: nifi-prod
  namespace: nifi
spec:
  security:
    ranger:
      serviceName: nifi-prod
      adminURL: https://ranger-admin.example.com:6182
      adminIdentity: "CN=ranger-admin.example.com, OU=Security, O=Acme, L=San Jose, ST=CA, C=US"
      policyPollIntervalMs: 15000
      audit:
        solr:
          url: http://solr.example.com:6083/solr/ranger_audits
          async: true
          maxQueueSize: 20480
          maxFlushIntervalMs: 10000
      tls:
        secretName: nifi-ranger-tls

ZooKeeper-based Solr discovery

spec:
  security:
    ranger:
      serviceName: nifi-prod
      adminURL: https://ranger-admin.example.com:6182
      adminIdentity: "CN=ranger-admin.example.com, OU=Security, O=Acme, L=San Jose, ST=CA, C=US"
      audit:
        solr:
          zookeepersURL: "zk1.example.com:2181,zk2.example.com:2181/solr"

Override with custom XML (escape hatch)

spec:
  security:
    ranger:
      serviceName: nifi-prod
      adminURL: https://ranger-admin.example.com:6182
      adminIdentity: "CN=ranger-admin.example.com, OU=Security, O=Acme, L=San Jose, ST=CA, C=US"
      configSecretName: nifi-ranger-custom-config
apiVersion: v1
kind: Secret
metadata:
  name: nifi-ranger-custom-config
  namespace: nifi
stringData:
  ranger-nifi-security.xml: |
    <?xml version="1.0"?>
    <configuration>
      <property>
        <name>ranger.plugin.nifi.service.name</name>
        <value>nifi-prod</value>
      </property>
      <property>
        <name>ranger.plugin.nifi.policy.source.impl</name>
        <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
      </property>
      <property>
        <name>ranger.plugin.nifi.policy.rest.url</name>
        <value>https://ranger-admin.example.com:6182</value>
      </property>
      <property>
        <name>ranger.plugin.nifi.policy.pollIntervalMs</name>
        <value>30000</value>
      </property>
      <property>
        <name>ranger.plugin.nifi.policy.cache.dir</name>
        <value>/tmp/ranger-nifi-security-cache</value>
      </property>
      <property>
        <name>xasecure.policymgr.clientssl.keystore</name>
        <value>/home/nifi/ranger-tls-keystore/keystore.jks</value>
      </property>
      <property>
        <name>xasecure.policymgr.clientssl.keystore.credential.file</name>
        <value>jceks://file/home/nifi/ranger-tls-keystore/keystore-credential.jceks</value>
      </property>
      <property>
        <name>xasecure.policymgr.clientssl.truststore</name>
        <value>/home/nifi/ranger-tls-truststore/truststore.jks</value>
      </property>
      <property>
        <name>xasecure.policymgr.clientssl.truststore.credential.file</name>
        <value>jceks://file/home/nifi/ranger-tls-truststore/truststore-credential.jceks</value>
      </property>
    </configuration>
  ranger-nifi-audit.xml: |
    <?xml version="1.0"?>
    <configuration>
      <property>
        <name>xasecure.audit.solr.enable</name>
        <value>true</value>
      </property>
      <property>
        <name>xasecure.audit.solr.async</name>
        <value>true</value>
      </property>
      <property>
        <name>xasecure.audit.solr.url</name>
        <value>http://solr.example.com:6083/solr/ranger_audits</value>
      </property>
      <property>
        <name>xasecure.audit.solr.async.max.queue.size</name>
        <value>10240</value>
      </property>
      <property>
        <name>xasecure.audit.solr.async.max.flush.interval.ms</name>
        <value>30000</value>
      </property>
    </configuration>

Generated Ranger XML files

When you do not set a config secret, Cloudera Flow Management Operator for Kubernetes generates the Ranger security and audit XML files from the structured spec fields.

When configSecretName is not set, the operator generates the two XML configuration files from the structured spec fields. The following examples show what the operator produces for a production configuration.

ranger-nifi-security.xml (generated)

<?xml version="1.0"?>
<configuration>
  <!-- Service identity and policy source -->
  <property>
    <name>ranger.plugin.nifi.service.name</name>
    <value>nifi-prod</value>
  </property>
  <property>
    <name>ranger.plugin.nifi.policy.source.impl</name>
    <value>org.apache.ranger.admin.client.RangerAdminRESTClient</value>
  </property>
  <property>
    <name>ranger.plugin.nifi.policy.rest.url</name>
    <value>https://ranger-admin.example.com:6182</value>
  </property>
  <property>
    <name>ranger.plugin.nifi.policy.pollIntervalMs</name>
    <value>15000</value>
  </property>

  <!-- Local policy cache used as fallback when Ranger Admin is unreachable -->
  <property>
    <name>ranger.plugin.nifi.policy.cache.dir</name>
    <value>/tmp/ranger-nifi-security-cache</value>
  </property>

  <!-- mTLS: keystore (present when tls.secretName is set) -->
  <property>
    <name>xasecure.policymgr.clientssl.keystore</name>
    <value>/home/nifi/ranger-tls-keystore/keystore.jks</value>
  </property>
  <property>
    <name>xasecure.policymgr.clientssl.keystore.password</name>
    <value>?RANGER_KEYSTORE_PASSWORD?</value>
  </property>

  <!-- mTLS: truststore (present when tls.secretName is set) -->
  <property>
    <name>xasecure.policymgr.clientssl.truststore</name>
    <value>/home/nifi/ranger-tls-truststore/truststore.jks</value>
  </property>
  <property>
    <name>xasecure.policymgr.clientssl.truststore.password</name>
    <value>?RANGER_TRUSTSTORE_PASSWORD?</value>
  </property>
</configuration>

ranger-nifi-audit.xml (generated, Solr enabled)

<?xml version="1.0"?>
<configuration>
  <property>
    <name>xasecure.audit.solr.enable</name>
    <value>true</value>
  </property>
  <property>
    <name>xasecure.audit.solr.async</name>
    <value>true</value>
  </property>
  <property>
    <name>xasecure.audit.solr.url</name>
    <value>http://solr.example.com:6083/solr/ranger_audits</value>
  </property>
  <property>
    <name>xasecure.audit.solr.async.max.queue.size</name>
    <value>20480</value>
  </property>
  <property>
    <name>xasecure.audit.solr.async.max.flush.interval.ms</name>
    <value>10000</value>
  </property>
</configuration>

ranger-nifi-audit.xml (generated, Solr disabled)

When spec.security.ranger.audit is omitted:

<?xml version="1.0"?>
<configuration>
  <property>
    <name>xasecure.audit.solr.enable</name>
    <value>false</value>
  </property>
</configuration>

TLS Secret format for Ranger authorization

Cloudera Flow Management Operator for Kubernetes expects a Kubernetes Secret with keystore and truststore files for mutual TLS between NiFi and Ranger Admin.

Keystore Secret

apiVersion: v1
kind: Secret
metadata:
  name: nifi-ranger-keystore
  namespace: nifi
type: Opaque
data:
  # base64-encoded JKS keystore file
  keystore.jks: <base64>
  # base64-encoded plaintext password string
  keystore.password: <base64>
  # base64-encoded JKS truststore file
  truststore.jks: <base64>
  # base64-encoded plaintext password string
  truststore.password: <base64>