You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by bb...@apache.org on 2017/06/09 17:55:10 UTC
[03/11] nifi git commit: NIFI-3653: - Introducing UserGroup and
Policy provider interfaces. - Introducing FileUserGroupProvider and
FileAccessPolicyProvider. - Refactoring FileAuthorizer to utilize the file
based implementations. - Introducing the Standa
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMerger.java
new file mode 100644
index 0000000..4b2406a
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMerger.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.AccessPolicyEntityMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class AccessPolicyEndpointMerger extends AbstractSingleEntityEndpoint<AccessPolicyEntity> implements EndpointResponseMerger {
+ public static final Pattern ACCESS_POLICIES_URI_PATTERN = Pattern.compile("/nifi-api/policies");
+ public static final Pattern ACCESS_POLICY_URI_PATTERN = Pattern.compile("/nifi-api/policies/[a-f0-9\\-]{36}");
+ public static final Pattern ACCESS_POLICY_LOOKUP_URI_PATTERN = Pattern.compile("/nifi-api/policies/(?:read|write)/(?:[\\w-]+?/?)+");
+ private final AccessPolicyEntityMerger accessPolicyEntityMerger = new AccessPolicyEntityMerger();
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ if (("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) && (ACCESS_POLICY_URI_PATTERN.matcher(uri.getPath()).matches())) {
+ return true;
+ } else if ("GET".equalsIgnoreCase(method) && ACCESS_POLICY_LOOKUP_URI_PATTERN.matcher(uri.getPath()).matches()) {
+ return true;
+ } else if ("POST".equalsIgnoreCase(method) && ACCESS_POLICIES_URI_PATTERN.matcher(uri.getPath()).matches()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected Class<AccessPolicyEntity> getEntityClass() {
+ return AccessPolicyEntity.class;
+ }
+
+ @Override
+ protected void mergeResponses(final AccessPolicyEntity clientEntity, final Map<NodeIdentifier, AccessPolicyEntity> entityMap,
+ final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses) {
+
+ accessPolicyEntityMerger.merge(clientEntity, entityMap);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/SearchUsersEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/SearchUsersEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/SearchUsersEndpointMerger.java
new file mode 100644
index 0000000..31996cb
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/SearchUsersEndpointMerger.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.api.entity.TenantsEntity;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class SearchUsersEndpointMerger implements EndpointResponseMerger {
+ public static final Pattern SEARCH_TENANTS_URI_PATTERN = Pattern.compile("/nifi-api/tenants/search-results");
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ return "GET".equalsIgnoreCase(method) && SEARCH_TENANTS_URI_PATTERN.matcher(uri.getPath()).matches();
+ }
+
+ @Override
+ public final NodeResponse merge(final URI uri, final String method, final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses, final NodeResponse clientResponse) {
+ if (!canHandle(uri, method)) {
+ throw new IllegalArgumentException("Cannot use Endpoint Mapper of type " + getClass().getSimpleName() + " to map responses for URI " + uri + ", HTTP Method " + method);
+ }
+
+ final TenantsEntity responseEntity = clientResponse.getClientResponse().getEntity(TenantsEntity.class);
+ final Collection<TenantEntity> userEntities = responseEntity.getUsers();
+ final Collection<TenantEntity> userGroupEntities = responseEntity.getUserGroups();
+
+ for (final NodeResponse nodeResponse : successfulResponses) {
+ final TenantsEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(TenantsEntity.class);
+
+ // only retain users/groups that all nodes agree on
+ userEntities.retainAll(nodeResponseEntity.getUsers());
+ userGroupEntities.retainAll(nodeResponseEntity.getUserGroups());
+ }
+
+ // create a new client response
+ return new NodeResponse(clientResponse, responseEntity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserEndpointMerger.java
new file mode 100644
index 0000000..afac159
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserEndpointMerger.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.cluster.manager.UserEntityMerger;
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserEntity;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class UserEndpointMerger extends AbstractSingleEntityEndpoint<UserEntity> implements EndpointResponseMerger {
+ public static final Pattern USERS_URI_PATTERN = Pattern.compile("/nifi-api/tenants/users");
+ public static final Pattern USER_URI_PATTERN = Pattern.compile("/nifi-api/tenants/users/[a-f0-9\\-]{36}");
+ private final UserEntityMerger userEntityMerger = new UserEntityMerger();
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ if (("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) && (USER_URI_PATTERN.matcher(uri.getPath()).matches())) {
+ return true;
+ } else if ("POST".equalsIgnoreCase(method) && USERS_URI_PATTERN.matcher(uri.getPath()).matches()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected Class<UserEntity> getEntityClass() {
+ return UserEntity.class;
+ }
+
+ @Override
+ protected void mergeResponses(final UserEntity clientEntity, final Map<NodeIdentifier, UserEntity> entityMap,
+ final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses) {
+
+ userEntityMerger.merge(clientEntity, entityMap);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupEndpointMerger.java
new file mode 100644
index 0000000..ca2d6e1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupEndpointMerger.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.cluster.manager.UserGroupEntityMerger;
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class UserGroupEndpointMerger extends AbstractSingleEntityEndpoint<UserGroupEntity> implements EndpointResponseMerger {
+ public static final Pattern USER_GROUPS_URI_PATTERN = Pattern.compile("/nifi-api/tenants/user-groups");
+ public static final Pattern USER_GROUP_URI_PATTERN = Pattern.compile("/nifi-api/tenants/user-groups/[a-f0-9\\-]{36}");
+ private final UserGroupEntityMerger userGroupEntityMerger = new UserGroupEntityMerger();
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ if (("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) && (USER_GROUP_URI_PATTERN.matcher(uri.getPath()).matches())) {
+ return true;
+ } else if ("POST".equalsIgnoreCase(method) && USER_GROUPS_URI_PATTERN.matcher(uri.getPath()).matches()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected Class<UserGroupEntity> getEntityClass() {
+ return UserGroupEntity.class;
+ }
+
+ @Override
+ protected void mergeResponses(final UserGroupEntity clientEntity, final Map<NodeIdentifier, UserGroupEntity> entityMap,
+ final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses) {
+
+ userGroupEntityMerger.merge(clientEntity, entityMap);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupsEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupsEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupsEndpointMerger.java
new file mode 100644
index 0000000..3b18814
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UserGroupsEndpointMerger.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.cluster.manager.UserGroupsEntityMerger;
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
+import org.apache.nifi.web.api.entity.UserGroupsEntity;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class UserGroupsEndpointMerger implements EndpointResponseMerger {
+ public static final Pattern USER_GROUPS_URI_PATTERN = Pattern.compile("/nifi-api/tenants/user-groups");
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ return "GET".equalsIgnoreCase(method) && USER_GROUPS_URI_PATTERN.matcher(uri.getPath()).matches();
+ }
+
+ @Override
+ public final NodeResponse merge(final URI uri, final String method, final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses, final NodeResponse clientResponse) {
+ if (!canHandle(uri, method)) {
+ throw new IllegalArgumentException("Cannot use Endpoint Mapper of type " + getClass().getSimpleName() + " to map responses for URI " + uri + ", HTTP Method " + method);
+ }
+
+ final UserGroupsEntity responseEntity = clientResponse.getClientResponse().getEntity(UserGroupsEntity.class);
+ final Collection<UserGroupEntity> userGroupEntities = responseEntity.getUserGroups();
+
+ final Map<String, Map<NodeIdentifier, UserGroupEntity>> entityMap = new HashMap<>();
+ for (final NodeResponse nodeResponse : successfulResponses) {
+ final UserGroupsEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(UserGroupsEntity.class);
+ final Collection<UserGroupEntity> nodeUserGroupEntities = nodeResponseEntity.getUserGroups();
+
+ // only retain user groups that all nodes agree on
+ userGroupEntities.retainAll(nodeUserGroupEntities);
+
+ for (final UserGroupEntity nodeUserGroupEntity : nodeUserGroupEntities) {
+ final NodeIdentifier nodeId = nodeResponse.getNodeId();
+ Map<NodeIdentifier, UserGroupEntity> innerMap = entityMap.get(nodeId);
+ if (innerMap == null) {
+ innerMap = new HashMap<>();
+ entityMap.put(nodeUserGroupEntity.getId(), innerMap);
+ }
+
+ innerMap.put(nodeResponse.getNodeId(), nodeUserGroupEntity);
+ }
+ }
+
+ UserGroupsEntityMerger.mergeUserGroups(userGroupEntities, entityMap);
+
+ // create a new client response
+ return new NodeResponse(clientResponse, responseEntity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UsersEndpointMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UsersEndpointMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UsersEndpointMerger.java
new file mode 100644
index 0000000..581b359
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/endpoints/UsersEndpointMerger.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.apache.nifi.cluster.coordination.http.EndpointResponseMerger;
+import org.apache.nifi.cluster.manager.NodeResponse;
+import org.apache.nifi.cluster.manager.UsersEntityMerger;
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserEntity;
+import org.apache.nifi.web.api.entity.UsersEntity;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+public class UsersEndpointMerger implements EndpointResponseMerger {
+ public static final Pattern TENANTS_URI_PATTERN = Pattern.compile("/nifi-api/tenants/users");
+
+ @Override
+ public boolean canHandle(final URI uri, final String method) {
+ return "GET".equalsIgnoreCase(method) && TENANTS_URI_PATTERN.matcher(uri.getPath()).matches();
+ }
+
+ @Override
+ public final NodeResponse merge(final URI uri, final String method, final Set<NodeResponse> successfulResponses, final Set<NodeResponse> problematicResponses, final NodeResponse clientResponse) {
+ if (!canHandle(uri, method)) {
+ throw new IllegalArgumentException("Cannot use Endpoint Mapper of type " + getClass().getSimpleName() + " to map responses for URI " + uri + ", HTTP Method " + method);
+ }
+
+ final UsersEntity responseEntity = clientResponse.getClientResponse().getEntity(UsersEntity.class);
+ final Collection<UserEntity> userEntities = responseEntity.getUsers();
+
+ final Map<String, Map<NodeIdentifier, UserEntity>> entityMap = new HashMap<>();
+ for (final NodeResponse nodeResponse : successfulResponses) {
+ final UsersEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().getEntity(UsersEntity.class);
+ final Collection<UserEntity> nodeUserEntities = nodeResponseEntity.getUsers();
+
+ // only retain users that all nodes agree on
+ userEntities.retainAll(nodeUserEntities);
+
+ for (final UserEntity nodeUserEntity : nodeUserEntities) {
+ final NodeIdentifier nodeId = nodeResponse.getNodeId();
+ Map<NodeIdentifier, UserEntity> innerMap = entityMap.get(nodeId);
+ if (innerMap == null) {
+ innerMap = new HashMap<>();
+ entityMap.put(nodeUserEntity.getId(), innerMap);
+ }
+
+ innerMap.put(nodeResponse.getNodeId(), nodeUserEntity);
+ }
+ }
+
+ UsersEntityMerger.mergeUsers(userEntities, entityMap);
+
+ // create a new client response
+ return new NodeResponse(clientResponse, responseEntity);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMerger.java
new file mode 100644
index 0000000..88a0faf
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMerger.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class AccessPolicyEntityMerger implements ComponentEntityMerger<AccessPolicyEntity> {
+ @Override
+ public void merge(AccessPolicyEntity clientEntity, Map<NodeIdentifier, AccessPolicyEntity> entityMap) {
+ ComponentEntityMerger.super.merge(clientEntity, entityMap);
+ }
+
+ /**
+ * Merges the AccessPolicyEntity responses.
+ *
+ * @param clientEntity the entity being returned to the client
+ * @param entityMap all node responses
+ */
+ public void mergeComponents(final AccessPolicyEntity clientEntity, final Map<NodeIdentifier, AccessPolicyEntity> entityMap) {
+ final AccessPolicyDTO clientDto = clientEntity.getComponent();
+ final Map<NodeIdentifier, AccessPolicyDTO> dtoMap = new HashMap<>();
+ for (final Map.Entry<NodeIdentifier, AccessPolicyEntity> entry : entityMap.entrySet()) {
+ final AccessPolicyEntity nodeAccessPolicyEntity = entry.getValue();
+ final AccessPolicyDTO nodeAccessPolicyDto = nodeAccessPolicyEntity.getComponent();
+ dtoMap.put(entry.getKey(), nodeAccessPolicyDto);
+ }
+
+ mergeDtos(clientDto, dtoMap);
+ }
+
+ private static void mergeDtos(final AccessPolicyDTO clientDto, final Map<NodeIdentifier, AccessPolicyDTO> dtoMap) {
+ // if unauthorized for the client dto, simple return
+ if (clientDto == null) {
+ return;
+ }
+
+ final Set<TenantEntity> users = new HashSet<>(clientDto.getUsers());
+ final Set<TenantEntity> userGroups = new HashSet<>(clientDto.getUserGroups());
+
+ for (final Map.Entry<NodeIdentifier, AccessPolicyDTO> nodeEntry : dtoMap.entrySet()) {
+ final AccessPolicyDTO nodeAccessPolicy = nodeEntry.getValue();
+
+ if (nodeAccessPolicy != null) {
+ users.retainAll(nodeAccessPolicy.getUsers());
+ userGroups.retainAll(nodeAccessPolicy.getUserGroups());
+ }
+ }
+
+ clientDto.setUsers(users);
+ clientDto.setUserGroups(userGroups);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserEntityMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserEntityMerger.java
new file mode 100644
index 0000000..e1e3fcc
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserEntityMerger.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.UserDTO;
+import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.api.entity.UserEntity;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class UserEntityMerger implements ComponentEntityMerger<UserEntity> {
+
+ @Override
+ public void merge(UserEntity clientEntity, Map<NodeIdentifier, UserEntity> entityMap) {
+ ComponentEntityMerger.super.merge(clientEntity, entityMap);
+ }
+
+ /**
+ * Merges the UserEntity responses.
+ *
+ * @param clientEntity the entity being returned to the client
+ * @param entityMap all node responses
+ */
+ public void mergeComponents(final UserEntity clientEntity, final Map<NodeIdentifier, UserEntity> entityMap) {
+ final UserDTO clientDto = clientEntity.getComponent();
+ final Map<NodeIdentifier, UserDTO> dtoMap = new HashMap<>();
+ for (final Map.Entry<NodeIdentifier, UserEntity> entry : entityMap.entrySet()) {
+ final UserEntity nodeUserEntity = entry.getValue();
+ final UserDTO nodeUserDto = nodeUserEntity.getComponent();
+ dtoMap.put(entry.getKey(), nodeUserDto);
+ }
+
+ mergeDtos(clientDto, dtoMap);
+ }
+
+ private static void mergeDtos(final UserDTO clientDto, final Map<NodeIdentifier, UserDTO> dtoMap) {
+ // if unauthorized for the client dto, simple return
+ if (clientDto == null) {
+ return;
+ }
+
+ final Set<AccessPolicySummaryEntity> accessPolicyEntities = new HashSet<>(clientDto.getAccessPolicies());
+ final Set<TenantEntity> tenantEntities = new HashSet<>(clientDto.getUserGroups());
+
+ for (final Map.Entry<NodeIdentifier, UserDTO> nodeEntry : dtoMap.entrySet()) {
+ final UserDTO nodeUser = nodeEntry.getValue();
+
+ if (nodeUser != null) {
+ accessPolicyEntities.retainAll(nodeUser.getAccessPolicies());
+ tenantEntities.retainAll(nodeUser.getUserGroups());
+ }
+ }
+
+ clientDto.setAccessPolicies(accessPolicyEntities);
+ clientDto.setUserGroups(tenantEntities);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupEntityMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupEntityMerger.java
new file mode 100644
index 0000000..8142b45
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupEntityMerger.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.UserGroupDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class UserGroupEntityMerger implements ComponentEntityMerger<UserGroupEntity> {
+ @Override
+ public void merge(UserGroupEntity clientEntity, Map<NodeIdentifier, UserGroupEntity> entityMap) {
+ ComponentEntityMerger.super.merge(clientEntity, entityMap);
+ }
+
+ /**
+ * Merges the UserGroupEntity responses.
+ *
+ * @param clientEntity the entity being returned to the client
+ * @param entityMap all node responses
+ */
+ public void mergeComponents(final UserGroupEntity clientEntity, final Map<NodeIdentifier, UserGroupEntity> entityMap) {
+ final UserGroupDTO clientDto = clientEntity.getComponent();
+ final Map<NodeIdentifier, UserGroupDTO> dtoMap = new HashMap<>();
+ for (final Map.Entry<NodeIdentifier, UserGroupEntity> entry : entityMap.entrySet()) {
+ final UserGroupEntity nodeUserGroupEntity = entry.getValue();
+ final UserGroupDTO nodeUserGroupDto = nodeUserGroupEntity.getComponent();
+ dtoMap.put(entry.getKey(), nodeUserGroupDto);
+ }
+
+ mergeDtos(clientDto, dtoMap);
+ }
+
+ private static void mergeDtos(final UserGroupDTO clientDto, final Map<NodeIdentifier, UserGroupDTO> dtoMap) {
+ // if unauthorized for the client dto, simple return
+ if (clientDto == null) {
+ return;
+ }
+
+ final Set<AccessPolicyEntity> accessPolicyEntities = new HashSet<>(clientDto.getAccessPolicies());
+ final Set<TenantEntity> userEntities = new HashSet<>(clientDto.getUsers());
+
+ for (final Map.Entry<NodeIdentifier, UserGroupDTO> nodeEntry : dtoMap.entrySet()) {
+ final UserGroupDTO nodeUserGroup = nodeEntry.getValue();
+
+ if (nodeUserGroup != null) {
+ accessPolicyEntities.retainAll(nodeUserGroup.getAccessPolicies());
+ userEntities.retainAll(nodeUserGroup.getUsers());
+ }
+ }
+
+ clientDto.setAccessPolicies(accessPolicyEntities);
+ clientDto.setUsers(userEntities);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupsEntityMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupsEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupsEntityMerger.java
new file mode 100644
index 0000000..6dbb0c6
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UserGroupsEntityMerger.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class UserGroupsEntityMerger implements ComponentEntityMerger<UserGroupEntity> {
+ private static final UserGroupEntityMerger userGroupEntityMerger = new UserGroupEntityMerger();
+
+ /**
+ * Merges multiple UserGroupEntity responses.
+ *
+ * @param userGroupEntities entities being returned to the client
+ * @param entityMap all node responses
+ */
+ public static void mergeUserGroups(final Collection<UserGroupEntity> userGroupEntities, final Map<String, Map<NodeIdentifier, UserGroupEntity>> entityMap) {
+ for (final UserGroupEntity entity : userGroupEntities) {
+ userGroupEntityMerger.merge(entity, entityMap.get(entity.getId()));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UsersEntityMerger.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UsersEntityMerger.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UsersEntityMerger.java
new file mode 100644
index 0000000..4874336
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/manager/UsersEntityMerger.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.entity.UserEntity;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class UsersEntityMerger implements ComponentEntityMerger<UserEntity> {
+ private static final UserEntityMerger userEntityMerger = new UserEntityMerger();
+
+ /**
+ * Merges multiple UserEntity responses.
+ *
+ * @param userEntities entities being returned to the client
+ * @param entityMap all node responses
+ */
+ public static void mergeUsers(final Collection<UserEntity> userEntities, final Map<String, Map<NodeIdentifier, UserEntity>> entityMap) {
+ for (final UserEntity entity : userEntities) {
+ userEntityMerger.merge(entity, entityMap.get(entity.getId()));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMergerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMergerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMergerTest.java
new file mode 100644
index 0000000..c8a06ed
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/endpoints/AccessPolicyEndpointMergerTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.coordination.http.endpoints;
+
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.UUID;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class AccessPolicyEndpointMergerTest {
+
+ @Test
+ public void testCanHandle() throws Exception {
+ final AccessPolicyEndpointMerger merger = new AccessPolicyEndpointMerger();
+ assertTrue(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies"), "POST"));
+ assertFalse(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies"), "GET"));
+ assertFalse(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies"), "PUT"));
+ assertTrue(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies/" + UUID.randomUUID().toString()), "PUT"));
+ assertFalse(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies/Read/flow"), "GET"));
+ assertTrue(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies/read/flow"), "GET"));
+ assertTrue(merger.canHandle(URI.create("http://localhost:8080/nifi-api/policies/read/processors/" + UUID.randomUUID().toString()), "GET"));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/replication/TestThreadPoolRequestReplicator.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/replication/TestThreadPoolRequestReplicator.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/replication/TestThreadPoolRequestReplicator.java
index d90c49b..b5eff63 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/replication/TestThreadPoolRequestReplicator.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/coordination/http/replication/TestThreadPoolRequestReplicator.java
@@ -27,6 +27,7 @@ import org.apache.commons.collections4.map.MultiValueMap;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserDetails;
import org.apache.nifi.authorization.user.StandardNiFiUser;
+import org.apache.nifi.authorization.user.StandardNiFiUser.Builder;
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
import org.apache.nifi.cluster.coordination.node.NodeConnectionState;
import org.apache.nifi.cluster.coordination.node.NodeConnectionStatus;
@@ -157,9 +158,9 @@ public class TestThreadPoolRequestReplicator {
final Entity entity = new ProcessorEntity();
// set the user
- final NiFiUser proxy2 = new StandardNiFiUser(proxyIdentity2);
- final NiFiUser proxy1 = new StandardNiFiUser(proxyIdentity1, proxy2);
- final NiFiUser user = new StandardNiFiUser(userIdentity, proxy1);
+ final NiFiUser proxy2 = new Builder().identity(proxyIdentity2).build();
+ final NiFiUser proxy1 = new Builder().identity(proxyIdentity1).chain(proxy2).build();
+ final NiFiUser user = new Builder().identity(userIdentity).chain(proxy1).build();
final Authentication authentication = new NiFiAuthenticationToken(new NiFiUserDetails(user));
SecurityContextHolder.getContext().setAuthentication(authentication);
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMergerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMergerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMergerTest.java
new file mode 100644
index 0000000..70a941a
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/AccessPolicyEntityMergerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+import org.apache.nifi.web.api.dto.PermissionsDTO;
+import org.apache.nifi.web.api.dto.TenantDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class AccessPolicyEntityMergerTest {
+
+ @Test
+ public void testMergeAccessPolicy() throws Exception {
+ final NodeIdentifier node1 = new NodeIdentifier("node-1", "host-1", 8080, "host-1", 19998, null, null, null, false);
+ final NodeIdentifier node2 = new NodeIdentifier("node-2", "host-2", 8081, "host-2", 19999, null, null, null, false);
+
+ final PermissionsDTO permissed = new PermissionsDTO();
+ permissed.setCanRead(true);
+ permissed.setCanWrite(true);
+
+ final TenantDTO user1DTO = new TenantDTO();
+ user1DTO.setId("user-1");
+
+ final TenantEntity user1Entity = new TenantEntity();
+ user1Entity.setPermissions(permissed);
+ user1Entity.setId(user1DTO.getId());
+ user1Entity.setComponent(user1DTO);
+
+ final TenantDTO user2DTO = new TenantDTO();
+ user1DTO.setId("user-2");
+
+ final TenantEntity user2Entity = new TenantEntity();
+ user2Entity.setPermissions(permissed);
+ user2Entity.setId(user2DTO.getId());
+ user2Entity.setComponent(user2DTO);
+
+ final AccessPolicyDTO accessPolicy1DTO = new AccessPolicyDTO();
+ accessPolicy1DTO.setId("policy-1");
+ accessPolicy1DTO.setUsers(Stream.of(user1Entity, user2Entity).collect(Collectors.toSet()));
+ accessPolicy1DTO.setUserGroups(Stream.of(user2Entity).collect(Collectors.toSet()));
+
+ final AccessPolicyEntity accessPolicy1Entity = new AccessPolicyEntity();
+ accessPolicy1Entity.setPermissions(permissed);
+ accessPolicy1Entity.setId(accessPolicy1DTO.getId());
+ accessPolicy1Entity.setComponent(accessPolicy1DTO);
+
+ final AccessPolicyDTO accessPolicy2DTO = new AccessPolicyDTO();
+ accessPolicy2DTO.setId("policy-2");
+ accessPolicy2DTO.setUsers(Stream.of(user1Entity).collect(Collectors.toSet()));
+ accessPolicy2DTO.setUserGroups(Stream.of(user1Entity, user2Entity).collect(Collectors.toSet()));
+
+ final AccessPolicyEntity accessPolicy2Entity = new AccessPolicyEntity();
+ accessPolicy2Entity.setPermissions(permissed);
+ accessPolicy2Entity.setId(accessPolicy2DTO.getId());
+ accessPolicy2Entity.setComponent(accessPolicy2DTO);
+
+ final Map<NodeIdentifier, AccessPolicyEntity> nodeMap = new HashMap<>();
+ nodeMap.put(node1, accessPolicy1Entity);
+ nodeMap.put(node2, accessPolicy2Entity);
+
+ final AccessPolicyEntityMerger merger = new AccessPolicyEntityMerger();
+ merger.merge(accessPolicy1Entity, nodeMap);
+
+ assertEquals(1, accessPolicy1DTO.getUserGroups().size());
+ assertTrue(accessPolicy1DTO.getUsers().contains(user1Entity));
+
+ assertEquals(1, accessPolicy1DTO.getUserGroups().size());
+ assertTrue(accessPolicy1DTO.getUserGroups().contains(user2Entity));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserEntityMergerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserEntityMergerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserEntityMergerTest.java
new file mode 100644
index 0000000..03db8b4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserEntityMergerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.AccessPolicySummaryDTO;
+import org.apache.nifi.web.api.dto.PermissionsDTO;
+import org.apache.nifi.web.api.dto.TenantDTO;
+import org.apache.nifi.web.api.dto.UserDTO;
+import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.api.entity.UserEntity;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class UserEntityMergerTest {
+
+ @Test
+ public void testMergeAccessPolicy() throws Exception {
+ final NodeIdentifier node1 = new NodeIdentifier("node-1", "host-1", 8080, "host-1", 19998, null, null, null, false);
+ final NodeIdentifier node2 = new NodeIdentifier("node-2", "host-2", 8081, "host-2", 19999, null, null, null, false);
+
+ final PermissionsDTO permissed = new PermissionsDTO();
+ permissed.setCanRead(true);
+ permissed.setCanWrite(true);
+
+ final TenantDTO userGroup1DTO = new TenantDTO();
+ userGroup1DTO.setId("user-group-1");
+
+ final TenantEntity userGroup1Entity = new TenantEntity();
+ userGroup1Entity.setPermissions(permissed);
+ userGroup1Entity.setId(userGroup1DTO.getId());
+ userGroup1Entity.setComponent(userGroup1DTO);
+
+ final TenantDTO userGroup2DTO = new TenantDTO();
+ userGroup1DTO.setId("user-group-2");
+
+ final TenantEntity userGroup2Entity = new TenantEntity();
+ userGroup2Entity.setPermissions(permissed);
+ userGroup2Entity.setId(userGroup2DTO.getId());
+ userGroup2Entity.setComponent(userGroup2DTO);
+
+ final AccessPolicySummaryDTO policy1DTO = new AccessPolicySummaryDTO();
+ policy1DTO.setId("policy-1");
+
+ final AccessPolicySummaryEntity policy1Entity = new AccessPolicySummaryEntity();
+ policy1Entity.setPermissions(permissed);
+ policy1Entity.setId(policy1DTO.getId());
+ policy1Entity.setComponent(policy1DTO);
+
+ final AccessPolicySummaryDTO policy2DTO = new AccessPolicySummaryDTO();
+ policy2DTO.setId("policy-2");
+
+ final AccessPolicySummaryEntity policy2Entity = new AccessPolicySummaryEntity();
+ policy2Entity.setPermissions(permissed);
+ policy2Entity.setId(policy2DTO.getId());
+ policy2Entity.setComponent(policy2DTO);
+
+ final UserDTO user1DTO = new UserDTO();
+ user1DTO.setId("user-1");
+ user1DTO.setAccessPolicies(Stream.of(policy1Entity, policy2Entity).collect(Collectors.toSet()));
+ user1DTO.setUserGroups(Stream.of(userGroup2Entity).collect(Collectors.toSet()));
+
+ final UserEntity user1Entity = new UserEntity();
+ user1Entity.setPermissions(permissed);
+ user1Entity.setId(user1DTO.getId());
+ user1Entity.setComponent(user1DTO);
+
+ final UserDTO user2DTO = new UserDTO();
+ user2DTO.setId("user-2");
+ user2DTO.setAccessPolicies(Stream.of(policy1Entity).collect(Collectors.toSet()));
+ user2DTO.setUserGroups(Stream.of(userGroup1Entity, userGroup2Entity).collect(Collectors.toSet()));
+
+ final UserEntity user2Entity = new UserEntity();
+ user2Entity.setPermissions(permissed);
+ user2Entity.setId(user2DTO.getId());
+ user2Entity.setComponent(user2DTO);
+
+ final Map<NodeIdentifier, UserEntity> nodeMap = new HashMap<>();
+ nodeMap.put(node1, user1Entity);
+ nodeMap.put(node2, user2Entity);
+
+ final UserEntityMerger merger = new UserEntityMerger();
+ merger.merge(user1Entity, nodeMap);
+
+ assertEquals(1, user1DTO.getUserGroups().size());
+ assertTrue(user1DTO.getAccessPolicies().contains(policy1Entity));
+
+ assertEquals(1, user1DTO.getUserGroups().size());
+ assertTrue(user1DTO.getUserGroups().contains(userGroup2Entity));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserGroupEntityMergerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserGroupEntityMergerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserGroupEntityMergerTest.java
new file mode 100644
index 0000000..cc975cb
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/java/org/apache/nifi/cluster/manager/UserGroupEntityMergerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.cluster.manager;
+
+import org.apache.nifi.cluster.protocol.NodeIdentifier;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
+import org.apache.nifi.web.api.dto.PermissionsDTO;
+import org.apache.nifi.web.api.dto.TenantDTO;
+import org.apache.nifi.web.api.dto.UserGroupDTO;
+import org.apache.nifi.web.api.entity.AccessPolicyEntity;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.api.entity.UserGroupEntity;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class UserGroupEntityMergerTest {
+
+ @Test
+ public void testMergeAccessPolicy() throws Exception {
+ final NodeIdentifier node1 = new NodeIdentifier("node-1", "host-1", 8080, "host-1", 19998, null, null, null, false);
+ final NodeIdentifier node2 = new NodeIdentifier("node-2", "host-2", 8081, "host-2", 19999, null, null, null, false);
+
+ final PermissionsDTO permissed = new PermissionsDTO();
+ permissed.setCanRead(true);
+ permissed.setCanWrite(true);
+
+ final TenantDTO user1DTO = new TenantDTO();
+ user1DTO.setId("user-1");
+
+ final TenantEntity user1Entity = new TenantEntity();
+ user1Entity.setPermissions(permissed);
+ user1Entity.setId(user1DTO.getId());
+ user1Entity.setComponent(user1DTO);
+
+ final TenantDTO user2DTO = new TenantDTO();
+ user1DTO.setId("user-2");
+
+ final TenantEntity user2Entity = new TenantEntity();
+ user2Entity.setPermissions(permissed);
+ user2Entity.setId(user2DTO.getId());
+ user2Entity.setComponent(user2DTO);
+
+ final AccessPolicyDTO policy1DTO = new AccessPolicyDTO();
+ policy1DTO.setId("policy-1");
+
+ final AccessPolicyEntity policy1Entity = new AccessPolicyEntity();
+ policy1Entity.setPermissions(permissed);
+ policy1Entity.setId(policy1DTO.getId());
+ policy1Entity.setComponent(policy1DTO);
+
+ final AccessPolicyDTO policy2DTO = new AccessPolicyDTO();
+ policy2DTO.setId("policy-2");
+
+ final AccessPolicyEntity policy2Entity = new AccessPolicyEntity();
+ policy2Entity.setPermissions(permissed);
+ policy2Entity.setId(policy2DTO.getId());
+ policy2Entity.setComponent(policy2DTO);
+
+ final UserGroupDTO userGroup1DTO = new UserGroupDTO();
+ userGroup1DTO.setId("user-1");
+ userGroup1DTO.setAccessPolicies(Stream.of(policy1Entity, policy2Entity).collect(Collectors.toSet()));
+ userGroup1DTO.setUsers(Stream.of(user2Entity).collect(Collectors.toSet()));
+
+ final UserGroupEntity userGroup1Entity = new UserGroupEntity();
+ userGroup1Entity.setPermissions(permissed);
+ userGroup1Entity.setId(userGroup1DTO.getId());
+ userGroup1Entity.setComponent(userGroup1DTO);
+
+ final UserGroupDTO userGroup2DTO = new UserGroupDTO();
+ userGroup2DTO.setId("user-2");
+ userGroup2DTO.setAccessPolicies(Stream.of(policy1Entity).collect(Collectors.toSet()));
+ userGroup2DTO.setUsers(Stream.of(user1Entity, user2Entity).collect(Collectors.toSet()));
+
+ final UserGroupEntity userGroup2Entity = new UserGroupEntity();
+ userGroup2Entity.setPermissions(permissed);
+ userGroup2Entity.setId(userGroup2DTO.getId());
+ userGroup2Entity.setComponent(userGroup2DTO);
+
+ final Map<NodeIdentifier, UserGroupEntity> nodeMap = new HashMap<>();
+ nodeMap.put(node1, userGroup1Entity);
+ nodeMap.put(node2, userGroup2Entity);
+
+ final UserGroupEntityMerger merger = new UserGroupEntityMerger();
+ merger.merge(userGroup1Entity, nodeMap);
+
+ assertEquals(1, userGroup1DTO.getUsers().size());
+ assertTrue(userGroup1DTO.getAccessPolicies().contains(policy1Entity));
+
+ assertEquals(1, userGroup1DTO.getUsers().size());
+ assertTrue(userGroup1DTO.getUsers().contains(user2Entity));
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/cluster/protocol/DataFlow.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/cluster/protocol/DataFlow.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/cluster/protocol/DataFlow.java
index 6e2b9fe..0317584 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/cluster/protocol/DataFlow.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/cluster/protocol/DataFlow.java
@@ -32,7 +32,7 @@ public interface DataFlow {
/**
* @return the raw byte array of the Authorizer's fingerprint,
- * null when not using a sub-class of AbstractPolicyBasedAuthorizer
+ * null when not using a ManagedAuthorizer
*/
public byte[] getAuthorizerFingerprint();
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
index 57522f5..9d00f49 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
@@ -188,6 +188,10 @@
<version>4.3.1.201605051710-r</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-authorizer</artifactId>
+ </dependency>
</dependencies>
<build>
<plugins>
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java
index b2c1628..f2387c2 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowService.java
@@ -17,8 +17,9 @@
package org.apache.nifi.controller;
import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authorization.AbstractPolicyBasedAuthorizer;
import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.AuthorizerCapabilityDetection;
+import org.apache.nifi.authorization.ManagedAuthorizer;
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.cluster.ConnectionException;
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
@@ -572,8 +573,8 @@ public class StandardFlowService implements FlowService, ProtocolHandler {
}
private byte[] getAuthorizerFingerprint() {
- final boolean isInternalAuthorizer = (authorizer instanceof AbstractPolicyBasedAuthorizer);
- return isInternalAuthorizer ? ((AbstractPolicyBasedAuthorizer) authorizer).getFingerprint().getBytes(StandardCharsets.UTF_8) : null;
+ final boolean isInternalAuthorizer = AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer);
+ return isInternalAuthorizer ? ((ManagedAuthorizer) authorizer).getFingerprint().getBytes(StandardCharsets.UTF_8) : null;
}
@Override
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
index 6f1e8e1..01dd35e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardFlowSynchronizer.java
@@ -18,8 +18,10 @@ package org.apache.nifi.controller;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.authorization.AbstractPolicyBasedAuthorizer;
import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.AuthorizerCapabilityDetection;
+import org.apache.nifi.authorization.ManagedAuthorizer;
+import org.apache.nifi.authorization.exception.UninheritableAuthorizationsException;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.cluster.protocol.DataFlow;
import org.apache.nifi.cluster.protocol.StandardDataFlow;
@@ -224,15 +226,15 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
logger.trace("Getting Authorizer fingerprint from controller");
final byte[] existingAuthFingerprint;
- final AbstractPolicyBasedAuthorizer policyBasedAuthorizer;
+ final ManagedAuthorizer managedAuthorizer;
final Authorizer authorizer = controller.getAuthorizer();
- if (authorizer instanceof AbstractPolicyBasedAuthorizer) {
- policyBasedAuthorizer = (AbstractPolicyBasedAuthorizer) authorizer;
- existingAuthFingerprint = policyBasedAuthorizer.getFingerprint().getBytes(StandardCharsets.UTF_8);
+ if (AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer)) {
+ managedAuthorizer = (ManagedAuthorizer) authorizer;
+ existingAuthFingerprint = managedAuthorizer.getFingerprint().getBytes(StandardCharsets.UTF_8);
} else {
existingAuthFingerprint = null;
- policyBasedAuthorizer = null;
+ managedAuthorizer = null;
}
final Set<String> missingComponents = new HashSet<>();
@@ -249,7 +251,7 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
if (existingFlowEmpty) {
configuration = parseFlowBytes(proposedFlow.getFlow());
if (configuration != null) {
- logger.trace("Checking bunde compatibility");
+ logger.trace("Checking bundle compatibility");
checkBundleCompatibility(configuration);
}
} else {
@@ -272,7 +274,7 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
logger.trace("Checking authorizer inheritability");
- final AuthorizerInheritability authInheritability = checkAuthorizerInheritability(existingDataFlow, proposedFlow);
+ final AuthorizerInheritability authInheritability = checkAuthorizerInheritability(authorizer, existingDataFlow, proposedFlow);
if (!authInheritability.isInheritable() && authInheritability.getReason() != null) {
throw new UninheritableFlowException("Proposed Authorizer is not inheritable by the flow controller because of Authorizer differences: " + authInheritability.getReason());
}
@@ -415,10 +417,10 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
}
// if auths are inheritable and we have a policy based authorizer, then inherit
- if (authInheritability.isInheritable() && policyBasedAuthorizer != null) {
+ if (authInheritability.isInheritable() && managedAuthorizer != null) {
logger.trace("Inheriting authorizations");
final String proposedAuthFingerprint = new String(proposedFlow.getAuthorizerFingerprint(), StandardCharsets.UTF_8);
- policyBasedAuthorizer.inheritFingerprint(proposedAuthFingerprint);
+ managedAuthorizer.inheritFingerprint(proposedAuthFingerprint);
}
logger.debug("Finished syncing flows");
@@ -1391,7 +1393,7 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
* @param proposedFlow the proposed DataFlow
* @return the AuthorizerInheritability result
*/
- public AuthorizerInheritability checkAuthorizerInheritability(final DataFlow existingFlow, final DataFlow proposedFlow) {
+ private AuthorizerInheritability checkAuthorizerInheritability(final Authorizer authorizer, final DataFlow existingFlow, final DataFlow proposedFlow) {
final byte[] existing = existingFlow.getAuthorizerFingerprint();
final byte[] proposed = proposedFlow.getAuthorizerFingerprint();
@@ -1414,15 +1416,20 @@ public class StandardFlowSynchronizer implements FlowSynchronizer {
// both are internal, but not the same
if (!Arrays.equals(existing, proposed)) {
- final byte[] emptyAuthBytes = AbstractPolicyBasedAuthorizer.EMPTY_FINGERPRINT.getBytes(StandardCharsets.UTF_8);
+ if (AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer)) {
+ final ManagedAuthorizer managedAuthorizer = (ManagedAuthorizer) authorizer;
- // if current is empty then we can take all the proposed authorizations
- // otherwise they are both internal authorizers and don't match so we can't proceed
- if (Arrays.equals(emptyAuthBytes, existing)) {
- return AuthorizerInheritability.inheritable();
+ try {
+ // if the configurations are not equal, see if the manager indicates the proposed configuration is inheritable
+ managedAuthorizer.checkInheritability(new String(proposed, StandardCharsets.UTF_8));
+ return AuthorizerInheritability.inheritable();
+ } catch (final UninheritableAuthorizationsException e) {
+ return AuthorizerInheritability.uninheritable("Proposed Authorizations do not match current Authorizations: " + e.getMessage());
+ }
} else {
+ // should never hit since the existing is only null when authorizer is not managed
return AuthorizerInheritability.uninheritable(
- "Proposed Authorizations do not match current Authorizations");
+ "Proposed Authorizations do not match current Authorizations and are not configured with an internal Authorizer");
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
index 14d3dcc..8326889 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java
@@ -18,7 +18,9 @@ package org.apache.nifi.nar;
import org.apache.nifi.annotation.behavior.RequiresInstanceClassLoading;
import org.apache.nifi.authentication.LoginIdentityProvider;
+import org.apache.nifi.authorization.AccessPolicyProvider;
import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.UserGroupProvider;
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.components.ConfigurableComponent;
@@ -82,6 +84,8 @@ public class ExtensionManager {
definitionMap.put(ReportingTask.class, new HashSet<>());
definitionMap.put(ControllerService.class, new HashSet<>());
definitionMap.put(Authorizer.class, new HashSet<>());
+ definitionMap.put(UserGroupProvider.class, new HashSet<>());
+ definitionMap.put(AccessPolicyProvider.class, new HashSet<>());
definitionMap.put(LoginIdentityProvider.class, new HashSet<>());
definitionMap.put(ProvenanceRepository.class, new HashSet<>());
definitionMap.put(ComponentStatusRepository.class, new HashSet<>());
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/NarThreadContextClassLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/NarThreadContextClassLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/NarThreadContextClassLoader.java
index e7faa02..0be99dc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/NarThreadContextClassLoader.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/NarThreadContextClassLoader.java
@@ -17,7 +17,9 @@
package org.apache.nifi.nar;
import org.apache.nifi.authentication.LoginIdentityProvider;
+import org.apache.nifi.authorization.AccessPolicyProvider;
import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.UserGroupProvider;
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.components.Validator;
import org.apache.nifi.components.state.StateProvider;
@@ -64,6 +66,8 @@ public class NarThreadContextClassLoader extends URLClassLoader {
narSpecificClasses.add(StreamCallback.class);
narSpecificClasses.add(ControllerService.class);
narSpecificClasses.add(Authorizer.class);
+ narSpecificClasses.add(UserGroupProvider.class);
+ narSpecificClasses.add(AccessPolicyProvider.class);
narSpecificClasses.add(LoginIdentityProvider.class);
narSpecificClasses.add(ProvenanceRepository.class);
narSpecificClasses.add(ComponentStatusRepository.class);
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
index 1816297..8e740a9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
@@ -141,7 +141,7 @@
<nifi.security.truststoreType />
<nifi.security.truststorePasswd />
<nifi.security.needClientAuth />
- <nifi.security.user.authorizer>file-provider</nifi.security.user.authorizer>
+ <nifi.security.user.authorizer>managed-authorizer</nifi.security.user.authorizer>
<nifi.security.user.login.identity.provider />
<nifi.security.x509.principal.extractor />
<nifi.security.ocsp.responder.url />
http://git-wip-us.apache.org/repos/asf/nifi/blob/4ed7511b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
index 46bf637..247c0e8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/authorizers.xml
@@ -14,13 +14,105 @@
limitations under the License.
-->
<!--
- This file lists the authority providers to use when running securely. In order
- to use a specific provider it must be configured here and it's identifier
- must be specified in the nifi.properties file.
+ This file lists the userGroupProviders, accessPolicyProviders, and authorizers to use when running securely. In order
+ to use a specific authorizer it must be configured here and it's identifier must be specified in the nifi.properties file.
+ If the authorizer is a managedAuthorizer, it may need to be configured with an accessPolicyProvider and an userGroupProvider.
+ This file allows for configuration of them, but they must be configured in order:
+
+ ...
+ all userGroupProviders
+ all accessPolicyProviders
+ all Authorizers
+ ...
-->
<authorizers>
<!--
+ The FileUserGroupProvider will provide support for managing users and groups which is backed by a file
+ on the local file system.
+
+ - Users File - The file where the FileUserGroupProvider will store users and groups.
+
+ - Legacy Authorized Users File - The full path to an existing authorized-users.xml that will be automatically
+ be used to load the users and groups into the Users File.
+
+ - Initial User Identity [unique key] - The identity of a users and systems to seed the Users File. The name of
+ each property must be unique, for example: "Initial User Identity A", "Initial User Identity B",
+ "Initial User Identity C" or "Initial User Identity 1", "Initial User Identity 2", "Initial User Identity 3"
+
+ NOTE: Any identity mapping rules specified in nifi.properties will also be applied to the user identities,
+ so the values should be the unmapped identities (i.e. full DN from a certificate).
+ -->
+ <userGroupProvider>
+ <identifier>file-user-group-provider</identifier>
+ <class>org.apache.nifi.authorization.FileUserGroupProvider</class>
+ <property name="Users File">./conf/users.xml</property>
+ <property name="Legacy Authorized Users File"></property>
+
+ <property name="Initial User Identity 1"></property>
+ </userGroupProvider>
+
+ <!--
+ The FileAccessPolicyProvider will provide support for managing access policies which is backed by a file
+ on the local file system.
+
+ - User Group Provider - The identifier for an User Group Provider defined above that will be used to access
+ users and groups for use in the managed access policies.
+
+ - Authorizations File - The file where the FileAccessPolicyProvider will store policies.
+
+ - Initial Admin Identity - The identity of an initial admin user that will be granted access to the UI and
+ given the ability to create additional users, groups, and policies. The value of this property could be
+ a DN when using certificates or LDAP, or a Kerberos principal. This property will only be used when there
+ are no other policies defined. If this property is specified then a Legacy Authorized Users File can not be specified.
+
+ NOTE: Any identity mapping rules specified in nifi.properties will also be applied to the initial admin identity,
+ so the value should be the unmapped identity. This identity must be found in the configured User Group Provider.
+
+ - Legacy Authorized Users File - The full path to an existing authorized-users.xml that will be automatically
+ converted to the new authorizations model. If this property is specified then an Initial Admin Identity can
+ not be specified, and this property will only be used when there are no other users, groups, and policies defined.
+
+ NOTE: Any users in the legacy users file must be found in the configured User Group Provider.
+
+ - Node Identity [unique key] - The identity of a NiFi cluster node. When clustered, a property for each node
+ should be defined, so that every node knows about every other node. If not clustered these properties can be ignored.
+ The name of each property must be unique, for example for a three node cluster:
+ "Node Identity A", "Node Identity B", "Node Identity C" or "Node Identity 1", "Node Identity 2", "Node Identity 3"
+
+ NOTE: Any identity mapping rules specified in nifi.properties will also be applied to the node identities,
+ so the values should be the unmapped identities (i.e. full DN from a certificate). This identity must be found
+ in the configured User Group Provider.
+ -->
+ <accessPolicyProvider>
+ <identifier>file-access-policy-provider</identifier>
+ <class>org.apache.nifi.authorization.FileAccessPolicyProvider</class>
+ <property name="User Group Provider">file-user-group-provider</property>
+ <property name="Authorizations File">./conf/authorizations.xml</property>
+ <property name="Initial Admin Identity"></property>
+ <property name="Legacy Authorized Users File"></property>
+
+ <property name="Node Identity 1"></property>
+ </accessPolicyProvider>
+
+ <!--
+ The StandardManagedAuthorizer. This authorizer implementation must be configured with the
+ Access Policy Provider which it will use to access and manage users, groups, and policies.
+ These users, groups, and policies will be used to make all access decisions during authorization
+ requests.
+
+ - Access Policy Provider - The identifier for an Access Policy Provider defined above.
+ -->
+ <authorizer>
+ <identifier>managed-authorizer</identifier>
+ <class>org.apache.nifi.authorization.StandardManagedAuthorizer</class>
+ <property name="Access Policy Provider">file-access-policy-provider</property>
+ </authorizer>
+
+ <!--
+ NOTE: This Authorizer has been replaced with the more granular approach configured above with the Standard
+ Managed Authorizer. However, it is still available for backwards compatibility reasons.
+
The FileAuthorizer is NiFi's provided authorizer and has the following properties:
- Authorizations File - The file where the FileAuthorizer will store policies.
@@ -48,7 +140,7 @@
NOTE: Any identity mapping rules specified in nifi.properties will also be applied to the node identities,
so the values should be the unmapped identities (i.e. full DN from a certificate).
-->
- <authorizer>
+ <!-- <authorizer>
<identifier>file-provider</identifier>
<class>org.apache.nifi.authorization.FileAuthorizer</class>
<property name="Authorizations File">./conf/authorizations.xml</property>
@@ -56,9 +148,7 @@
<property name="Initial Admin Identity"></property>
<property name="Legacy Authorized Users File"></property>
- <!-- Provide the identity (typically a DN) of each node when clustered, see above description of Node Identity.
<property name="Node Identity 1"></property>
- <property name="Node Identity 2"></property>
- -->
</authorizer>
+ -->
</authorizers>
\ No newline at end of file