- Adding an authorizeDownload method to the UserService.
- Removing an unused/deprecated unit test.
This commit is contained in:
Matt Gilman 2014-12-23 09:30:29 -05:00
parent df9529c561
commit 1c9393032d
6 changed files with 125 additions and 285 deletions

View File

@ -17,8 +17,11 @@
package org.apache.nifi.admin.service; package org.apache.nifi.admin.service;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.nifi.authorization.Authority; import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.user.NiFiUser; import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup; import org.apache.nifi.user.NiFiUserGroup;
@ -43,6 +46,16 @@ public interface UserService {
*/ */
Boolean hasPendingUserAccount(); Boolean hasPendingUserAccount();
/**
* Determines if the users in the dnChain are authorized to download content
* with the specified attributes.
*
* @param dnChain
* @param attributes
* @return
*/
DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes);
/** /**
* Updates a user group using the specified group comprised of the specified * Updates a user group using the specified group comprised of the specified
* users. Returns all the users that are currently in the specified group. * users. Returns all the users that are currently in the specified group.

View File

@ -0,0 +1,54 @@
/*
* 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.admin.service.action;
import java.util.List;
import java.util.Map;
import org.apache.nifi.admin.dao.DAOFactory;
import org.apache.nifi.admin.service.AccountNotFoundException;
import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.authorization.AuthorityProvider;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.authorization.exception.AuthorityAccessException;
import org.apache.nifi.authorization.exception.UnknownIdentityException;
/**
* Attempts to obtain authorization to download the content with the specified
* attributes for the specified user.
*/
public class AuthorizeDownloadAction implements AdministrationAction<DownloadAuthorization> {
private final List<String> dnChain;
private final Map<String, String> attributes;
public AuthorizeDownloadAction(List<String> dnChain, Map<String, String> attributes) {
this.dnChain = dnChain;
this.attributes = attributes;
}
@Override
public DownloadAuthorization execute(DAOFactory daoFactory, AuthorityProvider authorityProvider) {
try {
return authorityProvider.authorizeDownload(dnChain, attributes);
} catch (UnknownIdentityException uie) {
throw new AccountNotFoundException(uie.getMessage(), uie);
} catch (AuthorityAccessException aae) {
throw new AdministrationException(aae.getMessage(), aae);
}
}
}

View File

@ -18,6 +18,8 @@ package org.apache.nifi.admin.service.impl;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -27,6 +29,7 @@ import org.apache.nifi.admin.service.AccountDisabledException;
import org.apache.nifi.admin.service.AccountPendingException; import org.apache.nifi.admin.service.AccountPendingException;
import org.apache.nifi.admin.service.AdministrationException; import org.apache.nifi.admin.service.AdministrationException;
import org.apache.nifi.admin.service.UserService; import org.apache.nifi.admin.service.UserService;
import org.apache.nifi.admin.service.action.AuthorizeDownloadAction;
import org.apache.nifi.admin.service.action.AuthorizeUserAction; import org.apache.nifi.admin.service.action.AuthorizeUserAction;
import org.apache.nifi.admin.service.action.DeleteUserAction; import org.apache.nifi.admin.service.action.DeleteUserAction;
import org.apache.nifi.admin.service.action.DisableUserAction; import org.apache.nifi.admin.service.action.DisableUserAction;
@ -48,6 +51,7 @@ import org.apache.nifi.admin.service.transaction.Transaction;
import org.apache.nifi.admin.service.transaction.TransactionBuilder; import org.apache.nifi.admin.service.transaction.TransactionBuilder;
import org.apache.nifi.admin.service.transaction.TransactionException; import org.apache.nifi.admin.service.transaction.TransactionException;
import org.apache.nifi.authorization.Authority; import org.apache.nifi.authorization.Authority;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.user.NiFiUser; import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup; import org.apache.nifi.user.NiFiUserGroup;
import org.apache.nifi.util.FormatUtils; import org.apache.nifi.util.FormatUtils;
@ -440,7 +444,7 @@ public class StandardUserService implements UserService {
* modifying a user account. This method should only be invoked from within * modifying a user account. This method should only be invoked from within
* a write lock. * a write lock.
* *
* @param id * @param group
*/ */
@Override @Override
public void invalidateUserGroupAccount(String group) { public void invalidateUserGroupAccount(String group) {
@ -500,6 +504,36 @@ public class StandardUserService implements UserService {
} }
} }
@Override
public DownloadAuthorization authorizeDownload(final List<String> dnChain, final Map<String, String> attributes) {
Transaction transaction = null;
readLock.lock();
try {
// start the transaction
transaction = transactionBuilder.start();
// authorize the download
AuthorizeDownloadAction authorizeDownload = new AuthorizeDownloadAction(dnChain, attributes);
DownloadAuthorization downloadAuthorization = transaction.execute(authorizeDownload);
// commit the transaction
transaction.commit();
// return the authorization
return downloadAuthorization;
} catch (TransactionException | DataAccessException te) {
rollback(transaction);
throw new AdministrationException(te);
} catch (Throwable t) {
rollback(transaction);
throw t;
} finally {
closeQuietly(transaction);
readLock.unlock();
}
}
@Override @Override
public Collection<NiFiUser> getUsers() { public Collection<NiFiUser> getUsers() {
Transaction transaction = null; Transaction transaction = null;

View File

@ -24,6 +24,7 @@ import java.lang.reflect.Method;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
@ -365,6 +366,11 @@ public class AuthorityProviderFactoryBean implements FactoryBean, ApplicationCon
public void ungroup(String group) throws AuthorityAccessException { public void ungroup(String group) throws AuthorityAccessException {
} }
@Override
public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
return DownloadAuthorization.approved();
}
@Override @Override
public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException { public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
} }
@ -465,6 +471,13 @@ public class AuthorityProviderFactoryBean implements FactoryBean, ApplicationCon
} }
} }
@Override
public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
return baseProvider.authorizeDownload(dnChain, attributes);
}
}
@Override @Override
public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException { public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) { try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {

View File

@ -43,6 +43,8 @@ public class NiFiUser implements Serializable {
private AccountStatus status; private AccountStatus status;
private EnumSet<Authority> authorities; private EnumSet<Authority> authorities;
private NiFiUser chain;
/* getters / setters */ /* getters / setters */
public Date getCreation() { public Date getCreation() {
@ -117,6 +119,14 @@ public class NiFiUser implements Serializable {
this.lastAccessed = lastAccessed; this.lastAccessed = lastAccessed;
} }
public NiFiUser getChain() {
return chain;
}
public void setChain(NiFiUser chain) {
this.chain = chain;
}
public Set<Authority> getAuthorities() { public Set<Authority> getAuthorities() {
if (authorities == null) { if (authorities == null) {
authorities = EnumSet.noneOf(Authority.class); authorities = EnumSet.noneOf(Authority.class);

View File

@ -1,284 +0,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.
*/
package org.apache.nifi.admin.service.impl;
import org.junit.Ignore;
/**
*
*/
@Ignore
public class NiFiAuthorizationServiceTest {
// private static final String UNKNOWN_USER_IN_CACHE_DN = "unknown-user-in-cache-dn";
// private static final String PENDING_USER_DN = "pending-user-dn";
// private static final String DISABLED_USER_DN = "disabled-user-dn";
// private static final String UNKNOWN_USER_IN_IDENTITY_PROVIDER_DN = "unknown-user-in-identity-provider-dn";
// private static final String ACCESS_EXCEPTION_IN_IDENTITY_PROVIDER_DN = "access-exception-in-identity-provider-dn";
// private static final String UNABLE_TO_UPDATE_CACHE_DN = "unable-to-update-cache-dn";
// private static final String VERIFICATION_REQUIRED_DN = "verification-required-dn";
// private static final String VERIFICATION_NOT_REQUIRED_DN = "verification-not-required-dn";
// private static final String NEW_USER_DN = "new-user-dn";
//
// private UserService userService;
// private AuthorityProvider authorityProvider;
// private UserDAO userDAO;
//
// @Before
// public void setup() throws Exception {
// // mock the web security properties
// NiFiProperties properties = Mockito.mock(NiFiProperties.class);
// Mockito.when(properties.getSupportNewAccountRequests()).thenReturn(Boolean.TRUE);
// Mockito.when(properties.getUserCredentialCacheDurationSeconds()).thenReturn(60);
//
// // mock the authority provider
//
// // mock the admin service
// userDAO = Mockito.mock(UserDAO.class);
// Mockito.doAnswer(new Answer() {
//
// @Override
// public Object answer(InvocationOnMock invocation) throws Throwable {
// Object[] args = invocation.getArguments();
// String dn = (String) args[0];
//
// NiFiUser user = null;
// switch (dn) {
// case PENDING_USER_DN:
// user = new NiFiUser();
// user.setDn(dn);
// user.setStatus(AccountStatus.PENDING);
// break;
// case DISABLED_USER_DN:
// user = new NiFiUser();
// user.setDn(dn);
// user.setStatus(AccountStatus.DISABLED);
// break;
// case UNKNOWN_USER_IN_IDENTITY_PROVIDER_DN:
// case UNABLE_TO_UPDATE_CACHE_DN:
// case ACCESS_EXCEPTION_IN_IDENTITY_PROVIDER_DN:
// user = new NiFiUser();
// user.setDn(dn);
// user.setStatus(AccountStatus.ACTIVE);
// break;
// case VERIFICATION_REQUIRED_DN: {
// Calendar calendar = Calendar.getInstance();
// calendar.add(Calendar.SECOND, -65);
// user = new NiFiUser();
// user.setDn(dn);
// user.setStatus(AccountStatus.ACTIVE);
// user.setLastVerified(calendar.getTime());
// user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_ADMIN, Authority.ROLE_DFM));
// break;
// }
// case VERIFICATION_NOT_REQUIRED_DN: {
// Calendar calendar = Calendar.getInstance();
// calendar.add(Calendar.SECOND, -5);
// user = new NiFiUser();
// user.setDn(dn);
// user.setStatus(AccountStatus.ACTIVE);
// user.setLastVerified(calendar.getTime());
// user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_ADMIN, Authority.ROLE_DFM));
// break;
// }
// }
// return user;
// }
// }).when(userDAO).getUser(Mockito.anyString());
// Mockito.doAnswer(new Answer() {
//
// @Override
// public Object answer(InvocationOnMock invocation) throws Throwable {
// Object[] args = invocation.getArguments();
// NiFiUser user = (NiFiUser) args[0];
//
// if (UNABLE_TO_UPDATE_CACHE_DN.equals(user.getDn())) {
// throw new AdministrationException();
// }
// return user;
// }
// }).when(userDAO).updateUser(Mockito.any(NiFiUser.class));
// Mockito.doNothing().when(userDAO).createUser(Mockito.any(NiFiUser.class));
//
// // mock the authority provider
// authorityProvider = Mockito.mock(AuthorityProvider.class);
// Mockito.doAnswer(new Answer() {
//
// @Override
// public Object answer(InvocationOnMock invocation) throws Throwable {
// Object[] args = invocation.getArguments();
// String dn = (String) args[0];
//
// boolean hasDn = false;
// if (VERIFICATION_REQUIRED_DN.equals(dn) || NEW_USER_DN.equals(dn)) {
// hasDn = true;
// }
// return hasDn;
// }
// }).when(authorityProvider).doesDnExist(Mockito.anyString());
// Mockito.doAnswer(new Answer() {
//
// @Override
// public Object answer(InvocationOnMock invocation) throws Throwable {
// Object[] args = invocation.getArguments();
// String dn = (String) args[0];
//
// Set<String> authorities = null;
// switch (dn) {
// case VERIFICATION_REQUIRED_DN:
// case NEW_USER_DN:
// authorities = new HashSet<>();
// authorities.add("ROLE_MONITOR");
// break;
// case DISABLED_USER_DN:
// throw new UnknownIdentityException("Unable to find user");
// }
// return authorities;
// }
// }).when(authorityProvider).getAuthorities(Mockito.anyString());
//
// // create an instance of the authorization service
// userService = new UserServiceImpl();
// ((UserServiceImpl) userService).setAuthorityProvider(authorityProvider);
// ((UserServiceImpl) userService).set(authorityProvider);
//
//// authorizationService.setIdentityProvider(identityProvider);
//// authorizationService.setAuthorityProvider(authorityProvider);
//// authorizationService.setProperties(properties);
// }
//
// /**
// * Ensures the authorization service correctly handles users who are
// * unknown.
// *
// * @throws Exception
// */
// @Test(expected = org.springframework.security.core.userdetails.UsernameNotFoundException.class)
// public void testUnknownUserInCache() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(UNKNOWN_USER_IN_CACHE_DN));
// }
//
// /**
// * Ensures the authorization service correctly handles users whose accounts
// * are PENDING.
// *
// * @throws Exception
// */
// @Test(expected = nifi.admin.service.AccountPendingException.class)
// public void testPendingUser() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(PENDING_USER_DN));
// }
//
// /**
// * Ensures the authorization service correctly handles users whose accounts
// * are DISABLED.
// *
// * @throws Exception
// */
// @Test(expected = org.springframework.security.authentication.DisabledException.class)
// public void testDisabledUser() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(DISABLED_USER_DN));
// }
//
// /**
// * Ensures the authorization service correctly handles users whose are in
// * the cache but have been removed from the identity provider.
// *
// * @throws Exception
// */
// @Test(expected = org.springframework.security.authentication.DisabledException.class)
// public void testUnknownUserInIdentityProvider() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(UNKNOWN_USER_IN_IDENTITY_PROVIDER_DN));
// }
//
// /**
// * Ensures the authorization service correctly handles cases when the cache
// * is unable to be updated.
// *
// * @throws Exception
// */
// @Test(expected = org.springframework.security.authentication.AuthenticationServiceException.class)
// public void testUnableToUpdateCache() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(UNABLE_TO_UPDATE_CACHE_DN));
// }
//
// /**
// * Ensures the authorization service correctly handles cases when the
// * identity provider has an access exception.
// *
// * @throws Exception
// */
// @Test(expected = org.springframework.security.authentication.AuthenticationServiceException.class)
// public void testUnableToAccessIdentity() throws Exception {
// authorizationService.loadUserByUsername(WebUtils.formatProxyDn(ACCESS_EXCEPTION_IN_IDENTITY_PROVIDER_DN));
// }
//
// /**
// * Ensures that user authorities are properly loaded from the authority
// * provider.
// *
// * @throws Exception
// */
// @Test
// public void testVerificationRequiredUser() throws Exception {
// NiFiUserDetails userDetails = (NiFiUserDetails) authorizationService.loadUserByUsername(WebUtils.formatProxyDn(VERIFICATION_REQUIRED_DN));
// NiFiUser user = userDetails.getNiFiUser();
// Mockito.verify(authorityProvider).getAuthorities(VERIFICATION_REQUIRED_DN);
//
// // ensure the user details
// Assert.assertEquals(VERIFICATION_REQUIRED_DN, user.getDn());
// Assert.assertEquals(1, user.getAuthorities().size());
// Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
// }
//
// /**
// * Ensures that user authorities are not loaded when the cache is still
// * valid.
// *
// * @throws Exception
// */
// @Test
// public void testVerificationNotRequiredUser() throws Exception {
// NiFiUserDetails userDetails = (NiFiUserDetails) authorizationService.loadUserByUsername(WebUtils.formatProxyDn(VERIFICATION_NOT_REQUIRED_DN));
// NiFiUser user = userDetails.getNiFiUser();
// Mockito.verify(authorityProvider, Mockito.never()).getAuthorities(VERIFICATION_NOT_REQUIRED_DN);
//
// // ensure the user details
// Assert.assertEquals(VERIFICATION_NOT_REQUIRED_DN, user.getDn());
// Assert.assertEquals(2, user.getAuthorities().size());
// Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_ADMIN));
// Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_DFM));
// }
//
// /**
// * Ensures that new users are automatically created when the authority
// * provider has their authorities.
// *
// * @throws Exception
// */
// @Test
// public void testNewUser() throws Exception {
// NiFiUserDetails userDetails = (NiFiUserDetails) authorizationService.loadUserByUsername(WebUtils.formatProxyDn(NEW_USER_DN));
// NiFiUser user = userDetails.getNiFiUser();
// Mockito.verify(authorityProvider).getAuthorities(NEW_USER_DN);
//
// // ensure the user details
// Assert.assertEquals(NEW_USER_DN, user.getDn());
// Assert.assertEquals(1, user.getAuthorities().size());
// Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
// }
}