Repository: ranger Updated Branches: refs/heads/master 9f639f3c5 -> c18b3717e
RANGER-2157: Added NiFi Registry service Incorporated review comments Signed-off-by: rmani <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/ranger/repo Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/c18b3717 Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/c18b3717 Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/c18b3717 Branch: refs/heads/master Commit: c18b3717e35de2dd8b7aa069494f7b7f50dd6ce1 Parents: 9f639f3 Author: Koji Kawamura <[email protected]> Authored: Fri Feb 16 17:31:37 2018 +0900 Committer: rmani <[email protected]> Committed: Tue Sep 18 15:32:10 2018 -0700 ---------------------------------------------------------------------- .../plugin/store/EmbeddedServiceDefsUtil.java | 11 +- .../ranger-servicedef-nifi-registry.json | 167 ++++++++++++++ plugin-nifi-registry/.gitignore | 1 + plugin-nifi-registry/pom.xml | 65 ++++++ .../registry/RangerServiceNiFiRegistry.java | 71 ++++++ .../registry/client/NiFiRegistryAuthType.java | 29 +++ .../registry/client/NiFiRegistryClient.java | 217 +++++++++++++++++++ .../registry/client/NiFiRegistryConfigs.java | 37 ++++ .../client/NiFiRegistryConnectionMgr.java | 159 ++++++++++++++ .../registry/client/TestNiFiRegistryClient.java | 168 ++++++++++++++ .../client/TestNiFiRegistryConnectionMgr.java | 124 +++++++++++ .../src/test/resources/resources-response.json | 34 +++ pom.xml | 5 +- src/main/assembly/admin-web.xml | 13 ++ 14 files changed, 1097 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java ---------------------------------------------------------------------- diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java index 5e74da8..75dc128 100755 --- a/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/EmbeddedServiceDefsUtil.java @@ -48,7 +48,7 @@ public class EmbeddedServiceDefsUtil { // following servicedef list should be reviewed/updated whenever a new embedded service-def is added - private static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,sqoop,kylin"; + private static final String DEFAULT_BOOTSTRAP_SERVICEDEF_LIST = "tag,hdfs,hbase,hive,kms,knox,storm,yarn,kafka,solr,atlas,nifi,nifi-registry,sqoop,kylin"; private static final String PROPERTY_SUPPORTED_SERVICE_DEFS = "ranger.supportedcomponents"; private Set<String> supportedServiceDefs; public static final String EMBEDDED_SERVICEDEF_TAG_NAME = "tag"; @@ -62,6 +62,7 @@ public class EmbeddedServiceDefsUtil { public static final String EMBEDDED_SERVICEDEF_KAFKA_NAME = "kafka"; public static final String EMBEDDED_SERVICEDEF_SOLR_NAME = "solr"; public static final String EMBEDDED_SERVICEDEF_NIFI_NAME = "nifi"; + public static final String EMBEDDED_SERVICEDEF_NIFI_REGISTRY_NAME = "nifi-registry"; public static final String EMBEDDED_SERVICEDEF_ATLAS_NAME = "atlas"; public static final String EMBEDDED_SERVICEDEF_WASB_NAME = "wasb"; public static final String EMBEDDED_SERVICEDEF_SQOOP_NAME = "sqoop"; @@ -94,6 +95,7 @@ public class EmbeddedServiceDefsUtil { private RangerServiceDef kafkaServiceDef; private RangerServiceDef solrServiceDef; private RangerServiceDef nifiServiceDef; + private RangerServiceDef nifiRegistryServiceDef; private RangerServiceDef atlasServiceDef; private RangerServiceDef wasbServiceDef; private RangerServiceDef sqoopServiceDef; @@ -133,6 +135,7 @@ public class EmbeddedServiceDefsUtil { kafkaServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_KAFKA_NAME); solrServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_SOLR_NAME); nifiServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_NIFI_NAME); + nifiRegistryServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_NIFI_REGISTRY_NAME); atlasServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_ATLAS_NAME); tagServiceDef = getOrCreateServiceDef(store, EMBEDDED_SERVICEDEF_TAG_NAME); @@ -189,7 +192,11 @@ public class EmbeddedServiceDefsUtil { return getId(nifiServiceDef); } - public long getAtlasServiceDefId() { + public long getNiFiRegistryServiceDefId() { + return getId(nifiRegistryServiceDef); + } + + public long getAtlasServiceDefId() { return getId(atlasServiceDef); } http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/agents-common/src/main/resources/service-defs/ranger-servicedef-nifi-registry.json ---------------------------------------------------------------------- diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-nifi-registry.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-nifi-registry.json new file mode 100644 index 0000000..868543d --- /dev/null +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-nifi-registry.json @@ -0,0 +1,167 @@ +{ + "id":13, + "name":"nifi-registry", + "implClass":"org.apache.ranger.services.nifi.registry.RangerServiceNiFiRegistry", + "label":"NIFI Registry", + "description":"NiFi Registry", + "resources":[ + { + "itemId":100, + "name":"nifi-registry-resource", + "type":"string", + "level":10, + "parent":"", + "mandatory":true, + "lookupSupported":true, + "recursiveSupported":false, + "excludesSupported":false, + "matcher":"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions":{ + "wildCard":true, + "ignoreCase":true + }, + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"NiFi Registry Resource Identifier", + "description":"NiFi Registry Resource" + } + + ], + "accessTypes":[ + { + "itemId":100, + "name":"READ", + "label":"Read" + }, + { + "itemId":200, + "name":"WRITE", + "label":"Write" + }, + { + "itemId":300, + "name":"DELETE", + "label":"Delete" + } + ], + "configs":[ + { + "itemId":400, + "name":"nifi.registry.url", + "type":"string", + "mandatory":true, + "defaultValue":"http://localhost:18080/nifi-registry-api/policies/resources", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"{\"TextFieldWithIcon\":true, \"info\": \"The URL of the NiFi Registry REST API that provides the available resources.\"}", + "label":"NiFi Registry URL" + }, + { + "itemId": 410, + "name": "nifi.registry.authentication", + "type": "enum", + "subType": "authType", + "mandatory": true, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Authentication Type", + "defaultValue": "NONE" + }, + { + "itemId":500, + "name":"nifi.registry.ssl.keystore", + "type":"string", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Keystore" + }, + { + "itemId":510, + "name":"nifi.registry.ssl.keystoreType", + "type":"string", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Keystore Type" + }, + { + "itemId":520, + "name":"nifi.registry.ssl.keystorePassword", + "type":"password", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Keystore Password" + }, + { + "itemId":530, + "name":"nifi.registry.ssl.truststore", + "type":"string", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Truststore" + }, + { + "itemId":540, + "name":"nifi.registry.ssl.truststoreType", + "type":"string", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Truststore Type" + }, + { + "itemId":550, + "name":"nifi.registry.ssl.truststorePassword", + "type":"password", + "mandatory":false, + "defaultValue":"", + "validationRegEx":"", + "validationMessage":"", + "uiHint":"", + "label":"Truststore Password" + } + ], + "enums": + [ + { + "itemId": 1, + "name": "authType", + "elements": + [ + { + "itemId": 1, + "name": "NONE", + "label": "None" + }, + { + "itemId": 2, + "name": "SSL", + "label": "SSL" + } + ], + + "defaultIndex": 0 + } + ], + "contextEnrichers":[ + + ], + "policyConditions":[ + + ] +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/.gitignore ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/.gitignore b/plugin-nifi-registry/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/plugin-nifi-registry/.gitignore @@ -0,0 +1 @@ +/target http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/pom.xml ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/pom.xml b/plugin-nifi-registry/pom.xml new file mode 100644 index 0000000..3e99f04 --- /dev/null +++ b/plugin-nifi-registry/pom.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>ranger-nifi-registry-plugin</artifactId> + <name>NiFi Registry Security Plugin</name> + <description>NiFi Registry Security Plugin</description> + <packaging>jar</packaging> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <parent> + <artifactId>ranger</artifactId> + <groupId>org.apache.ranger</groupId> + <version>2.0.0-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-plugins-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>ranger-plugins-audit</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.ranger</groupId> + <artifactId>credentialbuilder</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/RangerServiceNiFiRegistry.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/RangerServiceNiFiRegistry.java b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/RangerServiceNiFiRegistry.java new file mode 100644 index 0000000..21587c7 --- /dev/null +++ b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/RangerServiceNiFiRegistry.java @@ -0,0 +1,71 @@ +/* + * 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.ranger.services.nifi.registry; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.service.RangerBaseService; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.services.nifi.registry.client.NiFiRegistryClient; +import org.apache.ranger.services.nifi.registry.client.NiFiRegistryConnectionMgr; + +import java.util.HashMap; +import java.util.List; + +/** + * RangerService for Apache NiFi Registry. + */ +public class RangerServiceNiFiRegistry extends RangerBaseService { + + private static final Log LOG = LogFactory.getLog(RangerServiceNiFiRegistry.class); + + @Override + public HashMap<String, Object> validateConfig() throws Exception { + HashMap<String, Object> ret; + String serviceName = getServiceName(); + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceNiFiRegistry.validateConfig Service: (" + serviceName + " )"); + } + + if (configs != null) { + try { + ret = NiFiRegistryConnectionMgr.connectionTest(serviceName, configs); + } catch (Exception e) { + LOG.error("<== RangerServiceNiFiRegistry.validateConfig Error:", e); + throw e; + } + } else { + throw new IllegalStateException("No Configuration found"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceNiFiRegistry.validateConfig Response : (" + ret + " )"); + } + + return ret; + } + + @Override + public List<String> lookupResource(ResourceLookupContext context) throws Exception { + final NiFiRegistryClient client = NiFiRegistryConnectionMgr.getNiFiRegistryClient(serviceName, configs); + return client.getResources(context); + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryAuthType.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryAuthType.java b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryAuthType.java new file mode 100644 index 0000000..2956afe --- /dev/null +++ b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryAuthType.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.ranger.services.nifi.registry.client; + +/** + * Possible authentication types for NiFi Registry. + */ +public enum NiFiRegistryAuthType { + + NONE, + SSL + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryClient.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryClient.java b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryClient.java new file mode 100644 index 0000000..7eff5f3 --- /dev/null +++ b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryClient.java @@ -0,0 +1,217 @@ +/* + * 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.ranger.services.nifi.registry.client; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ranger.plugin.client.BaseClient; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.ObjectMapper; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.ws.rs.core.Response; +import java.security.cert.Certificate; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +/** + * Client to communicate with NiFi Registry and retrieve available resources. + */ +public class NiFiRegistryClient { + + private static final Log LOG = LogFactory.getLog(NiFiRegistryClient.class); + + static final String SUCCESS_MSG = "ConnectionTest Successful"; + static final String FAILURE_MSG = "Unable to retrieve any resources using given parameters. "; + + private final String url; + private final SSLContext sslContext; + private final HostnameVerifier hostnameVerifier; + private final ObjectMapper mapper = new ObjectMapper(); + + public NiFiRegistryClient(final String url, final SSLContext sslContext) { + this.url = url; + this.sslContext = sslContext; + this.hostnameVerifier = new NiFiRegistryHostnameVerifier(); + } + + public HashMap<String, Object> connectionTest() { + String errMsg = ""; + boolean connectivityStatus; + HashMap<String, Object> responseData = new HashMap<>(); + + try { + final WebResource resource = getWebResource(); + final ClientResponse response = getResponse(resource, "application/json"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Got response from NiFi with status code " + response.getStatus()); + } + + if (Response.Status.OK.getStatusCode() == response.getStatus()) { + connectivityStatus = true; + } else { + connectivityStatus = false; + errMsg = "Status Code = " + response.getStatus(); + } + + } catch (Exception e) { + LOG.error("Connection to NiFi failed due to " + e.getMessage(), e); + connectivityStatus = false; + errMsg = e.getMessage(); + } + + if (connectivityStatus) { + BaseClient.generateResponseDataMap(connectivityStatus, SUCCESS_MSG, SUCCESS_MSG, null, null, responseData); + } else { + BaseClient.generateResponseDataMap(connectivityStatus, FAILURE_MSG, FAILURE_MSG + errMsg, null, null, responseData); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Response Data - " + responseData); + } + + return responseData; + } + + public List<String> getResources(ResourceLookupContext context) throws Exception { + final WebResource resource = getWebResource(); + final ClientResponse response = getResponse(resource, "application/json"); + + if (Response.Status.OK.getStatusCode() != response.getStatus()) { + String errorMsg = IOUtils.toString(response.getEntityInputStream()); + throw new Exception("Unable to retrieve resources from NiFi Registry due to: " + errorMsg); + } + + JsonNode rootNode = mapper.readTree(response.getEntityInputStream()); + if (rootNode == null) { + throw new Exception("Unable to retrieve resources from NiFi Registry"); + } + + List<String> identifiers = rootNode.findValuesAsText("identifier"); + + final String userInput = context.getUserInput(); + if (StringUtils.isBlank(userInput)) { + return identifiers; + } else { + List<String> filteredIdentifiers = new ArrayList<>(); + + for (String identifier : identifiers) { + if (identifier.contains(userInput)) { + filteredIdentifiers.add(identifier); + } + } + + return filteredIdentifiers; + } + } + + protected WebResource getWebResource() { + final ClientConfig config = new DefaultClientConfig(); + if (sslContext != null) { + config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, + new HTTPSProperties(hostnameVerifier, sslContext)); + } + + final Client client = Client.create(config); + return client.resource(url); + } + + protected ClientResponse getResponse(WebResource resource, String accept) { + return resource.accept(accept).get(ClientResponse.class); + } + + public String getUrl() { + return url; + } + + public SSLContext getSslContext() { + return sslContext; + } + + public HostnameVerifier getHostnameVerifier() { + return hostnameVerifier; + } + + /** + * Custom hostname verifier that checks subject alternative names against the hostname of the URI. + */ + private static class NiFiRegistryHostnameVerifier implements HostnameVerifier { + + @Override + public boolean verify(final String hostname, final SSLSession ssls) { + try { + for (final Certificate peerCertificate : ssls.getPeerCertificates()) { + if (peerCertificate instanceof X509Certificate) { + final X509Certificate x509Cert = (X509Certificate) peerCertificate; + final List<String> subjectAltNames = getSubjectAlternativeNames(x509Cert); + if (subjectAltNames.contains(hostname.toLowerCase())) { + return true; + } + } + } + } catch (final SSLPeerUnverifiedException | CertificateParsingException ex) { + LOG.warn("Hostname Verification encountered exception verifying hostname due to: " + ex, ex); + } + + return false; + } + + private List<String> getSubjectAlternativeNames(final X509Certificate certificate) throws CertificateParsingException { + final List<String> result = new ArrayList<>(); + final Collection<List<?>> altNames = certificate.getSubjectAlternativeNames(); + if (altNames == null) { + return result; + } + + for (final List<?> generalName : altNames) { + /** + * generalName has the name type as the first element a String or byte array for the second element. We return any general names that are String types. + * + * We don't inspect the numeric name type because some certificates incorrectly put IPs and DNS names under the wrong name types. + */ + if (generalName.size() > 1) { + final Object value = generalName.get(1); + if (value instanceof String) { + result.add(((String) value).toLowerCase()); + } + } + + } + return result; + } + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConfigs.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConfigs.java b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConfigs.java new file mode 100644 index 0000000..ea91ca4 --- /dev/null +++ b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConfigs.java @@ -0,0 +1,37 @@ +/* + * 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.ranger.services.nifi.registry.client; + +/** + * Config property names from the NiFi Registry service definition. + */ +public interface NiFiRegistryConfigs { + + String NIFI_REG_URL = "nifi.registry.url"; + String NIFI_REG_AUTHENTICATION_TYPE = "nifi.registry.authentication"; + + String NIFI_REG_SSL_KEYSTORE = "nifi.registry.ssl.keystore"; + String NIFI_REG_SSL_KEYSTORE_TYPE = "nifi.registry.ssl.keystoreType"; + String NIFI_REG_SSL_KEYSTORE_PASSWORD = "nifi.registry.ssl.keystorePassword"; + + String NIFI_REG_SSL_TRUSTSTORE = "nifi.registry.ssl.truststore"; + String NIFI_REG_SSL_TRUSTSTORE_TYPE = "nifi.registry.ssl.truststoreType"; + String NIFI_REG_SSL_TRUSTSTORE_PASSWORD = "nifi.registry.ssl.truststorePassword"; + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConnectionMgr.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConnectionMgr.java b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConnectionMgr.java new file mode 100644 index 0000000..d606d25 --- /dev/null +++ b/plugin-nifi-registry/src/main/java/org/apache/ranger/services/nifi/registry/client/NiFiRegistryConnectionMgr.java @@ -0,0 +1,159 @@ +/* + * 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.ranger.services.nifi.registry.client; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; + +/** + * Creates a NiFiRegistryClient and provides method to test a connection to NiFi Registry. + */ +public class NiFiRegistryConnectionMgr { + + private static final Log LOG = LogFactory.getLog(NiFiRegistryConnectionMgr.class); + + private static final String API_RESOURCES_PATH = "/nifi-registry-api/policies/resources"; + static final String INVALID_URL_MSG = "NiFi Registry URL must be a valid URL of the form " + + "http(s)://<hostname>(:<port>)" + API_RESOURCES_PATH; + + + static public NiFiRegistryClient getNiFiRegistryClient(String serviceName, Map<String, String> configs) throws Exception { + final String url = configs.get(NiFiRegistryConfigs.NIFI_REG_URL); + validateNotBlank(url, "NiFi Registry URL is required for " + serviceName); + validateUrl(url); + + final String authTypeStr = configs.get(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE); + validateNotBlank(authTypeStr, "Authentication Type is required for " + serviceName); + + final NiFiRegistryAuthType authType = NiFiRegistryAuthType.valueOf(authTypeStr); + if (LOG.isDebugEnabled()) { + LOG.debug("NiFiRegistryAuthType is " + authType.name()); + } + + SSLContext sslContext = null; + + if (authType == NiFiRegistryAuthType.SSL) { + + if (!url.startsWith("https")) { + throw new IllegalArgumentException("Authentication Type of SSL requires an https URL"); + } + + final String keystore = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE); + final String keystoreType = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_TYPE); + final String keystorePassword = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_PASSWORD); + + validateNotBlank(keystore, "Keystore is required for " + serviceName + " with Authentication Type of SSL"); + validateNotBlank(keystoreType, "Keystore Type is required for " + serviceName + " with Authentication Type of SSL"); + validateNotBlank(keystorePassword, "Keystore Password is required for " + serviceName + " with Authentication Type of SSL"); + + final String truststore = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE); + final String truststoreType = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_TYPE); + final String truststorePassword = configs.get(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_PASSWORD); + + validateNotBlank(truststore, "Truststore is required for " + serviceName + " with Authentication Type of SSL"); + validateNotBlank(truststoreType, "Truststore Type is required for " + serviceName + " with Authentication Type of SSL"); + validateNotBlank(truststorePassword, "Truststore Password is required for " + serviceName + " with Authentication Type of SSL"); + + LOG.debug("Creating SSLContext for NiFi Registry connection"); + + sslContext = createSslContext( + keystore.trim(), + keystorePassword.trim().toCharArray(), + keystoreType.trim(), + truststore.trim(), + truststorePassword.trim().toCharArray(), + truststoreType.trim(), + "TLS"); + } + + return new NiFiRegistryClient(url.trim(), sslContext); + } + + public static HashMap<String, Object> connectionTest(String serviceName, Map<String, String> configs) throws Exception { + NiFiRegistryClient client = getNiFiRegistryClient(serviceName, configs); + return client.connectionTest(); + } + + private static void validateNotBlank(final String input, final String message) { + if (input == null || input.trim().isEmpty()) { + throw new IllegalArgumentException(message); + } + } + + private static void validateUrl(String url) { + URI nifiUri; + try { + nifiUri = new URI(url); + if (!nifiUri.getPath().endsWith(API_RESOURCES_PATH)) { + throw new IllegalArgumentException(INVALID_URL_MSG); + } + } catch (URISyntaxException urie) { + throw new IllegalArgumentException(INVALID_URL_MSG); + } + } + + private static SSLContext createSslContext( + final String keystore, final char[] keystorePasswd, final String keystoreType, + final String truststore, final char[] truststorePasswd, final String truststoreType, + final String protocol) + throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, + UnrecoverableKeyException, KeyManagementException { + + // prepare the keystore + final KeyStore keyStore = KeyStore.getInstance(keystoreType); + try (final InputStream keyStoreStream = new FileInputStream(keystore)) { + keyStore.load(keyStoreStream, keystorePasswd); + } + final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + keyManagerFactory.init(keyStore, keystorePasswd); + + // prepare the truststore + final KeyStore trustStore = KeyStore.getInstance(truststoreType); + try (final InputStream trustStoreStream = new FileInputStream(truststore)) { + trustStore.load(trustStoreStream, truststorePasswd); + } + final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStore); + + // initialize the ssl context + final SSLContext sslContext = SSLContext.getInstance(protocol); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); + return sslContext; + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryClient.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryClient.java b/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryClient.java new file mode 100644 index 0000000..7db646f --- /dev/null +++ b/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryClient.java @@ -0,0 +1,168 @@ +/* + * 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.ranger.services.nifi.registry.client; + +import com.google.common.io.Resources; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import javax.ws.rs.core.Response; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.mockito.Mockito.when; + +public class TestNiFiRegistryClient { + + private NiFiRegistryClient registryClient; + + @Before + public void setup() throws IOException { + final URL responseFile = TestNiFiRegistryClient.class.getResource("/resources-response.json"); + final String resourcesResponse = Resources.toString(responseFile, StandardCharsets.UTF_8); + registryClient = new MockNiFiRegistryClient(resourcesResponse, 200); + } + + @Test + public void testGetResourcesNoUserInput() throws Exception { + ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class); + when(resourceLookupContext.getUserInput()).thenReturn(""); + + final List<String> expectedResources = new ArrayList<>(); + expectedResources.add("/policies"); + expectedResources.add("/tenants"); + expectedResources.add("/proxy"); + expectedResources.add("/actuator"); + expectedResources.add("/swagger"); + expectedResources.add("/buckets"); + expectedResources.add("/buckets/fc0625e4-a9ae-4277-bab7-a2bc984f6c4f"); + expectedResources.add("/buckets/0b5edba5-da83-4839-b64a-adf5f21abaf4"); + + List<String> resources = registryClient.getResources(resourceLookupContext); + Assert.assertNotNull(resources); + Assert.assertEquals(expectedResources.size(), resources.size()); + + Assert.assertTrue(resources.containsAll(expectedResources)); + } + + @Test + public void testGetResourcesWithUserInputBeginning() throws Exception { + ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class); + when(resourceLookupContext.getUserInput()).thenReturn("/p"); + + final List<String> expectedResources = new ArrayList<>(); + expectedResources.add("/policies"); + expectedResources.add("/proxy"); + + List<String> resources = registryClient.getResources(resourceLookupContext); + Assert.assertNotNull(resources); + Assert.assertEquals(expectedResources.size(), resources.size()); + + Assert.assertTrue(resources.containsAll(expectedResources)); + } + + @Test + public void testGetResourcesWithUserInputAnywhere() throws Exception { + ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class); + when(resourceLookupContext.getUserInput()).thenReturn("ant"); + + final List<String> expectedResources = new ArrayList<>(); + expectedResources.add("/tenants"); + + List<String> resources = registryClient.getResources(resourceLookupContext); + Assert.assertNotNull(resources); + Assert.assertEquals(expectedResources.size(), resources.size()); + + Assert.assertTrue(resources.containsAll(expectedResources)); + } + + @Test + public void testGetResourcesErrorResponse() { + final String errorMsg = "unknown error"; + registryClient = new MockNiFiRegistryClient(errorMsg, Response.Status.BAD_REQUEST.getStatusCode()); + + ResourceLookupContext resourceLookupContext = Mockito.mock(ResourceLookupContext.class); + when(resourceLookupContext.getUserInput()).thenReturn(""); + + try { + registryClient.getResources(resourceLookupContext); + Assert.fail("should have thrown exception"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains(errorMsg)); + } + } + + @Test + public void testConnectionTestSuccess() { + HashMap<String, Object> ret = registryClient.connectionTest(); + Assert.assertNotNull(ret); + Assert.assertEquals(NiFiRegistryClient.SUCCESS_MSG, ret.get("message")); + } + + @Test + public void testConnectionTestFailure() { + final String errorMsg = "unknown error"; + registryClient = new MockNiFiRegistryClient(errorMsg, Response.Status.BAD_REQUEST.getStatusCode()); + + HashMap<String, Object> ret = registryClient.connectionTest(); + Assert.assertNotNull(ret); + Assert.assertEquals(NiFiRegistryClient.FAILURE_MSG, ret.get("message")); + } + + + /** + * Extend NiFiRegistryClient to return mock responses. + */ + private static final class MockNiFiRegistryClient extends NiFiRegistryClient { + + private int statusCode; + private String responseEntity; + + private MockNiFiRegistryClient(String responseEntity, int statusCode) { + super("http://localhost:18080/nifi-registry-api/policiesresources", null); + this.statusCode = statusCode; + this.responseEntity = responseEntity; + } + + @Override + protected WebResource getWebResource() { + return Mockito.mock(WebResource.class); + } + + @Override + protected ClientResponse getResponse(WebResource resource, String accept) { + ClientResponse response = Mockito.mock(ClientResponse.class); + when(response.getStatus()).thenReturn(statusCode); + when(response.getEntityInputStream()).thenReturn(new ByteArrayInputStream( + responseEntity.getBytes(StandardCharsets.UTF_8) + )); + return response; + } + } +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryConnectionMgr.java ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryConnectionMgr.java b/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryConnectionMgr.java new file mode 100644 index 0000000..95a7999 --- /dev/null +++ b/plugin-nifi-registry/src/test/java/org/apache/ranger/services/nifi/registry/client/TestNiFiRegistryConnectionMgr.java @@ -0,0 +1,124 @@ +/* + * 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.ranger.services.nifi.registry.client; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.Map; + +public class TestNiFiRegistryConnectionMgr { + + @Test (expected = IllegalArgumentException.class) + public void testValidURLWithWrongEndPoint() throws Exception { + final String nifiRegistryUrl = "http://localhost:18080/nifi-registry"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.NONE.name()); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + + @Test (expected = IllegalArgumentException.class) + public void testInvalidURL() throws Exception { + final String nifiRegistryUrl = "not a url"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.NONE.name()); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + + @Test + public void testAuthTypeNone() throws Exception { + final String nifiRegistryUrl = "http://localhost:18080/nifi-registry-api/policies/resources"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.NONE.name()); + + NiFiRegistryClient client = NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi", configs); + Assert.assertNotNull(client); + Assert.assertEquals(nifiRegistryUrl, client.getUrl()); + Assert.assertNull(client.getSslContext()); + } + + @Test(expected = IllegalArgumentException.class) + public void testAuthTypeNoneMissingURL() throws Exception { + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, null); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.NONE.name()); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + + @Test(expected = FileNotFoundException.class) + public void testAuthTypeSSL() throws Exception { + final String nifiRegistryUrl = "https://localhost:18080/nifi-registry-api/policies/resources"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.SSL.name()); + + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE, "src/test/resources/missing.jks"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_PASSWORD, "password"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_TYPE, "JKS"); + + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE, "src/test/resources/missing.jks"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_PASSWORD, "password"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_TYPE, "JKS"); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + + @Test(expected = IllegalArgumentException.class) + public void testAuthTypeSSLWithNonHttpsUrl() throws Exception { + final String nifiRegistryUrl = "http://localhost:18080/nifi-registry-api/policies/resources"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.SSL.name()); + + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE, "src/test/resources/missing.jks"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_PASSWORD, "password"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_KEYSTORE_TYPE, "JKS"); + + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE, "src/test/resources/missing.jks"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_PASSWORD, "password"); + configs.put(NiFiRegistryConfigs.NIFI_REG_SSL_TRUSTSTORE_TYPE, "JKS"); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + + @Test(expected = IllegalArgumentException.class) + public void testAuthTypeSSLMissingConfigs() throws Exception { + final String nifiRegistryUrl = "http://localhost:18080/nifi-registry"; + + Map<String,String> configs = new HashMap<>(); + configs.put(NiFiRegistryConfigs.NIFI_REG_URL, nifiRegistryUrl); + configs.put(NiFiRegistryConfigs.NIFI_REG_AUTHENTICATION_TYPE, NiFiRegistryAuthType.SSL.name()); + + NiFiRegistryConnectionMgr.getNiFiRegistryClient("nifi-registry", configs); + } + +} http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/plugin-nifi-registry/src/test/resources/resources-response.json ---------------------------------------------------------------------- diff --git a/plugin-nifi-registry/src/test/resources/resources-response.json b/plugin-nifi-registry/src/test/resources/resources-response.json new file mode 100644 index 0000000..38a8e6a --- /dev/null +++ b/plugin-nifi-registry/src/test/resources/resources-response.json @@ -0,0 +1,34 @@ +[ + { + "identifier": "/policies", + "name": "Access Policies" + }, + { + "identifier": "/tenants", + "name": "Tenants" + }, + { + "identifier": "/proxy", + "name": "Proxy User Requests" + }, + { + "identifier": "/actuator", + "name": "Actuator" + }, + { + "identifier": "/swagger", + "name": "Swagger" + }, + { + "identifier": "/buckets", + "name": "Buckets" + }, + { + "identifier": "/buckets/fc0625e4-a9ae-4277-bab7-a2bc984f6c4f", + "name": "Bucket A" + }, + { + "identifier": "/buckets/0b5edba5-da83-4839-b64a-adf5f21abaf4", + "name": "Bucket B" + } +] \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 41bcd90..ebf5d48 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,8 @@ <module>security-admin</module> <module>plugin-kafka</module> <module>plugin-solr</module> - <module>plugin-nifi</module> + <module>plugin-nifi</module> + <module>plugin-nifi-registry</module> <module>ugsync</module> <module>ugsync/ldapconfigchecktool/ldapconfigcheck</module> <module>unixauthclient</module> @@ -112,7 +113,7 @@ <module>ranger-sqoop-plugin-shim</module> <module>plugin-kylin</module> <module>ranger-kylin-plugin-shim</module> - </modules> + </modules> <properties> <maven.version.required>3.3.3</maven.version.required> <java.version.required>1.8</java.version.required> http://git-wip-us.apache.org/repos/asf/ranger/blob/c18b3717/src/main/assembly/admin-web.xml ---------------------------------------------------------------------- diff --git a/src/main/assembly/admin-web.xml b/src/main/assembly/admin-web.xml index d0f3545..b3ec885 100644 --- a/src/main/assembly/admin-web.xml +++ b/src/main/assembly/admin-web.xml @@ -320,6 +320,19 @@ <moduleSet> <binaries> <includeDependencies>true</includeDependencies> + <outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/nifi-registry</outputDirectory> + <unpack>false</unpack> + <directoryMode>755</directoryMode> + <fileMode>644</fileMode> + </binaries> + <includes> + <include>org.apache.ranger:ranger-nifi-registry-plugin</include> + </includes> + </moduleSet> + + <moduleSet> + <binaries> + <includeDependencies>true</includeDependencies> <outputDirectory>/ews/webapp/WEB-INF/classes/ranger-plugins/atlas</outputDirectory> <unpack>false</unpack> <directoryMode>755</directoryMode>
