/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.security.operation.plugin;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DelegatingSubject;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ddf.catalog.operation.Query;
import ddf.catalog.operation.impl.CreateRequestImpl;
import ddf.catalog.operation.impl.DeleteRequestImpl;
import ddf.catalog.operation.impl.QueryRequestImpl;
import ddf.catalog.operation.impl.ResourceRequestById;
import ddf.catalog.operation.impl.UpdateRequestImpl;
import ddf.catalog.plugin.PolicyPlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.security.SecurityConstants;
import ddf.security.Subject;
import ddf.security.permission.CollectionPermission;
import ddf.security.permission.KeyValueCollectionPermission;
public class OperationPluginTest {
OperationPlugin plugin;
Subject subject;
@Before
public void setup() {
plugin = new OperationPlugin();
AuthorizingRealm realm = mock(AuthorizingRealm.class);
when(realm.getName()).thenReturn("mockRealm");
when(realm.isPermitted(any(PrincipalCollection.class), any(Permission.class))).then(
makeDecision());
Collection<Realm> realms = new ArrayList<Realm>();
realms.add(realm);
DefaultSecurityManager manager = new DefaultSecurityManager();
manager.setRealms(realms);
SimplePrincipalCollection principalCollection =
new SimplePrincipalCollection(new Principal() {
@Override
public String getName() {
return "testuser";
}
}, realm.getName());
subject = new MockSubject(manager, principalCollection);
}
private Answer<Boolean> makeDecision() {
Map<String, List<String>> testRoleMap = new HashMap<String, List<String>>();
List<String> testRoles = new ArrayList<String>();
testRoles.add("A");
testRoles.add("B");
testRoleMap.put("Roles", testRoles);
final KeyValueCollectionPermission testUserPermission = new KeyValueCollectionPermission(
CollectionPermission.READ_ACTION,
testRoleMap);
return new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Permission incomingPermission = (Permission) args[1];
return testUserPermission.implies(incomingPermission);
}
};
}
@Test
public void allowedRequestTest() throws Exception {
testPluginWithRole("A");
}
@Test(expected = StopProcessingException.class)
public void rejectedRequestTest() throws Exception {
testPluginWithRole("Z");
}
@Test(expected = StopProcessingException.class)
public void noSubjectRequestTest() throws Exception {
Map<String, Serializable> properties = new HashMap<>();
HashMap<String, Set<String>> perms = new HashMap<>();
Set<String> roles = new HashSet<>();
roles.add("A");
perms.put("Roles", roles);
properties.put(PolicyPlugin.OPERATION_SECURITY, perms);
CreateRequestImpl request = new CreateRequestImpl(new ArrayList<>(), properties);
plugin.processPreCreate(request);
}
@Test
public void noPropertiesRequestTest() throws Exception {
CreateRequestImpl request = new CreateRequestImpl(new ArrayList<>(), null);
plugin.processPreCreate(request);
}
@Test
public void noPolicyRequestTest() throws Exception {
Map<String, Serializable> properties = new HashMap<>();
properties.put(SecurityConstants.SECURITY_SUBJECT, subject);
CreateRequestImpl request = new CreateRequestImpl(new ArrayList<>(), properties);
plugin.processPreCreate(request);
}
private void testPluginWithRole(String role) throws Exception {
Map<String, Serializable> properties = new HashMap<>();
properties.put(SecurityConstants.SECURITY_SUBJECT, subject);
HashMap<String, Set<String>> perms = new HashMap<>();
Set<String> roles = new HashSet<>();
roles.add(role);
perms.put("Roles", roles);
properties.put(PolicyPlugin.OPERATION_SECURITY, perms);
CreateRequestImpl request = new CreateRequestImpl(new ArrayList<>(), properties);
QueryRequestImpl queryRequest = new QueryRequestImpl(mock(Query.class), properties);
UpdateRequestImpl updateRequest = new UpdateRequestImpl(new ArrayList<>(), "", properties);
DeleteRequestImpl deleteRequest = new DeleteRequestImpl(new String[] {""}, properties);
ResourceRequestById resourceRequestById = new ResourceRequestById("", properties);
plugin.processPreCreate(request);
plugin.processPreQuery(queryRequest);
plugin.processPreUpdate(updateRequest, new HashMap<>());
plugin.processPreDelete(deleteRequest);
plugin.processPreResource(resourceRequestById);
}
private class MockSubject extends DelegatingSubject implements Subject {
public MockSubject(SecurityManager manager, PrincipalCollection principals) {
super(principals,
true,
null,
new SimpleSession(UUID.randomUUID()
.toString()),
manager);
}
@Override
public boolean isGuest() {
return false;
}
}
}