NIFIREG-325: support for node identity group
- updated admin guide
- adjusting PR / fixing issues found during review

This closes #235.

Signed-off-by: Bryan Bende <bbende@apache.org>
diff --git a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
index 765e62f..b9bc1df 100644
--- a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
@@ -348,6 +348,7 @@
 |`Authorizations File`| The file where the FileAccessPolicyProvider will store policies. By default, _authorizations.xml_ in the `conf` directory is chosen.
 |`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. For example, a certificate DN, LDAP identity, or Kerberos principal.
 |`NiFi Identity`| The identity of a NiFi instance/node that will be accessing this registry. Each NiFi Identity will be granted permission to proxy user requests, as well as read any bucket to perform synchronization status checks.
+|`NiFi Group Name`| The name of the group, whose members are NiFi instance/node identities, that will be accessing this registry. The members of this group will be granted permission to proxy user requests, as well as read any bucket to perform synchronization checks.
 |==================================================================================================================================================
 
 NOTE: The identities configured in the Initial Admin Identity and NiFi Identity properties must be available in the configured User Group Provider. Initial Admin Identity and NiFi Identity properties are only read by NiFi Registry when the Authorizations File is missing or empty on startup in order to seed the initial Authorizations File.
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
index 5eb1874..8c32ab8 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
@@ -24,6 +24,7 @@
 import org.apache.nifi.registry.security.authorization.AccessPolicyProviderInitializationContext;
 import org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
 import org.apache.nifi.registry.security.authorization.ConfigurableAccessPolicyProvider;
+import org.apache.nifi.registry.security.authorization.Group;
 import org.apache.nifi.registry.security.authorization.RequestAction;
 import org.apache.nifi.registry.security.authorization.User;
 import org.apache.nifi.registry.security.authorization.UserGroupProvider;
@@ -73,6 +74,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
@@ -147,6 +149,7 @@
 
     static final String PROP_NIFI_IDENTITY_PREFIX = "NiFi Identity ";
     static final String PROP_USER_GROUP_PROVIDER = "User Group Provider";
+    static final String PROP_NIFI_GROUP_NAME = "NiFi Group Name";
     static final String PROP_AUTHORIZATIONS_FILE = "Authorizations File";
     static final String PROP_INITIAL_ADMIN_IDENTITY = "Initial Admin Identity";
     static final Pattern NIFI_IDENTITY_PATTERN = Pattern.compile(PROP_NIFI_IDENTITY_PREFIX + "\\S+");
@@ -156,6 +159,7 @@
     private File authorizationsFile;
     private String initialAdminIdentity;
     private Set<String> nifiIdentities;
+    private String nifiIdentityGroupIdentifier;
     private List<IdentityMapping> identityMappings;
 
     private UserGroupProvider userGroupProvider;
@@ -215,6 +219,23 @@
                 }
             }
 
+            PropertyValue identityGroupNameProp = configurationContext.getProperty(PROP_NIFI_GROUP_NAME);
+            String identityGroupName = (identityGroupNameProp != null && identityGroupNameProp.isSet()) ? identityGroupNameProp.getValue() : null;
+            if (!StringUtils.isBlank(identityGroupName)) {
+                logger.debug("{} is: {}", PROP_NIFI_GROUP_NAME, identityGroupName);
+                Set<Group> groups = userGroupProvider.getGroups();
+                logger.trace("All authorization groups: {}", groups);
+                Optional<Group> identityGroupsOptional =
+                        groups.stream()
+                            .filter(group -> group.getName().equals(identityGroupName))
+                            .findFirst();
+                Group identityGroup = identityGroupsOptional
+                        .orElseThrow(() ->
+                            new SecurityProviderCreationException(String.format("Authorizations node group '%s' could not be found", identityGroupName))
+                        );
+                logger.debug("Identity Group is: {}", identityGroup);
+                nifiIdentityGroupIdentifier = identityGroup.getIdentifier();
+            }
             // load the authorizations
             load();
 
@@ -508,6 +529,13 @@
                 populateNiFiIdentities(authorizations);
             }
 
+            if (!StringUtils.isEmpty(nifiIdentityGroupIdentifier)) {
+                logger.info("Populating proxy authorizations for NiFi identity group: [{}]", nifiIdentityGroupIdentifier);
+                // grant access to the resources needed for initial nifi-proxy identities
+                for (ResourceActionPair resourceAction : NIFI_ACCESS_POLICIES) {
+                    addGroupToAccessPolicy(authorizations, resourceAction.resource, nifiIdentityGroupIdentifier, resourceAction.actionCode);
+                }
+            }
             saveAndRefreshHolder(authorizations);
         } else {
             this.authorizationsHolder.set(authorizationsHolder);
@@ -564,6 +592,34 @@
         }
     }
 
+    private void addGroupToAccessPolicy(Authorizations authorizations, String resource, String nifiIdentityGroupIdentifier, String action) {
+    Optional<Policy> policyOptional = authorizations.getPolicies().getPolicy().stream()
+            .filter(policy -> policy.getResource().equals(resource))
+            .filter(policy -> policy.getAction().equals(action))
+        .findAny();
+    if (policyOptional.isPresent()) {
+        Policy policy = policyOptional.get();
+        Policy.Group group = new Policy.Group();
+        group.setIdentifier(nifiIdentityGroupIdentifier);
+        policy.getGroup().add(group);
+    } else {
+        AccessPolicy.Builder accessPolicyBuilder =
+            new AccessPolicy.Builder()
+              .identifierGenerateFromSeed(resource + action)
+              .resource(resource)
+              .addGroup(nifiIdentityGroupIdentifier);
+      if (action.equals(READ_CODE)) {
+          accessPolicyBuilder.action(RequestAction.READ);
+      } else if (action.equals(WRITE_CODE)) {
+          accessPolicyBuilder.action(RequestAction.WRITE);
+      } else if (action.equals(DELETE_CODE)) {
+          accessPolicyBuilder.action(RequestAction.DELETE);
+      } else {
+          throw new IllegalStateException("Unknown Policy Action: " + action);
+      }
+      authorizations.getPolicies().getPolicy().add(createJAXBPolicy(accessPolicyBuilder.build()));
+    }
+  }
 
     /**
      * Creates and adds an access policy for the given resource, identity, and actions to the specified authorizations.
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
index 26999d4..9f63754 100644
--- a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
@@ -232,6 +232,9 @@
             NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the nifi 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.
+        - NiFi Group Name: The name of the group, whose members are NiFi instance/node identities,
+            that will have access to this NiFi Registry and will be able to act as a proxy on behalf of a NiFi Registry end user.
+            The members of this group will be granted permission to proxy user requests, as well as read any bucket to perform synchronization checks.
     -->
     <accessPolicyProvider>
         <identifier>file-access-policy-provider</identifier>
@@ -239,6 +242,7 @@
         <property name="User Group Provider">file-user-group-provider</property>
         <property name="Authorizations File">./conf/authorizations.xml</property>
         <property name="Initial Admin Identity"><!-- CN=abc, OU=xyz --></property>
+        <property name="NiFi Group Name"></property>
 
         <!--<property name="NiFi Identity 1"></property>-->
     </accessPolicyProvider>