Repository: nifi
Updated Branches:
  refs/heads/master 2ee0af966 -> be2ed060a


NIFI-5542 Added support for node groups to FileAccessPolicyProvider

This closes #2970.

Signed-off-by: Kevin Doran <kdo...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/be2ed060
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/be2ed060
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/be2ed060

Branch: refs/heads/master
Commit: be2ed060a29228424ee647fd617ff0e1010dc25e
Parents: 2ee0af9
Author: Andrew I. Christianson <a...@andyic.org>
Authored: Thu Aug 23 11:50:54 2018 -0400
Committer: Kevin Doran <kdo...@apache.org>
Committed: Thu Sep 20 10:27:28 2018 -0400

----------------------------------------------------------------------
 .../src/main/asciidoc/administration-guide.adoc |  1 +
 .../authorization/FileAccessPolicyProvider.java | 81 +++++++++++++++++++-
 .../FileAccessPolicyProviderTest.java           | 43 +++++++++++
 .../src/main/resources/conf/authorizers.xml     |  7 +-
 4 files changed, 129 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/be2ed060/nifi-docs/src/main/asciidoc/administration-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc 
b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index 18702fb..d4c4fc9 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -892,6 +892,7 @@ The default AccessPolicyProvider is the 
FileAccessPolicyProvider, however, you c
 |`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.
 |`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.
 |`Node Identity` | 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"
+|`Node Group` | The name of a group containing NiFi cluster nodes. The typical 
use for this is when nodes are dynamically added/removed from the cluster.
 
 
|==================================================================================================================================================
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/be2ed060/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java
index fa2a527..b1a6f91 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAccessPolicyProvider.java
@@ -114,6 +114,7 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
     static final String WRITE_CODE = "W";
 
     static final String PROP_NODE_IDENTITY_PREFIX = "Node Identity ";
+    static final String PROP_NODE_GROUP_NAME = "Node Group";
     static final String PROP_USER_GROUP_PROVIDER = "User Group Provider";
     static final String PROP_AUTHORIZATIONS_FILE = "Authorizations File";
     static final String PROP_INITIAL_ADMIN_IDENTITY = "Initial Admin Identity";
@@ -128,6 +129,7 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
     private String initialAdminIdentity;
     private String legacyAuthorizedUsersFile;
     private Set<String> nodeIdentities;
+    private String nodeGroupIdentifier;
     private List<PortDTO> ports = new ArrayList<>();
     private List<IdentityMapping> identityMappings;
     private List<IdentityMapping> groupMappings;
@@ -222,6 +224,27 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
                 }
             }
 
+            // read node group name
+            PropertyValue nodeGroupNameProp = 
configurationContext.getProperty(PROP_NODE_GROUP_NAME);
+            String nodeGroupName = (nodeGroupNameProp != null && 
nodeGroupNameProp.isSet()) ? nodeGroupNameProp.getValue() : null;
+
+            // look up node group identifier using node group name
+            nodeGroupIdentifier = null;
+
+            if (nodeGroupName != null) {
+                for (Group group : userGroupProvider.getGroups()) {
+                    if (group.getName().equals(nodeGroupName)) {
+                        nodeGroupIdentifier = group.getIdentifier();
+                        break;
+                    }
+                }
+
+                if (nodeGroupIdentifier == null) {
+                    throw new AuthorizerCreationException(String.format(
+                            "Authorizations node group '%s' could not be 
found", nodeGroupName));
+                }
+            }
+
             // load the authorizations
             load();
 
@@ -604,12 +627,12 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
      * @param authorizations the overall authorizations
      */
     private void populateNodes(Authorizations authorizations) {
+        // authorize static nodes
         for (String nodeIdentity : nodeIdentities) {
             final User node = 
userGroupProvider.getUserByIdentity(nodeIdentity);
             if (node == null) {
                 throw new AuthorizerCreationException("Unable to locate node " 
+ nodeIdentity + " to seed policies.");
             }
-
             // grant access to the proxy resource
             addUserToAccessPolicy(authorizations, 
ResourceType.Proxy.getValue(), node.getIdentifier(), WRITE_CODE);
 
@@ -619,6 +642,16 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
                 addUserToAccessPolicy(authorizations, 
ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + 
rootGroupId, node.getIdentifier(), WRITE_CODE);
             }
         }
+
+        // authorize dynamic nodes (node group)
+        if (nodeGroupIdentifier != null) {
+            addGroupToAccessPolicy(authorizations, 
ResourceType.Proxy.getValue(), nodeGroupIdentifier, WRITE_CODE);
+
+            if (rootGroupId != null) {
+                addGroupToAccessPolicy(authorizations, 
ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + 
rootGroupId, nodeGroupIdentifier, READ_CODE);
+                addGroupToAccessPolicy(authorizations, 
ResourceType.Data.getValue() + ResourceType.ProcessGroup.getValue() + "/" + 
rootGroupId, nodeGroupIdentifier, WRITE_CODE);
+            }
+        }
     }
 
     /**
@@ -811,6 +844,52 @@ public class FileAccessPolicyProvider implements 
ConfigurableAccessPolicyProvide
         }
     }
 
+    /**
+     * Creates and adds an access policy for the given resource, group 
identity, and actions to the specified authorizations.
+     *
+     * @param authorizations the Authorizations instance to add the policy to
+     * @param resource       the resource for the policy
+     * @param groupIdentifier the identifier for the group to add to the policy
+     * @param action         the action for the policy
+     */
+    private void addGroupToAccessPolicy(final Authorizations authorizations, 
final String resource, final String groupIdentifier, final String action) {
+        // first try to find an existing policy for the given resource and 
action
+        Policy foundPolicy = null;
+        for (Policy policy : authorizations.getPolicies().getPolicy()) {
+            if (policy.getResource().equals(resource) && 
policy.getAction().equals(action)) {
+                foundPolicy = policy;
+                break;
+            }
+        }
+
+        if (foundPolicy == null) {
+            // if we didn't find an existing policy create a new one
+            final String uuidSeed = resource + action;
+
+            final AccessPolicy.Builder builder = new AccessPolicy.Builder()
+                    .identifierGenerateFromSeed(uuidSeed)
+                    .resource(resource)
+                    .addGroup(groupIdentifier);
+
+            if (action.equals(READ_CODE)) {
+                builder.action(RequestAction.READ);
+            } else if (action.equals(WRITE_CODE)) {
+                builder.action(RequestAction.WRITE);
+            } else {
+                throw new IllegalStateException("Unknown Policy Action: " + 
action);
+            }
+
+            final AccessPolicy accessPolicy = builder.build();
+            final Policy jaxbPolicy = createJAXBPolicy(accessPolicy);
+            authorizations.getPolicies().getPolicy().add(jaxbPolicy);
+        } else {
+            // otherwise add the user to the existing policy
+            Policy.Group policyGroup = new Policy.Group();
+            policyGroup.setIdentifier(groupIdentifier);
+            foundPolicy.getGroup().add(policyGroup);
+        }
+    }
+
     private Policy createJAXBPolicy(final AccessPolicy accessPolicy) {
         final Policy policy = new Policy();
         policy.setIdentifier(accessPolicy.getIdentifier());

http://git-wip-us.apache.org/repos/asf/nifi/blob/be2ed060/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java
index 9176434..d02ada7 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAccessPolicyProviderTest.java
@@ -117,6 +117,22 @@ public class FileAccessPolicyProviderTest {
                     "  </users>" +
                     "</tenants>";
 
+    private static final String TENANTS_FOR_ADMIN_AND_NODE_GROUP =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
+                    "<tenants>" +
+                    "  <groups>" +
+                    "    <group identifier=\"cluster-nodes\" name=\"Cluster 
Nodes\">" +
+                    "       <user identifier=\"node1\" />" +
+                    "       <user identifier=\"node2\" />" +
+                    "    </group>" +
+                    "  </groups>" +
+                    "  <users>" +
+                    "    <user identifier=\"admin-user\" 
identity=\"admin-user\"/>" +
+                    "    <user identifier=\"node1\" identity=\"node1\"/>" +
+                    "    <user identifier=\"node2\" identity=\"node2\"/>" +
+                    "  </users>" +
+                    "</tenants>";
+
     // This is the root group id from the flow.xml.gz in src/test/resources
     private static final String ROOT_GROUP_ID = 
"e530e14c-adcf-41c2-b5d6-d9a59ba8765c";
 
@@ -732,6 +748,33 @@ public class FileAccessPolicyProviderTest {
         
assertTrue(proxyWritePolicy.getUsers().contains(nodeUser2.getIdentifier()));
     }
 
+    @Test
+    public void testOnConfiguredWhenNodeGroupProvided() throws Exception {
+        final String adminIdentity = "admin-user";
+        final String nodeGroupName = "Cluster Nodes";
+        final String nodeGroupIdentifier = "cluster-nodes";
+        final String nodeIdentity1 = "node1";
+        final String nodeIdentity2 = "node2";
+
+        
when(configurationContext.getProperty(eq(FileAccessPolicyProvider.PROP_INITIAL_ADMIN_IDENTITY)))
+                .thenReturn(new StandardPropertyValue(adminIdentity, null));
+        
when(configurationContext.getProperty(eq(FileAccessPolicyProvider.PROP_NODE_GROUP_NAME)))
+                .thenReturn(new StandardPropertyValue(nodeGroupName, null));
+
+        writeFile(primaryAuthorizations, EMPTY_AUTHORIZATIONS_CONCISE);
+        writeFile(primaryTenants, TENANTS_FOR_ADMIN_AND_NODE_GROUP);
+
+        userGroupProvider.onConfigured(configurationContext);
+        accessPolicyProvider.onConfigured(configurationContext);
+
+        User nodeUser1 = userGroupProvider.getUserByIdentity(nodeIdentity1);
+        User nodeUser2 = userGroupProvider.getUserByIdentity(nodeIdentity2);
+
+        AccessPolicy proxyWritePolicy = 
accessPolicyProvider.getAccessPolicy(ResourceType.Proxy.getValue(), 
RequestAction.WRITE);
+
+        assertNotNull(proxyWritePolicy);
+        assertTrue(proxyWritePolicy.getGroups().contains(nodeGroupIdentifier));
+    }
 
     @Test
     public void testOnConfiguredWhenTenantsAndAuthorizationsFileDoesNotExist() 
{

http://git-wip-us.apache.org/repos/asf/nifi/blob/be2ed060/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 3808404..b57239a 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
@@ -238,6 +238,9 @@
             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.
+
+        - Node Group - The name of a group containing NiFi cluster nodes. The 
typical use for this is when nodes are dynamically
+            added/removed from the cluster.
     -->
     <accessPolicyProvider>
         <identifier>file-access-policy-provider</identifier>
@@ -246,8 +249,8 @@
         <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>
+        <property name="Node Group"></property>
     </accessPolicyProvider>
 
     <!--
@@ -306,4 +309,4 @@
         <property name="Node Identity 1"></property>
     </authorizer>
     -->
-</authorizers>
\ No newline at end of file
+</authorizers>

Reply via email to