http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java index 9c2cad5..02a5e75 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java @@ -16,38 +16,33 @@ */ package org.apache.nifi.authorization; -import java.io.File; import java.io.IOException; -import java.util.Collection; +import java.util.ArrayList; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; import org.apache.nifi.authorization.annotation.AuthorityProviderContext; import org.apache.nifi.authorization.exception.AuthorityAccessException; import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException; import org.apache.nifi.authorization.exception.ProviderCreationException; import org.apache.nifi.authorization.exception.UnknownIdentityException; -import org.apache.nifi.util.file.FileUtils; import org.apache.nifi.user.generated.ObjectFactory; import org.apache.nifi.user.generated.Role; import org.apache.nifi.user.generated.User; -import org.apache.nifi.user.generated.Users; import org.apache.nifi.util.NiFiProperties; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.authorized.users.AuthorizedUsers; +import org.apache.nifi.authorized.users.AuthorizedUsers.CreateUser; +import org.apache.nifi.authorized.users.AuthorizedUsers.FindUser; +import org.apache.nifi.authorized.users.AuthorizedUsers.FindUsers; +import org.apache.nifi.authorized.users.AuthorizedUsers.HasUser; +import org.apache.nifi.authorized.users.AuthorizedUsers.UpdateUser; +import org.apache.nifi.authorized.users.AuthorizedUsers.UpdateUsers; +import org.apache.nifi.user.generated.NiFiUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xml.sax.SAXException; /** * Provides identity checks and grants authorities. @@ -55,84 +50,26 @@ import org.xml.sax.SAXException; public class FileAuthorizationProvider implements AuthorityProvider { private static final Logger logger = LoggerFactory.getLogger(FileAuthorizationProvider.class); - private static final String USERS_XSD = "/users.xsd"; - private static final String JAXB_GENERATED_PATH = "org.apache.nifi.user.generated"; - private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext(); - - /** - * Load the JAXBContext. - */ - private static JAXBContext initializeJaxbContext() { - try { - return JAXBContext.newInstance(JAXB_GENERATED_PATH, FileAuthorizationProvider.class.getClassLoader()); - } catch (JAXBException e) { - throw new RuntimeException("Unable to create JAXBContext."); - } - } private NiFiProperties properties; - private File usersFile; - private File restoreUsersFile; - private Users users; private final Set<String> defaultAuthorities = new HashSet<>(); + private AuthorizedUsers authorizedUsers; + @Override public void initialize(final AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException { } @Override public void onConfigured(final AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException { - try { - final String usersFilePath = configurationContext.getProperty("Authorized Users File"); - if (usersFilePath == null || usersFilePath.trim().isEmpty()) { - throw new ProviderCreationException("The authorized users file must be specified."); - } - - // the users file instance will never be null because a default is used - usersFile = new File(usersFilePath); - final File usersFileDirectory = usersFile.getParentFile(); - - // the restore directory is optional and may be null - final File restoreDirectory = properties.getRestoreDirectory(); - - if (restoreDirectory != null) { - - // sanity check that restore directory is a directory, creating it if necessary - FileUtils.ensureDirectoryExistAndCanAccess(restoreDirectory); - - // check that restore directory is not the same as the primary directory - if (usersFileDirectory.getAbsolutePath().equals(restoreDirectory.getAbsolutePath())) { - throw new ProviderCreationException(String.format("Authorized User's directory '%s' is the same as restore directory '%s' ", - usersFileDirectory.getAbsolutePath(), restoreDirectory.getAbsolutePath())); - } - - // the restore copy will have same file name, but reside in a different directory - restoreUsersFile = new File(restoreDirectory, usersFile.getName()); - - // sync the primary copy with the restore copy - try { - FileUtils.syncWithRestore(usersFile, restoreUsersFile, logger); - } catch (final IOException | IllegalStateException ioe) { - throw new ProviderCreationException(ioe); - } - - } + final String usersFilePath = configurationContext.getProperty("Authorized Users File"); + if (usersFilePath == null || usersFilePath.trim().isEmpty()) { + throw new ProviderCreationException("The authorized users file must be specified."); + } - // load the users from the specified file - if (usersFile.exists()) { - // find the schema - final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - final Schema schema = schemaFactory.newSchema(FileAuthorizationProvider.class.getResource(USERS_XSD)); - - // attempt to unmarshal - final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller(); - unmarshaller.setSchema(schema); - final JAXBElement<Users> element = unmarshaller.unmarshal(new StreamSource(usersFile), Users.class); - users = element.getValue(); - } else { - final ObjectFactory objFactory = new ObjectFactory(); - users = objFactory.createUsers(); - } + try { + // initialize the authorized users + authorizedUsers = AuthorizedUsers.getInstance(usersFilePath, properties); // attempt to load a default roles final String rawDefaultAuthorities = configurationContext.getProperty("Default User Roles"); @@ -157,10 +94,9 @@ public class FileAuthorizationProvider implements AuthorityProvider { StringUtils.join(invalidDefaultAuthorities, ", "), StringUtils.join(Authority.getRawAuthorities(), ", "))); } } - } catch (IOException | ProviderCreationException | SAXException | JAXBException e) { + } catch (IOException | IllegalStateException | ProviderCreationException e) { throw new ProviderCreationException(e); } - } @Override @@ -172,67 +108,78 @@ public class FileAuthorizationProvider implements AuthorityProvider { } @Override - public boolean doesDnExist(String dn) throws AuthorityAccessException { + public boolean doesDnExist(final String dn) throws AuthorityAccessException { if (hasDefaultRoles()) { return true; } - final User user = getUser(dn); - return user != null; + return authorizedUsers.hasUser(new HasUser() { + @Override + public boolean hasUser(List<NiFiUser> users) { + // attempt to get the user and ensure it was located + NiFiUser desiredUser = null; + for (final NiFiUser user : users) { + if (dn.equalsIgnoreCase(authorizedUsers.getUserIdentity(user))) { + desiredUser = user; + break; + } + } + + return desiredUser != null; + } + }); } @Override - public synchronized Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException { + public Set<Authority> getAuthorities(final String dn) throws UnknownIdentityException, AuthorityAccessException { final Set<Authority> authorities = EnumSet.noneOf(Authority.class); // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - if (hasDefaultRoles()) { - logger.debug(String.format("User DN not found: %s. Creating new user with default roles.", dn)); - - // create the user (which will automatically add any default authorities) - addUser(dn, null); + final NiFiUser user = authorizedUsers.getUser(new FindUser() { + @Override + public NiFiUser findUser(List<NiFiUser> users) { + final FindUser byDn = new FindUserByIdentity(dn); + NiFiUser user = byDn.findUser(users); + + // if the user is not found, add them and locate them + if (user == null) { + if (hasDefaultRoles()) { + logger.debug(String.format("User identity not found: %s. Creating new user with default roles.", dn)); + + // create the user (which will automatically add any default authorities) + addUser(dn, null); + + // find the user that was just added + user = byDn.findUser(users); + } else { + throw new UnknownIdentityException(String.format("User identity not found: %s.", dn)); + } + } - // get the authorities for the newly created user - authorities.addAll(getAuthorities(dn)); - } else { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); - } - } else { - // create the authorities that this user has - for (final Role role : user.getRole()) { - authorities.add(Authority.valueOfAuthority(role.getName())); + return user; } + }); + + // create the authorities that this user has + for (final Role role : user.getRole()) { + authorities.add(Authority.valueOfAuthority(role.getName())); } return authorities; } @Override - public synchronized void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException { - // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); - } - - // add the user authorities - setUserAuthorities(user, authorities); - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + public void setAuthorities(final String dn, final Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException { + authorizedUsers.updateUser(new FindUserByIdentity(dn), new UpdateUser() { + @Override + public void updateUser(NiFiUser user) { + // add the user authorities + setUserAuthorities(user, authorities); + } + }); } - private void setUserAuthorities(final User user, final Set<Authority> authorities) { + private void setUserAuthorities(final NiFiUser user, final Set<Authority> authorities) { // clear the existing rules user.getRole().clear(); @@ -248,186 +195,118 @@ public class FileAuthorizationProvider implements AuthorityProvider { } @Override - public synchronized void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException { - final User user = getUser(dn); + public void addUser(final String dn, final String group) throws IdentityAlreadyExistsException, AuthorityAccessException { + authorizedUsers.createUser(new CreateUser() { + @Override + public NiFiUser createUser() { + final NiFiUser user = authorizedUsers.getUser(new FindUserByIdentity(dn)); + + // ensure the user doesn't already exist + if (user != null) { + throw new IdentityAlreadyExistsException(String.format("User identity already exists: %s", dn)); + } - // ensure the user doesn't already exist - if (user != null) { - throw new IdentityAlreadyExistsException(String.format("User DN already exists: %s", dn)); - } + // only support adding PreAuthenticatedUser's via this API - LoginUser's are added + // via the LoginIdentityProvider + final ObjectFactory objFactory = new ObjectFactory(); + final User newUser = objFactory.createUser(); - // create the new user - final ObjectFactory objFactory = new ObjectFactory(); - final User newUser = objFactory.createUser(); + // set the user properties + newUser.setDn(dn); + newUser.setGroup(group); - // set the user properties - newUser.setDn(dn); - newUser.setGroup(group); + // add default roles if appropriate + if (hasDefaultRoles()) { + for (final String authority : defaultAuthorities) { + Role role = objFactory.createRole(); + role.setName(authority); - // add default roles if appropriate - if (hasDefaultRoles()) { - for (final String authority : defaultAuthorities) { - Role role = objFactory.createRole(); - role.setName(authority); + // add the role + newUser.getRole().add(role); + } + } - // add the role - newUser.getRole().add(role); + return newUser; } - } - - // add the user - users.getUser().add(newUser); - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + }); } @Override - public synchronized Set<String> getUsers(Authority authority) throws AuthorityAccessException { - final Set<String> userSet = new HashSet<>(); - for (final User user : users.getUser()) { - for (final Role role : user.getRole()) { - if (role.getName().equals(authority.toString())) { - userSet.add(user.getDn()); + public Set<String> getUsers(final Authority authority) throws AuthorityAccessException { + final List<NiFiUser> matchingUsers = authorizedUsers.getUsers(new FindUsers() { + @Override + public List<NiFiUser> findUsers(List<NiFiUser> users) throws UnknownIdentityException { + final List<NiFiUser> matchingUsers = new ArrayList<>(); + for (final NiFiUser user : users) { + for (final Role role : user.getRole()) { + if (role.getName().equals(authority.toString())) { + matchingUsers.add(user); + } + } } + return matchingUsers; } + }); + + final Set<String> userSet = new HashSet<>(); + for (final NiFiUser user : matchingUsers) { + userSet.add(authorizedUsers.getUserIdentity(user)); } + return userSet; } @Override - public synchronized void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException { - // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); - } - - // remove the specified user - users.getUser().remove(user); - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + public void revokeUser(final String dn) throws UnknownIdentityException, AuthorityAccessException { + authorizedUsers.removeUser(new FindUserByIdentity(dn)); } @Override - public void setUsersGroup(Set<String> dns, String group) throws UnknownIdentityException, AuthorityAccessException { - final Collection<User> groupedUsers = new HashSet<>(); - - // get the specified users - for (final String dn : dns) { - // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); + public void setUsersGroup(final Set<String> dns, final String group) throws UnknownIdentityException, AuthorityAccessException { + authorizedUsers.updateUsers(new FindUsersByIdentity(dns), new UpdateUsers() { + @Override + public void updateUsers(List<NiFiUser> users) { + // update each user group + for (final NiFiUser user : users) { + user.setGroup(group); + } } - - groupedUsers.add(user); - } - - // update each user group - for (final User user : groupedUsers) { - user.setGroup(group); - } - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + }); } @Override public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException { - // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); - } - - // remove the users group - user.setGroup(null); - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + authorizedUsers.updateUser(new FindUserByIdentity(dn), new UpdateUser() { + @Override + public void updateUser(NiFiUser user) { + // remove the users group + user.setGroup(null); + } + }); } @Override - public void ungroup(String group) throws AuthorityAccessException { - // get the user group - final Collection<User> userGroup = getUserGroup(group); - - // ensure the user group was located - if (userGroup == null) { - return; - } - - // update each user group - for (final User user : userGroup) { - user.setGroup(null); - } - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + public void ungroup(final String group) throws AuthorityAccessException { + authorizedUsers.updateUsers(new FindUsersByGroup(group), new UpdateUsers() { + @Override + public void updateUsers(List<NiFiUser> users) { + // update each user group + for (final NiFiUser user : users) { + user.setGroup(null); + } + } + }); } @Override - public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException { - // get the user - final User user = getUser(dn); - - // ensure the user was located - if (user == null) { - throw new UnknownIdentityException(String.format("User DN not found: %s.", dn)); - } - + public String getGroupForUser(final String dn) throws UnknownIdentityException, AuthorityAccessException { + final NiFiUser user = authorizedUsers.getUser(new FindUserByIdentity(dn)); return user.getGroup(); } @Override public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException { - // get the user group - final Collection<User> userGroup = getUserGroup(group); - - // ensure the user group was located - if (userGroup == null) { - throw new UnknownIdentityException(String.format("User group not found: %s.", group)); - } - - // remove each user in the group - for (final User user : userGroup) { - users.getUser().remove(user); - } - - try { - // save the file - save(); - } catch (Exception e) { - throw new AuthorityAccessException(e.getMessage(), e); - } + authorizedUsers.removeUsers(new FindUsersByGroup(group)); } /** @@ -438,59 +317,108 @@ public class FileAuthorizationProvider implements AuthorityProvider { return DownloadAuthorization.approved(); } - private User getUser(String dn) throws UnknownIdentityException { - // ensure the DN was specified - if (dn == null) { - throw new UnknownIdentityException("User DN not specified."); - } + @AuthorityProviderContext + public void setNiFiProperties(NiFiProperties properties) { + this.properties = properties; + } - // attempt to get the user and ensure it was located - User desiredUser = null; - for (final User user : users.getUser()) { - if (dn.equalsIgnoreCase(user.getDn())) { - desiredUser = user; - break; + public class FindUserByIdentity implements FindUser { + + private final String identity; + + public FindUserByIdentity(String identity) { + // ensure the identity was specified + if (identity == null) { + throw new UnknownIdentityException("User identity not specified."); } + + this.identity = identity; } - return desiredUser; + @Override + public NiFiUser findUser(List<NiFiUser> users) { + // attempt to get the user and ensure it was located + NiFiUser desiredUser = null; + for (final NiFiUser user : users) { + if (identity.equalsIgnoreCase(authorizedUsers.getUserIdentity(user))) { + desiredUser = user; + break; + } + } + + if (desiredUser == null) { + throw new UnknownIdentityException(String.format("User identity not found: %s.", identity)); + } + + return desiredUser; + } } - private Collection<User> getUserGroup(String group) throws UnknownIdentityException { - // ensure the DN was specified - if (group == null) { - throw new UnknownIdentityException("User group not specified."); + public static class FindUsersByGroup implements FindUsers { + + private final String group; + + public FindUsersByGroup(String group) { + // ensure the group was specified + if (group == null) { + throw new UnknownIdentityException("User group not specified."); + } + + this.group = group; } - // get all users with this group - Collection<User> userGroup = null; - for (final User user : users.getUser()) { - if (group.equals(user.getGroup())) { - if (userGroup == null) { - userGroup = new HashSet<>(); + @Override + public List<NiFiUser> findUsers(List<NiFiUser> users) throws UnknownIdentityException { + // get all users with this group + List<NiFiUser> userGroup = new ArrayList<>(); + for (final NiFiUser user : users) { + if (group.equals(user.getGroup())) { + userGroup.add(user); } - userGroup.add(user); } - } - return userGroup; + // ensure the user group was located + if (userGroup.isEmpty()) { + throw new UnknownIdentityException(String.format("User group not found: %s.", group)); + } + + return userGroup; + } } - private void save() throws Exception { - final Marshaller marshaller = JAXB_CONTEXT.createMarshaller(); - marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + public class FindUsersByIdentity implements FindUsers { + + private final Set<String> identities; - // save users to restore directory before primary directory - if (restoreUsersFile != null) { - marshaller.marshal(users, restoreUsersFile); + public FindUsersByIdentity(Set<String> identities) { + // ensure the group was specified + if (identities == null) { + throw new UnknownIdentityException("User identities not specified."); + } + + this.identities = identities; } - // save users to primary directory - marshaller.marshal(users, usersFile); - } + @Override + public List<NiFiUser> findUsers(List<NiFiUser> users) throws UnknownIdentityException { + final Set<String> copy = new HashSet<>(identities); + + // get all users with this group + List<NiFiUser> userList = new ArrayList<>(); + for (final NiFiUser user : users) { + final String userIdentity = authorizedUsers.getUserIdentity(user); + if (copy.contains(userIdentity)) { + copy.remove(userIdentity); + userList.add(user); + } + } - @AuthorityProviderContext - public void setNiFiProperties(NiFiProperties properties) { - this.properties = properties; + if (!copy.isEmpty()) { + throw new UnknownIdentityException("Unable to find users with identities: " + StringUtils.join(copy, ", ")); + } + + return userList; + } } + }
http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd deleted file mode 100644 index 4ee1e17..0000000 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorization-provider/src/main/xsd/users.xsd +++ /dev/null @@ -1,64 +0,0 @@ -<?xml version="1.0"?> -<!-- - 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. ---> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <!-- role --> - <xs:complexType name="Role"> - <xs:attribute name="name"> - <xs:simpleType> - <xs:restriction base="xs:string"> - <xs:enumeration value="ROLE_MONITOR"/> - <xs:enumeration value="ROLE_PROVENANCE"/> - <xs:enumeration value="ROLE_DFM"/> - <xs:enumeration value="ROLE_ADMIN"/> - <xs:enumeration value="ROLE_PROXY"/> - <xs:enumeration value="ROLE_NIFI"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - </xs:complexType> - - <!-- user --> - <xs:complexType name="User"> - <xs:sequence> - <xs:element name="role" type="Role" minOccurs="0" maxOccurs="unbounded"/> - </xs:sequence> - <xs:attribute name="dn"> - <xs:simpleType> - <xs:restriction base="xs:string"> - <xs:minLength value="1"/> - <xs:pattern value=".*[^\s].*"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute name="group"> - <xs:simpleType> - <xs:restriction base="xs:string"> - <xs:minLength value="1"/> - <xs:pattern value=".*[^\s].*"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - </xs:complexType> - - <!-- users --> - <xs:element name="users"> - <xs:complexType> - <xs:sequence> - <xs:element name="user" type="User" minOccurs="0" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> - </xs:element> -</xs:schema> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml new file mode 100644 index 0000000..9dc5d02 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/pom.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-framework</artifactId> + <version>0.3.1-SNAPSHOT</version> + </parent> + <artifactId>nifi-file-identity-provider</artifactId> + <packaging>jar</packaging> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-properties</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-authorized-users</artifactId> + </dependency> + </dependencies> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java new file mode 100644 index 0000000..6e72880 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/java/org/apache/nifi/authentication/FileLoginIdentityProvider.java @@ -0,0 +1,101 @@ +/* + * 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.authentication; + +import java.io.IOException; +import java.util.List; +import org.apache.nifi.authentication.annotation.LoginIdentityProviderContext; +import org.apache.nifi.authorization.exception.ProviderCreationException; +import org.apache.nifi.authorization.exception.ProviderDestructionException; +import org.apache.nifi.authorized.users.AuthorizedUsers; +import org.apache.nifi.authorized.users.AuthorizedUsers.HasUser; +import org.apache.nifi.user.generated.LoginUser; +import org.apache.nifi.user.generated.NiFiUser; +import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.util.StringUtils; + +/** + * + */ +public class FileLoginIdentityProvider implements LoginIdentityProvider { + + private AuthorizedUsers authorizedUsers; + private NiFiProperties properties; + + @Override + public void initialize(LoginIdentityProviderInitializationContext initializationContext) throws ProviderCreationException { + } + + @Override + public void onConfigured(LoginIdentityProviderConfigurationContext configurationContext) throws ProviderCreationException { + final String usersFilePath = configurationContext.getProperty("Authenticated Users File"); + if (usersFilePath == null || usersFilePath.trim().isEmpty()) { + throw new ProviderCreationException("The authorized users file must be specified."); + } + + try { + // initialize the authorized users + authorizedUsers = AuthorizedUsers.getInstance(usersFilePath, properties); + } catch (IOException | IllegalStateException e) { + throw new ProviderCreationException(e); + } + } + + @Override + public boolean supportsRegistration() { + return false; + } + + @Override + public void register(LoginCredentials credentials) { + } + + @Override + public boolean authenticate(final LoginCredentials credentials) { + if (StringUtils.isBlank(credentials.getUsername()) || StringUtils.isBlank(credentials.getPassword())) { + return false; + } + + return authorizedUsers.hasUser(new HasUser() { + @Override + public boolean hasUser(List<NiFiUser> users) { + for (final NiFiUser user : users) { + // only consider LoginUsers + if (LoginUser.class.isAssignableFrom(user.getClass())) { + final LoginUser loginUser = (LoginUser) user; + + // TODO - need to properly encrypt and hash password + final String loginUserPassword = loginUser.getPassword(); + if (credentials.getUsername().equals(loginUser.getUsername()) && credentials.getPassword().equals(loginUserPassword)) { + return true; + } + } + } + return false; + } + }); + } + + @Override + public void preDestruction() throws ProviderDestructionException { + } + + @LoginIdentityProviderContext + public void setNiFiProperties(NiFiProperties properties) { + this.properties = properties; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider new file mode 100644 index 0000000..3dc6354 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-identity-provider/src/main/resources/META-INF/services/org.apache.nifi.authentication.LoginIdentityProvider @@ -0,0 +1,15 @@ +# 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. +org.apache.nifi.authentication.FileLoginIdentityProvider http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java index 9bbc3a3..489b80e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/ExtensionManager.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; +import org.apache.nifi.authentication.LoginIdentityProvider; import org.apache.nifi.authorization.AuthorityProvider; import org.apache.nifi.controller.ControllerService; @@ -65,6 +66,7 @@ public class ExtensionManager { definitionMap.put(FlowFileRepository.class, new HashSet<Class>()); definitionMap.put(FlowFileSwapManager.class, new HashSet<Class>()); definitionMap.put(ContentRepository.class, new HashSet<Class>()); + definitionMap.put(LoginIdentityProvider.class, new HashSet<Class>()); } /** http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml new file mode 100644 index 0000000..5b4cf88 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/login-identity-providers.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + 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. +--> +<!-- + This file lists the login identity 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. +--> +<loginIdentityProviders> + <provider> + <identifier>file-provider</identifier> + <class>org.apache.nifi.authentication.FileLoginIdentityProvider</class> + <property name="Authenticated Users File">./conf/authorized-users.xml</property> + </provider> +</loginIdentityProviders> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties index 54b5283..b25d05a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties @@ -25,6 +25,7 @@ nifi.administrative.yield.duration=${nifi.administrative.yield.duration} nifi.bored.yield.duration=${nifi.bored.yield.duration} nifi.authority.provider.configuration.file=${nifi.authority.provider.configuration.file} +nifi.login.identity.provider.configuration.file=${nifi.login.identity.provider.configuration.file} nifi.templates.directory=${nifi.templates.directory} nifi.ui.banner.text=${nifi.ui.banner.text} nifi.ui.autorefresh.interval=${nifi.ui.autorefresh.interval} @@ -124,7 +125,9 @@ nifi.security.truststorePasswd=${nifi.security.truststorePasswd} nifi.security.needClientAuth=${nifi.security.needClientAuth} nifi.security.user.credential.cache.duration=${nifi.security.user.credential.cache.duration} nifi.security.user.authority.provider=${nifi.security.user.authority.provider} +nifi.security.user.login.identity.provider=${nifi.security.user.login.identity.provider} nifi.security.support.new.account.requests=${nifi.security.support.new.account.requests} +nifi.security.anonymous.authorities=${nifi.security.anonymous.authorities} nifi.security.ocsp.responder.url=${nifi.security.ocsp.responder.url} nifi.security.ocsp.responder.certificate=${nifi.security.ocsp.responder.certificate} http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java index 99c11a8..b2b3013 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java @@ -614,8 +614,9 @@ public class JettyServer implements NiFiServer { private SslContextFactory createSslContextFactory() { final SslContextFactory contextFactory = new SslContextFactory(); - // need client auth - contextFactory.setNeedClientAuth(props.getNeedClientAuth()); + // client auth + contextFactory.setWantClientAuth(true); + contextFactory.setNeedClientAuth(false); /* below code sets JSSE system properties when values are provided */ // keystore properties http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index c98b1e4..f4d5821 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -1236,6 +1236,13 @@ public interface NiFiServiceFacade { Collection<UserDTO> getUsers(Boolean grouped); /** + * Creates a new account request. + * + * @return user + */ + UserDTO createUser(); + + /** * Updates the specified user accordingly. * * @param user The user to update http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java new file mode 100644 index 0000000..58b0af8 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiConfiguration.java @@ -0,0 +1,40 @@ +/* + * 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.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.ImportResource; + +/** + * + */ +@Configuration +@Import({NiFiWebApiSecurityConfiguration.class}) +@ImportResource({"classpath:nifi-context.xml", + "classpath:nifi-administration-context.xml", + "classpath:nifi-cluster-manager-context.xml", + "classpath:nifi-cluster-protocol-context.xml", + "classpath:nifi-web-security-context.xml", + "classpath:nifi-web-api-context.xml"}) +public class NiFiWebApiConfiguration { + + public NiFiWebApiConfiguration() { + super(); + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java new file mode 100644 index 0000000..7aeb105 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java @@ -0,0 +1,192 @@ +/* + * 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.web; + +import javax.servlet.Filter; +import org.apache.nifi.admin.service.UserService; +import org.apache.nifi.authentication.LoginIdentityProvider; +import org.apache.nifi.util.NiFiProperties; +import org.apache.nifi.web.security.NiFiAuthenticationProvider; +import org.apache.nifi.web.security.anonymous.NiFiAnonymousUserFilter; +import org.apache.nifi.web.security.NiFiAuthenticationEntryPoint; +import org.apache.nifi.web.security.form.LoginAuthenticationFilter; +import org.apache.nifi.web.security.form.LoginAuthenticationProvider; +import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter; +import org.apache.nifi.web.security.jwt.JwtAuthenticationProvider; +import org.apache.nifi.web.security.jwt.JwtService; +import org.apache.nifi.web.security.node.NodeAuthorizedUserFilter; +import org.apache.nifi.web.security.x509.SubjectDnX509PrincipalExtractor; +import org.apache.nifi.web.security.x509.X509AuthenticationFilter; +import org.apache.nifi.web.security.x509.X509AuthenticationProvider; +import org.apache.nifi.web.security.x509.X509CertificateExtractor; +import org.apache.nifi.web.security.x509.ocsp.OcspCertificateValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.AuthenticationUserDetailsService; +import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * NiFi Web Api Spring security + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapter { + + private NiFiProperties properties; + private UserService userService; + private AuthenticationUserDetailsService userDetailsService; + private JwtService jwtService; + private LoginIdentityProvider loginIdentityProvider; + + public NiFiWebApiSecurityConfiguration() { + super(true); // disable defaults + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .rememberMe().disable() + .exceptionHandling() + .authenticationEntryPoint(new NiFiAuthenticationEntryPoint()) + .and() + .authorizeRequests() + .anyRequest().fullyAuthenticated() + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + // verify that login authentication is enabled + if (loginIdentityProvider != null) { + // login authentication for /token - exchanges for JWT for subsequent API usage + http.addFilterBefore(buildLoginFilter("/token"), UsernamePasswordAuthenticationFilter.class); + + // login registration + if (loginIdentityProvider.supportsRegistration()) { + http.addFilterBefore(buildRegistrationFilter("/registration"), UsernamePasswordAuthenticationFilter.class); + } + } + + // cluster authorized user + http.addFilterBefore(buildNodeAuthorizedUserFilter(), AnonymousAuthenticationFilter.class); + + // x509 + http.addFilterBefore(buildX509Filter(), AnonymousAuthenticationFilter.class); + + // jwt + http.addFilterBefore(buildJwtFilter(), AnonymousAuthenticationFilter.class); + + // anonymous + http.anonymous().authenticationFilter(buildAnonymousFilter()); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + // override xxxBean method so the authentication manager is available in app context (necessary for the method level security) + return super.authenticationManagerBean(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + final LoginAuthenticationProvider baseLoginAuthenticationProvider = new LoginAuthenticationProvider(); + baseLoginAuthenticationProvider.setLoginIdentityProvider(loginIdentityProvider); + + final AuthenticationProvider loginAuthenticationProvider = new NiFiAuthenticationProvider(baseLoginAuthenticationProvider, userDetailsService); + final AuthenticationProvider x509AuthenticationProvider = new NiFiAuthenticationProvider(new X509AuthenticationProvider(), userDetailsService); + final AuthenticationProvider jwtAuthenticationProvider = new NiFiAuthenticationProvider(new JwtAuthenticationProvider(), userDetailsService); + + auth + .authenticationProvider(loginAuthenticationProvider) + .authenticationProvider(x509AuthenticationProvider) + .authenticationProvider(jwtAuthenticationProvider); + } + + private LoginAuthenticationFilter buildLoginFilter(final String url) { + final LoginAuthenticationFilter loginFilter = new LoginAuthenticationFilter(url); + loginFilter.setJwtService(jwtService); + loginFilter.setLoginIdentityProvider(loginIdentityProvider); + loginFilter.setPrincipalExtractor(new SubjectDnX509PrincipalExtractor()); + loginFilter.setCertificateExtractor(new X509CertificateExtractor()); + return loginFilter; + } + + private Filter buildRegistrationFilter(final String url) { + return null; + } + + private NodeAuthorizedUserFilter buildNodeAuthorizedUserFilter() { + return new NodeAuthorizedUserFilter(properties); + } + + private JwtAuthenticationFilter buildJwtFilter() throws Exception { + final JwtAuthenticationFilter jwtFilter = new JwtAuthenticationFilter(); + jwtFilter.setJwtService(jwtService); + jwtFilter.setAuthenticationManager(authenticationManager()); + return jwtFilter; + } + + private X509AuthenticationFilter buildX509Filter() throws Exception { + final X509AuthenticationFilter x509Filter = new X509AuthenticationFilter(); + x509Filter.setPrincipalExtractor(new SubjectDnX509PrincipalExtractor()); + x509Filter.setCertificateExtractor(new X509CertificateExtractor()); + x509Filter.setCertificateValidator(new OcspCertificateValidator(properties)); + x509Filter.setAuthenticationManager(authenticationManager()); + return x509Filter; + } + + private AnonymousAuthenticationFilter buildAnonymousFilter() { + final NiFiAnonymousUserFilter anonymousFilter = new NiFiAnonymousUserFilter(); + anonymousFilter.setUserService(userService); + return anonymousFilter; + } + + @Autowired + public void setUserDetailsService(AuthenticationUserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + + @Autowired + public void setUserService(UserService userService) { + this.userService = userService; + } + + @Autowired + public void setProperties(NiFiProperties properties) { + this.properties = properties; + } + + @Autowired + public void setJwtService(JwtService jwtService) { + this.jwtService = jwtService; + } + + @Autowired + public void setLoginIdentityProvider(LoginIdentityProvider loginIdentityProvider) { + this.loginIdentityProvider = loginIdentityProvider; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java ---------------------------------------------------------------------- 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 39426c0..75cd140 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 @@ -169,6 +169,7 @@ import org.apache.nifi.web.api.dto.status.ClusterProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.NodeProcessGroupStatusDTO; import org.apache.nifi.web.dao.ControllerServiceDAO; import org.apache.nifi.web.dao.ReportingTaskDAO; +import org.apache.nifi.web.security.user.NewAccountRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; @@ -1809,6 +1810,23 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override + public UserDTO createUser() { + NewAccountRequest newAccountRequest = NiFiUserUtils.getNewAccountRequest(); + + // log the new user account request + logger.info("Requesting new user account for " + newAccountRequest.getUsername()); + + // get the justification + String justification = newAccountRequest.getJustification(); + if (justification == null) { + justification = StringUtils.EMPTY; + } + + // create the pending user account + return dtoFactory.createUserDTO(userService.createPendingUserAccount(newAccountRequest.getUsername(), justification)); + } + + @Override public UserDTO updateUser(UserDTO userDto) { NiFiUser user; @@ -3437,8 +3455,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } /** - * Utility method for extracting component counts from the specified group - * status. + * Utility method for extracting component counts from the specified group status. */ private ProcessGroupCounts extractProcessGroupCounts(ProcessGroupStatus groupStatus) { int running = 0; http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java index 3bad5e3..2e15d30 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ApplicationResource.java @@ -23,7 +23,6 @@ import com.sun.jersey.server.impl.model.method.dispatch.FormDispatchProvider; import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; -import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; @@ -45,9 +44,8 @@ import org.apache.nifi.action.Operation; import org.apache.nifi.cluster.context.ClusterContext; import org.apache.nifi.cluster.context.ClusterContextThreadLocal; import org.apache.nifi.cluster.manager.impl.WebClusterManager; -import org.apache.nifi.web.security.DnUtils; +import org.apache.nifi.web.security.ProxiedEntitiesUtils; import org.apache.nifi.web.security.user.NiFiUserDetails; -import org.apache.nifi.web.security.x509.X509CertificateExtractor; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.api.entity.Entity; import org.apache.nifi.web.api.request.ClientIdParameter; @@ -362,12 +360,10 @@ public abstract class ApplicationResource { result.put(PROXY_SCHEME_HTTP_HEADER, httpServletRequest.getScheme()); } - // if this is a secure request, add the custom headers for proxying user requests - final X509Certificate cert = new X509CertificateExtractor().extractClientCertificate(httpServletRequest); - if (cert != null) { + if (httpServletRequest.isSecure()) { // add the certificate DN to the proxy chain - final String xProxiedEntitiesChain = DnUtils.getXProxiedEntitiesChain(httpServletRequest); + final String xProxiedEntitiesChain = ProxiedEntitiesUtils.getXProxiedEntitiesChain(httpServletRequest); if (StringUtils.isNotBlank(xProxiedEntitiesChain)) { result.put(PROXIED_ENTITIES_CHAIN_HTTP_HEADER, xProxiedEntitiesChain); } http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java index 4883721..31b256e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java @@ -79,6 +79,7 @@ import org.apache.nifi.web.api.request.IntegerParameter; import org.apache.nifi.web.api.request.LongParameter; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity; +import org.apache.nifi.web.api.entity.IdentityEntity; import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -239,7 +240,7 @@ public class ControllerResource extends ApplicationResource { public ProcessGroupResource getGroupResource( @ApiParam( value = "The id of the process group that is the parent of the requested resource(s). If the desired process group is " - + "the root group an alias 'root' may be used as the process-group-id.", + + "the root group an alias 'root' may be used as the process-group-id.", required = true ) @PathParam("process-group-id") String groupId) { @@ -454,13 +455,13 @@ public class ControllerResource extends ApplicationResource { @ApiOperation( value = "Gets the current revision of this NiFi", notes = "NiFi employs an optimistic locking strategy where the client must include a revision in their request when " - + "performing an update. If the specified revision does not match the current base revision a 409 status code " - + "is returned. The revision is comprised of a clientId and a version number. The version is a simple integer " - + "value that is incremented with each change. Including the most recent version tells NiFi that your working " - + "with the most recent flow. In addition to the version the client who is performing the updates is recorded. " - + "This allows the same client to submit multiple requests without having to wait for the previously ones to " - + "return. Invoking this endpoint will return the current base revision. It is also available when retrieving " - + "a process group and in the response of all mutable requests.", + + "performing an update. If the specified revision does not match the current base revision a 409 status code " + + "is returned. The revision is comprised of a clientId and a version number. The version is a simple integer " + + "value that is incremented with each change. Including the most recent version tells NiFi that your working " + + "with the most recent flow. In addition to the version the client who is performing the updates is recorded. " + + "This allows the same client to submit multiple requests without having to wait for the previously ones to " + + "return. Invoking this endpoint will return the current base revision. It is also available when retrieving " + + "a process group and in the response of all mutable requests.", response = Entity.class, authorizations = { @Authorization(value = "Read Only", type = "ROLE_MONITOR"), @@ -845,6 +846,47 @@ public class ControllerResource extends ApplicationResource { } /** + * Retrieves the identity of the user making the request. + * + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. + * @return An identityEntity + */ + @GET + @Consumes(MediaType.WILDCARD) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Path("/identity") + @ApiOperation( + value = "Retrieves the user identity of the user making the request", + response = IdentityEntity.class + ) + public Response getIdentity( + @ApiParam( + value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", + required = false + ) + @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + + // note that the cluster manager will handle this request directly + final NiFiUser user = NiFiUserUtils.getNiFiUser(); + if (user == null) { + throw new WebApplicationException(new Throwable("Unable to access details for current user.")); + } + + // create the revision + final RevisionDTO revision = new RevisionDTO(); + revision.setClientId(clientId.getClientId()); + + // create the response entity + IdentityEntity entity = new IdentityEntity(); + entity.setRevision(revision); + entity.setUserId(user.getId()); + entity.setIdentity(user.getDn()); + + // generate the response + return clusterContext(generateOkResponse(entity)).build(); + } + + /** * Retrieves the user details, including the authorities, about the user making the request. * * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java index 4a61ef4..8999f71 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/UserResource.java @@ -16,12 +16,14 @@ */ package org.apache.nifi.web.api; +import com.sun.jersey.api.Responses; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; import com.wordnik.swagger.annotations.ApiParam; import com.wordnik.swagger.annotations.ApiResponse; import com.wordnik.swagger.annotations.ApiResponses; import com.wordnik.swagger.annotations.Authorization; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -39,6 +41,7 @@ import javax.ws.rs.DefaultValue; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.HttpMethod; +import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -59,9 +62,11 @@ import org.apache.nifi.web.api.entity.UserSearchResultsEntity; import org.apache.nifi.web.api.entity.UsersEntity; import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.user.NiFiUser; import org.apache.nifi.web.NiFiServiceFacade; import static org.apache.nifi.web.api.ApplicationResource.CLIENT_ID; import org.apache.nifi.web.api.dto.RevisionDTO; +import org.apache.nifi.web.security.user.NiFiUserUtils; import org.springframework.security.access.prepost.PreAuthorize; /** @@ -83,12 +88,35 @@ public class UserResource extends ApplicationResource { private NiFiProperties properties; private NiFiServiceFacade serviceFacade; + @POST + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.TEXT_PLAIN) + @Path("") // necessary due to a bug in swagger + @ApiOperation( + value = "Creates a user", + response = String.class + ) + public Response createUser() { + if (!properties.getSupportNewAccountRequests()) { + return Responses.notFound().entity("This NiFi does not support new account requests.").build(); + } + + final NiFiUser nifiUser = NiFiUserUtils.getNiFiUser(); + if (nifiUser != null) { + throw new IllegalArgumentException("User account already created " + nifiUser.getDn()); + } + + // create an account request for the current user + final UserDTO user = serviceFacade.createUser(); + + final String uri = generateResourceUri("controller", "templates", user.getId()); + return generateCreatedResponse(URI.create(uri), "Not authorized. User account created. Authorization pending.").build(); + } + /** * Gets all users that are registered within this Controller. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param grouped Whether to return the users in their groups. * @return A usersEntity. */ @@ -144,9 +172,7 @@ public class UserResource extends ApplicationResource { /** * Gets the details for the specified user. * - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The user id. * @return A userEntity. */ @@ -315,12 +341,9 @@ public class UserResource extends ApplicationResource { * Updates the specified user. * * @param httpServletRequest request - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @param id The id of the user to update. - * @param rawAuthorities Array of authorities to assign to the specified - * user. + * @param rawAuthorities Array of authorities to assign to the specified user. * @param status The status of the specified users account. * @param formParams form params * @return A userEntity @@ -491,9 +514,7 @@ public class UserResource extends ApplicationResource { * * @param httpServletRequest request * @param id The user id - * @param clientId Optional client id. If the client id is not specified, a - * new one will be generated. This value (whether specified or generated) is - * included in the response. + * @param clientId Optional client id. If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response. * @return A userEntity. */ @DELETE http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index 8bf5553..3bc8120 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -113,6 +113,7 @@ import org.apache.nifi.authorization.DownloadAuthorization; import org.apache.nifi.processor.DataUnit; import org.apache.nifi.reporting.BulletinQuery; import org.apache.nifi.reporting.ComponentType; +import org.apache.nifi.web.security.ProxiedEntitiesUtils; import org.apache.nifi.web.security.user.NiFiUserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -822,17 +823,7 @@ public class ControllerFacade { final Map<String, String> attributes = event.getAttributes(); // calculate the dn chain - final List<String> dnChain = new ArrayList<>(); - - // build the dn chain - NiFiUser chainedUser = user; - do { - // add the entry for this user - dnChain.add(chainedUser.getDn()); - - // go to the next user in the chain - chainedUser = chainedUser.getChain(); - } while (chainedUser != null); + final List<String> dnChain = ProxiedEntitiesUtils.getXProxiedEntitiesChain(user); // ensure the users in this chain are allowed to download this content final DownloadAuthorization downloadAuthorization = userService.authorizeDownload(dnChain, attributes); http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml index 4ce319e..b57998d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/webapp/WEB-INF/web.xml @@ -16,15 +16,12 @@ <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>nifi-api</display-name> <context-param> + <param-name>contextClass</param-name> + <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> + </context-param> + <context-param> <param-name>contextConfigLocation</param-name> - <param-value> - classpath:nifi-context.xml - classpath:nifi-web-api-context.xml - classpath:nifi-web-security-context.xml - classpath:nifi-administration-context.xml - classpath:nifi-cluster-manager-context.xml - classpath:nifi-cluster-protocol-context.xml - </param-value> + <param-value>org.apache.nifi.web</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java index 52f4522..c0e9246 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/integration/util/NiFiTestUser.java @@ -22,8 +22,7 @@ import com.sun.jersey.api.client.WebResource; import com.sun.jersey.core.util.MultivaluedMapImpl; import java.util.Map; import javax.ws.rs.core.MediaType; -import org.apache.nifi.web.security.DnUtils; -import org.apache.nifi.web.security.x509.X509AuthenticationFilter; +import org.apache.nifi.web.security.ProxiedEntitiesUtils; /** * @@ -37,7 +36,7 @@ public class NiFiTestUser { public NiFiTestUser(Client client, String dn) { this.client = client; - this.proxyDn = DnUtils.formatProxyDn(dn); + this.proxyDn = ProxiedEntitiesUtils.formatProxyDn(dn); } /** @@ -70,7 +69,7 @@ public class NiFiTestUser { } // perform the query - return resource.accept(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn).get(ClientResponse.class); + return resource.accept(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn).get(ClientResponse.class); } /** @@ -94,7 +93,7 @@ public class NiFiTestUser { */ public ClientResponse testPost(String url, Object entity) throws Exception { // get the resource - WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // include the request entity if (entity != null) { @@ -115,7 +114,7 @@ public class NiFiTestUser { */ public ClientResponse testPostMultiPart(String url, Object entity) throws Exception { // get the resource - WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_XML).type(MediaType.MULTIPART_FORM_DATA).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_XML).type(MediaType.MULTIPART_FORM_DATA).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // include the request entity if (entity != null) { @@ -143,7 +142,7 @@ public class NiFiTestUser { // get the resource WebResource.Builder resourceBuilder - = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // add the form data if necessary if (!entity.isEmpty()) { @@ -164,7 +163,7 @@ public class NiFiTestUser { */ public ClientResponse testPut(String url, Object entity) throws Exception { // get the resource - WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // include the request entity if (entity != null) { @@ -192,7 +191,7 @@ public class NiFiTestUser { // get the resource WebResource.Builder resourceBuilder - = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + = client.resource(url).accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // add the form data if necessary if (!entity.isEmpty()) { @@ -224,7 +223,7 @@ public class NiFiTestUser { */ public ClientResponse testDelete(String url, Object entity) throws Exception { // get the resource - WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn); + WebResource.Builder resourceBuilder = client.resource(url).accept(MediaType.APPLICATION_JSON).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn); // append any query parameters if (entity != null) { @@ -255,7 +254,7 @@ public class NiFiTestUser { } // perform the request - return resource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(X509AuthenticationFilter.PROXY_ENTITIES_CHAIN, proxyDn).delete(ClientResponse.class); + return resource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_FORM_URLENCODED).header(ProxiedEntitiesUtils.PROXY_ENTITIES_CHAIN, proxyDn).delete(ClientResponse.class); } } http://git-wip-us.apache.org/repos/asf/nifi/blob/a40e5a07/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties index 0aa5a14..fc20d78 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties @@ -93,6 +93,7 @@ nifi.security.truststoreType=JKS nifi.security.truststorePasswd=localtest nifi.security.needClientAuth=true nifi.security.user.authority.provider=test-provider +nifi.security.user.login.identity.provider= nifi.security.authorizedUsers.file=target/test-classes/access-control/users.xml nifi.security.user.credential.cache.duration=1 hr nifi.security.support.new.account.requests=
