This is an automated email from the ASF dual-hosted git repository. mattyb149 pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push: new 1f7aeb9002 NIFI-13823 Corrected Certificate Generation for Web Proxy Host Property 1f7aeb9002 is described below commit 1f7aeb9002aa1a74734c394006eeb0088484da80 Author: exceptionfactory <exceptionfact...@apache.org> AuthorDate: Wed Oct 2 16:20:36 2024 -0500 NIFI-13823 Corrected Certificate Generation for Web Proxy Host Property - Added processing to split on comma separator and remove optional port number Signed-off-by: Matt Burgess <mattyb...@apache.org> This closes #9339 --- .../SecurityApplicationPropertyHandler.java | 32 +++++++++++++++-- .../SecurityApplicationPropertyHandlerTest.java | 42 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandler.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandler.java index 173d252340..ea84b4dcf6 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandler.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandler.java @@ -47,10 +47,14 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.HexFormat; import java.util.List; import java.util.Objects; import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Standard implementation for application security generates Key Pair and Certificate when not configured @@ -74,6 +78,12 @@ public class SecurityApplicationPropertyHandler implements ApplicationPropertyHa private static final String PROPERTY_SEPARATOR = "="; + private static final Pattern HOST_PORT_PATTERN = Pattern.compile("^([\\w-.]{1,63}):?\\d{0,5}$"); + + private static final int HOST_GROUP = 1; + + private static final Pattern HOST_PORT_GROUP_SEPARATOR = Pattern.compile("\\s*,\\s*"); + private final Logger logger; public SecurityApplicationPropertyHandler(final Logger logger) { @@ -236,9 +246,8 @@ public class SecurityApplicationPropertyHandler implements ApplicationPropertyHa subjectAlternativeNames.add(localHostName); final String proxyHost = applicationProperties.getProperty(SecurityProperty.WEB_PROXY_HOST.getName()); - if (!isBlank(proxyHost)) { - subjectAlternativeNames.add(proxyHost); - } + final Set<String> proxyHostNames = getHosts(proxyHost); + subjectAlternativeNames.addAll(proxyHostNames); return subjectAlternativeNames; } catch (final UnknownHostException e) { @@ -288,6 +297,23 @@ public class SecurityApplicationPropertyHandler implements ApplicationPropertyHa } } + private Set<String> getHosts(final String property) { + final Set<String> hosts = new HashSet<>(); + + if (property != null) { + final String[] hostPortGroups = HOST_PORT_GROUP_SEPARATOR.split(property); + for (final String hostPortGroup : hostPortGroups) { + final Matcher hostPortMatcher = HOST_PORT_PATTERN.matcher(hostPortGroup); + if (hostPortMatcher.matches()) { + final String host = hostPortMatcher.group(HOST_GROUP); + hosts.add(host); + } + } + } + + return hosts; + } + private boolean isBlank(final String propertyValue) { return propertyValue == null || propertyValue.isBlank(); } diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandlerTest.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandlerTest.java index c41e2226e1..e038356702 100644 --- a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandlerTest.java +++ b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/property/SecurityApplicationPropertyHandlerTest.java @@ -31,10 +31,16 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyStore; +import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; import java.util.Properties; 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.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -53,6 +59,16 @@ class SecurityApplicationPropertyHandlerTest { private static final String TRUSTSTORE_FILE = "truststore.p12"; + private static final int DNS_NAME_TYPE = 2; + + private static final String FIRST_PROXY_HOST = "nifi.apache.org"; + + private static final int FIRST_PROXY_HOST_PORT = 443; + + private static final String SECOND_PROXY_HOST = "nifi.local"; + + private static final String WEB_PROXY_HOST_PROPERTY = "%s:%d,%s".formatted(FIRST_PROXY_HOST, FIRST_PROXY_HOST_PORT, SECOND_PROXY_HOST); + private static final Logger logger = LoggerFactory.getLogger(SecurityApplicationPropertyHandlerTest.class); @TempDir @@ -68,6 +84,7 @@ class SecurityApplicationPropertyHandlerTest { @Test void testHandlePropertiesSuccess() throws IOException, GeneralSecurityException { final Properties sourceProperties = getSourceProperties(); + sourceProperties.setProperty(SecurityProperty.WEB_PROXY_HOST.getName(), WEB_PROXY_HOST_PROPERTY); final Path propertiesPath = writeProperties(sourceProperties); @@ -155,6 +172,31 @@ class SecurityApplicationPropertyHandlerTest { assertNotNull(certificate); assertEquals(SecurityApplicationPropertyHandler.CERTIFICATE_ISSUER, certificate.getIssuerX500Principal()); assertEquals(SecurityApplicationPropertyHandler.CERTIFICATE_ISSUER, certificate.getSubjectX500Principal()); + + assertSubjectAlternativeNamesFound(certificate); + } + + private void assertSubjectAlternativeNamesFound(final X509Certificate certificate) throws CertificateParsingException { + final Collection<List<?>> subjectAlternativeNames = certificate.getSubjectAlternativeNames(); + + assertFalse(subjectAlternativeNames.isEmpty()); + + final List<String> alternativeNames = new ArrayList<>(); + + for (final List<?> subjectAlternativeName : subjectAlternativeNames) { + final Iterator<?> generalNameValue = subjectAlternativeName.iterator(); + assertTrue(generalNameValue.hasNext()); + + final Object generalName = generalNameValue.next(); + assertEquals(DNS_NAME_TYPE, generalName); + + assertTrue(generalNameValue.hasNext()); + final Object alternativeName = generalNameValue.next(); + alternativeNames.add(alternativeName.toString()); + } + + assertTrue(alternativeNames.contains(FIRST_PROXY_HOST), "Web Proxy Host [%s] not found".formatted(FIRST_PROXY_HOST)); + assertTrue(alternativeNames.contains(SECOND_PROXY_HOST), "Web Proxy Host [%s] not found".formatted(SECOND_PROXY_HOST)); } private void assertStoreCreated(final Properties properties, final SecurityProperty securityProperty) {