diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a863895e..15f5ee041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - hadoop: Add precompiled hadoop for later reuse in dependent images ([#1466]). +- nifi: Add version `2.9.0` ([#1463]). ### Changed @@ -21,6 +22,7 @@ All notable changes to this project will be documented in this file. [#1452]: https://github.com/stackabletech/docker-images/pull/1452 [#1453]: https://github.com/stackabletech/docker-images/pull/1453 [#1454]: https://github.com/stackabletech/docker-images/pull/1454 +[#1463]: https://github.com/stackabletech/docker-images/pull/1463 [#1466]: https://github.com/stackabletech/docker-images/pull/1466 ## [26.3.0] - 2026-03-16 diff --git a/java-devel/Dockerfile b/java-devel/Dockerfile index 2cee2b743..98c12c75f 100644 --- a/java-devel/Dockerfile +++ b/java-devel/Dockerfile @@ -12,7 +12,7 @@ ARG STACKABLE_USER_UID # Find the latest version here: https://github.com/apache/maven/releases # renovate: datasource=github-tags packageName=apache/maven -ARG MAVEN_VERSION="3.9.11" +ARG MAVEN_VERSION="3.9.14" # See: https://adoptium.net/en-gb/installation/linux/#_centosrhelfedora_instructions RUN cat < /etc/yum.repos.d/adoptium.repo diff --git a/nifi/boil-config.toml b/nifi/boil-config.toml index a0eb755c3..486b88d10 100644 --- a/nifi/boil-config.toml +++ b/nifi/boil-config.toml @@ -7,7 +7,7 @@ java-devel = "11" git-sync-version = "v4.4.1" # Check for new versions at the upstream: https://github.com/stackabletech/nifi-opa-plugin/tags # Checkout a Patchable version (patch-series) for the new tag -nifi-opa-authorizer-plugin-version = "0.4.0" +nifi-opa-authorizer-plugin-version = "0.5.0" [versions."2.6.0".local-images] java-base = "21" @@ -18,7 +18,7 @@ java-devel = "21" git-sync-version = "v4.4.1" # Check for new versions at the upstream: https://github.com/stackabletech/nifi-opa-plugin/tags # Checkout a Patchable version (patch-series) for the new tag -nifi-opa-authorizer-plugin-version = "0.4.0" +nifi-opa-authorizer-plugin-version = "0.5.0" # Release a new version here: https://github.com/stackabletech/nifi-iceberg-bundle # Checkout a Patchable version (patch-series) for the new tag @@ -33,4 +33,15 @@ java-devel = "21" git-sync-version = "v4.4.1" # Check for new versions at the upstream: https://github.com/stackabletech/nifi-opa-plugin/tags # Checkout a Patchable version (patch-series) for the new tag -nifi-opa-authorizer-plugin-version = "0.4.0" +nifi-opa-authorizer-plugin-version = "0.5.0" + +[versions."2.9.0".local-images] +java-base = "21" # As stated in GitHub README +java-devel = "21" +"shared/logback" = "1.5.32" # https://github.com/apache/nifi/blob/rel/nifi-2.9.0/pom.xml#L171 + +[versions."2.9.0".build-arguments] +git-sync-version = "v4.4.1" +# Check for new versions at the upstream: https://github.com/stackabletech/nifi-opa-plugin/tags +# Checkout a Patchable version (patch-series) for the new tag +nifi-opa-authorizer-plugin-version = "0.5.0" diff --git a/nifi/opa-plugin/stackable/patches/0.5.0/patchable.toml b/nifi/opa-plugin/stackable/patches/0.5.0/patchable.toml new file mode 100644 index 000000000..69112099c --- /dev/null +++ b/nifi/opa-plugin/stackable/patches/0.5.0/patchable.toml @@ -0,0 +1,2 @@ +mirror = "https://github.com/stackabletech/nifi-opa-plugin.git" +base = "e544db52f445c449f97d809441079b04b5cb1a0b" diff --git a/nifi/stackable/patches/2.9.0/0001-no-zip-assembly.patch b/nifi/stackable/patches/2.9.0/0001-no-zip-assembly.patch new file mode 100644 index 000000000..6a3833d2b --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0001-no-zip-assembly.patch @@ -0,0 +1,21 @@ +From d4f0275b86729bd28d83f8d4b28166c827a3385a Mon Sep 17 00:00:00 2001 +From: Nick Larsen +Date: Mon, 17 Feb 2025 17:26:20 +0100 +Subject: no zip assembly + +--- + nifi-assembly/pom.xml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/nifi-assembly/pom.xml b/nifi-assembly/pom.xml +index 60250bd60e..d49fe6d0d9 100644 +--- a/nifi-assembly/pom.xml ++++ b/nifi-assembly/pom.xml +@@ -66,7 +66,6 @@ language governing permissions and limitations under the License. --> + posix + + dir +- zip + + + diff --git a/nifi/stackable/patches/2.9.0/0002-add-cyclonedx-plugin.patch b/nifi/stackable/patches/2.9.0/0002-add-cyclonedx-plugin.patch new file mode 100644 index 000000000..f76a7b92b --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0002-add-cyclonedx-plugin.patch @@ -0,0 +1,38 @@ +From a5e683212fa31aca9386654878e810a506154e16 Mon Sep 17 00:00:00 2001 +From: Nick Larsen +Date: Mon, 17 Feb 2025 17:31:17 +0100 +Subject: add cyclonedx plugin + +--- + pom.xml | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/pom.xml b/pom.xml +index 3a865337ec..8ca44ad5ac 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -1075,6 +1075,24 @@ + + + ++ ++ org.cyclonedx ++ cyclonedx-maven-plugin ++ 2.8.0 ++ ++ application ++ 1.5 ++ false ++ ++ ++ ++ package ++ ++ makeBom ++ ++ ++ ++ + + + diff --git a/nifi/stackable/patches/2.9.0/0003-disable-host-port-validation-if-list-of-allowed-host.patch b/nifi/stackable/patches/2.9.0/0003-disable-host-port-validation-if-list-of-allowed-host.patch new file mode 100644 index 000000000..f9951cf15 --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0003-disable-host-port-validation-if-list-of-allowed-host.patch @@ -0,0 +1,48 @@ +From 43fc3a1d33ae436c2add60adf72d2e0148ea7b56 Mon Sep 17 00:00:00 2001 +From: Benedikt Labrenz +Date: Thu, 22 May 2025 14:47:24 +0200 +Subject: disable host port validation if list of allowed hosts only contains + '*' + +--- + .../connector/FrameworkServerConnectorFactory.java | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java +index 24ce43a51f..526695b9da 100644 +--- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java ++++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java +@@ -54,6 +54,8 @@ public class FrameworkServerConnectorFactory extends StandardServerConnectorFact + + private final String excludeCipherSuites; + ++ private final boolean disableHostPortValidator; ++ + private final Set validPorts; + + private SslContextFactory.Server sslContextFactory; +@@ -72,6 +74,11 @@ public class FrameworkServerConnectorFactory extends StandardServerConnectorFact + headerSize = DataUnit.parseDataSize(properties.getWebMaxHeaderSize(), DataUnit.B).intValue(); + validPorts = getValidPorts(properties); + ++ // Check if the property for allowed hosts has only the wildcard entry and ++ // if so store this in disableHostPortValidator for later use ++ List configuredHostNames = properties.getAllowedHostsAsList(); ++ disableHostPortValidator = configuredHostNames.size() == 1 && configuredHostNames.contains("*"); ++ + if (properties.isHTTPSConfigured()) { + if (properties.isClientAuthRequiredForRestApi()) { + setNeedClientAuth(true); +@@ -102,8 +109,10 @@ public class FrameworkServerConnectorFactory extends StandardServerConnectorFact + // Add HostHeaderCustomizer to set Host Header for HTTP/2 and HostHeaderHandler + httpConfiguration.addCustomizer(new HostHeaderCustomizer()); + +- final HostPortValidatorCustomizer hostPortValidatorCustomizer = new HostPortValidatorCustomizer(validPorts); +- httpConfiguration.addCustomizer(hostPortValidatorCustomizer); ++ if (!disableHostPortValidator) { ++ final HostPortValidatorCustomizer hostPortValidatorCustomizer = new HostPortValidatorCustomizer(validPorts); ++ httpConfiguration.addCustomizer(hostPortValidatorCustomizer); ++ } + + return httpConfiguration; + } diff --git a/nifi/stackable/patches/2.9.0/0004-NIFI-14858-Make-SNI-checking-configurable.patch b/nifi/stackable/patches/2.9.0/0004-NIFI-14858-Make-SNI-checking-configurable.patch new file mode 100644 index 000000000..05f4257f2 --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0004-NIFI-14858-Make-SNI-checking-configurable.patch @@ -0,0 +1,108 @@ +From 6a6b84866f01dd160701af869870a25b90c48a02 Mon Sep 17 00:00:00 2001 +From: Lars Francke +Date: Wed, 13 Aug 2025 14:16:55 +0200 +Subject: NIFI-14858: Make SNI checking configurable + +Introduces two new properties: +- nifi.web.https.sni.required (default: false) +- nifi.web.https.sni.host.check (default: true) + +These defaults mean that SNI is not required (this is the current behavior already) but if SNI is provided then the host has to match. +--- + .../StandardServerConnectorFactory.java | 24 +++++++++++++++++++ + .../org/apache/nifi/util/NiFiProperties.java | 10 ++++++++ + .../FrameworkServerConnectorFactory.java | 4 ++++ + 3 files changed, 38 insertions(+) + +diff --git a/nifi-commons/nifi-jetty-configuration/src/main/java/org/apache/nifi/jetty/configuration/connector/StandardServerConnectorFactory.java b/nifi-commons/nifi-jetty-configuration/src/main/java/org/apache/nifi/jetty/configuration/connector/StandardServerConnectorFactory.java +index 892755cded..856ef646b0 100644 +--- a/nifi-commons/nifi-jetty-configuration/src/main/java/org/apache/nifi/jetty/configuration/connector/StandardServerConnectorFactory.java ++++ b/nifi-commons/nifi-jetty-configuration/src/main/java/org/apache/nifi/jetty/configuration/connector/StandardServerConnectorFactory.java +@@ -70,6 +70,10 @@ public class StandardServerConnectorFactory implements ServerConnectorFactory { + + private int requestHeaderSize = 8192; + ++ private boolean sniRequired = false; ++ ++ private boolean sniHostCheck = true; ++ + /** + * Standard Server Connector Factory Constructor with required properties + * +@@ -181,6 +185,24 @@ public class StandardServerConnectorFactory implements ServerConnectorFactory { + this.requestHeaderSize = requestHeaderSize; + } + ++ /** ++ * Set to true if a SNI certificate is required, else requests will be rejected with 400 response. ++ * ++ * @param sniRequired SNI Required status ++ */ ++ public void setSniRequired(final boolean sniRequired) { ++ this.sniRequired = sniRequired; ++ } ++ ++ /** ++ * Set to true if the SNI Host name must match when there is an SNI certificate. ++ * ++ * @param sniHostCheck SNI Host Check status ++ */ ++ public void setSniHostCheck(final boolean sniHostCheck) { ++ this.sniHostCheck = sniHostCheck; ++ } ++ + protected Server getServer() { + return server; + } +@@ -195,6 +217,8 @@ public class StandardServerConnectorFactory implements ServerConnectorFactory { + httpConfiguration.setSendServerVersion(SEND_SERVER_VERSION); + + final SecureRequestCustomizer secureRequestCustomizer = new SecureRequestCustomizer(); ++ secureRequestCustomizer.setSniRequired(sniRequired); ++ secureRequestCustomizer.setSniHostCheck(sniHostCheck); + httpConfiguration.addCustomizer(secureRequestCustomizer); + } + +diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java +index 94f79197d9..11ca1424ab 100644 +--- a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java ++++ b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java +@@ -219,6 +219,8 @@ public class NiFiProperties extends ApplicationProperties { + public static final String WEB_HTTPS_CIPHERSUITES_INCLUDE = "nifi.web.https.ciphersuites.include"; + public static final String WEB_HTTPS_CIPHERSUITES_EXCLUDE = "nifi.web.https.ciphersuites.exclude"; + public static final String WEB_HTTPS_NETWORK_INTERFACE_PREFIX = "nifi.web.https.network.interface."; ++ public static final String WEB_HTTPS_SNI_REQUIRED = "nifi.web.https.sni.required"; ++ public static final String WEB_HTTPS_SNI_HOST_CHECK = "nifi.web.https.sni.host.check"; + public static final String WEB_WORKING_DIR = "nifi.web.jetty.working.directory"; + public static final String WEB_THREADS = "nifi.web.jetty.threads"; + public static final String WEB_MAX_HEADER_SIZE = "nifi.web.max.header.size"; +@@ -720,6 +722,14 @@ public class NiFiProperties extends ApplicationProperties { + return Arrays.stream(protocols.split("\\s+")).collect(Collectors.toSet()); + } + ++ public boolean isWebHttpsSniRequired() { ++ return Boolean.parseBoolean(getProperty(WEB_HTTPS_SNI_REQUIRED, "false")); ++ } ++ ++ public boolean isWebHttpsSniHostCheck() { ++ return Boolean.parseBoolean(getProperty(WEB_HTTPS_SNI_HOST_CHECK, "true")); ++ } ++ + public String getWebMaxHeaderSize() { + return getProperty(WEB_MAX_HEADER_SIZE, DEFAULT_WEB_MAX_HEADER_SIZE); + } +diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java +index 526695b9da..1ad87bacce 100644 +--- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java ++++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/connector/FrameworkServerConnectorFactory.java +@@ -90,6 +90,10 @@ public class FrameworkServerConnectorFactory extends StandardServerConnectorFact + + // Set Transport Layer Security Protocols based on platform configuration + setIncludeSecurityProtocols(TlsPlatform.getPreferredProtocols().toArray(new String[0])); ++ ++ // Set SNI configuration from properties ++ setSniRequired(properties.isWebHttpsSniRequired()); ++ setSniHostCheck(properties.isWebHttpsSniHostCheck()); + } + } + diff --git a/nifi/stackable/patches/2.9.0/0005-replace-process-groups-root-with-root-ID.patch b/nifi/stackable/patches/2.9.0/0005-replace-process-groups-root-with-root-ID.patch new file mode 100644 index 000000000..3dcbe607e --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0005-replace-process-groups-root-with-root-ID.patch @@ -0,0 +1,212 @@ +From bccc902cd63db4c9972c40b52b6dd543b3f1c11e Mon Sep 17 00:00:00 2001 +From: Andrew Kenworthy +Date: Fri, 23 Jan 2026 12:41:58 +0100 +Subject: replace process groups root with root ID + +--- + .../org/apache/nifi/util/NiFiProperties.java | 3 ++ + .../nifi/flow/FlowInitializationCallback.java | 11 ++++ + .../FileAccessPolicyProvider.java | 53 +++++++++++++++++++ + .../FileAuthorizerInitializer.java | 25 +++++++++ + .../nifi/controller/StandardFlowService.java | 17 ++++++ + 5 files changed, 109 insertions(+) + create mode 100644 nifi-framework-api/src/main/java/org/apache/nifi/flow/FlowInitializationCallback.java + create mode 100644 nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizerInitializer.java + +diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java +index 11ca1424ab..777de8d565 100644 +--- a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java ++++ b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java +@@ -348,6 +348,9 @@ public class NiFiProperties extends ApplicationProperties { + // performance tracking defaults + public static final int DEFAULT_TRACK_PERFORMANCE_PERCENTAGE = 0; + ++ // root process group replacement ++ public static final String ROOT_PROCESS_GROUP_PLACEHOLDER ="nifi.process.group.root.placeholder"; ++ + // defaults + public static final Boolean DEFAULT_AUTO_RESUME_STATE = true; + public static final String DEFAULT_AUTHORIZER_CONFIGURATION_FILE = "conf/authorizers.xml"; +diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/flow/FlowInitializationCallback.java b/nifi-framework-api/src/main/java/org/apache/nifi/flow/FlowInitializationCallback.java +new file mode 100644 +index 0000000000..7f81967537 +--- /dev/null ++++ b/nifi-framework-api/src/main/java/org/apache/nifi/flow/FlowInitializationCallback.java +@@ -0,0 +1,11 @@ ++package org.apache.nifi.flow; ++ ++/** ++ * Simple callback interface invoked when the root process group has been ++ * loaded and the flow is fully initialized for the first time. ++ */ ++public interface FlowInitializationCallback { ++ void onRootGroupLoaded(); ++} ++ ++ +diff --git a/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java b/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java +index 3d271dd394..f153cea1ae 100644 +--- a/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java ++++ b/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java +@@ -16,6 +16,7 @@ + */ + package org.apache.nifi.authorization; + ++import jakarta.xml.bind.JAXBException; + import org.apache.commons.lang3.StringUtils; + import org.apache.nifi.authorization.annotation.AuthorizerContext; + import org.apache.nifi.authorization.exception.AuthorizationAccessException; +@@ -26,6 +27,7 @@ import org.apache.nifi.authorization.resource.ResourceType; + import org.apache.nifi.authorization.util.IdentityMapping; + import org.apache.nifi.authorization.util.IdentityMappingUtil; + import org.apache.nifi.components.PropertyValue; ++import org.apache.nifi.controller.StandardFlowService; + import org.apache.nifi.util.FlowInfo; + import org.apache.nifi.util.FlowParser; + import org.apache.nifi.util.NiFiProperties; +@@ -58,6 +60,8 @@ import java.util.concurrent.atomic.AtomicReference; + import java.util.regex.Matcher; + import java.util.regex.Pattern; + ++import static org.apache.nifi.util.NiFiProperties.ROOT_PROCESS_GROUP_PLACEHOLDER; ++ + import static org.apache.nifi.authorization.RequestAction.READ; + import static org.apache.nifi.authorization.RequestAction.WRITE; + +@@ -92,6 +96,9 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide + @Override + public void initialize(AccessPolicyProviderInitializationContext initializationContext) throws AuthorizerCreationException { + userGroupProviderLookup = initializationContext.getUserGroupProviderLookup(); ++ ++ // Register flow initialization hook ++ StandardFlowService.registerInitializationCallback(new FileAuthorizerInitializer(this)); + } + + @Override +@@ -588,6 +595,52 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide + } + } + ++ /** ++ * Replaces process group root references with the process group ID. ++ * Relevant when a static authorizations file is provided, which can ++ * then use "root" as a placeholder. ++ */ ++ public void replaceWithRootGroupId() throws JAXBException { ++ String placeholder = this.properties.getProperty(ROOT_PROCESS_GROUP_PLACEHOLDER, ""); ++ ++ if (StringUtils.isNotBlank(placeholder)) { ++ if (rootGroupId == null) { ++ logger.info("Parsing flow as rootGroupId is not yet defined"); ++ parseFlow(); ++ } ++ if (rootGroupId != null) { ++ logger.info("Parsing root group with {}", rootGroupId); ++ ++ final AuthorizationsHolder holder = authorizationsHolder.get(); ++ final List currentPolicies = holder.getPolicies(); ++ final ListIterator accessPolicies = currentPolicies.listIterator(); ++ ++ boolean authorizationsChanged = false; ++ ++ while (accessPolicies.hasNext()) { ++ final AccessPolicy accessPolicy = accessPolicies.next(); ++ String resource = accessPolicy.getResource(); ++ String processGroupRoot = ResourceType.ProcessGroup.getValue() + "/" + placeholder; ++ if (resource.endsWith(processGroupRoot)) { ++ int pos = resource.indexOf(processGroupRoot); ++ accessPolicies.remove(); ++ final AccessPolicy updatedPolicy = new AccessPolicy.Builder(accessPolicy).resource(resource.substring(0, pos) + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId).build(); ++ accessPolicies.add(updatedPolicy); ++ authorizationsChanged = true; ++ } ++ } ++ ++ if (authorizationsChanged) { ++ saveAndRefreshHolder(currentPolicies); ++ } ++ } else { ++ // this is not expected as this is called from the flow service ++ // once it has been configured ++ logger.info("rootGroupId still not established!"); ++ } ++ } ++ } ++ + /** + * Creates and adds an access policy for the given resource, identity, and actions to the specified authorizations. + * +diff --git a/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizerInitializer.java b/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizerInitializer.java +new file mode 100644 +index 0000000000..f67328ef84 +--- /dev/null ++++ b/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizerInitializer.java +@@ -0,0 +1,25 @@ ++package org.apache.nifi.authorization; ++ ++import org.apache.nifi.flow.FlowInitializationCallback; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++ ++ ++public class FileAuthorizerInitializer implements FlowInitializationCallback { ++ private static final Logger logger = LoggerFactory.getLogger(FileAuthorizerInitializer.class); ++private FileAccessPolicyProvider fileAccessPolicyProvider; ++ ++ public FileAuthorizerInitializer(FileAccessPolicyProvider fileAccessPolicyProvider) { ++ this.fileAccessPolicyProvider = fileAccessPolicyProvider; ++ } ++ ++ @Override ++ public void onRootGroupLoaded() { ++ try { ++ logger.info("Flow initialized; ensuring root group ID is recorded in authorizations.xml"); ++ this.fileAccessPolicyProvider.replaceWithRootGroupId(); ++ } catch (Exception e) { ++ logger.warn("Unable to update authorizations.xml with root group ID", e); ++ } ++ } ++} +\ No newline at end of file +diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java +index fc212ad88e..72137e3a83 100644 +--- a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java ++++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java +@@ -55,6 +55,7 @@ import org.apache.nifi.controller.serialization.FlowSynchronizationException; + import org.apache.nifi.controller.status.ProcessGroupStatus; + import org.apache.nifi.engine.FlowEngine; + import org.apache.nifi.events.BulletinFactory; ++import org.apache.nifi.flow.FlowInitializationCallback; + import org.apache.nifi.groups.BundleUpdateStrategy; + import org.apache.nifi.groups.ProcessGroup; + import org.apache.nifi.groups.RemoteProcessGroup; +@@ -149,6 +150,13 @@ public class StandardFlowService implements FlowService, ProtocolHandler { + private static final String CONNECTION_EXCEPTION_MSG_PREFIX = "Failed to connect node to cluster"; + private static final Logger logger = LoggerFactory.getLogger(StandardFlowService.class); + ++ // Static callback registration for post-initialization hooks ++ private static volatile FlowInitializationCallback initializationCallback; ++ ++ public static void registerInitializationCallback(FlowInitializationCallback callback) { ++ initializationCallback = callback; ++ } ++ + public static StandardFlowService createStandaloneInstance( + final FlowController controller, + final NiFiProperties nifiProperties, +@@ -960,6 +968,15 @@ public class StandardFlowService implements FlowService, ProtocolHandler { + // start the processors as indicated by the dataflow + controller.onFlowInitialized(autoResumeState); + ++ // this should be done once the flow has been initialized ++ if (initializationCallback != null) { ++ try { ++ initializationCallback.onRootGroupLoaded(); ++ } catch (Exception e) { ++ logger.warn("Error invoking FlowInitializationCallback", e); ++ } ++ } ++ + loadSnippets(dataFlow.getSnippets()); + + controller.startHeartbeating(); diff --git a/nifi/stackable/patches/2.9.0/patchable.toml b/nifi/stackable/patches/2.9.0/patchable.toml new file mode 100644 index 000000000..5caa2f961 --- /dev/null +++ b/nifi/stackable/patches/2.9.0/patchable.toml @@ -0,0 +1 @@ +base = "02a8c6e75e7c9835f2afc7cf42c45a6b0478504b" diff --git a/shared/logback/boil-config.toml b/shared/logback/boil-config.toml index 8a5a32242..e2b0497c8 100644 --- a/shared/logback/boil-config.toml +++ b/shared/logback/boil-config.toml @@ -12,3 +12,6 @@ java-devel = "21" [versions."1.5.24".local-images] java-devel = "21" + +[versions."1.5.32".local-images] +java-devel = "21" diff --git a/shared/logback/stackable/patches/1.5.32/patchable.toml b/shared/logback/stackable/patches/1.5.32/patchable.toml new file mode 100644 index 000000000..abccc9398 --- /dev/null +++ b/shared/logback/stackable/patches/1.5.32/patchable.toml @@ -0,0 +1 @@ +base = "e807335a67535b4eacce94e942c0bcb649665d93"