diff --git a/examples/README-entra-example.md b/examples/README-entra-example.md new file mode 100644 index 00000000..cdc8508c --- /dev/null +++ b/examples/README-entra-example.md @@ -0,0 +1,104 @@ +# Examples + +## Overview + +This note provides some explanatory information when running the EntraID example. +This example demonstrates how to provide a static set of RBAC permissions for users that are fetched from an EntraID backend. +The user- and group-identifiers are those used by EntraID, but other UUIDs - such as for the policy identifiers - are automatically generated when required by Nifi or are honoured if UUIDs (which are unique, after all) are provided. +It is often helpful if the initial (or "root") process group is readable by the initial admin, and the Nifi code has been patched to make this possible. + +## Cluster + +Create a new local cluster (e.g. with [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/) and the [stackablectl tool](https://github.com/stackabletech/stackablectl)). +This creates a cluster named `stackable-data-platform`. +Install the operators required by the example. + +```text +kind create cluster --name stackable-data-platform +stackablectl operator install commons secret listener nifi +``` + +## Prerequisites + +This example assumes that an EntraID backend is available and that an Application (in this example, Nifi-Entra-Test) has been configured with a web redirect URI. + +Create a dedicated namespace in which to run the example: + +```text +kubectl create namespace nifi +``` + +Apply a secret containing the following fields necessary for EntraID connectivity: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: oidc-secret +stringData: + auth.endpoint: https://login.microsoftonline.com + directory.id: + client.id: + client.secret: + filter.prefix: # e.g. Nifi-Entra + initial.admin: # an existing EntraID user + discovery.url: https://login.microsoftonline.com//v2.0/.well-known/openid-configuration +``` + +Apply the Nifi cluster resource: + +```text +kubectl apply -f examples/entra_nifi.yaml -n nifi +``` + +## Usage + +Once the cluster is running, you will need to make a note of the listener endpoint. +This can be found by inspecting the listener class: + +```text +kubectl get listeners/test-nifi-node -n nifi -o yaml | yq '[.status][0] | ("https://" + .ingressAddresses[0].address + ":" + .nodePorts.https)' +``` + +which yields e.g. + +```text +https://172.19.0.3:31131 +``` + +The web endpoint for app running against Entra needs to be updated with this endpoint as the prefix i.e. + +![EntraID Web URI](entra-redirect-uri.png) + +Paste this endpoint into the browser and you will be directed to the Azure portal login portal (to enter the credentials for the user designated as the intiial admin) and then redirected back to the Nifi UI. +The UI opens up on a writable canvas, in this case with the UUID `ea060c65-019a-1000-766b-0854b414d37e`: + +![Nifi canvas](canvas.png) + +The initial admin has immediate access as the static `authorizations.xml` file provided via the ConfigMap defined this: + +```xml + + + +``` + +and the `root` part of this has been updated with the actual root process group: + +```xml + + + +``` + +This requires that the following be set: + +```yaml +configOverrides: + nifi.properties: + ... + nifi.process.group.root.placeholder: "root" +``` + +so that it is clear which placeholder - if any - should be patched. diff --git a/examples/canvas.png b/examples/canvas.png new file mode 100644 index 00000000..a008f363 Binary files /dev/null and b/examples/canvas.png differ diff --git a/examples/entra-redirect-uri.png b/examples/entra-redirect-uri.png new file mode 100644 index 00000000..5f7949b4 Binary files /dev/null and b/examples/entra-redirect-uri.png differ diff --git a/examples/entra_nifi.yaml b/examples/entra_nifi.yaml new file mode 100644 index 00000000..03b508c2 --- /dev/null +++ b/examples/entra_nifi.yaml @@ -0,0 +1,295 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: custom-authorizer +data: + users.xml: | + + + + + + + + + authorizers.xml: | + + + + + file-user-group-provider + org.apache.nifi.authorization.FileUserGroupProvider + ./custom-authorizer/users.xml + CN=generated certificate for pod + + + + aad-user-group-provider + org.apache.nifi.authorization.azure.AzureGraphUserGroupProvider + 5 mins + ${env:OIDC_AUTHORITY_ENDPOINT} + ${env:OIDC_DIRECTORY_ID} + ${env:OIDC_CLIENT_ID} + ${env:OIDC_CLIENT_SECRET} + ${env:OIDC_GROUP_FILTER_PREFIX} + 100 + + + + composite-configurable-user-group-provider + org.apache.nifi.authorization.CompositeConfigurableUserGroupProvider + file-user-group-provider + aad-user-group-provider + + + + file-access-policy-provider + org.apache.nifi.authorization.FileAccessPolicyProvider + composite-configurable-user-group-provider + ./custom-authorizer/authorizations.xml + ${env:INITIAL_ADMIN} + CN=generated certificate for pod + + + + managed-authorizer + org.apache.nifi.authorization.StandardManagedAuthorizer + file-access-policy-provider + + + + + authorizations.xml: | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--- +apiVersion: authentication.stackable.tech/v1alpha1 +kind: AuthenticationClass +metadata: + name: simple-nifi-users +spec: + provider: + static: + userCredentialsSecret: + name: simple-nifi-admin-credentials +--- +apiVersion: v1 +kind: Secret +metadata: + name: simple-nifi-admin-credentials +stringData: + admin: adminadmin + +# needs to be provided separately... +# --- +# apiVersion: v1 +# kind: Secret +# metadata: +# name: oidc-secret +# stringData: +# auth.endpoint: +# directory.id: +# client.id: +# client.secret: +# filter.prefix: +# initial.admin: +# discovery.url: + +--- +apiVersion: nifi.stackable.tech/v1alpha1 +kind: NifiCluster +metadata: + name: test-nifi +spec: + image: + custom: null + productVersion: 2.6.0 + pullPolicy: IfNotPresent + clusterConfig: + zookeeperConfigMapName: null + authentication: + - authenticationClass: simple-nifi-users + hostHeaderCheck: + allowAll: false + sensitiveProperties: + keySecret: nifi-sensitive-property-key + autoGenerate: true + nodes: + roleConfig: + listenerClass: external-unstable + roleGroups: + default: + replicas: 1 + configOverrides: + nifi.properties: + nifi.web.https.sni.required: "false" + nifi.web.https.sni.host.check: "false" + nifi.authorizer.configuration.file: "/stackable/nifi/custom-authorizer/authorizers.xml" + nifi.security.user.authorizer: "managed-authorizer" + nifi.security.user.oidc.discovery.url: "${env:OIDC_DISCOVERY_URL}" + nifi.security.user.oidc.connect.timeout: "5 secs" + nifi.security.user.oidc.read.timeout: "5 secs" + nifi.security.user.oidc.client.id: "${env:OIDC_CLIENT_ID}" + nifi.security.user.oidc.client.secret: "${env:OIDC_CLIENT_SECRET}" + nifi.security.user.oidc.additional.scopes: "profile" + nifi.security.user.oidc.claim.identifying.user: "upn" + nifi.process.group.root.placeholder: "root" + podOverrides: + spec: + initContainers: + - name: prepare + env: + - name: OIDC_CLIENT_ID + valueFrom: + secretKeyRef: + name: oidc-secret + key: client.id + - name: OIDC_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: oidc-secret + key: client.secret + - name: OIDC_DISCOVERY_URL + valueFrom: + secretKeyRef: + name: oidc-secret + key: discovery.url + - name: prep-custom-authorizers + image: oci.stackable.tech/sdp/nifi:2.4.0-stackable0.0.0-dev + env: + - name: OIDC_AUTHORITY_ENDPOINT + valueFrom: + secretKeyRef: + name: oidc-secret + key: auth.endpoint + - name: OIDC_DIRECTORY_ID + valueFrom: + secretKeyRef: + name: oidc-secret + key: directory.id + - name: OIDC_CLIENT_ID + valueFrom: + secretKeyRef: + name: oidc-secret + key: client.id + - name: OIDC_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: oidc-secret + key: client.secret + - name: OIDC_GROUP_FILTER_PREFIX + valueFrom: + secretKeyRef: + name: oidc-secret + key: filter.prefix + - name: INITIAL_ADMIN + valueFrom: + secretKeyRef: + name: oidc-secret + key: initial.admin + - name: OIDC_DISCOVERY_URL + valueFrom: + secretKeyRef: + name: oidc-secret + key: discovery.url + args: + - | + echo Copying custom files... + cp /tmp/custom-authorizer/authorizers.xml /stackable/nifi/custom-authorizer/ + echo Templating custom authorizer file... + config-utils template /stackable/nifi/custom-authorizer/authorizers.xml + cp /tmp/custom-authorizer/authorizations.xml /stackable/nifi/custom-authorizer/ + cp /tmp/custom-authorizer/users.xml /stackable/nifi/custom-authorizer/ + command: + - /bin/bash + - -c + - -euo + - pipefail + volumeMounts: + - name: custom-authorizer + mountPath: /tmp/custom-authorizer + - name: nifi-auth-config + mountPath: /stackable/nifi/custom-authorizer + containers: + - name: nifi + volumeMounts: + - name: nifi-auth-config + mountPath: /stackable/nifi/custom-authorizer + volumes: + - name: custom-authorizer + configMap: + name: custom-authorizer + - name: nifi-auth-config + emptyDir: {}