package org.geoserver.security.impl; import org.springframework.security.core.context.SecurityContextHolder; import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.FeatureTypeInfo; import org.geoserver.ows.Dispatcher; import org.geoserver.ows.Request; import org.geoserver.security.ResourceAccessManager; import org.geoserver.security.SecureCatalogImpl; import org.geoserver.security.decorators.ReadOnlyDataStoreTest; import org.geoserver.security.decorators.SecuredDataStoreInfo; import org.geoserver.security.decorators.SecuredFeatureTypeInfo; import org.geoserver.security.decorators.SecuredLayerInfo; public class SecureCatalogImplTest extends AbstractAuthorizationTest { @Override protected void setUp() throws Exception { super.setUp(); populateCatalog(); } public void testWideOpen() throws Exception { ResourceAccessManager manager = buildManager("wideOpen.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // use no user at all SecurityContextHolder.getContext().setAuthentication(anonymous); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(states, sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(featureTypes, sc.getFeatureTypes()); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(statesStore, sc.getDataStoreByName("states")); assertSame(roadsStore, sc.getDataStoreByName("roads")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); } public void testLockedDown() throws Exception { ResourceAccessManager manager = buildManager("lockedDown.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // try with read only user SecurityContextHolder.getContext().setAuthentication(roUser); assertNull(sc.getFeatureTypeByName("topp:states")); assertNull(sc.getCoverageByName("nurc:arcgrid")); assertNull(sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertNull(sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(0, sc.getFeatureTypes().size()); assertEquals(0, sc.getCoverages().size()); assertEquals(0, sc.getWorkspaces().size()); assertNull(sc.getWorkspaceByName("topp")); assertNull(sc.getDataStoreByName("states")); assertNull(sc.getDataStoreByName("roads")); assertNull(sc.getCoverageStoreByName("arcGrid")); // try with write enabled user SecurityContextHolder.getContext().setAuthentication(rwUser); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(states, sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(featureTypes, sc.getFeatureTypes()); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(statesStore, sc.getDataStoreByName("states")); assertSame(roadsStore, sc.getDataStoreByName("roads")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); } public void testLockedChallenge() throws Exception { ResourceAccessManager manager = buildManager("lockedDownChallenge.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // try with read only user SecurityContextHolder.getContext().setAuthentication(roUser); // check a direct access to the data does trigger a security challenge try { sc.getFeatureTypeByName("topp:states").getFeatureSource(null, null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getCoverageByName("nurc:arcgrid").getGridCoverage(null, null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getResourceByName("topp:states", FeatureTypeInfo.class).getFeatureSource(null, null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getResourceByName("nurc:arcgrid", CoverageInfo.class).getGridCoverage(null, null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } sc.getWorkspaceByName("topp"); try { sc.getDataStoreByName("states").getDataStore(null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getDataStoreByName("roads").getDataStore(null); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getCoverageStoreByName("arcGrid").getFormat(); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } // check we still get the lists out so that capabilities can be built assertEquals(featureTypes.size(), sc.getFeatureTypes().size()); assertEquals(coverages.size(), sc.getCoverages().size()); assertEquals(workspaces.size(), sc.getWorkspaces().size()); // try with write enabled user SecurityContextHolder.getContext().setAuthentication(rwUser); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(states, sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(featureTypes, sc.getFeatureTypes()); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(statesStore, sc.getDataStoreByName("states")); assertSame(roadsStore, sc.getDataStoreByName("roads")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); } public void testLockedMixed() throws Exception { ResourceAccessManager manager = buildManager("lockedDownMixed.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // try with read only user and GetFeatures request SecurityContextHolder.getContext().setAuthentication(roUser); Request request = org.easymock.classextension.EasyMock.createNiceMock(Request.class); org.easymock.classextension.EasyMock.expect(request.getRequest()).andReturn("GetFeatures").anyTimes(); org.easymock.classextension.EasyMock.replay(request); Dispatcher.REQUEST.set(request); // check a direct access does trigger a security challenge try { sc.getFeatureTypeByName("topp:states"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getCoverageByName("nurc:arcgrid"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getResourceByName("topp:states", FeatureTypeInfo.class); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getResourceByName("nurc:arcgrid", CoverageInfo.class); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getWorkspaceByName("topp"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getDataStoreByName("states"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getDataStoreByName("roads"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } try { sc.getCoverageStoreByName("arcGrid"); fail("Should have failed with a security exception"); } catch(Exception e) { if (ReadOnlyDataStoreTest.isSpringSecurityException(e)==false) fail("Should have failed with a security exception"); } // try with a getCapabilities, make sure the lists are empty request = org.easymock.classextension.EasyMock.createNiceMock(Request.class); org.easymock.classextension.EasyMock.expect(request.getRequest()).andReturn("GetCapabilities").anyTimes(); org.easymock.classextension.EasyMock.replay(request); Dispatcher.REQUEST.set(request); // check the lists used to build capabilities are empty assertEquals(0, sc.getFeatureTypes().size()); assertEquals(0, sc.getCoverages().size()); assertEquals(0, sc.getWorkspaces().size()); // try with write enabled user SecurityContextHolder.getContext().setAuthentication(rwUser); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(states, sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(featureTypes, sc.getFeatureTypes()); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(statesStore, sc.getDataStoreByName("states")); assertSame(roadsStore, sc.getDataStoreByName("roads")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); } public void testPublicRead() throws Exception { ResourceAccessManager manager = buildManager("publicRead.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // try with read only user SecurityContextHolder.getContext().setAuthentication(roUser); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); // .. the following should have been wrapped assertNotNull(sc.getFeatureTypeByName("topp:states")); assertTrue(sc.getFeatureTypeByName("topp:states") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getResourceByName("topp:states", FeatureTypeInfo.class) instanceof SecuredFeatureTypeInfo); assertEquals(featureTypes.size(), sc.getFeatureTypes().size()); for (FeatureTypeInfo ft : sc.getFeatureTypes()) { assertTrue(ft instanceof SecuredFeatureTypeInfo); } assertNotNull(sc.getLayerByName("topp:states")); assertTrue(sc.getLayerByName("topp:states") instanceof SecuredLayerInfo); assertTrue(sc.getDataStoreByName("states") instanceof SecuredDataStoreInfo); assertTrue(sc.getDataStoreByName("roads") instanceof SecuredDataStoreInfo); // try with write enabled user (nothing has been wrapped) SecurityContextHolder.getContext().setAuthentication(rwUser); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertSame(arcGrid, sc.getCoverageByName("nurc:arcgrid")); assertSame(states, sc.getResourceByName("topp:states", FeatureTypeInfo.class)); assertSame(arcGrid, sc.getResourceByName("nurc:arcgrid", CoverageInfo.class)); assertEquals(featureTypes, sc.getFeatureTypes()); assertEquals(coverages, sc.getCoverages()); assertEquals(workspaces, sc.getWorkspaces()); assertEquals(toppWs, sc.getWorkspaceByName("topp")); assertSame(statesStore, sc.getDataStoreByName("states")); assertSame(roadsStore, sc.getDataStoreByName("roads")); assertSame(arcGridStore, sc.getCoverageStoreByName("arcGrid")); } public void testComplex() throws Exception { ResourceAccessManager manager = buildManager("complex.properties"); SecureCatalogImpl sc = new SecureCatalogImpl(catalog, manager); // try with anonymous user SecurityContextHolder.getContext().setAuthentication(anonymous); // ... roads follows generic ns rule, read only, nobody can write it assertTrue(sc.getFeatureTypeByName("topp:roads") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getDataStoreByName("roads") instanceof SecuredDataStoreInfo); // ... states requires READER role assertNull(sc.getFeatureTypeByName("topp:states")); // ... but the datastore is visible since the namespace rules do apply instead assertTrue(sc.getDataStoreByName("states") instanceof SecuredDataStoreInfo); // ... landmarks requires WRITER role to be written assertTrue(sc.getFeatureTypeByName("topp:landmarks") instanceof SecuredFeatureTypeInfo); // ... bases requires one to be in the military assertNull(sc.getFeatureTypeByName("topp:bases")); // ok, let's try the same with read only user SecurityContextHolder.getContext().setAuthentication(roUser); assertTrue(sc.getFeatureTypeByName("topp:roads") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getDataStoreByName("roads") instanceof SecuredDataStoreInfo); assertTrue(sc.getFeatureTypeByName("topp:states") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getDataStoreByName("states") instanceof SecuredDataStoreInfo); assertTrue(sc.getFeatureTypeByName("topp:landmarks") instanceof SecuredFeatureTypeInfo); assertNull(sc.getFeatureTypeByName("topp:bases")); // now with the write enabled user SecurityContextHolder.getContext().setAuthentication(rwUser); assertTrue(sc.getFeatureTypeByName("topp:roads") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getDataStoreByName("roads") instanceof SecuredDataStoreInfo); assertSame(states, sc.getFeatureTypeByName("topp:states")); assertTrue(sc.getDataStoreByName("states") instanceof SecuredDataStoreInfo); assertSame(landmarks, sc.getFeatureTypeByName("topp:landmarks")); assertNull(sc.getFeatureTypeByName("topp:bases")); // finally let's try the military type SecurityContextHolder.getContext().setAuthentication(milUser); assertTrue(sc.getFeatureTypeByName("topp:roads") instanceof SecuredFeatureTypeInfo); assertTrue(sc.getDataStoreByName("roads") instanceof SecuredDataStoreInfo); assertNull(sc.getFeatureTypeByName("topp:states")); assertTrue(sc.getDataStoreByName("states") instanceof SecuredDataStoreInfo); assertTrue(sc.getFeatureTypeByName("topp:landmarks") instanceof SecuredFeatureTypeInfo); // ... bases requires one to be in the military assertSame(bases, sc.getFeatureTypeByName("topp:bases")); } }