diff --git a/nifi-commons/nifi-security-proxied-entity/pom.xml b/nifi-commons/nifi-security-proxied-entity/pom.xml new file mode 100644 index 000000000000..5f439a0ab1d0 --- /dev/null +++ b/nifi-commons/nifi-security-proxied-entity/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + org.apache.nifi + nifi-commons + 2.1.0-SNAPSHOT + + nifi-security-proxied-entity + Shared security components for handling Proxied Entities in HTTP requests and response + + diff --git a/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/ProxiedEntityEncoder.java b/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/ProxiedEntityEncoder.java new file mode 100644 index 000000000000..382e6aa812ea --- /dev/null +++ b/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/ProxiedEntityEncoder.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.security.proxied.entity; + +/** + * Proxied Entity Encoder sanitizes and formats identities for transmission as HTTP request headers + */ +public interface ProxiedEntityEncoder { + /** + * Get encoded representation of identity suitable for transmission + * @param identity Identity to be encoded + * @return Encoded Entity + */ + String getEncodedEntity(String identity); +} diff --git a/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoder.java b/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoder.java new file mode 100644 index 000000000000..41325374745c --- /dev/null +++ b/nifi-commons/nifi-security-proxied-entity/src/main/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoder.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.security.proxied.entity; + +import java.nio.charset.CharsetEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +/** + * Standard implementation singleton instance of Proxied Entity Encoder + */ +public class StandardProxiedEntityEncoder implements ProxiedEntityEncoder { + private static final String DELIMITED_FORMAT = "<%s>"; + + private static final String GT = ">"; + + private static final String ESCAPED_GT = "\\\\>"; + + private static final String LT = "<"; + + private static final String ESCAPED_LT = "\\\\<"; + + private static final CharsetEncoder headerValueCharsetEncoder = StandardCharsets.US_ASCII.newEncoder(); + + private static final Base64.Encoder headerValueEncoder = Base64.getEncoder(); + + private static final StandardProxiedEntityEncoder encoder = new StandardProxiedEntityEncoder(); + + private StandardProxiedEntityEncoder() { + + } + + /** + * Get singleton instance of standard encoder + * + * @return Proxied Entity Encoder + */ + public static ProxiedEntityEncoder getInstance() { + return encoder; + } + + /** + * Get encoded entity sanitized and formatted for transmission as an HTTP header + * + * @param identity Identity to be encoded + * @return Encoded Entity + */ + @Override + public String getEncodedEntity(final String identity) { + final String sanitizedIdentity = getSanitizedIdentity(identity); + return DELIMITED_FORMAT.formatted(sanitizedIdentity); + } + + private String getSanitizedIdentity(final String identity) { + final String sanitized; + + if (identity == null || identity.isEmpty()) { + sanitized = identity; + } else { + final String escaped = identity.replaceAll(LT, ESCAPED_LT).replaceAll(GT, ESCAPED_GT); + + if (headerValueCharsetEncoder.canEncode(escaped)) { + // Strings limited to US-ASCII characters can be transmitted as HTTP header values without encoding + sanitized = escaped; + } else { + // Non-ASCII characters require Base64 encoding and additional wrapping for transmission as headers + final byte[] escapedBinary = escaped.getBytes(StandardCharsets.UTF_8); + final String escapedEncoded = headerValueEncoder.encodeToString(escapedBinary); + sanitized = DELIMITED_FORMAT.formatted(escapedEncoded); + } + } + + return sanitized; + } +} diff --git a/nifi-commons/nifi-security-proxied-entity/src/test/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoderTest.java b/nifi-commons/nifi-security-proxied-entity/src/test/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoderTest.java new file mode 100644 index 000000000000..752b4361acea --- /dev/null +++ b/nifi-commons/nifi-security-proxied-entity/src/test/java/org/apache/nifi/security/proxied/entity/StandardProxiedEntityEncoderTest.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.security.proxied.entity; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class StandardProxiedEntityEncoderTest { + + @ParameterizedTest + @CsvSource( + delimiter = ':', + value = { + ":", + "'':<>", + "username:", + "CN=Common Name, OU=Organizational Unit:", + "CN=nifi.apache.org, O=Organization:", + ":<\\>", + "<>:<\\<\\\\>>", + "CN=\uD83D\uDE00:<>" + } + ) + void testGetEncodedEntity(final String identity, final String expected) { + final String encodedEntity = StandardProxiedEntityEncoder.getInstance().getEncodedEntity(identity); + + assertEquals(expected, encodedEntity); + } +} diff --git a/nifi-commons/pom.xml b/nifi-commons/pom.xml index f46e703535a7..0f7065e99735 100644 --- a/nifi-commons/pom.xml +++ b/nifi-commons/pom.xml @@ -51,6 +51,7 @@ nifi-security-identity nifi-security-kerberos-api nifi-security-kerberos + nifi-security-proxied-entity nifi-security-ssl nifi-security-utils-api nifi-single-user-utils diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml index dc54975cc8e0..083f266672f4 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml @@ -111,6 +111,11 @@ nifi-security-cert 2.1.0-SNAPSHOT + + org.apache.nifi + nifi-security-proxied-entity + 2.1.0-SNAPSHOT + com.github.ben-manes.caffeine caffeine diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java index af02ec543498..d032f703fad2 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/ProxiedEntitiesUtils.java @@ -29,6 +29,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUserUtils; +import org.apache.nifi.security.proxied.entity.ProxiedEntityEncoder; +import org.apache.nifi.security.proxied.entity.StandardProxiedEntityEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.AuthenticationException; @@ -51,32 +53,7 @@ public class ProxiedEntitiesUtils { private static final String ANONYMOUS_CHAIN = "<>"; private static final String ANONYMOUS_IDENTITY = ""; - /** - * Formats a list of DN/usernames to be set as a HTTP header using well known conventions. - * - * @param proxiedEntities the raw identities (usernames and DNs) to be formatted as a chain - * @return the value to use in the X-ProxiedEntitiesChain header - */ - public static String getProxiedEntitiesChain(final String... proxiedEntities) { - return getProxiedEntitiesChain(Arrays.asList(proxiedEntities)); - } - - /** - * Formats a list of DN/usernames to be set as a HTTP header using well known conventions. - * - * @param proxiedEntities the raw identities (usernames and DNs) to be formatted as a chain - * @return the value to use in the X-ProxiedEntitiesChain header - */ - public static String getProxiedEntitiesChain(final List proxiedEntities) { - if (proxiedEntities == null) { - return null; - } - - final List proxiedEntityChain = proxiedEntities.stream() - .map(org.apache.nifi.registry.security.util.ProxiedEntitiesUtils::formatProxyDn) - .collect(Collectors.toList()); - return StringUtils.join(proxiedEntityChain, ""); - } + private static final ProxiedEntityEncoder proxiedEntityEncoder = StandardProxiedEntityEncoder.getInstance(); /** * Tokenizes the specified proxy chain. @@ -134,15 +111,13 @@ public static String buildProxiedEntitiesChainString(final NiFiUser user) { if (proxyChain.isEmpty()) { return ANONYMOUS_CHAIN; } - proxyChain = proxyChain.stream().map(ProxiedEntitiesUtils::formatProxyDn).collect(Collectors.toList()); + proxyChain = proxyChain.stream().map(proxiedEntityEncoder::getEncodedEntity).collect(Collectors.toList()); return StringUtils.join(proxyChain, ""); } /** * Builds the string representation for a set of groups that belong to a proxied entity. - * * The resulting string will be formatted similar to a proxied-entity chain. - * * Example: * Groups set: ("group1", "group2", "group3") * Returns: {@code " } @@ -155,7 +130,7 @@ public static String buildProxiedEntityGroupsString(final Set groups) { return PROXY_ENTITY_GROUPS_EMPTY; } - final List formattedGroups = groups.stream().map(ProxiedEntitiesUtils::formatProxyDn).collect(Collectors.toList()); + final List formattedGroups = groups.stream().map(proxiedEntityEncoder::getEncodedEntity).collect(Collectors.toList()); return StringUtils.join(formattedGroups, ""); } @@ -187,68 +162,6 @@ public static void unsuccessfulAuthentication( } } - /** - * Formats the specified DN to be set as a HTTP header using well known conventions. - * - * @param dn raw dn - * @return the dn formatted as an HTTP header - */ - public static String formatProxyDn(final String dn) { - return LT + sanitizeDn(dn) + GT; - } - - /** - * Sanitizes a DN for safe and lossless transmission. - * - * Sanitization requires: - *
    - *
  1. Encoded so that it can be sent losslessly using US-ASCII (the character set of HTTP Header values)
  2. - *
  3. Resilient to a DN with the sequence '><' to attempt to escape the tokenization process and impersonate another user.
  4. - *
- * - *

- * Example: - *

- * Provided DN: {@code jdoe> {@code } would allow the user to impersonate jdoe - *

Алйс - * Provided DN: {@code Алйс} -> {@code <Алйс>} cannot be encoded/decoded as ASCII - * - * @param rawDn the unsanitized DN - * @return the sanitized DN - */ - private static String sanitizeDn(final String rawDn) { - if (StringUtils.isEmpty(rawDn)) { - return rawDn; - } else { - - // First, escape any GT [>] or LT [<] characters, which are not safe - final String escapedDn = rawDn.replaceAll(GT, ESCAPED_GT).replaceAll(LT, ESCAPED_LT); - if (!escapedDn.equals(rawDn)) { - logger.warn("The provided DN [{}] contained dangerous characters that were escaped to [{}]", rawDn, escapedDn); - } - - // Second, check for characters outside US-ASCII. - // This is necessary because X509 Certs can contain international/Unicode characters, - // but this value will be passed in an HTTP Header which must be US-ASCII. - // If non-ascii characters are present, base64 encode the DN and wrap in , - // to indicate to the receiving end that the value must be decoded. - // Note: We could have decided to always base64 encode these values, - // not only to avoid the isPureAscii(...) check, but also as a - // method of sanitizing GT [>] or LT [<] chars. However, there - // are advantages to encoding only when necessary, namely: - // 1. Backwards compatibility - // 2. Debugging this X-ProxiedEntitiesChain headers is easier unencoded. - // This algorithm can be revisited as part of the next major version change. - if (isPureAscii(escapedDn)) { - return escapedDn; - } else { - final String encodedDn = base64Encode(escapedDn); - logger.debug("The provided DN [{}] contained non-ASCII characters and was encoded as [{}]", rawDn, encodedDn); - return encodedDn; - } - } - } - /** * Reconstitutes the original DN from the sanitized version passed in the proxy chain. *

@@ -281,19 +194,7 @@ private static String unsanitizeDn(final String sanitizedDn) { } /** - * Base64 encodes a DN and wraps it in angled brackets to indicate the value is base64 and not a raw DN. - * - * @param rawValue The value to encode - * @return A string containing a wrapped, encoded value. - */ - private static String base64Encode(final String rawValue) { - final String base64String = Base64.getEncoder().encodeToString(rawValue.getBytes(StandardCharsets.UTF_8)); - final String wrappedEncodedValue = LT + base64String + GT; - return wrappedEncodedValue; - } - - /** - * Performs the reverse of ${@link #base64Encode(String)}. + * Performs the reverse of Base64 encoding * * @param encodedValue the encoded value to decode. * @return The original, decoded string. @@ -314,7 +215,7 @@ private static boolean isValidChainFormat(final String rawProxiedEntitiesChain) } /** - * Check if a value has been encoded by ${@link #base64Encode(String)}, and therefore needs to be decoded. + * Check if a value has been encoded by Base64 encoding and therefore needs to be decoded. * * @param token the value to check * @return true if the value is encoded, false otherwise. @@ -332,14 +233,4 @@ private static boolean isBase64Encoded(final String token) { private static boolean isWrappedInAngleBrackets(final String string) { return string.startsWith(LT) && string.endsWith(GT); } - - /** - * Check if a string contains only pure ascii characters. - * - * @param stringWithUnknownCharacters - the string to check - * @return true if string can be encoded as ascii. false otherwise. - */ - private static boolean isPureAscii(final String stringWithUnknownCharacters) { - return StandardCharsets.US_ASCII.newEncoder().canEncode(stringWithUnknownCharacters); - } } diff --git a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/ProxiedEntitiesUtilsTest.java b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/ProxiedEntitiesUtilsTest.java index 503ae3cb94cc..8eb72b5f23b9 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/ProxiedEntitiesUtilsTest.java +++ b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/test/java/org/apache/nifi/web/security/ProxiedEntitiesUtilsTest.java @@ -19,8 +19,6 @@ import org.apache.nifi.authorization.user.NiFiUser; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -33,7 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -45,7 +42,6 @@ public class ProxiedEntitiesUtilsTest { private static final String SAFE_USER_NAME_PROXY_2 = "proxy2.nifi.apache.org"; private static final String SAFE_USER_DN_PROXY_2 = "CN=" + SAFE_USER_NAME_PROXY_2 + ", OU=Apache NiFi"; private static final String MALICIOUS_USER_NAME_JOHN = SAFE_USER_NAME_JOHN + ", OU=Apache NiFi>"; @@ -62,57 +58,6 @@ private static String base64Encode(String dn) { return Base64.getEncoder().encodeToString(dn.getBytes(StandardCharsets.UTF_8)); } - @ParameterizedTest - @MethodSource("getMaliciousNames" ) - public void testSanitizeDnShouldHandleFuzzing(String maliciousName) { - assertNotEquals(formatDn(SAFE_USER_NAME_JOHN), ProxiedEntitiesUtils.formatProxyDn(maliciousName)); - } - - // Contains various attempted >< escapes, trailing NULL, and BACKSPACE + 'n' - private static List getMaliciousNames() { - return Arrays.asList(MALICIOUS_USER_NAME_JOHN, - SAFE_USER_NAME_JOHN + ">", - SAFE_USER_NAME_JOHN + "><>", - SAFE_USER_NAME_JOHN + "\\>", - SAFE_USER_NAME_JOHN + "\u003e", - SAFE_USER_NAME_JOHN + "\u005c\u005c\u003e", - SAFE_USER_NAME_JOHN + "\u0000", - SAFE_USER_NAME_JOHN + "\u0008n"); - } - - @Test - public void testShouldFormatProxyDn() { - assertEquals(formatDn(SAFE_USER_DN_JOHN), ProxiedEntitiesUtils.formatProxyDn(SAFE_USER_DN_JOHN)); - } - - @Test - public void testFormatProxyDnShouldHandleMaliciousInput() { - assertEquals(formatSanitizedDn(MALICIOUS_USER_DN_JOHN), ProxiedEntitiesUtils.formatProxyDn(MALICIOUS_USER_DN_JOHN)); - } - - @Test - public void testGetProxiedEntitiesChain() { - String[] input = new String[] {SAFE_USER_NAME_JOHN, SAFE_USER_DN_PROXY_1, SAFE_USER_DN_PROXY_2}; - assertEquals(formatDns(input), ProxiedEntitiesUtils.getProxiedEntitiesChain(input)); - } - - @Test - public void testGetProxiedEntitiesChainShouldHandleMaliciousInput() { - final String expectedOutput = formatSanitizedDn(MALICIOUS_USER_DN_JOHN) + formatDns(SAFE_USER_DN_PROXY_1, SAFE_USER_DN_PROXY_2); - assertEquals(expectedOutput, ProxiedEntitiesUtils.getProxiedEntitiesChain(MALICIOUS_USER_DN_JOHN, SAFE_USER_DN_PROXY_1, SAFE_USER_DN_PROXY_2)); - } - - @Test - public void testGetProxiedEntitiesChainShouldEncodeUnicode() { - assertEquals(formatDns(SAFE_USER_NAME_JOHN, UNICODE_DN_1_ENCODED, UNICODE_DN_2_ENCODED), - ProxiedEntitiesUtils.getProxiedEntitiesChain(SAFE_USER_NAME_JOHN, UNICODE_DN_1, UNICODE_DN_2)); - } - - @Test - public void testFormatProxyDnShouldEncodeNonAsciiCharacters() { - assertEquals(formatDn(UNICODE_DN_1_ENCODED), ProxiedEntitiesUtils.formatProxyDn(UNICODE_DN_1)); - } - @Test public void testShouldBuildProxyChain(@Mock NiFiUser proxy1, @Mock NiFiUser john) { when(proxy1.getIdentity()).thenReturn(SAFE_USER_NAME_PROXY_1); diff --git a/nifi-toolkit/nifi-toolkit-cli/pom.xml b/nifi-toolkit/nifi-toolkit-cli/pom.xml index be0e7fa4fc26..12fdd474a2c1 100644 --- a/nifi-toolkit/nifi-toolkit-cli/pom.xml +++ b/nifi-toolkit/nifi-toolkit-cli/pom.xml @@ -24,7 +24,6 @@ Tooling to make tls configuration easier - 33.3.1-jre 3.27.1 @@ -85,12 +84,6 @@ nifi-registry-client 2.1.0-SNAPSHOT - - - com.google.guava - guava - ${guava.version} - org.apache.nifi nifi-security-kerberos diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportAllFlows.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportAllFlows.java index 306be0bef5d3..40995466f19d 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportAllFlows.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportAllFlows.java @@ -21,7 +21,6 @@ import org.apache.commons.cli.ParseException; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import com.google.common.collect.ComparisonChain; import org.apache.nifi.flow.VersionedFlowCoordinates; import org.apache.nifi.flow.VersionedProcessGroup; import org.apache.nifi.registry.bucket.Bucket; @@ -47,6 +46,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -116,11 +116,9 @@ public StringResult doExecute(final NiFiRegistryClient client, final Properties final List files = getFilePathList(properties); // As we need to keep the version order the list needs to be sorted - files.sort((o1, o2) -> ComparisonChain.start() - .compare(o1.getBucketName(), o2.getBucketName()) - .compare(o1.getFlowName(), o2.getFlowName()) - .compare(o1.getVersion(), o2.getVersion()) - .result()); + files.sort(Comparator.comparing(VersionFileMetaData::getBucketName) + .thenComparing(VersionFileMetaData::getFlowName) + .thenComparing(VersionFileMetaData::getVersion)); for (VersionFileMetaData file : files) { final String inputSource = file.getInputSource(); diff --git a/nifi-toolkit/nifi-toolkit-client/pom.xml b/nifi-toolkit/nifi-toolkit-client/pom.xml index 9a1f95b0ebed..fba20dbfcc37 100644 --- a/nifi-toolkit/nifi-toolkit-client/pom.xml +++ b/nifi-toolkit/nifi-toolkit-client/pom.xml @@ -23,7 +23,22 @@ language governing permissions and limitations under the License. --> org.apache.nifi - nifi-web-security + nifi-security-utils-api + 2.1.0-SNAPSHOT + + + org.apache.nifi + nifi-security-ssl + 2.1.0-SNAPSHOT + + + org.apache.nifi.registry + nifi-registry-security-utils + 2.1.0-SNAPSHOT + + + org.apache.nifi + nifi-security-proxied-entity 2.1.0-SNAPSHOT @@ -36,6 +51,18 @@ language governing permissions and limitations under the License. --> nifi-client-dto 2.1.0-SNAPSHOT + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.glassfish.jersey.core + jersey-client + + + org.glassfish.jersey.media + jersey-media-json-jackson + org.apache.commons commons-lang3 diff --git a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyAccessClient.java b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyAccessClient.java index 60c8a6ccd46c..4fb4dbf20854 100644 --- a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyAccessClient.java +++ b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyAccessClient.java @@ -20,11 +20,11 @@ import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Form; +import org.apache.commons.lang3.StringUtils; import org.apache.nifi.toolkit.client.AccessClient; import org.apache.nifi.toolkit.client.NiFiClientException; import org.apache.nifi.toolkit.client.RequestConfig; import org.apache.nifi.toolkit.client.impl.request.BearerTokenRequestConfig; -import org.apache.nifi.util.StringUtils; import java.io.IOException; import java.util.Map; diff --git a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyTenantsClient.java b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyTenantsClient.java index d12e90d514e4..05c1bba74887 100644 --- a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyTenantsClient.java +++ b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyTenantsClient.java @@ -19,10 +19,10 @@ import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.MediaType; +import org.apache.commons.lang3.StringUtils; import org.apache.nifi.toolkit.client.NiFiClientException; import org.apache.nifi.toolkit.client.RequestConfig; import org.apache.nifi.toolkit.client.TenantsClient; -import org.apache.nifi.util.StringUtils; import org.apache.nifi.web.api.entity.UserEntity; import org.apache.nifi.web.api.entity.UserGroupEntity; import org.apache.nifi.web.api.entity.UserGroupsEntity; diff --git a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/request/ProxiedEntityRequestConfig.java b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/request/ProxiedEntityRequestConfig.java index 6cbe1cf46a49..4ce050488ae9 100644 --- a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/request/ProxiedEntityRequestConfig.java +++ b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/request/ProxiedEntityRequestConfig.java @@ -17,8 +17,8 @@ package org.apache.nifi.toolkit.client.impl.request; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.security.proxied.entity.StandardProxiedEntityEncoder; import org.apache.nifi.toolkit.client.RequestConfig; -import org.apache.nifi.web.security.ProxiedEntitiesUtils; import java.util.Arrays; import java.util.HashMap; @@ -33,6 +33,8 @@ */ public class ProxiedEntityRequestConfig implements RequestConfig { + private static final String PROXIED_ENTITIES_CHAIN_HEADER = "X-Proxied-Entities-Chain"; + private final String[] proxiedEntities; public ProxiedEntityRequestConfig(final String... proxiedEntities) { @@ -41,22 +43,22 @@ public ProxiedEntityRequestConfig(final String... proxiedEntities) { @Override public Map getHeaders() { - final String proxiedEntitiesValue = getProxiedEntitesValue(proxiedEntities); + final String proxiedEntitiesValue = getProxiedEntitiesValue(proxiedEntities); final Map headers = new HashMap<>(); if (proxiedEntitiesValue != null) { - headers.put(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxiedEntitiesValue); + headers.put(PROXIED_ENTITIES_CHAIN_HEADER, proxiedEntitiesValue); } return headers; } - private String getProxiedEntitesValue(final String[] proxiedEntities) { + private String getProxiedEntitiesValue(final String[] proxiedEntities) { if (proxiedEntities == null) { return null; } final List proxiedEntityChain = Arrays.stream(proxiedEntities) - .map(ProxiedEntitiesUtils::formatProxyDn) + .map(StandardProxiedEntityEncoder.getInstance()::getEncodedEntity) .collect(Collectors.toList()); return StringUtils.join(proxiedEntityChain, ""); }