This is an automated email from the ASF dual-hosted git repository. kdoran pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push: new d35d15c NIFI-6027 d35d15c is described below commit d35d15cdda32c2aedd5bfd4124662f522461c159 Author: Matt Gilman <matt.c.gil...@gmail.com> AuthorDate: Mon Mar 18 13:01:15 2019 -0400 NIFI-6027 - Allowing user or group existence enforcement to be parameterized. - Fixing error handling when loading user groups which may have resulted in stack trace leaking. This closes #3377. Signed-off-by: Kevin Doran <kdo...@apache.org> --- .../apache/nifi/web/StandardNiFiServiceFacade.java | 70 +++++++++++++--------- .../web/security/NiFiAuthenticationFilter.java | 19 ++++-- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index a960dbf..fbce19b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -39,8 +39,8 @@ import org.apache.nifi.authorization.User; import org.apache.nifi.authorization.UserContextKeys; import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.EnforcePolicyPermissionsThroughBaseResource; -import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.resource.OperationAuthorizable; +import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.bundle.BundleCoordinate; @@ -48,10 +48,10 @@ import org.apache.nifi.cluster.coordination.ClusterCoordinator; import org.apache.nifi.cluster.coordination.heartbeat.HeartbeatMonitor; import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat; import org.apache.nifi.cluster.coordination.node.ClusterRoles; -import org.apache.nifi.cluster.coordination.node.OffloadCode; import org.apache.nifi.cluster.coordination.node.DisconnectionCode; import org.apache.nifi.cluster.coordination.node.NodeConnectionState; import org.apache.nifi.cluster.coordination.node.NodeConnectionStatus; +import org.apache.nifi.cluster.coordination.node.OffloadCode; import org.apache.nifi.cluster.event.NodeEvent; import org.apache.nifi.cluster.manager.exception.IllegalNodeDeletionException; import org.apache.nifi.cluster.manager.exception.UnknownNodeException; @@ -599,8 +599,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { authorizable, () -> accessPolicyDAO.updateAccessPolicy(accessPolicyDTO), accessPolicy -> { - final Set<TenantEntity> users = accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); - final Set<TenantEntity> userGroups = accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()); + final Set<TenantEntity> users = accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()); + final Set<TenantEntity> userGroups = accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()); final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); return dtoFactory.createAccessPolicyDto(accessPolicy, userGroups, users, componentReference); }); @@ -618,7 +618,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { usersAuthorizable, () -> userDAO.updateUser(userDTO), user -> { - final Set<TenantEntity> tenantEntities = groups.stream().map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()); + final Set<TenantEntity> tenantEntities = groups.stream().map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = policies.stream().map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); return dtoFactory.createUserDto(user, tenantEntities, policyEntities); }); @@ -635,7 +635,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { userGroupsAuthorizable, () -> userGroupDAO.updateUserGroup(userGroupDTO), userGroup -> { - final Set<TenantEntity> tenantEntities = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); + final Set<TenantEntity> tenantEntities = userGroup.getUsers().stream().map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = policies.stream().map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); return dtoFactory.createUserGroupDto(userGroup, tenantEntities, policyEntities); } @@ -1254,7 +1254,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final User user = userDAO.getUser(userId); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); final Set<TenantEntity> userGroups = user != null ? userGroupDAO.getUserGroupsForUser(userId).stream() - .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()) : null; + .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()) : null; final Set<AccessPolicySummaryEntity> policyEntities = user != null ? userGroupDAO.getAccessPoliciesForUser(userId).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()) : null; @@ -1289,7 +1289,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final Group userGroup = userGroupDAO.getUserGroup(userGroupId); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); final Set<TenantEntity> users = userGroup != null ? userGroup.getUsers().stream() - .map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null; + .map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()) : null; final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(userGroup.getIdentifier()).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); @@ -1324,8 +1324,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(accessPolicyId); final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getAccessPolicyById(accessPolicyId)); - final Set<TenantEntity> userGroups = accessPolicy != null ? accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()) : null; - final Set<TenantEntity> users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null; + final Set<TenantEntity> userGroups = accessPolicy != null ? accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()) : null; + final Set<TenantEntity> users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()) : null; final AccessPolicyDTO snapshot = deleteComponent( revision, new Resource() { @@ -1700,7 +1700,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final AccessPolicy newAccessPolicy = accessPolicyDAO.createAccessPolicy(accessPolicyDTO); final ComponentReferenceEntity componentReference = createComponentReferenceEntity(newAccessPolicy.getResource()); final AccessPolicyDTO newAccessPolicyDto = dtoFactory.createAccessPolicyDto(newAccessPolicy, - newAccessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()), + newAccessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()), newAccessPolicy.getUsers().stream().map(userId -> { final RevisionDTO userRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userId)); return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(userDAO.getUser(userId)), userRevision, @@ -1716,7 +1716,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final String creator = NiFiUserUtils.getNiFiUserIdentity(); final User newUser = userDAO.createUser(userDTO); final Set<TenantEntity> tenantEntities = userGroupDAO.getUserGroupsForUser(newUser.getIdentifier()).stream() - .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()); + .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUser(newUser.getIdentifier()).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); final UserDTO newUserDto = dtoFactory.createUserDto(newUser, tenantEntities, policyEntities); @@ -1762,7 +1762,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { public UserGroupEntity createUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) { final String creator = NiFiUserUtils.getNiFiUserIdentity(); final Group newUserGroup = userGroupDAO.createUserGroup(userGroupDTO); - final Set<TenantEntity> tenantEntities = newUserGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); + final Set<TenantEntity> tenantEntities = newUserGroup.getUsers().stream().map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(newUserGroup.getIdentifier()).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, tenantEntities, policyEntities); @@ -3302,39 +3302,39 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); return entityFactory.createAccessPolicyEntity( dtoFactory.createAccessPolicyDto(accessPolicy, - accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()), - accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()), componentReference), + accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity(false)).collect(Collectors.toSet()), + accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity(false)).collect(Collectors.toSet()), componentReference), revision, permissions); } @Override public UserEntity getUser(final String userId) { final User user = userDAO.getUser(userId); - return createUserEntity(user); + return createUserEntity(user, true); } @Override public Set<UserEntity> getUsers() { final Set<User> users = userDAO.getUsers(); return users.stream() - .map(user -> createUserEntity(user)) + .map(user -> createUserEntity(user, false)) .collect(Collectors.toSet()); } - private UserEntity createUserEntity(final User user) { + private UserEntity createUserEntity(final User user, final boolean enforceUserExistence) { final RevisionDTO userRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(user.getIdentifier())); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); final Set<TenantEntity> userGroups = userGroupDAO.getUserGroupsForUser(user.getIdentifier()).stream() - .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()); + .map(g -> g.getIdentifier()).map(mapUserGroupIdToTenantEntity(enforceUserExistence)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUser(user.getIdentifier()).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); return entityFactory.createUserEntity(dtoFactory.createUserDto(user, userGroups, policyEntities), userRevision, permissions); } - private UserGroupEntity createUserGroupEntity(final Group userGroup) { + private UserGroupEntity createUserGroupEntity(final Group userGroup, final boolean enforceGroupExistence) { final RevisionDTO userGroupRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userGroup.getIdentifier())); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); - final Set<TenantEntity> users = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); + final Set<TenantEntity> users = userGroup.getUsers().stream().map(mapUserIdToTenantEntity(enforceGroupExistence)).collect(Collectors.toSet()); final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(userGroup.getIdentifier()).stream() .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users, policyEntities), userGroupRevision, permissions); @@ -3343,14 +3343,14 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public UserGroupEntity getUserGroup(final String userGroupId) { final Group userGroup = userGroupDAO.getUserGroup(userGroupId); - return createUserGroupEntity(userGroup); + return createUserGroupEntity(userGroup, true); } @Override public Set<UserGroupEntity> getUserGroups() { final Set<Group> userGroups = userGroupDAO.getUserGroups(); return userGroups.stream() - .map(userGroup -> createUserGroupEntity(userGroup)) + .map(userGroup -> createUserGroupEntity(userGroup, false)) .collect(Collectors.toSet()); } @@ -4740,18 +4740,34 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } /* reusable function declarations for converting ids to tenant entities */ - private Function<String, TenantEntity> mapUserGroupIdToTenantEntity() { + private Function<String, TenantEntity> mapUserGroupIdToTenantEntity(final boolean enforceGroupExistence) { return userGroupId -> { final RevisionDTO userGroupRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userGroupId)); - return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(userGroupDAO.getUserGroup(userGroupId)), userGroupRevision, + + final Group group; + if (enforceGroupExistence || userGroupDAO.hasUserGroup(userGroupId)) { + group = userGroupDAO.getUserGroup(userGroupId); + } else { + group = new Group.Builder().identifier(userGroupId).name("Group ID - " + userGroupId + " (removed externally)").build(); + } + + return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(group), userGroupRevision, dtoFactory.createPermissionsDto(authorizableLookup.getTenant())); }; } - private Function<String, TenantEntity> mapUserIdToTenantEntity() { + private Function<String, TenantEntity> mapUserIdToTenantEntity(final boolean enforceUserExistence) { return userId -> { final RevisionDTO userRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userId)); - return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(userDAO.getUser(userId)), userRevision, + + final User user; + if (enforceUserExistence || userDAO.hasUser(userId)) { + user = userDAO.getUser(userId); + } else { + user = new User.Builder().identifier(userId).identity("User ID - " + userId + " (removed externally)").build(); + } + + return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(user), userRevision, dtoFactory.createPermissionsDto(authorizableLookup.getTenant())); }; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java index 75f1c56..030b19e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/NiFiAuthenticationFilter.java @@ -67,7 +67,6 @@ public abstract class NiFiAuthenticationFilter extends GenericFilterBean { } private void authenticate(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException { - String dnChain = null; try { final Authentication authenticationRequest = attemptAuthentication(request); if (authenticationRequest != null) { @@ -79,13 +78,25 @@ public abstract class NiFiAuthenticationFilter extends GenericFilterBean { final Authentication authenticated = authenticationManager.authenticate(authenticationRequest); successfulAuthorization(request, response, authenticated); } - - // continue - chain.doFilter(request, response); } catch (final AuthenticationException ae) { // invalid authentication - always error out unsuccessfulAuthorization(request, response, ae); + return; + } catch (final Exception e) { + log.error(String.format("Unable to authorize: %s", e.getMessage()), e); + + // set the response status + response.setContentType("text/plain"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + // other exception - always error out + PrintWriter out = response.getWriter(); + out.println(String.format("Failed to authorize request. Please contact the system administrator.")); + return; } + + // continue + chain.doFilter(request, response); } /**