You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by me...@apache.org on 2018/09/19 05:37:33 UTC
[1/4] ranger git commit: RANGER-2198 - Remove deprecated client API
from HBase plugin
Repository: ranger
Updated Branches:
refs/heads/ranger-1 c1c299eca -> b7998dee4
RANGER-2198 - Remove deprecated client API from HBase plugin
Signed-off-by: Colm O hEigeartaigh <co...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/93de9e5b
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/93de9e5b
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/93de9e5b
Branch: refs/heads/ranger-1
Commit: 93de9e5b9aff36a6a83bcacf4fe8e66c0ec3b87c
Parents: c1c299e
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri Aug 24 12:19:43 2018 +0100
Committer: Mehul Parikh <me...@apache.org>
Committed: Wed Sep 19 11:03:33 2018 +0530
----------------------------------------------------------------------
.../hbase/RangerHBaseResource.java | 2 +-
.../services/hbase/client/HBaseClient.java | 50 ++++++++++----------
2 files changed, 25 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ranger/blob/93de9e5b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerHBaseResource.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerHBaseResource.java b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerHBaseResource.java
index 1055618..8f84662 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerHBaseResource.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/authorization/hbase/RangerHBaseResource.java
@@ -81,7 +81,7 @@ public class RangerHBaseResource extends RangerAccessResourceImpl {
if (StringUtils.equals(key, KEY_TABLE)) {
Object value = getValue(key);
if (value instanceof List) {
- List tableNames = (List) value;
+ List<?> tableNames = (List<?>) value;
if (!tableNames.isEmpty()) {
super.setValue(key, tableNames.get(0));
}
http://git-wip-us.apache.org/repos/asf/ranger/blob/93de9e5b/hbase-agent/src/main/java/org/apache/ranger/services/hbase/client/HBaseClient.java
----------------------------------------------------------------------
diff --git a/hbase-agent/src/main/java/org/apache/ranger/services/hbase/client/HBaseClient.java b/hbase-agent/src/main/java/org/apache/ranger/services/hbase/client/HBaseClient.java
index 8c47b57..e74c3e5 100644
--- a/hbase-agent/src/main/java/org/apache/ranger/services/hbase/client/HBaseClient.java
+++ b/hbase-agent/src/main/java/org/apache/ranger/services/hbase/client/HBaseClient.java
@@ -33,13 +33,13 @@ import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
+import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.Admin;
+import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.ranger.plugin.client.BaseClient;
import org.apache.ranger.plugin.client.HadoopException;
-import com.google.protobuf.ServiceException;
-
public class HBaseClient extends BaseClient {
private static final Log LOG = LogFactory.getLog(HBaseClient.class);
@@ -129,13 +129,14 @@ public class HBaseClient extends BaseClient {
@Override
public Boolean run() {
Boolean hbaseStatus1 = false;
+ Admin admin = null;
try {
LOG.info("getHBaseStatus: creating default Hbase configuration");
LOG.info("getHBaseStatus: setting config values from client");
- setClientConfigValues(conf);
+ setClientConfigValues(conf);
LOG.info("getHBaseStatus: checking HbaseAvailability with the new config");
- HBaseAdmin.checkHBaseAvailable(conf);
+ admin = ConnectionFactory.createConnection(conf).getAdmin();
LOG.info("getHBaseStatus: no exception: HbaseAvailability true");
hbaseStatus1 = true;
} catch (ZooKeeperConnectionException zce) {
@@ -160,15 +161,6 @@ public class HBaseClient extends BaseClient {
LOG.error(msgDesc + mnre);
throw hdpException;
- } catch (ServiceException se) {
- String msgDesc = "getHBaseStatus: Unable to check availability of "
- + "Hbase environment [" + getConfigHolder().getDatasourceName() + "].";
- HadoopException hdpException = new HadoopException(msgDesc, se);
- hdpException.generateResponseDataMap(false, getMessage(se),
- msgDesc + errMsg, null, null);
- LOG.error(msgDesc + se);
- throw hdpException;
-
} catch(IOException io) {
String msgDesc = "getHBaseStatus: Unable to check availability of"
+ " Hbase environment [" + getConfigHolder().getDatasourceName() + "].";
@@ -187,7 +179,15 @@ public class HBaseClient extends BaseClient {
hdpException.generateResponseDataMap(false, getMessage(e),
msgDesc + errMsg, null, null);
throw hdpException;
- }
+ } finally {
+ if (admin != null) {
+ try {
+ admin.close();
+ } catch (IOException e) {
+ LOG.error("Unable to close HBase connection [" + getConfigHolder().getDatasourceName() + "]", e);
+ }
+ }
+ }
return hbaseStatus1;
}
});
@@ -217,7 +217,7 @@ public class HBaseClient extends BaseClient {
if (v != null && !v.equalsIgnoreCase(e.getValue())) {
conf.set(e.getKey(), e.getValue());
}
- }
+ }
}
public List<String> getTableList(final String tableNameMatching, final List<String> existingTableList ) throws HadoopException {
@@ -239,14 +239,13 @@ public class HBaseClient extends BaseClient {
public List<String> run() {
List<String> tableList = new ArrayList<String>();
- HBaseAdmin admin = null;
+ Admin admin = null;
try {
LOG.info("getTableList: setting config values from client");
- setClientConfigValues(conf);
+ setClientConfigValues(conf);
LOG.info("getTableList: checking HbaseAvailability with the new config");
- HBaseAdmin.checkHBaseAvailable(conf);
+ admin = ConnectionFactory.createConnection(conf).getAdmin();
LOG.info("getTableList: no exception: HbaseAvailability true");
- admin = new HBaseAdmin(conf);
HTableDescriptor [] htds = admin.listTables(tableNameMatching);
if (htds != null) {
for (HTableDescriptor htd : htds) {
@@ -339,18 +338,17 @@ public class HBaseClient extends BaseClient {
@Override
public List<String> run() {
List<String> colfList = new ArrayList<String>();
- HBaseAdmin admin = null;
+ Admin admin = null;
try {
LOG.info("getColumnFamilyList: setting config values from client");
- setClientConfigValues(conf);
+ setClientConfigValues(conf);
LOG.info("getColumnFamilyList: checking HbaseAvailability with the new config");
- HBaseAdmin.checkHBaseAvailable(conf);
+ admin = ConnectionFactory.createConnection(conf).getAdmin();
LOG.info("getColumnFamilyList: no exception: HbaseAvailability true");
- admin = new HBaseAdmin(conf);
if (tableList != null) {
for (String tableName: tableList) {
tblName = tableName;
- HTableDescriptor htd = admin.getTableDescriptor(tblName.getBytes());
+ HTableDescriptor htd = admin.getTableDescriptor(TableName.valueOf(tblName.getBytes()));
if (htd != null) {
for (HColumnDescriptor hcd : htd.getColumnFamilies()) {
String colf = hcd.getNameAsString();
@@ -404,7 +402,7 @@ public class HBaseClient extends BaseClient {
hdpException.generateResponseDataMap(false, getMessage(se),
msgDesc + errMsg, null, null);
LOG.error(msgDesc + se);
- throw hdpException;
+ throw hdpException;
} catch (Throwable e) {
String msgDesc = "getColumnFamilyList: Unable to get HBase ColumnFamilyList for "
[2/4] ranger git commit: RANGER-2226 - Define explicit (test)
dependency on json-smart in the Knox agent
Posted by me...@apache.org.
RANGER-2226 - Define explicit (test) dependency on json-smart in the Knox agent
Signed-off-by: Colm O hEigeartaigh <co...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/6b5d7871
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/6b5d7871
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/6b5d7871
Branch: refs/heads/ranger-1
Commit: 6b5d787129d0f29e33ac568aba0d8ac87d8eae0d
Parents: 93de9e5
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri Sep 14 12:36:23 2018 +0100
Committer: Mehul Parikh <me...@apache.org>
Committed: Wed Sep 19 11:03:47 2018 +0530
----------------------------------------------------------------------
knox-agent/pom.xml | 16 ++++++++++++++++
pom.xml | 1 +
2 files changed, 17 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ranger/blob/6b5d7871/knox-agent/pom.xml
----------------------------------------------------------------------
diff --git a/knox-agent/pom.xml b/knox-agent/pom.xml
index 3130f29..5fafa73 100644
--- a/knox-agent/pom.xml
+++ b/knox-agent/pom.xml
@@ -112,6 +112,18 @@
<artifactId>gateway-server</artifactId>
<scope>test</scope>
<version>${knox.gateway.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ <scope>test</scope>
+ <version>${jsonsmart.version}</version>
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
@@ -129,6 +141,10 @@
<groupId>org.apache.knox</groupId>
<artifactId>gateway-provider-security-pac4j</artifactId>
</exclusion>
+ <exclusion>
+ <groupId>net.minidev</groupId>
+ <artifactId>json-smart</artifactId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/ranger/blob/6b5d7871/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0ae3315..4ba8c52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -181,6 +181,7 @@
<jettison.version>1.1</jettison.version>
<jline.version>0.9.94</jline.version>
<json4s.version>3.2.11</json4s.version>
+ <jsonsmart.version>2.3</jsonsmart.version>
<jsr305.version>1.3.9</jsr305.version>
<junit.version>4.12</junit.version>
<kafka.version>1.0.0</kafka.version>
[3/4] ranger git commit: RANGER-2186: Part II - check for NPE when
incrementing service-specific policy and tag versions after update
transaction is committed
Posted by me...@apache.org.
RANGER-2186: Part II - check for NPE when incrementing service-specific policy and tag versions after update transaction is committed
Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/8e10e20a
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/8e10e20a
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/8e10e20a
Branch: refs/heads/ranger-1
Commit: 8e10e20aff5575c541c52f515f2c50292326d7a0
Parents: 6b5d787
Author: Abhay Kulkarni <ak...@hortonworks.com>
Authored: Mon Sep 17 11:42:02 2018 -0700
Committer: Mehul Parikh <me...@apache.org>
Committed: Wed Sep 19 11:06:23 2018 +0530
----------------------------------------------------------------------
.../org/apache/ranger/biz/ServiceDBStore.java | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ranger/blob/8e10e20a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 32af4cd..6c699ca 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -2880,14 +2880,16 @@ public class ServiceDBStore extends AbstractServiceStore {
} else {
XXService service = daoMgr.getXXService().getById(id);
- serviceVersionInfoDbObj = new XXServiceVersionInfo();
- serviceVersionInfoDbObj.setServiceId(service.getId());
- serviceVersionInfoDbObj.setPolicyVersion(1L);
- serviceVersionInfoDbObj.setPolicyUpdateTime(new Date());
- serviceVersionInfoDbObj.setTagVersion(1L);
- serviceVersionInfoDbObj.setTagUpdateTime(new Date());
-
- serviceVersionInfoDao.create(serviceVersionInfoDbObj);
+ if (service != null) {
+ serviceVersionInfoDbObj = new XXServiceVersionInfo();
+ serviceVersionInfoDbObj.setServiceId(service.getId());
+ serviceVersionInfoDbObj.setPolicyVersion(1L);
+ serviceVersionInfoDbObj.setPolicyUpdateTime(new Date());
+ serviceVersionInfoDbObj.setTagVersion(1L);
+ serviceVersionInfoDbObj.setTagUpdateTime(new Date());
+
+ serviceVersionInfoDao.create(serviceVersionInfoDbObj);
+ }
}
}
[4/4] ranger git commit: RANGER-2157: Added NiFi Registry service
Posted by me...@apache.org.
RANGER-2157: Added NiFi Registry service
Incorporated review comments
Signed-off-by: rmani <rm...@hortonworks.com>
Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/b7998dee
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/b7998dee
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/b7998dee
Branch: refs/heads/ranger-1
Commit: b7998dee47c0262d5c96e0bdc5228221a2664a11
Parents: 8e10e20
Author: Koji Kawamura <ij...@gmail.com>
Authored: Fri Feb 16 17:31:37 2018 +0900
Committer: Mehul Parikh <me...@apache.org>
Committed: Wed Sep 19 11:06:38 2018 +0530
----------------------------------------------------------------------
.../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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/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/b7998dee/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 4ba8c52..18be2e5 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/b7998dee/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>