001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.auth.integration;
019
020import static org.fcrepo.kernel.modeshape.FedoraSessionImpl.getJcrSession;
021import static org.junit.Assert.assertEquals;
022import static org.mockito.Matchers.any;
023import static org.mockito.Matchers.eq;
024import static org.mockito.Mockito.atLeastOnce;
025import static org.mockito.Mockito.mock;
026import static org.mockito.Mockito.verify;
027import static org.mockito.Mockito.when;
028import static org.slf4j.LoggerFactory.getLogger;
029
030import java.security.Principal;
031
032import javax.inject.Inject;
033import javax.jcr.AccessDeniedException;
034import javax.jcr.RepositoryException;
035import javax.jcr.Session;
036import javax.servlet.http.HttpServletRequest;
037
038import org.apache.http.auth.BasicUserPrincipal;
039import org.fcrepo.auth.common.FedoraAuthorizationDelegate;
040import org.fcrepo.auth.common.ServletContainerAuthenticationProvider;
041import org.fcrepo.kernel.api.FedoraRepository;
042import org.fcrepo.kernel.api.FedoraSession;
043import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
044import org.fcrepo.kernel.api.services.ContainerService;
045import org.fcrepo.kernel.modeshape.services.ContainerServiceImpl;
046import org.junit.Assert;
047import org.junit.Test;
048import org.junit.runner.RunWith;
049import org.mockito.Mockito;
050import org.modeshape.jcr.api.ServletCredentials;
051import org.modeshape.jcr.value.Path;
052import org.slf4j.Logger;
053import org.springframework.test.context.ContextConfiguration;
054import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
055
056/**
057 * @author Peter Eichman
058 */
059@RunWith(SpringJUnit4ClassRunner.class)
060@ContextConfiguration(locations = { "/spring-test/mocked-fad-repo-3.xml" })
061public class DelegatedUserIT {
062
063    private static Logger logger =
064            getLogger(DelegatedUserIT.class);
065
066    @Inject
067    private FedoraRepository repo;
068
069    @Inject
070    private FedoraAuthorizationDelegate fad;
071
072    private final HttpServletRequest request = mock(HttpServletRequest.class);
073
074    @Test
075    public void testFactory() {
076        Assert.assertNotNull(
077                "AuthenticationProvider must return a AuthenticationProvider",
078                ServletContainerAuthenticationProvider.getInstance());
079    }
080
081    @Test
082    public void testDelegatedUserAccess() throws RepositoryException {
083
084        // mock request by an admin user, on behalf of a regular user
085        when(request.getRemoteUser()).thenReturn("admin1");
086        when(request.getUserPrincipal()).thenReturn(new BasicUserPrincipal("admin1"));
087        when(request.isUserInRole(eq(ServletContainerAuthenticationProvider.FEDORA_ADMIN_ROLE))).thenReturn(true);
088        when(request.getHeader("On-Behalf-Of")).thenReturn("user1");
089
090        Mockito.reset(fad);
091        // set up a restrictive mock FAD, which should deny non-admin users
092        when(fad.hasPermission(any(Session.class), any(Path.class), any(String[].class))).thenReturn(false);
093
094        final ServletCredentials credentials = new ServletCredentials(request);
095        final FedoraSession session = repo.login(credentials);
096        final Session jcrSession = getJcrSession(session);
097        assertEquals("Session user principal is user1",
098                "user1",
099                ((Principal) jcrSession.getAttribute(FedoraAuthorizationDelegate.FEDORA_USER_PRINCIPAL)).getName());
100
101        // try to create an object, this should fail because it is being executed as a non-admin user
102        final ContainerService os = new ContainerServiceImpl();
103        try {
104            os.findOrCreate(session, "/myobject");
105        } catch (final RepositoryRuntimeException e) {
106            final Throwable cause = e.getCause();
107            if (cause != null && cause instanceof AccessDeniedException) {
108                logger.debug("caught expected access denied exception");
109            } else {
110                throw e;
111            }
112        }
113        verify(fad, atLeastOnce()).hasPermission(any(Session.class), any(Path.class), any(String[].class));
114    }
115
116}