From 9aa1e71cdd8e93d4acc3a04e6f62c1aaf52ac22e Mon Sep 17 00:00:00 2001 From: Bryan Bende Date: Fri, 24 Jun 2016 17:04:44 -0400 Subject: [PATCH] NIFI-1916 Improvements to FileAuthorizer to not parse flow when unncessary and to recreate missing authorizations.xml --- .../nifi/authorization/FileAuthorizer.java | 118 ++++++++++-------- .../authorization/FileAuthorizerTest.java | 5 + 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java index 20a43c37fae9..906d36993b97 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/main/java/org/apache/nifi/authorization/FileAuthorizer.java @@ -16,6 +16,7 @@ */ package org.apache.nifi.authorization; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.authorization.annotation.AuthorizerContext; import org.apache.nifi.authorization.exception.AuthorizationAccessException; @@ -47,6 +48,7 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -138,7 +140,8 @@ public void onConfigured(final AuthorizerConfigurationContext configurationConte // get the authorizations file and ensure it exists authorizationsFile = new File(authorizationsPath.getValue()); if (!authorizationsFile.exists()) { - throw new AuthorizerCreationException("The authorizations file must exist."); + logger.info("Creating new authorizations file at {}", new Object[] {authorizationsFile.getAbsolutePath()}); + saveAndRefreshHolder(new Authorizations()); } final File authorizationsFileDirectory = authorizationsFile.getAbsoluteFile().getParentFile(); @@ -172,9 +175,6 @@ public void onConfigured(final AuthorizerConfigurationContext configurationConte final PropertyValue legacyAuthorizedUsersProp = configurationContext.getProperty(PROP_LEGACY_AUTHORIZED_USERS_FILE); legacyAuthorizedUsersFile = legacyAuthorizedUsersProp == null ? null : legacyAuthorizedUsersProp.getValue(); - // try to extract the root group id from the flow configuration file specified in nifi.properties - rootGroupId = getRootGroupId(); - // load the authorizations load(); @@ -190,6 +190,58 @@ public void onConfigured(final AuthorizerConfigurationContext configurationConte } } + /** + * Loads the authorizations file and populates the AuthorizationsHolder, only called during start-up. + * + * @throws JAXBException Unable to reload the authorized users file + * @throws IOException Unable to sync file with restore + * @throws IllegalStateException Unable to sync file with restore + */ + private synchronized void load() throws JAXBException, IOException, IllegalStateException { + // attempt to unmarshal + final Unmarshaller unmarshaller = JAXB_AUTHORIZATIONS_CONTEXT.createUnmarshaller(); + unmarshaller.setSchema(authorizationsSchema); + final JAXBElement element = unmarshaller.unmarshal(new StreamSource(authorizationsFile), Authorizations.class); + + final Authorizations authorizations = element.getValue(); + + if (authorizations.getUsers() == null) { + authorizations.setUsers(new Users()); + } + if (authorizations.getGroups() == null) { + authorizations.setGroups(new Groups()); + } + if (authorizations.getPolicies() == null) { + authorizations.setPolicies(new Policies()); + } + + final AuthorizationsHolder authorizationsHolder = new AuthorizationsHolder(authorizations); + final boolean emptyAuthorizations = authorizationsHolder.getAllUsers().isEmpty() && authorizationsHolder.getAllPolicies().isEmpty(); + final boolean hasInitialAdminIdentity = (initialAdminIdentity != null && !StringUtils.isBlank(initialAdminIdentity)); + final boolean hasLegacyAuthorizedUsers = (legacyAuthorizedUsersFile != null && !StringUtils.isBlank(legacyAuthorizedUsersFile)); + + // if we are starting fresh then we might need to populate an initial admin or convert legacy users + if (emptyAuthorizations) { + // try to extract the root group id from the flow configuration file specified in nifi.properties + rootGroupId = getRootGroupId(); + + if (hasInitialAdminIdentity && hasLegacyAuthorizedUsers) { + throw new AuthorizerCreationException("Cannot provide an Initial Admin Identity and a Legacy Authorized Users File"); + } else if (hasInitialAdminIdentity) { + logger.info("Populating authorizations for Initial Admin: " + initialAdminIdentity); + populateInitialAdmin(authorizations); + } else if (hasLegacyAuthorizedUsers) { + logger.info("Converting " + legacyAuthorizedUsersFile + " to new authorizations model"); + convertLegacyAuthorizedUsers(authorizations); + } + + // save any changes that were made and repopulate the holder + saveAndRefreshHolder(authorizations); + } else { + this.authorizationsHolder.set(authorizationsHolder); + } + } + /** * Extracts the root group id from the flow configuration file provided in nifi.properties. * @@ -218,6 +270,12 @@ private String getRootGroupId() { try (final InputStream in = Files.newInputStream(flowPath, StandardOpenOption.READ); final InputStream gzipIn = new GZIPInputStream(in)) { + final byte[] flowBytes = IOUtils.toByteArray(gzipIn); + if (flowBytes == null || flowBytes.length == 0) { + logger.debug("Could not extract root group id because Flow Configuration File was empty"); + return null; + } + // create validating document builder final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); @@ -225,7 +283,7 @@ private String getRootGroupId() { // parse the flow final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - final Document document = docBuilder.parse(gzipIn); + final Document document = docBuilder.parse(new ByteArrayInputStream(flowBytes)); // extract the root group id final Element rootElement = document.getDocumentElement(); @@ -250,56 +308,6 @@ private String getRootGroupId() { } } - /** - * Loads the authorizations file and populates the AuthorizationsHolder, only called during start-up. - * - * @throws JAXBException Unable to reload the authorized users file - * @throws IOException Unable to sync file with restore - * @throws IllegalStateException Unable to sync file with restore - */ - private synchronized void load() throws JAXBException, IOException, IllegalStateException { - // attempt to unmarshal - final Unmarshaller unmarshaller = JAXB_AUTHORIZATIONS_CONTEXT.createUnmarshaller(); - unmarshaller.setSchema(authorizationsSchema); - final JAXBElement element = unmarshaller.unmarshal(new StreamSource(authorizationsFile), Authorizations.class); - - final Authorizations authorizations = element.getValue(); - - if (authorizations.getUsers() == null) { - authorizations.setUsers(new Users()); - } - if (authorizations.getGroups() == null) { - authorizations.setGroups(new Groups()); - } - if (authorizations.getPolicies() == null) { - authorizations.setPolicies(new Policies()); - } - - final AuthorizationsHolder authorizationsHolder = new AuthorizationsHolder(authorizations); - final boolean emptyAuthorizations = authorizationsHolder.getAllUsers().isEmpty() && authorizationsHolder.getAllPolicies().isEmpty(); - final boolean hasInitialAdminIdentity = (initialAdminIdentity != null && !StringUtils.isBlank(initialAdminIdentity)); - final boolean hasLegacyAuthorizedUsers = (legacyAuthorizedUsersFile != null && !StringUtils.isBlank(legacyAuthorizedUsersFile)); - - // if we are starting fresh then we might need to populate an initial admin or convert legacy users - if (emptyAuthorizations) { - - if (hasInitialAdminIdentity && hasLegacyAuthorizedUsers) { - throw new AuthorizerCreationException("Cannot provide an Initial Admin Identity and a Legacy Authorized Users File"); - } else if (hasInitialAdminIdentity) { - logger.debug("Populating authorizations for Initial Admin: " + initialAdminIdentity); - populateInitialAdmin(authorizations); - } else if (hasLegacyAuthorizedUsers) { - logger.debug("Converting " + legacyAuthorizedUsersFile + " to new authorizations model"); - convertLegacyAuthorizedUsers(authorizations); - } - - // save any changes that were made and repopulate the holder - saveAndRefreshHolder(authorizations); - } else { - this.authorizationsHolder.set(authorizationsHolder); - } - } - /** * Creates the initial admin user and policies for access the flow and managing users and policies. */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java index 6d18b4b9b8a5..30a1230a7cab 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/src/test/java/org/apache/nifi/authorization/FileAuthorizerTest.java @@ -427,6 +427,11 @@ public void testOnConfiguredWhenInitialAdminProvidedAndFlowIsNull() throws Excep assertFalse(foundRootGroupPolicy); } + @Test + public void testOnConfiguredWhenAuthorizationsFileDoesNotExist() { + authorizer.onConfigured(configurationContext); + assertEquals(0, authorizer.getAccessPolicies().size()); + } @Test public void testOnConfiguredWhenRestoreDoesNotExist() throws Exception {