diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java index c7440e2696..9a310a2fcc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java @@ -361,10 +361,6 @@ public class FileAuthorizer extends AbstractPolicyBasedAuthorizer { // grant access to the proxy resource addAccessPolicy(authorizations, ResourceType.Proxy.getValue(), jaxbNodeUser.getIdentifier(), WRITE_CODE); - //grant access to controller resource - addAccessPolicy(authorizations, ResourceType.Controller.getValue(), jaxbNodeUser.getIdentifier(), READ_CODE); - addAccessPolicy(authorizations, ResourceType.Controller.getValue(), jaxbNodeUser.getIdentifier(), WRITE_CODE); - // grant the user read/write access data of the root group if (rootGroupId != null) { addAccessPolicy(authorizations, ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + rootGroupId, jaxbNodeUser.getIdentifier(), READ_CODE); diff --git a/nifi-toolkit/nifi-toolkit-admin/pom.xml b/nifi-toolkit/nifi-toolkit-admin/pom.xml index 37500c653d..795cb0530d 100644 --- a/nifi-toolkit/nifi-toolkit-admin/pom.xml +++ b/nifi-toolkit/nifi-toolkit-admin/pom.xml @@ -47,10 +47,37 @@ language governing permissions and limitations under the License. --> org.apache.nifi nifi-client-dto ${client.version} + + + ch.qos.logback + logback-classic + + + + + org.apache.nifi + nifi-web-security + ${client.version} + + + ch.qos.logback + logback-classic + + + + + javax.servlet + javax.servlet-api org.apache.nifi nifi-properties + + + ch.qos.logback + logback-classic + + org.apache.nifi @@ -65,6 +92,12 @@ language governing permissions and limitations under the License. --> org.apache.nifi nifi-security-utils + + + ch.qos.logback + logback-classic + + org.codehaus.jackson diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/AbstractAdminTool.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/AbstractAdminTool.groovy index aed30274ca..79c5ef1f2b 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/AbstractAdminTool.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/AbstractAdminTool.groovy @@ -87,7 +87,7 @@ public abstract class AbstractAdminTool { final String versionStr = AdminUtil.getNiFiVersion(nifiConfDir,nifiLibDir) if(!StringUtils.isEmpty(versionStr)){ - Version version = new Version(versionStr,".") + Version version = new Version(versionStr.replace("-","."),".") Version minVersion = new Version(supportedMinimumVersion,".") Version.VERSION_COMPARATOR.compare(version,minVersion) >= 0 }else{ diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtil.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtil.groovy index d4e5ff60e4..011cb1aa20 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtil.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtil.groovy @@ -27,6 +27,7 @@ import org.apache.nifi.web.api.dto.NodeDTO import org.apache.nifi.web.api.dto.util.DateTimeAdapter import org.apache.nifi.web.api.entity.ClusterEntity import org.apache.nifi.web.api.entity.NodeEntity +import org.apache.nifi.web.security.ProxiedEntitiesUtils import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -85,7 +86,7 @@ public class NiFiClientUtil { urlBuilder.toString() } - public static ClusterEntity getCluster(final Client client, NiFiProperties niFiProperties, List activeUrls){ + public static ClusterEntity getCluster(final Client client, NiFiProperties niFiProperties, List activeUrls, final String proxyDN){ if(activeUrls.isEmpty()){ final String url = getUrl(niFiProperties,null) @@ -98,15 +99,21 @@ public class NiFiClientUtil { String url = activeUrl + GET_CLUSTER_ENDPOINT final WebResource webResource = client.resource(url) - final ClientResponse response = webResource.type("application/json").get(ClientResponse.class) + ClientResponse response - Integer status = response.getStatus() + if(url.startsWith("https")) { + response = webResource.type("application/json").header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, ProxiedEntitiesUtils.formatProxyDn(proxyDN)).get(ClientResponse.class) + }else{ + response = webResource.type("application/json").get(ClientResponse.class) + } + + Integer status = response.status if (status != 200) { if (status == 404) { logger.warn("This node is not attached to a cluster. Please connect to a node that is attached to the cluster for information") } else { - logger.warn("Failed with HTTP error code: {}, message: {}", status, response.getStatusInfo().getReasonPhrase()) + logger.warn("Failed with HTTP error code: {}, message: {}", status, response.getEntity(String.class)) } } else if (status == 200) { return response.getEntity(ClusterEntity.class) @@ -122,9 +129,9 @@ public class NiFiClientUtil { } - public static List getActiveClusterUrls(final Client client, NiFiProperties niFiProperties){ + public static List getActiveClusterUrls(final Client client, NiFiProperties niFiProperties, final String proxyDN){ - final ClusterEntity clusterEntity = getCluster(client, niFiProperties, Lists.newArrayList()) + final ClusterEntity clusterEntity = getCluster(client, niFiProperties, Lists.newArrayList(),proxyDN) final List activeNodes = clusterEntity.cluster.nodes.findAll{ it.status == "CONNECTED" } final List activeUrls = Lists.newArrayList() diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerTool.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerTool.groovy index 3a1c4dfc03..b39c93c7cf 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerTool.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerTool.groovy @@ -35,6 +35,7 @@ import org.apache.nifi.util.StringUtils import org.apache.nifi.web.api.dto.NodeDTO import org.apache.nifi.web.api.entity.ClusterEntity import org.apache.nifi.web.api.entity.NodeEntity +import org.apache.nifi.web.security.ProxiedEntitiesUtils import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -45,6 +46,7 @@ public class NodeManagerTool extends AbstractAdminTool { private static final String DEFAULT_DESCRIPTION = "This tool is used to manage nodes within a cluster. Supported functionality will remove node from cluster. " private static final String HELP_ARG = "help" private static final String VERBOSE_ARG = "verbose" + private static final String PROXY_DN = "proxyDn" private static final String BOOTSTRAP_CONF = "bootstrapConf" private static final String NIFI_INSTALL_DIR = "nifiInstallDir" private static final String CLUSTER_URLS = "clusterUrls" @@ -75,6 +77,7 @@ public class NodeManagerTool extends AbstractAdminTool { final Options options = new Options() options.addOption(Option.builder("h").longOpt(HELP_ARG).desc("Print help info").build()) options.addOption(Option.builder("v").longOpt(VERBOSE_ARG).desc("Set mode to verbose (default is false)").build()) + options.addOption(Option.builder("p").longOpt(PROXY_DN).hasArg().desc("User or Proxy DN that has permission to send a notification. User must have view and modify privileges to 'access the controller' in NiFi").build()) options.addOption(Option.builder("b").longOpt(BOOTSTRAP_CONF).hasArg().desc("Existing Bootstrap Configuration file").build()) options.addOption(Option.builder("d").longOpt(NIFI_INSTALL_DIR).hasArg().desc("NiFi Installation Directory").build()) options.addOption(Option.builder("o").longOpt(OPERATION).hasArg().desc("Operation to connect, disconnect or remove node from cluster").build()) @@ -89,7 +92,7 @@ public class NodeManagerTool extends AbstractAdminTool { return nodeDTOs.find{ it.address == nodeHost } } - NodeEntity updateNode(final String url, final Client client, final NodeDTO nodeDTO, final STATUS nodeStatus){ + NodeEntity updateNode(final String url, final Client client, final NodeDTO nodeDTO, final STATUS nodeStatus,final String proxyDN){ final WebResource webResource = client.resource(url) nodeDTO.status = nodeStatus String json = NiFiClientUtil.convertToJson(nodeDTO) @@ -98,36 +101,47 @@ public class NodeManagerTool extends AbstractAdminTool { logger.info("Sending node info for update: " + json) } - final ClientResponse response = webResource.type("application/json").put(ClientResponse.class,json) + ClientResponse response - if(response.getStatus() != 200){ - throw new RuntimeException("Failed with HTTP error code: " + response.getStatus()) + if(url.startsWith("https")) { + response = webResource.type("application/json").header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, ProxiedEntitiesUtils.formatProxyDn(proxyDN)).put(ClientResponse.class, json) + }else{ + response = webResource.type("application/json").put(ClientResponse.class, json) + } + + if(response.status != 200){ + throw new RuntimeException("Failed with HTTP error code " + response.status + " with reason: " +response.getEntity(String.class)) }else{ response.getEntity(NodeEntity.class) } } - void deleteNode(final String url, final Client client){ + void deleteNode(final String url, final Client client, final String proxyDN){ final WebResource webResource = client.resource(url) if(isVerbose){ logger.info("Attempting to delete node" ) } + ClientResponse response - final ClientResponse response = webResource.type("application/json").delete(ClientResponse.class) + if(url.startsWith("https")) { + response = webResource.type("application/json").header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, ProxiedEntitiesUtils.formatProxyDn(proxyDN)).delete(ClientResponse.class) + }else{ + response = webResource.type("application/json").delete(ClientResponse.class) + } - if(response.getStatus() != 200){ - throw new RuntimeException("Failed with HTTP error code: " + response.getStatus()) + if(response.status != 200){ + throw new RuntimeException("Failed with HTTP error code " + response.status + " with reason: " +response.getEntity(String.class)) } } - void disconnectNode(final Client client, NiFiProperties niFiProperties, List activeUrls){ - final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls) + void disconnectNode(final Client client, NiFiProperties niFiProperties, List activeUrls, final String proxyDN){ + final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls,proxyDN) NodeDTO currentNode = getCurrentNode(clusterEntity,niFiProperties) for(String activeUrl: activeUrls) { try { final String url = activeUrl + NODE_ENDPOINT + File.separator + currentNode.nodeId - updateNode(url, client, currentNode, STATUS.DISCONNECTING) + updateNode(url, client, currentNode, STATUS.DISCONNECTING,proxyDN) return } catch (Exception ex){ logger.warn("Could not connect to node on "+activeUrl+". Exception: "+ex.toString()) @@ -136,13 +150,13 @@ public class NodeManagerTool extends AbstractAdminTool { throw new RuntimeException("Could not successfully complete request") } - void connectNode(final Client client, NiFiProperties niFiProperties,List activeUrls){ - final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls) + void connectNode(final Client client, NiFiProperties niFiProperties,List activeUrls, final String proxyDN){ + final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls,proxyDN) NodeDTO currentNode = getCurrentNode(clusterEntity,niFiProperties) for(String activeUrl: activeUrls) { try { final String url = activeUrl + NODE_ENDPOINT + File.separator + currentNode.nodeId - updateNode(url, client, currentNode, STATUS.CONNECTING) + updateNode(url, client, currentNode, STATUS.CONNECTING,proxyDN) return } catch (Exception ex){ logger.warn("Could not connect to node on "+activeUrl+". Exception: "+ex.toString()) @@ -151,9 +165,9 @@ public class NodeManagerTool extends AbstractAdminTool { throw new RuntimeException("Could not successfully complete request") } - void removeNode(final Client client, NiFiProperties niFiProperties, List activeUrls){ + void removeNode(final Client client, NiFiProperties niFiProperties, List activeUrls, final String proxyDN){ - final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls) + final ClusterEntity clusterEntity = NiFiClientUtil.getCluster(client, niFiProperties, activeUrls,proxyDN) NodeDTO currentNode = getCurrentNode(clusterEntity,niFiProperties) if(currentNode != null) { @@ -169,11 +183,11 @@ public class NodeManagerTool extends AbstractAdminTool { } if(currentNode.status == "CONNECTED") { - currentNode = updateNode(url, client, currentNode, STATUS.DISCONNECTING).node + currentNode = updateNode(url, client, currentNode, STATUS.DISCONNECTING,proxyDN).node } if(currentNode.status == "DISCONNECTED") { - deleteNode(url, client) + deleteNode(url, client,proxyDN) } if(isVerbose){ @@ -210,6 +224,7 @@ public class NodeManagerTool extends AbstractAdminTool { } final String bootstrapConfFileName = commandLine.getOptionValue(BOOTSTRAP_CONF) + final String proxyDN = commandLine.getOptionValue(PROXY_DN) final File bootstrapConf = new File(bootstrapConfFileName) Properties bootstrapProperties = getBootstrapConf(Paths.get(bootstrapConfFileName)) String nifiConfDir = getRelativeDirectory(bootstrapProperties.getProperty("conf.dir"), bootstrapConf.getCanonicalFile().getParentFile().getParentFile().getCanonicalPath()) @@ -218,6 +233,10 @@ public class NodeManagerTool extends AbstractAdminTool { final String key = NiFiPropertiesLoader.extractKeyFromBootstrapFile(bootstrapConfFileName) final NiFiProperties niFiProperties = NiFiPropertiesLoader.withKey(key).load(nifiPropertiesFileName) + if(!StringUtils.isEmpty(niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_PORT)) && StringUtils.isEmpty(proxyDN)) { + throw new UnsupportedOperationException("Proxy DN is required for sending a notification to this node or cluster") + } + final String nifiInstallDir = commandLine.getOptionValue(NIFI_INSTALL_DIR) if(supportedNiFiMinimumVersion(nifiConfDir,nifiLibDir,SUPPORTED_MINIMUM_VERSION) && NiFiClientUtil.isCluster(niFiProperties)){ @@ -235,7 +254,7 @@ public class NodeManagerTool extends AbstractAdminTool { final String urlList = commandLine.getOptionValue(CLUSTER_URLS) activeUrls = urlList.tokenize(',') }else{ - activeUrls = NiFiClientUtil.getActiveClusterUrls(client,niFiProperties) + activeUrls = NiFiClientUtil.getActiveClusterUrls(client,niFiProperties,proxyDN) } if(isVerbose){ @@ -243,13 +262,13 @@ public class NodeManagerTool extends AbstractAdminTool { } if(operation.toLowerCase().equals(REMOVE)){ - removeNode(client,niFiProperties,activeUrls) + removeNode(client,niFiProperties,activeUrls,proxyDN) } else if(operation.toLowerCase().equals(DISCONNECT)){ - disconnectNode(client,niFiProperties,activeUrls) + disconnectNode(client,niFiProperties,activeUrls,proxyDN) } else if(operation.toLowerCase().equals(CONNECT)){ - connectNode(client,niFiProperties,activeUrls) + connectNode(client,niFiProperties,activeUrls,proxyDN) } else{ throw new ParseException("Invalid operation provided: " + operation) diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/notify/NotificationTool.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/notify/NotificationTool.groovy index ce87499c8a..215aee839e 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/notify/NotificationTool.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/notify/NotificationTool.groovy @@ -34,6 +34,7 @@ import org.apache.nifi.toolkit.admin.client.NiFiClientFactory import org.apache.nifi.util.NiFiProperties import org.apache.nifi.web.api.dto.BulletinDTO import org.apache.nifi.web.api.entity.BulletinEntity +import org.apache.nifi.web.security.ProxiedEntitiesUtils import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -45,6 +46,7 @@ public class NotificationTool extends AbstractAdminTool { private static final String HELP_ARG = "help" private static final String VERBOSE_ARG = "verbose" private static final String BOOTSTRAP_CONF = "bootstrapConf" + private static final String PROXY_DN = "proxyDn" private static final String NIFI_INSTALL_DIR = "nifiInstallDir" private static final String NOTIFICATION_MESSAGE = "message" private static final String NOTIFICATION_LEVEL = "level" @@ -70,6 +72,7 @@ public class NotificationTool extends AbstractAdminTool { final Options options = new Options() options.addOption(Option.builder("h").longOpt(HELP_ARG).desc("Print help info").build()) options.addOption(Option.builder("v").longOpt(VERBOSE_ARG).desc("Set mode to verbose (default is false)").build()) + options.addOption(Option.builder("p").longOpt(PROXY_DN).hasArg().desc("User or Proxy DN that has permission to send a notification. User must have view and modify privileges to 'access the controller' in NiFi").build()) options.addOption(Option.builder("b").longOpt(BOOTSTRAP_CONF).hasArg().desc("Existing Bootstrap Configuration file").build()) options.addOption(Option.builder("d").longOpt(NIFI_INSTALL_DIR).hasArg().desc("NiFi Installation Directory").build()) options.addOption(Option.builder("m").longOpt(NOTIFICATION_MESSAGE).hasArg().desc("Notification message for nifi instance or cluster").build()) @@ -77,7 +80,7 @@ public class NotificationTool extends AbstractAdminTool { options } - void notifyCluster(final ClientFactory clientFactory, final String nifiPropertiesFile, final String bootstrapConfFile, final String nifiInstallDir, final String message, final String level){ + void notifyCluster(final ClientFactory clientFactory, final String nifiPropertiesFile, final String bootstrapConfFile, final String nifiInstallDir, final String message, final String level, final String proxyDN){ if(isVerbose){ logger.info("Loading nifi properties for host information") @@ -99,7 +102,19 @@ public class NotificationTool extends AbstractAdminTool { bulletinDTO.category = "NOTICE" bulletinDTO.level = StringUtils.isEmpty(level) ? "INFO" : level bulletinEntity.bulletin = bulletinDTO - final ClientResponse response = webResource.type("application/json").post(ClientResponse.class, bulletinEntity) + + ClientResponse response + if(!org.apache.nifi.util.StringUtils.isEmpty(niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_PORT))) { + + if(StringUtils.isEmpty(proxyDN)){ + throw new UnsupportedOperationException("Proxy DN is required for sending a notification to this node or cluster") + } + + response = webResource.type("application/json").header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, ProxiedEntitiesUtils.formatProxyDn(proxyDN)).post(ClientResponse.class, bulletinEntity) + } + else { + response = webResource.type("application/json").post(ClientResponse.class, bulletinEntity) + } Integer status = response.getStatus() @@ -107,7 +122,7 @@ public class NotificationTool extends AbstractAdminTool { if(status == 404){ throw new RuntimeException("The notification feature is not supported by each node in the cluster") }else{ - throw new RuntimeException("Failed with HTTP error code: " + status) + throw new RuntimeException("Failed with HTTP error code " + status + " with reason: " +response.getEntity(String.class)) } } @@ -130,6 +145,7 @@ public class NotificationTool extends AbstractAdminTool { final String bootstrapConfFileName = commandLine.getOptionValue(BOOTSTRAP_CONF) final File bootstrapConf = new File(bootstrapConfFileName) final Properties bootstrapProperties = getBootstrapConf(Paths.get(bootstrapConfFileName)) + final String proxyDN = commandLine.getOptionValue(PROXY_DN) final String parentPathName = bootstrapConf.getCanonicalFile().getParentFile().getParentFile().getCanonicalPath() final String nifiConfDir = getRelativeDirectory(bootstrapProperties.getProperty("conf.dir"),parentPathName) final String nifiLibDir = getRelativeDirectory(bootstrapProperties.getProperty("lib.dir"),parentPathName) @@ -143,7 +159,7 @@ public class NotificationTool extends AbstractAdminTool { logger.info("Attempting to connect with nifi using properties:", nifiPropertiesFileName) } - notifyCluster(clientFactory, nifiPropertiesFileName, bootstrapConfFileName,nifiInstallDir,notificationMessage,notificationLevel) + notifyCluster(clientFactory, nifiPropertiesFileName, bootstrapConfFileName,nifiInstallDir,notificationMessage,notificationLevel,proxyDN) if(isVerbose) { logger.info("Message sent successfully to NiFi.") @@ -169,7 +185,7 @@ public class NotificationTool extends AbstractAdminTool { try{ tool.parse(clientFactory,args) - } catch (ParseException | UnsupportedOperationException e) { + } catch (ParseException | UnsupportedOperationException | RuntimeException e) { tool.printUsage(e.message); System.exit(1) } diff --git a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/util/Version.groovy b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/util/Version.groovy index db5dc04b19..33a11a7cb9 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/util/Version.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/main/groovy/org/apache/nifi/toolkit/admin/util/Version.groovy @@ -64,11 +64,17 @@ class Version { String[] o2V = o2.versionNumber for(int i = 0; i < o1V.length; i++) { - Integer val1 = Integer.parseInt(o1V[i]) - Integer val2 = Integer.parseInt(o2V[i]) - if (val1.compareTo(val2) != 0) { - return val1.compareTo(val2) + + if(o2V.length == i ){ + return 1 + }else { + Integer val1 = Integer.parseInt(o1V[i]) + Integer val2 = Integer.parseInt(o2V[i]) + if (val1.compareTo(val2) != 0) { + return val1.compareTo(val2) + } } + } return 0 } diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtilSpec.groovy b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtilSpec.groovy index 32a1522739..0400efe919 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtilSpec.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/client/NiFiClientUtilSpec.groovy @@ -63,7 +63,7 @@ class NiFiClientUtilSpec extends Specification{ def ClusterEntity clusterEntity = Mock ClusterEntity when: - def entity = NiFiClientUtil.getCluster(client, niFiProperties, []) + def entity = NiFiClientUtil.getCluster(client, niFiProperties, [], null) then: @@ -77,6 +77,35 @@ class NiFiClientUtilSpec extends Specification{ } + def "get secured cluster info successfully"(){ + + given: + def Client client = Mock Client + def NiFiProperties niFiProperties = Mock NiFiProperties + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + + when: + def entity = NiFiClientUtil.getCluster(client, niFiProperties, [], "ydavis@nifi") + + then: + + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_PORT) >> "8081" + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_HOST) >> "localhost" + + 1 * client.resource(_ as String) >> resource + 1 * resource.type(_) >> builder + 1 * builder.header(_,_) >> builder + 1 * builder.get(_) >> response + 1 * response.getStatus() >> 200 + 1 * response.getEntity(ClusterEntity.class) >> clusterEntity + entity == clusterEntity + + } + + def "get cluster info fails"(){ given: @@ -89,7 +118,7 @@ class NiFiClientUtilSpec extends Specification{ when: - NiFiClientUtil.getCluster(client, niFiProperties, []) + NiFiClientUtil.getCluster(client, niFiProperties, [],null) then: @@ -98,8 +127,7 @@ class NiFiClientUtilSpec extends Specification{ 1 * resource.type(_) >> builder 1 * builder.get(_) >> response 1 * response.getStatus() >> 500 - 1 * response.getStatusInfo() >> statusType - 1 * statusType.getReasonPhrase() >> "Only a node connected to a cluster can process the request." + 1 * response.getEntity(String.class) >> "Only a node connected to a cluster can process the request." def e = thrown(RuntimeException) e.message == "Unable to obtain cluster information" diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerToolSpec.groovy b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerToolSpec.groovy index e482bbc071..5fd7d3d4b1 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerToolSpec.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/nodemanager/NodeManagerToolSpec.groovy @@ -1,4 +1,3 @@ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,6 +31,8 @@ import org.junit.contrib.java.lang.system.ExpectedSystemExit import org.junit.contrib.java.lang.system.SystemOutRule import spock.lang.Specification +import javax.ws.rs.core.Response + class NodeManagerToolSpec extends Specification{ @Rule @@ -174,7 +175,7 @@ class NodeManagerToolSpec extends Specification{ def config = new NodeManagerTool() when: - config.deleteNode(url,client) + config.deleteNode(url,client,null) then: @@ -185,6 +186,30 @@ class NodeManagerToolSpec extends Specification{ } + def "delete secured node successfully"(){ + + given: + def String url = "https://locahost:8080/nifi-api/controller" + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def config = new NodeManagerTool() + + when: + config.deleteNode(url,client,null) + + then: + + 1 * client.resource(_ as String) >> resource + 1 * resource.type(_) >> builder + 1 * builder.header(_,_) >> builder + 1 * builder.delete(_) >> response + 1 * response.getStatus() >> 200 + + } + + def "delete node failed"(){ given: @@ -193,18 +218,20 @@ class NodeManagerToolSpec extends Specification{ def WebResource resource = Mock WebResource def WebResource.Builder builder = Mock WebResource.Builder def ClientResponse response = Mock ClientResponse + def Response.StatusType statusType = Mock Response.StatusType def config = new NodeManagerTool() when: - config.deleteNode(url,client) + config.deleteNode(url,client,null) then: 1 * client.resource(_ as String) >> resource 1 * resource.type(_) >> builder 1 * builder.delete(_) >> response 2 * response.getStatus() >> 403 + 1 * response.getEntity(String.class) >> "Unauthorized User" def e = thrown(RuntimeException) - e.message == "Failed with HTTP error code: 403" + e.message == "Failed with HTTP error code 403 with reason: Unauthorized User" } @@ -221,7 +248,7 @@ class NodeManagerToolSpec extends Specification{ def config = new NodeManagerTool() when: - def entity = config.updateNode(url,client,nodeDTO,NodeManagerTool.STATUS.DISCONNECTING) + def entity = config.updateNode(url,client,nodeDTO,NodeManagerTool.STATUS.DISCONNECTING,null) then: 1 * client.resource(_ as String) >> resource @@ -233,6 +260,32 @@ class NodeManagerToolSpec extends Specification{ } + def "update secured node successfully"(){ + + given: + def String url = "https://locahost:8080/nifi-api/controller" + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def NodeDTO nodeDTO = new NodeDTO() + def NodeEntity nodeEntity = Mock NodeEntity + def config = new NodeManagerTool() + + when: + def entity = config.updateNode(url,client,nodeDTO,NodeManagerTool.STATUS.DISCONNECTING,null) + + then: + 1 * client.resource(_ as String) >> resource + 1 * resource.type(_) >> builder + 1 * builder.header(_,_) >> builder + 1 * builder.put(_,_) >> response + 1 * response.getStatus() >> 200 + 1 * response.getEntity(NodeEntity.class) >> nodeEntity + entity == nodeEntity + + } + def "update node fails"(){ given: @@ -241,19 +294,21 @@ class NodeManagerToolSpec extends Specification{ def WebResource resource = Mock WebResource def WebResource.Builder builder = Mock WebResource.Builder def ClientResponse response = Mock ClientResponse + def Response.StatusType statusType = Mock Response.StatusType def NodeDTO nodeDTO = new NodeDTO() def config = new NodeManagerTool() when: - config.updateNode(url,client,nodeDTO,NodeManagerTool.STATUS.DISCONNECTING) + config.updateNode(url,client,nodeDTO,NodeManagerTool.STATUS.DISCONNECTING,null) then: 1 * client.resource(_ as String) >> resource 1 * resource.type(_) >> builder 1 * builder.put(_,_) >> response 2 * response.getStatus() >> 403 + 1 * response.getEntity(String.class) >> "Unauthorized User" def e = thrown(RuntimeException) - e.message == "Failed with HTTP error code: 403" + e.message == "Failed with HTTP error code 403 with reason: Unauthorized User" } @@ -290,10 +345,48 @@ class NodeManagerToolSpec extends Specification{ nodeDTO.address >> "localhost" expect: - config.disconnectNode(client, niFiProperties,["http://localhost:8080"]) + config.disconnectNode(client, niFiProperties,["http://localhost:8080"],null) } + + def "disconnect secured node successfully"(){ + + setup: + def NiFiProperties niFiProperties = Mock NiFiProperties + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + def ClusterDTO clusterDTO = Mock ClusterDTO + def NodeDTO nodeDTO = new NodeDTO() + nodeDTO.address = "localhost" + nodeDTO.nodeId = "1" + nodeDTO.status = "CONNECTED" + def List nodeDTOs = [nodeDTO] + def NodeEntity nodeEntity = new NodeEntity() + nodeEntity.node = nodeDTO + def config = new NodeManagerTool() + + + niFiProperties.getProperty(_) >> "localhost" + client.resource(_ as String) >> resource + resource.type(_) >> builder + builder.get(ClientResponse.class) >> response + builder.header(_,_) >> builder + builder.put(_,_) >> response + response.getStatus() >> 200 + response.getEntity(ClusterEntity.class) >> clusterEntity + response.getEntity(NodeEntity.class) >> nodeEntity + clusterEntity.getCluster() >> clusterDTO + clusterDTO.getNodes() >> nodeDTOs + nodeDTO.address >> "localhost" + + expect: + config.disconnectNode(client, niFiProperties,["https://localhost:8080"],null) + + } def "connect node successfully"(){ setup: @@ -327,7 +420,7 @@ class NodeManagerToolSpec extends Specification{ nodeDTO.address >> "localhost" expect: - config.connectNode(client, niFiProperties,["http://localhost:8080"]) + config.connectNode(client, niFiProperties,["http://localhost:8080"],null) } @@ -365,7 +458,7 @@ class NodeManagerToolSpec extends Specification{ nodeDTO.address >> "localhost" expect: - config.removeNode(client, niFiProperties,["http://localhost:8080"]) + config.removeNode(client, niFiProperties,["http://localhost:8080"],null) } @@ -410,5 +503,172 @@ class NodeManagerToolSpec extends Specification{ } + def "parse args and fail connecting secured node"(){ + + setup: + def NiFiProperties niFiProperties = Mock NiFiProperties + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + def ClusterDTO clusterDTO = Mock ClusterDTO + def NodeDTO nodeDTO = new NodeDTO() + nodeDTO.address = "localhost" + nodeDTO.nodeId = "1" + nodeDTO.status = "DISCONNECTED" + def List nodeDTOs = [nodeDTO] + def NodeEntity nodeEntity = new NodeEntity() + nodeEntity.node = nodeDTO + def config = new NodeManagerTool() + + + niFiProperties.getProperty(_) >> "localhost" + clientFactory.getClient(_,_) >> client + client.resource(_ as String) >> resource + resource.type(_) >> builder + builder.get(ClientResponse.class) >> response + builder.header(_,_) >> builder + builder.put(_,_) >> response + response.getStatus() >> 200 + response.getEntity(ClusterEntity.class) >> clusterEntity + response.getEntity(NodeEntity.class) >> nodeEntity + clusterEntity.getCluster() >> clusterDTO + clusterDTO.getNodes() >> nodeDTOs + nodeDTO.address >> "localhost" + + when: + config.parse(clientFactory,["-b","src/test/resources/notify/conf_secure/bootstrap.conf","-d","/bogus/nifi/dir","-o","connect","-u","https://localhost:8080,https://localhost1:8080"] as String[]) + + then: + def e = thrown(UnsupportedOperationException) + e.message == "Proxy DN is required for sending a notification to this node or cluster" + + + } + + def "parse args and connect secured node"(){ + + setup: + def NiFiProperties niFiProperties = Mock NiFiProperties + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + def ClusterDTO clusterDTO = Mock ClusterDTO + def NodeDTO nodeDTO = new NodeDTO() + nodeDTO.address = "localhost" + nodeDTO.nodeId = "1" + nodeDTO.status = "DISCONNECTED" + def List nodeDTOs = [nodeDTO] + def NodeEntity nodeEntity = new NodeEntity() + nodeEntity.node = nodeDTO + def config = new NodeManagerTool() + + + niFiProperties.getProperty(_) >> "localhost" + clientFactory.getClient(_,_) >> client + client.resource(_ as String) >> resource + resource.type(_) >> builder + builder.get(ClientResponse.class) >> response + builder.header(_,_) >> builder + builder.put(_,_) >> response + response.getStatus() >> 200 + response.getEntity(ClusterEntity.class) >> clusterEntity + response.getEntity(NodeEntity.class) >> nodeEntity + clusterEntity.getCluster() >> clusterDTO + clusterDTO.getNodes() >> nodeDTOs + nodeDTO.address >> "localhost" + + expect: + config.parse(clientFactory,["-b","src/test/resources/notify/conf_secure/bootstrap.conf","-d","/bogus/nifi/dir","-o","connect","-u","https://localhost:8080,https://localhost1:8080","-p","ydavis@nifi"] as String[]) + + } + + def "parse args and disconnect secured node"(){ + + setup: + def NiFiProperties niFiProperties = Mock NiFiProperties + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + def ClusterDTO clusterDTO = Mock ClusterDTO + def NodeDTO nodeDTO = new NodeDTO() + nodeDTO.address = "localhost" + nodeDTO.nodeId = "1" + nodeDTO.status = "CONNECTED" + def List nodeDTOs = [nodeDTO] + def NodeEntity nodeEntity = new NodeEntity() + nodeEntity.node = nodeDTO + def config = new NodeManagerTool() + + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_PORT) >> "8081" + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_HOST) >> "localhost" + clientFactory.getClient(_,_) >> client + client.resource(_ as String) >> resource + resource.type(_) >> builder + builder.get(ClientResponse.class) >> response + builder.header(_,_) >> builder + builder.put(_,_) >> response + response.getStatus() >> 200 + response.getEntity(ClusterEntity.class) >> clusterEntity + response.getEntity(NodeEntity.class) >> nodeEntity + clusterEntity.getCluster() >> clusterDTO + clusterDTO.getNodes() >> nodeDTOs + nodeDTO.address >> "localhost" + + expect: + config.parse(clientFactory,["-b","src/test/resources/notify/conf_secure/bootstrap.conf","-d","/bogus/nifi/dir","-o","disconnect","-u","https://localhost:8080,https://localhost1:8080","-p","ydavis@nifi"] as String[]) + + } + + def "parse args and delete secured node"(){ + + setup: + def NiFiProperties niFiProperties = Mock NiFiProperties + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def ClusterEntity clusterEntity = Mock ClusterEntity + def ClusterDTO clusterDTO = Mock ClusterDTO + def NodeDTO nodeDTO = new NodeDTO() + nodeDTO.address = "localhost" + nodeDTO.nodeId = "1" + nodeDTO.status = "CONNECTED" + def List nodeDTOs = [nodeDTO] + def NodeEntity nodeEntity = new NodeEntity() + nodeEntity.node = nodeDTO + def config = new NodeManagerTool() + + + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_PORT) >> "8081" + niFiProperties.getProperty(NiFiProperties.WEB_HTTPS_HOST) >> "localhost" + clientFactory.getClient(_,_) >> client + client.resource(_ as String) >> resource + resource.type(_) >> builder + builder.get(ClientResponse.class) >> response + builder.header(_,_) >> builder + builder.put(_,_) >> response + builder.delete(ClientResponse.class,_) >> response + response.getStatus() >> 200 + response.getEntity(ClusterEntity.class) >> clusterEntity + response.getEntity(NodeEntity.class) >> nodeEntity + clusterEntity.getCluster() >> clusterDTO + clusterDTO.getNodes() >> nodeDTOs + nodeDTO.address >> "localhost" + + expect: + config.parse(clientFactory,["-b","src/test/resources/notify/conf_secure/bootstrap.conf","-d","/bogus/nifi/dir","-o","remove","-u","https://localhost:8080,https://localhost1:8080","-p","ydavis@nifi"] as String[]) + + } + } diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/notify/NotificationToolSpec.groovy b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/notify/NotificationToolSpec.groovy index 57468c075d..a0ec50fb89 100644 --- a/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/notify/NotificationToolSpec.groovy +++ b/nifi-toolkit/nifi-toolkit-admin/src/test/groovy/org/apache/nifi/toolkit/admin/notify/NotificationToolSpec.groovy @@ -21,12 +21,19 @@ import com.sun.jersey.api.client.Client import com.sun.jersey.api.client.ClientResponse import com.sun.jersey.api.client.WebResource import org.apache.commons.cli.ParseException +import org.apache.commons.lang3.SystemUtils import org.apache.nifi.toolkit.admin.client.ClientFactory +import org.apache.nifi.toolkit.tls.standalone.TlsToolkitStandalone +import org.apache.nifi.toolkit.tls.standalone.TlsToolkitStandaloneCommandLine import org.junit.Rule import org.junit.contrib.java.lang.system.ExpectedSystemExit import org.junit.contrib.java.lang.system.SystemOutRule import spock.lang.Specification +import javax.ws.rs.core.Response +import java.nio.file.Files +import java.nio.file.attribute.PosixFilePermission + class NotificationToolSpec extends Specification{ @Rule @@ -104,7 +111,7 @@ class NotificationToolSpec extends Specification{ def config = new NotificationTool() when: - config.notifyCluster(clientFactory,"src/test/resources/notify/conf/nifi.properties","src/test/resources/notify/conf/bootstrap.conf","/bogus/nifi/dir","shutting down in 30 seconds","WARN") + config.notifyCluster(clientFactory,"src/test/resources/notify/conf/nifi.properties","src/test/resources/notify/conf/bootstrap.conf","/bogus/nifi/dir","shutting down in 30 seconds","WARN",null) then: @@ -116,9 +123,21 @@ class NotificationToolSpec extends Specification{ } - def "cluster message failed"(){ + def "send secured cluster cluster message successfully"(){ given: + + def File tmpDir = setupTmpDir() + def File testDir = new File("target/tmp/keys") + def toolkitCommandLine = ["-O", "-o",testDir.absolutePath,"-n","localhost","-C", "CN=user1","-S", "badKeyPass", "-K", "badKeyPass", "-P", "badTrustPass"] + + TlsToolkitStandaloneCommandLine tlsToolkitStandaloneCommandLine = new TlsToolkitStandaloneCommandLine() + tlsToolkitStandaloneCommandLine.parse(toolkitCommandLine as String[]) + new TlsToolkitStandalone().createNifiKeystoresAndTrustStores(tlsToolkitStandaloneCommandLine.createConfig()) + + def bootstrapConfFile = "src/test/resources/notify/conf/bootstrap.conf" + def nifiPropertiesFile = "src/test/resources/notify/conf/nifi-secured.properties" + def ClientFactory clientFactory = Mock ClientFactory def Client client = Mock Client def WebResource resource = Mock WebResource @@ -128,7 +147,38 @@ class NotificationToolSpec extends Specification{ def config = new NotificationTool() when: - config.notifyCluster(clientFactory,"src/test/resources/notify/conf/nifi.properties","src/test/resources/notify/conf/bootstrap.conf","/bogus/nifi/dir","shutting down in 30 seconds","WARN") + config.notifyCluster(clientFactory,nifiPropertiesFile,bootstrapConfFile,"/bogus/nifi/dir","shutting down in 30 seconds","WARN","ydavis@nifi") + + then: + + 1 * clientFactory.getClient(_,_) >> client + 1 * client.resource(_ as String) >> resource + 1 * resource.type(_) >> builder + 1 * builder.header(_,_) >> builder + 1 * builder.post(_,_) >> response + 1 * response.getStatus() >> 200 + + cleanup: + tmpDir.deleteDir() + + } + + + + def "cluster message failed"(){ + + given: + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + def Response.StatusType statusType = Mock Response.StatusType + + def config = new NotificationTool() + + when: + config.notifyCluster(clientFactory,"src/test/resources/notify/conf/nifi.properties","src/test/resources/notify/conf/bootstrap.conf","/bogus/nifi/dir","shutting down in 30 seconds","WARN","ydavis@nifi") then: @@ -137,8 +187,47 @@ class NotificationToolSpec extends Specification{ 1 * resource.type(_) >> builder 1 * builder.post(_,_) >> response 1 * response.getStatus() >> 403 + 1 * response.getEntity(String.class) >> "Unauthorized User" def e = thrown(RuntimeException) - e.message == "Failed with HTTP error code: 403" + e.message == "Failed with HTTP error code 403 with reason: Unauthorized User" + + } + + def "send secured cluster cluster message fails due to missing proxy dn"(){ + + given: + + def File tmpDir = setupTmpDir() + def File testDir = new File("target/tmp/keys") + def toolkitCommandLine = ["-O", "-o",testDir.absolutePath,"-n","localhost","-C", "CN=user1","-S", "badKeyPass", "-K", "badKeyPass", "-P", "badTrustPass"] + + TlsToolkitStandaloneCommandLine tlsToolkitStandaloneCommandLine = new TlsToolkitStandaloneCommandLine() + tlsToolkitStandaloneCommandLine.parse(toolkitCommandLine as String[]) + new TlsToolkitStandalone().createNifiKeystoresAndTrustStores(tlsToolkitStandaloneCommandLine.createConfig()) + + def bootstrapConfFile = "src/test/resources/notify/conf/bootstrap.conf" + def nifiPropertiesFile = "src/test/resources/notify/conf/nifi-secured.properties" + + def ClientFactory clientFactory = Mock ClientFactory + def Client client = Mock Client + def WebResource resource = Mock WebResource + def WebResource.Builder builder = Mock WebResource.Builder + def ClientResponse response = Mock ClientResponse + + def config = new NotificationTool() + + when: + config.notifyCluster(clientFactory,nifiPropertiesFile,bootstrapConfFile,"/bogus/nifi/dir","shutting down in 30 seconds","WARN",null) + + then: + + 1 * clientFactory.getClient(_,_) >> client + 1 * client.resource(_ as String) >> resource + def e = thrown(UnsupportedOperationException) + e.message == "Proxy DN is required for sending a notification to this node or cluster" + + cleanup: + tmpDir.deleteDir() } @@ -166,6 +255,25 @@ class NotificationToolSpec extends Specification{ } + def setFilePermissions(File file, List permissions = []) { + if (SystemUtils.IS_OS_WINDOWS) { + file?.setReadable(permissions.contains(PosixFilePermission.OWNER_READ)) + file?.setWritable(permissions.contains(PosixFilePermission.OWNER_WRITE)) + file?.setExecutable(permissions.contains(PosixFilePermission.OWNER_EXECUTE)) + } else { + Files.setPosixFilePermissions(file?.toPath(), permissions as Set) + } + } + def setupTmpDir(String tmpDirPath = "target/tmp/") { + File tmpDir = new File(tmpDirPath) + tmpDir.mkdirs() + setFilePermissions(tmpDir, [PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE, + PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_WRITE, PosixFilePermission.GROUP_EXECUTE, + PosixFilePermission.OTHERS_READ, PosixFilePermission.OTHERS_WRITE, PosixFilePermission.OTHERS_EXECUTE]) + tmpDir + } + + } diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/bootstrap.conf b/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/bootstrap.conf new file mode 100644 index 0000000000..6dbcb577a8 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/bootstrap.conf @@ -0,0 +1,74 @@ +# +# 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. +# + +# Java command to use when running NiFi +java=java + +# Username to use when running NiFi. This value will be ignored on Windows. +run.as= + +# Configure where NiFi's lib and conf directories live + lib.dir=./lib +conf.dir=./conf_secure + +# How long to wait after telling NiFi to shutdown before explicitly killing the Process +graceful.shutdown.seconds=20 + +# Disable JSR 199 so that we can use JSP's without running a JDK +java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true + +# JVM memory settings +java.arg.2=-Xms1024m +java.arg.3=-Xmx1024m + +# Enable Remote Debugging +java.arg.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 + +java.arg.4=-Djava.net.preferIPv4Stack=true + +# allowRestrictedHeaders is required for Cluster/Node communications to work properly +java.arg.5=-Dsun.net.http.allowRestrictedHeaders=true +java.arg.6=-Djava.protocol.handler.pkgs=sun.net.www.protocol + +# The G1GC is still considered experimental but has proven to be very advantageous in providing great +# performance without significant "stop-the-world" delays. +java.arg.13=-XX:+UseG1GC + +#Set headless mode by default +java.arg.14=-Djava.awt.headless=true + +# Master key in hexadecimal format for encrypted sensitive configuration values +nifi.bootstrap.sensitive.key= + +### +# Notification Services for notifying interested parties when NiFi is stopped, started, dies +### + +# XML File that contains the definitions of the notification services + notification.services.file=./conf/bootstrap-notification-services.xml + +# In the case that we are unable to send a notification for an event, how many times should we retry? +notification.max.attempts=5 + +# Comma-separated list of identifiers that are present in the notification.services.file; which services should be used to notify when NiFi is started? +#nifi.start.notification.services=email-notification + +# Comma-separated list of identifiers that are present in the notification.services.file; which services should be used to notify when NiFi is stopped? +#nifi.stop.notification.services=email-notification + +# Comma-separated list of identifiers that are present in the notification.services.file; which services should be used to notify when NiFi dies? +#nifi.dead.notification.services=email-notification diff --git a/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/nifi.properties b/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/nifi.properties new file mode 100644 index 0000000000..d3e2990a9d --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-admin/src/test/resources/notify/conf_secure/nifi.properties @@ -0,0 +1,107 @@ +# 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. + +# core properties # +nifi.flow.configuration.file=./conf/flow.xml.gz +nifi.flow.configuration.archive.dir=./conf/archive/ +nifi.task.configuration.file=./conf/reporting-tasks.xml +nifi.service.configuration.file=./conf/controller-services.xml +nifi.database.directory=./database_repository +nifi.flowfile.repository.directory=./flowfile_repository +nifi.flowfile.repository.partitions=4096 +nifi.flowfile.repository.checkpoint.millis=120000 +nifi.content.repository.directory.default=./content_repository +nifi.provenance.repository.capacity=25000 +nifi.templates.directory=./conf/templates +nifi.version=1.2.0-SNAPSHOT +nifi.ui.banner.text=DEFAULT BANNER +nifi.ui.autorefresh.interval.seconds=30 +nifi.flowcontroller.autoStartProcessors=true +nifi.flowcontroller.schedulestrategy=delay +nifi.flowcontroller.minimum.nanoseconds=1000000 +nifi.flowcontroller.graceful.shutdown.seconds=10 +nifi.nar.library.directory=./lib +nifi.nar.working.directory=./work/nar/ +nifi.flowservice.writedelay.seconds=2 +nifi.sensitive.props.key=REPLACE_ME +nifi.sensitive.props.algorithm=PBEWITHMD5AND256BITAES-CBC-OPENSSL +nifi.sensitive.props.provider=BC +nifi.h2.repository.maxmemoryrows=100000 +nifi.h2.url.append=;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE +nifi.h2.max.connections=20 +nifi.h2.login.timeout=500 +#For testing purposes. Default value should actually be empty! +nifi.remote.input.socket.port=5000 +nifi.remote.input.secure=true + +# web properties # +nifi.web.war.directory=./lib +nifi.web.http.host= +nifi.web.http.port= +nifi.web.https.host= +nifi.web.https.port=5050 +nifi.web.jetty.working.directory=./work/jetty + +# security properties # +nifi.security.keystore=target/tmp/keys/localhost/keystore.jks +nifi.security.keystoreType=JKS +nifi.security.keystorePasswd=badKeyPass +nifi.security.keyPasswd=badKeyPass +nifi.security.truststore=target/tmp/keys/localhost/truststore.jks +nifi.security.truststoreType=JKS +nifi.security.truststorePasswd=badTrustPass +nifi.security.needClientAuth=true +nifi.security.user.authorizer= + +# cluster common properties (cluster manager and nodes must have same values) # +nifi.cluster.protocol.heartbeat.tick.seconds=10 +nifi.cluster.protocol.is.secure=true +nifi.cluster.protocol.socket.timeout.ms=30000 +nifi.cluster.protocol.connection.handshake.timeout.seconds=45 +# if multicast is used, then nifi.cluster.protocol.multicast.xxx properties must be configured # +nifi.cluster.protocol.use.multicast=false +nifi.cluster.protocol.multicast.address= +nifi.cluster.protocol.multicast.port= +nifi.cluster.protocol.multicast.service.broadcast.delay.ms=500 +nifi.cluster.protocol.multicast.service.locator.attempts=3 +nifi.cluster.protocol.multicast.service.locator.attempts.delay.seconds=1 +#For testing purposes. Default value should actually be empty! +nifi.cluster.remote.input.socket.port=5000 +nifi.cluster.remote.input.secure=true + +# cluster node properties (only configure for cluster nodes) # +nifi.cluster.is.node=true +nifi.cluster.node.address= +nifi.cluster.node.protocol.port= +nifi.cluster.node.protocol.threads=2 +# if multicast is not used, nifi.cluster.node.unicast.xxx must have same values as nifi.cluster.manager.xxx # +nifi.cluster.node.unicast.manager.address= +nifi.cluster.node.unicast.manager.protocol.port= +nifi.cluster.node.unicast.manager.authority.provider.port= + +# cluster manager properties (only configure for cluster manager) # +nifi.cluster.is.manager=true +nifi.cluster.manager.address=localhost +nifi.cluster.manager.protocol.port=3030 +nifi.cluster.manager.authority.provider.port=4040 +nifi.cluster.manager.authority.provider.threads=10 +nifi.cluster.manager.node.firewall.file= +nifi.cluster.manager.node.event.history.size=10 +nifi.cluster.manager.node.api.connection.timeout.ms=30000 +nifi.cluster.manager.node.api.read.timeout.ms=30000 +nifi.cluster.manager.node.api.request.threads=10 +nifi.cluster.manager.flow.retrieval.delay.seconds=5 +nifi.cluster.manager.protocol.threads=10 +nifi.cluster.manager.safemode.seconds=0