From 977a7a352131b082a98739f15e421f2bff747567 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 1 Mar 2011 13:12:33 +0000 Subject: [PATCH] Improve security Extend Geotools support git-svn-id: https://svn.argeo.org/commons/trunk@4250 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- gis/runtime/org.argeo.gis.geotools/pom.xml | 15 +- .../org/argeo/geotools/GeoToolsUtils.java | 48 ++++ .../org/argeo/geotools/jcr/GeoJcrIndex.java | 234 ++++++++++++++++++ .../org/argeo/geotools/jcr/GeoJcrUtils.java | 98 ++++++++ .../dep/org.argeo.security.dep.node/pom.xml | 10 + .../META-INF/MANIFEST.MF | 3 +- .../META-INF/spring/ldap-osgi.xml | 15 +- .../META-INF/spring/ldap.xml | 16 +- .../ldap.properties | 2 - .../META-INF/MANIFEST.MF | 6 +- .../META-INF/spring/osgi.xml | 17 +- .../META-INF/spring/services.xml | 21 ++ .../org.argeo.security.equinox/plugin.xml | 4 +- .../AbstractSecureApplication.java | 8 +- .../org.argeo.security.activemq/pom.xml | 4 +- .../runtime/org.argeo.security.core/pom.xml | 5 +- .../org/argeo/security/ArgeoSecurityDao.java | 46 +--- .../argeo/security/ArgeoSecurityService.java | 1 + .../org/argeo/security/CurrentUserDao.java | 27 ++ .../argeo/security/SystemAuthentication.java | 8 + .../security/SystemExecutionService.java | 18 ++ .../java/org/argeo/security/UserAdminDao.java | 56 +++++ .../org/argeo/security/UserAdminService.java | 2 + .../core/DefaultCurrentUserService.java | 82 ++++++ .../security/core/DefaultSecurityService.java | 44 +--- .../security/core/InternalAuthentication.java | 4 +- .../core/KeyBasedSystemExecutionService.java | 57 +++++ .../org.argeo.security.jackrabbit/.classpath | 7 + .../org.argeo.security.jackrabbit/.project | 28 +++ .../.settings/org.eclipse.jdt.core.prefs | 8 + .../.settings/org.eclipse.pde.core.prefs | 4 + .../build.properties | 4 + .../org.argeo.security.jackrabbit/pom.xml | 58 +++++ .../spring/GrantedAuthorityPrincipal.java | 20 ++ .../jackrabbit/spring/SpringLoginModule.java | 85 +++++++ .../security/ldap/ArgeoSecurityDaoLdap.java | 28 +-- security/runtime/pom.xml | 1 + .../pom.xml | 5 + .../META-INF/MANIFEST.MF | 2 +- .../org.argeo.server.jackrabbit/pom.xml | 19 +- .../org.argeo.server.jcr/build.properties | 6 +- server/runtime/org.argeo.server.jcr/pom.xml | 11 +- .../src/main/java/org/argeo/jcr/JcrUtils.java | 8 + .../main/java/org/argeo/jcr/gis/GisNames.java | 12 + .../main/java/org/argeo/jcr/gis/GisTypes.java | 8 + .../resources/org/argeo/jcr/gis/argeo_gis.cnd | 16 ++ 46 files changed, 1023 insertions(+), 158 deletions(-) create mode 100644 gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/GeoToolsUtils.java create mode 100644 gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java create mode 100644 gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrUtils.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/CurrentUserDao.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminDao.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultCurrentUserService.java create mode 100644 security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java create mode 100644 security/runtime/org.argeo.security.jackrabbit/.classpath create mode 100644 security/runtime/org.argeo.security.jackrabbit/.project create mode 100644 security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.jdt.core.prefs create mode 100644 security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.pde.core.prefs create mode 100644 security/runtime/org.argeo.security.jackrabbit/build.properties create mode 100644 security/runtime/org.argeo.security.jackrabbit/pom.xml create mode 100644 security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/GrantedAuthorityPrincipal.java create mode 100644 security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/SpringLoginModule.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisNames.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisTypes.java create mode 100644 server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/gis/argeo_gis.cnd diff --git a/gis/runtime/org.argeo.gis.geotools/pom.xml b/gis/runtime/org.argeo.gis.geotools/pom.xml index 46168eb9d..92a81f8cd 100644 --- a/gis/runtime/org.argeo.gis.geotools/pom.xml +++ b/gis/runtime/org.argeo.gis.geotools/pom.xml @@ -30,6 +30,7 @@ org.argeo.geotools.* + org.argeo.jcr.gis,* @@ -53,7 +54,14 @@ - + + + org.argeo.commons.server + org.argeo.server.jcr + ${version.argeo-commons} + + + org.argeo.dep.osgi org.argeo.dep.osgi.geotools @@ -82,6 +90,11 @@ org.argeo.dep.osgi org.argeo.dep.osgi.java3d + + + org.hsqldb + com.springsource.org.hsqldb + org.apache.commons diff --git a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/GeoToolsUtils.java b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/GeoToolsUtils.java new file mode 100644 index 000000000..88ab84995 --- /dev/null +++ b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/GeoToolsUtils.java @@ -0,0 +1,48 @@ +package org.argeo.geotools; + +import java.io.IOException; + +import org.argeo.ArgeoException; +import org.geotools.data.DataStore; +import org.geotools.data.FeatureSource; +import org.geotools.data.FeatureStore; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.Name; + +/** Utilities related to the GeoTools framework */ +public class GeoToolsUtils { + + /** Opens a read/write feature store */ + public static FeatureStore getFeatureStore( + DataStore dataStore, Name name) { + FeatureSource featureSource; + try { + featureSource = dataStore.getFeatureSource(name); + } catch (IOException e) { + throw new ArgeoException("Cannot open feature source " + name + + " in data store " + dataStore, e); + } + if (!(featureSource instanceof FeatureStore)) { + throw new ArgeoException("Feature source " + name + + " is not writable."); + } + return (FeatureStore) featureSource; + } + + /** Creates the provided schema in the data store. */ + public static void createSchemaIfNeeded(DataStore dataStore, + SimpleFeatureType featureType) { + try { + dataStore.getSchema(featureType.getName()); + } catch (IOException e) { + // assume it does not exist + try { + dataStore.createSchema(featureType); + } catch (IOException e1) { + throw new ArgeoException("Cannot create schema " + featureType, + e); + } + } + } +} diff --git a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java new file mode 100644 index 000000000..e6afb9430 --- /dev/null +++ b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java @@ -0,0 +1,234 @@ +package org.argeo.geotools.jcr; + +import java.io.IOException; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.Event; +import javax.jcr.observation.EventIterator; +import javax.jcr.observation.EventListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.geotools.GeoToolsUtils; +import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.gis.GisNames; +import org.argeo.jcr.gis.GisTypes; +import org.argeo.security.SystemExecutionService; +import org.geotools.data.DataStore; +import org.geotools.data.DefaultTransaction; +import org.geotools.data.FeatureStore; +import org.geotools.data.Transaction; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.filter.FilterFactoryImpl; +import org.geotools.referencing.CRS; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.identity.FeatureId; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; + +public class GeoJcrIndex implements EventListener { + public final static SimpleFeatureType JCR_POINT; + + final static String JCR_POINT_NAME = "JCR_POINT"; + // PostGIS convention + final static String DEFAULT_GEOM_NAME = "the_geom"; + + private final static Log log = LogFactory.getLog(GeoJcrIndex.class); + + static { + SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); + builder.setNamespaceURI(GisNames.GIS_NAMESPACE); + builder.setName(JCR_POINT_NAME); + + builder.setDefaultGeometry(DEFAULT_GEOM_NAME); + builder.add(DEFAULT_GEOM_NAME, Point.class); + + builder.add(JcrUtils.normalize(Property.JCR_UUID), String.class); + builder.add(JcrUtils.normalize(Property.JCR_PATH), String.class); + builder.add(JcrUtils.normalize(Property.JCR_PRIMARY_TYPE), String.class); + // mix:created + // builder.add(JcrUtils.normalize(Property.JCR_CREATED), Date.class); + // builder.add(JcrUtils.normalize(Property.JCR_CREATED_BY), + // String.class); + // mix:lastModified + builder.add(JcrUtils.normalize(Property.JCR_LAST_MODIFIED), Date.class); + builder.add(JcrUtils.normalize(Property.JCR_LAST_MODIFIED_BY), + String.class); + + JCR_POINT = builder.buildFeatureType(); + } + + private DataStore dataStore; + private FeatureStore pointsIndex; + private Session session; + private SystemExecutionService systemExecutionService; + + // TODO: use common factory finder? + private FilterFactory2 ff = new FilterFactoryImpl(); + + // TODO: use finder? + private GeometryFactory geometryFactory = new GeometryFactory(); + + public void init() { + GeoToolsUtils.createSchemaIfNeeded(dataStore, JCR_POINT); + pointsIndex = GeoToolsUtils.getFeatureStore(dataStore, + JCR_POINT.getName()); + + systemExecutionService.executeAsSystem(new Runnable() { + public void run() { + try { + session.getWorkspace() + .getObservationManager() + .addEventListener(GeoJcrIndex.this, + Event.NODE_ADDED | Event.NODE_REMOVED, "/", + true, null, + new String[] { GisTypes.GIS_GEOMETRY }, + false); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot initialize GeoJcr index", + e); + } + + } + }); + } + + public void dispose() { + } + + public void onEvent(EventIterator events) { + FeatureCollection pointsToAdd = FeatureCollections + .newCollection(); + Set pointsToRemove = new HashSet(); + while (events.hasNext()) { + Event event = events.nextEvent(); + try { + Integer eventType = event.getType(); + if (Event.NODE_ADDED == eventType) { + Node node = session.getNodeByIdentifier(event + .getIdentifier()); + if (node.isNodeType(GisTypes.GIS_POINT)) { + Point point = nodeToPoint(node); + SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder( + JCR_POINT); + featureBuilder.set(DEFAULT_GEOM_NAME, point); + mapNodeToFeature(node, featureBuilder); + pointsToAdd.add(featureBuilder.buildFeature(node + .getIdentifier())); + } + } else if (Event.NODE_REMOVED == eventType) { + String id = event.getIdentifier(); + pointsToRemove.add(ff.featureId(id)); + } + } catch (Exception e) { + log.error("Cannot process event " + event, e); + } + } + + // persist + // TODO: this may be more optimal to persist in one single transaction, + // but we will loose modifications on all nodes if one fails + try { + Transaction transaction = new DefaultTransaction(); + pointsIndex.setTransaction(transaction); + try { + // points + pointsIndex.addFeatures(pointsToAdd); + if (pointsToRemove.size() != 0) + pointsIndex.removeFeatures(ff.id(pointsToRemove)); + transaction.commit(); + } catch (Exception e) { + transaction.rollback(); + throw new ArgeoException("Cannot persist changes", e); + } finally { + transaction.close(); + } + } catch (ArgeoException e) { + throw e; + } catch (IOException e) { + throw new ArgeoException("Unexpected issue with the transaction", e); + } + } + + protected void mapNodeToFeature(Node node, + SimpleFeatureBuilder featureBuilder) { + try { + featureBuilder.set(JcrUtils.normalize(Property.JCR_UUID), + node.getIdentifier()); + featureBuilder.set(JcrUtils.normalize(Property.JCR_PATH), + node.getPath()); + featureBuilder.set(JcrUtils.normalize(Property.JCR_PRIMARY_TYPE), + node.getPrimaryNodeType().getName()); + if (node.hasProperty(Property.JCR_LAST_MODIFIED)) + featureBuilder.set( + JcrUtils.normalize(Property.JCR_LAST_MODIFIED), node + .getProperty(Property.JCR_LAST_MODIFIED) + .getDate().getTime()); + if (node.hasProperty(Property.JCR_LAST_MODIFIED_BY)) + featureBuilder + .set(JcrUtils.normalize(Property.JCR_LAST_MODIFIED_BY), + node.getProperty(Property.JCR_LAST_MODIFIED_BY) + .getString()); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot map " + node + " to " + + featureBuilder.getFeatureType(), e); + } + } + + /** Return the node as a point in the CRS of the related feature store. */ + protected Point nodeToPoint(Node node) { + CoordinateReferenceSystem featureStoreCrs = pointsIndex.getSchema() + .getCoordinateReferenceSystem(); + DirectPosition nodePosition = GeoJcrUtils.nodeToPosition(node); + CoordinateReferenceSystem nodeCrs = nodePosition + .getCoordinateReferenceSystem(); + + // transform if not same CRS + DirectPosition targetPosition; + if (!featureStoreCrs.getIdentifiers().contains(nodeCrs.getName())) { + MathTransform transform; + try { + transform = CRS.findMathTransform(nodeCrs, featureStoreCrs); + targetPosition = transform.transform(nodePosition, null); + } catch (Exception e) { + throw new ArgeoException("Cannot transform from " + nodeCrs + + " to " + featureStoreCrs, e); + } + } else { + targetPosition = nodePosition; + } + double[] coo = targetPosition.getCoordinate(); + return geometryFactory.createPoint(new Coordinate(coo[0], coo[1])); + } + + public void setDataStore(DataStore dataStore) { + this.dataStore = dataStore; + } + + public void setSession(Session session) { + this.session = session; + } + + public void setSystemExecutionService( + SystemExecutionService systemExecutionService) { + this.systemExecutionService = systemExecutionService; + } + +} diff --git a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrUtils.java b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrUtils.java new file mode 100644 index 000000000..7b390ca3a --- /dev/null +++ b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrUtils.java @@ -0,0 +1,98 @@ +package org.argeo.geotools.jcr; + +import javax.jcr.Node; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.ArgeoException; +import org.argeo.jcr.gis.GisNames; +import org.argeo.jcr.gis.GisTypes; +import org.geotools.geometry.DirectPosition2D; +import org.geotools.referencing.CRS; +import org.opengis.geometry.DirectPosition; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; + +/** Utilities to map JCR from/to JTS and GeoTools */ +public class GeoJcrUtils { + private final static Log log = LogFactory.getLog(GeoJcrUtils.class); + + /** Transforms a geometry node into position within its CRS */ + public static DirectPosition nodeToPosition(Node node) { + try { + if (node.isNodeType(GisTypes.GIS_POINT)) { + CoordinateReferenceSystem crs = getCoordinateReferenceSystem(node); + Point point = (Point) nodeToGeometry(node); + return new DirectPosition2D(crs, point.getX(), point.getY()); + } else { + throw new ArgeoException(node + " is not of a supported type"); + } + } catch (Exception e) { + throw new ArgeoException("Cannot extract position from " + node, e); + } + } + + /** Transforms a geometry node into a JTS geometry. */ + public static Geometry nodeToGeometry(Node node) { + try { + if (node.isNodeType(GisTypes.GIS_POINT) + || node.isNodeType(GisTypes.GIS_COORDINATE)) { + Coordinate coo; + if (node.hasProperty(GisNames.GIS_Z)) + coo = new Coordinate(node.getProperty(GisNames.GIS_X) + .getDouble(), node.getProperty(GisNames.GIS_Y) + .getDouble(), node.getProperty(GisNames.GIS_Z) + .getDouble()); + else + coo = new Coordinate(node.getProperty(GisNames.GIS_X) + .getDouble(), node.getProperty(GisNames.GIS_Y) + .getDouble()); + + // TODO: use factory finder + // GeometryFactory geometryFactory = + // JTSFactoryFinder.getGeometryFactory(null); + GeometryFactory geometryFactory = new GeometryFactory(); + return geometryFactory.createPoint(coo); + } else { + throw new ArgeoException(node + " is not of a supported type"); + } + } catch (Exception e) { + throw new ArgeoException("Cannot map " + node + " to a geometry", e); + } + } + + /** Reads and interpret the coordinate reference system from a node. */ + public static CoordinateReferenceSystem getCoordinateReferenceSystem( + Node node) { + try { + if (!node.isNodeType(GisTypes.GIS_GEOMETRY)) + throw new ArgeoException(node + " is not of type " + + GisTypes.GIS_GEOMETRY); + // Coordinate reference system + String srs = node.getProperty(GisNames.GIS_SRS).getString(); + CoordinateReferenceSystem crs; + try { + // first, try to decode an EPSG code + crs = CRS.decode(srs); + } catch (Exception e) { + // if it fails, try a WKT + try { + crs = CRS.parseWKT(srs); + } catch (Exception e1) { + // if it fails as well, log the error + log.error("Cannot parse WKT " + srs, e1); + // and then the previous error (probably more relevant) + throw e; + } + } + return crs; + } catch (Exception e) { + throw new ArgeoException( + "Cannot get coordinate reference system for " + node, e); + } + } +} diff --git a/security/dep/org.argeo.security.dep.node/pom.xml b/security/dep/org.argeo.security.dep.node/pom.xml index fa40e2525..4e2d71be7 100644 --- a/security/dep/org.argeo.security.dep.node/pom.xml +++ b/security/dep/org.argeo.security.dep.node/pom.xml @@ -78,12 +78,22 @@ ${version.argeo-commons} pom + + org.argeo.commons.security + org.argeo.security.activemq + ${version.argeo-commons} + org.argeo.commons.server org.argeo.server.jackrabbit ${version.argeo-commons} + + org.argeo.commons.security + org.argeo.security.jackrabbit + ${version.argeo-commons} + org.argeo.commons.server org.argeo.server.jcr.mvc diff --git a/security/modules/org.argeo.security.manager.ldap/META-INF/MANIFEST.MF b/security/modules/org.argeo.security.manager.ldap/META-INF/MANIFEST.MF index b800a45c9..5325587bb 100644 --- a/security/modules/org.argeo.security.manager.ldap/META-INF/MANIFEST.MF +++ b/security/modules/org.argeo.security.manager.ldap/META-INF/MANIFEST.MF @@ -9,13 +9,12 @@ Import-Package: com.sun.jndi.ldap;resolution:=optional, org.springframework.beans.factory.config, org.springframework.ldap.core.support, org.springframework.security, - org.springframework.security.adapters;specification-version="2.0.4.A", org.springframework.security.ldap, org.springframework.security.ldap.populator, org.springframework.security.providers, + org.springframework.security.providers.encoding;specification-version="2.0.6.RELEASE", org.springframework.security.providers.ldap, org.springframework.security.providers.ldap.authenticator, - org.springframework.security.providers.rememberme;specification-version="2.0.4.A", org.springframework.security.userdetails, org.springframework.security.userdetails.ldap Bundle-Name: Security Manager LDAP diff --git a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap-osgi.xml b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap-osgi.xml index 12f8909eb..b3a95cefc 100644 --- a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap-osgi.xml +++ b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap-osgi.xml @@ -6,19 +6,22 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - + + + + + - - diff --git a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap.xml b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap.xml index bd117530d..0c3c8a684 100644 --- a/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap.xml +++ b/security/modules/org.argeo.security.manager.ldap/META-INF/spring/ldap.xml @@ -14,20 +14,8 @@ - - - - - - - - - - - - - + diff --git a/security/modules/org.argeo.security.manager.ldap/ldap.properties b/security/modules/org.argeo.security.manager.ldap/ldap.properties index bb4298292..1b24ee3d1 100644 --- a/security/modules/org.argeo.security.manager.ldap/ldap.properties +++ b/security/modules/org.argeo.security.manager.ldap/ldap.properties @@ -4,5 +4,3 @@ argeo.ldap.host=localhost argeo.ldap.port=10389 argeo.ldap.manager.userdn=uid=admin,ou=system argeo.ldap.manager.password=secret - -argeo.security.systemKey=argeo diff --git a/security/modules/org.argeo.security.services/META-INF/MANIFEST.MF b/security/modules/org.argeo.security.services/META-INF/MANIFEST.MF index d005b164f..3d22df281 100644 --- a/security/modules/org.argeo.security.services/META-INF/MANIFEST.MF +++ b/security/modules/org.argeo.security.services/META-INF/MANIFEST.MF @@ -3,5 +3,9 @@ Bundle-Version: 0.2.3.SNAPSHOT Import-Package: org.argeo.security, org.argeo.security.core, org.springframework.beans.factory.config;specification-version="2.5.6.SEC01", - org.springframework.security;specification-version="2.0.4.A" + org.springframework.security;specification-version="2.0.4.A", + org.springframework.security.adapters;specification-version="2.0.6.RELEASE", + org.springframework.security.providers;specification-version="2.0.6.RELEASE", + org.springframework.security.providers.encoding;specification-version="2.0.6.RELEASE", + org.springframework.security.providers.rememberme;specification-version="2.0.6.RELEASE" Bundle-Name: Security Services diff --git a/security/modules/org.argeo.security.services/META-INF/spring/osgi.xml b/security/modules/org.argeo.security.services/META-INF/spring/osgi.xml index 8913486fc..62872b1c0 100644 --- a/security/modules/org.argeo.security.services/META-INF/spring/osgi.xml +++ b/security/modules/org.argeo.security.services/META-INF/spring/osgi.xml @@ -6,8 +6,21 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - + + - + + + + + + + + + + \ No newline at end of file diff --git a/security/modules/org.argeo.security.services/META-INF/spring/services.xml b/security/modules/org.argeo.security.services/META-INF/spring/services.xml index 97fe92eda..bb79de265 100644 --- a/security/modules/org.argeo.security.services/META-INF/spring/services.xml +++ b/security/modules/org.argeo.security.services/META-INF/spring/services.xml @@ -15,7 +15,28 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/security/plugins/org.argeo.security.equinox/plugin.xml b/security/plugins/org.argeo.security.equinox/plugin.xml index b407360ac..78f0d9cb1 100644 --- a/security/plugins/org.argeo.security.equinox/plugin.xml +++ b/security/plugins/org.argeo.security.equinox/plugin.xml @@ -19,8 +19,8 @@ - name="Spring Login Module" + point="org.eclipse.equinox.security.loginModule" + name="Spring Login Module"> diff --git a/security/plugins/org.argeo.security.ui.application/src/main/java/org/argeo/security/ui/application/AbstractSecureApplication.java b/security/plugins/org.argeo.security.ui.application/src/main/java/org/argeo/security/ui/application/AbstractSecureApplication.java index a0a2f922b..955066000 100644 --- a/security/plugins/org.argeo.security.ui.application/src/main/java/org/argeo/security/ui/application/AbstractSecureApplication.java +++ b/security/plugins/org.argeo.security.ui.application/src/main/java/org/argeo/security/ui/application/AbstractSecureApplication.java @@ -16,13 +16,16 @@ import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.application.WorkbenchAdvisor; +/** + * Common base class for authenticated access to the Eclipse UI framework (RAP and + * RCP) + */ public abstract class AbstractSecureApplication implements IApplication { private static final Log log = LogFactory .getLog(AbstractSecureApplication.class); protected abstract WorkbenchAdvisor createWorkbenchAdvisor(); - @SuppressWarnings("unchecked") public Object start(IApplicationContext context) throws Exception { Integer returnCode = null; @@ -51,8 +54,7 @@ public abstract class AbstractSecureApplication implements IApplication { ErrorDialog.openError(null, "Error", "Shutdown...", status); return status.getSeverity(); } - if (log.isDebugEnabled()) - log.debug("Logged in as " + username); + returnCode = (Integer) Subject.doAs(subject, getRunAction(display)); SecureApplicationActivator.getLoginContext().logout(); return processReturnCode(returnCode); diff --git a/security/runtime/org.argeo.security.activemq/pom.xml b/security/runtime/org.argeo.security.activemq/pom.xml index 0405a5c05..d9e408956 100644 --- a/security/runtime/org.argeo.security.activemq/pom.xml +++ b/security/runtime/org.argeo.security.activemq/pom.xml @@ -41,12 +41,12 @@ org.argeo.commons.basic org.argeo.basic.nodeps - 0.2.3-SNAPSHOT + ${version.argeo-commons} org.argeo.commons.security org.argeo.security.core - 0.2.3-SNAPSHOT + ${version.argeo-commons} diff --git a/security/runtime/org.argeo.security.core/pom.xml b/security/runtime/org.argeo.security.core/pom.xml index b36f10d56..5c9a1f9eb 100644 --- a/security/runtime/org.argeo.security.core/pom.xml +++ b/security/runtime/org.argeo.security.core/pom.xml @@ -62,7 +62,10 @@ org.springframework.security org.springframework.security.core - + + org.springframework + org.springframework.transaction + org.slf4j diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java index 67c4cb2ec..81baa5e28 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityDao.java @@ -16,53 +16,11 @@ package org.argeo.security; -import java.util.Set; /** * Access to the users and roles referential (dependent from the underlying * storage, e.g. LDAP). */ -public interface ArgeoSecurityDao { - // public ArgeoUser getCurrentUser(); - - /** List all users */ - public Set listUsers(); - - /** List roles that can be modified */ - public Set listEditableRoles(); - - /** - * Creates a new user in the underlying storage. DO NOT CALL DIRECTLY - * use {@link ArgeoSecurityService#newUser(ArgeoUser)} instead. - */ - public void createUser(ArgeoUser user); - - public void updateUser(ArgeoUser user); - - public void deleteUser(String username); - - /** - * Creates a new role in the underlying storage. DO NOT CALL DIRECTLY - * use {@link ArgeoSecurityService#newRole(String)} instead. - */ - public void createRole(String role, String superuserName); - - public void deleteRole(String role); - - /** List all users having this role. */ - public Set listUsersInRole(String role); - - public Boolean userExists(String username); - - public ArgeoUser getUser(String username); - - public ArgeoUser getUserWithPassword(String username); - - public String getDefaultRole(); - - /** Validates a raw password against an encoded one. */ - public Boolean isPasswordValid(String encoded, String raw); - - /** Encodes a raw password. */ - public String encodePassword(String raw); +@Deprecated +public interface ArgeoSecurityDao extends CurrentUserDao,UserAdminDao{ } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java index 76933e0e5..172fba189 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/ArgeoSecurityService.java @@ -21,6 +21,7 @@ package org.argeo.security; * High level access to the user referential (independent from the underlying * storage). */ +@Deprecated public interface ArgeoSecurityService extends CurrentUserService, UserAdminService { } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/CurrentUserDao.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/CurrentUserDao.java new file mode 100644 index 000000000..b9fee6f3a --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/CurrentUserDao.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 Mathieu Baudier + * + * Licensed 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.argeo.security; + +/** + * Access to user backend for the currently logged in user + */ +public interface CurrentUserDao { + public void updateUser(ArgeoUser user); + + public String getDefaultRole(); + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java new file mode 100644 index 000000000..0aa553313 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemAuthentication.java @@ -0,0 +1,8 @@ +package org.argeo.security; + +/** + * Marks a system authentication, that is which did not require a login process. + */ +public interface SystemAuthentication { + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java new file mode 100644 index 000000000..f5ef357c0 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/SystemExecutionService.java @@ -0,0 +1,18 @@ +package org.argeo.security; + +import org.springframework.core.task.TaskExecutor; + +/** + * Allows to execute code authenticated as a system user (that is not a real + * person) + */ +public interface SystemExecutionService { + /** + * Executes this Runnable within a system authenticated context. + * Implementations should make sure that this method is properly secured via + * Java permissions since it could access to everything without credentials. + */ + public void executeAsSystem(Runnable runnable); + + public TaskExecutor createSystemAuthenticatedTaskExecutor(); +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminDao.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminDao.java new file mode 100644 index 000000000..0d07daec3 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminDao.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Mathieu Baudier + * + * Licensed 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.argeo.security; + +import java.util.Set; + +/** + * Access to the users and roles referential (dependent from the underlying + * storage, e.g. LDAP). + */ +public interface UserAdminDao{ + /** List all users */ + public Set listUsers(); + + /** List roles that can be modified */ + public Set listEditableRoles(); + + /** + * Creates a new user in the underlying storage. DO NOT CALL DIRECTLY + * use {@link ArgeoSecurityService#newUser(ArgeoUser)} instead. + */ + public void createUser(ArgeoUser user); + + public void deleteUser(String username); + + /** + * Creates a new role in the underlying storage. DO NOT CALL DIRECTLY + * use {@link ArgeoSecurityService#newRole(String)} instead. + */ + public void createRole(String role, String superuserName); + + public void deleteRole(String role); + + /** List all users having this role. */ + public Set listUsersInRole(String role); + + public Boolean userExists(String username); + + public ArgeoUser getUser(String username); + + public ArgeoUser getUserWithPassword(String username); +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java index 47ea65ecc..4bd887ec7 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/UserAdminService.java @@ -35,5 +35,7 @@ public interface UserAdminService { /* * SYSTEM */ + @Deprecated + /** @deprecated Use ${link SystemExecutionService} instead.*/ public Runnable wrapWithSystemAuthentication(final Runnable runnable); } diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultCurrentUserService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultCurrentUserService.java new file mode 100644 index 000000000..49e9efe5d --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultCurrentUserService.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 Mathieu Baudier + * + * Licensed 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.argeo.security.core; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Map; +import java.util.Random; + +import org.argeo.ArgeoException; +import org.argeo.security.ArgeoUser; +import org.argeo.security.CurrentUserDao; +import org.argeo.security.CurrentUserService; +import org.argeo.security.SimpleArgeoUser; +import org.argeo.security.UserNature; +import org.springframework.security.providers.encoding.PasswordEncoder; + +public class DefaultCurrentUserService implements CurrentUserService { + private CurrentUserDao currentUserDao; + private PasswordEncoder passwordEncoder; + private Random random; + + public DefaultCurrentUserService() { + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + random = new Random(System.currentTimeMillis()); + } + } + + public ArgeoUser getCurrentUser() { + ArgeoUser argeoUser = ArgeoUserDetails.securityContextUser(); + if (argeoUser == null) + return null; + if (argeoUser.getRoles().contains(currentUserDao.getDefaultRole())) + argeoUser.getRoles().remove(currentUserDao.getDefaultRole()); + return argeoUser; + } + + public void updateCurrentUserPassword(String oldPassword, String newPassword) { + SimpleArgeoUser user = new SimpleArgeoUser(getCurrentUser()); + if (!passwordEncoder.isPasswordValid(user.getPassword(), oldPassword, + null)) + throw new ArgeoException("Old password is not correct."); + user.setPassword(encodePassword(newPassword)); + currentUserDao.updateUser(user); + } + + protected String encodePassword(String password) { + byte[] salt = new byte[16]; + random.nextBytes(salt); + return passwordEncoder.encodePassword(password, salt); + } + + public void updateCurrentUserNatures(Map userNatures) { + // TODO Auto-generated method stub + + } + + public void setCurrentUserDao(CurrentUserDao dao) { + this.currentUserDao = dao; + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { + this.passwordEncoder = passwordEncoder; + } + +} diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java index e005e1ad4..68f97d4a0 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/DefaultSecurityService.java @@ -17,16 +17,14 @@ package org.argeo.security.core; import java.util.Iterator; -import java.util.Map; import java.util.Set; -import org.argeo.ArgeoException; import org.argeo.security.ArgeoSecurity; import org.argeo.security.ArgeoSecurityDao; import org.argeo.security.ArgeoSecurityService; import org.argeo.security.ArgeoUser; import org.argeo.security.SimpleArgeoUser; -import org.argeo.security.UserNature; +import org.argeo.security.UserAdminService; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.core.task.TaskExecutor; import org.springframework.security.Authentication; @@ -34,22 +32,14 @@ import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; -public class DefaultSecurityService implements ArgeoSecurityService { +public class DefaultSecurityService extends DefaultCurrentUserService implements + UserAdminService, ArgeoSecurityService { private ArgeoSecurity argeoSecurity = new DefaultArgeoSecurity(); private ArgeoSecurityDao securityDao; private AuthenticationManager authenticationManager; private String systemAuthenticationKey; - public ArgeoUser getCurrentUser() { - ArgeoUser argeoUser = ArgeoUserDetails.securityContextUser(); - if (argeoUser == null) - return null; - if (argeoUser.getRoles().contains(securityDao.getDefaultRole())) - argeoUser.getRoles().remove(securityDao.getDefaultRole()); - return argeoUser; - } - public ArgeoSecurityDao getSecurityDao() { return securityDao; } @@ -61,15 +51,7 @@ public class DefaultSecurityService implements ArgeoSecurityService { public void updateUserPassword(String username, String password) { SimpleArgeoUser user = new SimpleArgeoUser( securityDao.getUser(username)); - user.setPassword(securityDao.encodePassword(password)); - securityDao.updateUser(user); - } - - public void updateCurrentUserPassword(String oldPassword, String newPassword) { - SimpleArgeoUser user = new SimpleArgeoUser(getCurrentUser()); - if (!securityDao.isPasswordValid(user.getPassword(), oldPassword)) - throw new ArgeoException("Old password is not correct."); - user.setPassword(securityDao.encodePassword(newPassword)); + user.setPassword(encodePassword(password)); securityDao.updateUser(user); } @@ -78,11 +60,11 @@ public class DefaultSecurityService implements ArgeoSecurityService { // normalize password if (user instanceof SimpleArgeoUser) { if (user.getPassword() == null || user.getPassword().equals("")) - ((SimpleArgeoUser) user).setPassword(securityDao - .encodePassword(user.getUsername())); + ((SimpleArgeoUser) user).setPassword(encodePassword(user + .getUsername())); else if (!user.getPassword().startsWith("{")) - ((SimpleArgeoUser) user).setPassword(securityDao - .encodePassword(user.getPassword())); + ((SimpleArgeoUser) user).setPassword(encodePassword(user + .getPassword())); } securityDao.createUser(user); } @@ -101,7 +83,7 @@ public class DefaultSecurityService implements ArgeoSecurityService { password = securityDao.getUserWithPassword(user.getUsername()) .getPassword(); if (!password.startsWith("{")) - password = securityDao.encodePassword(user.getPassword()); + password = encodePassword(user.getPassword()); SimpleArgeoUser simpleArgeoUser = new SimpleArgeoUser(user); simpleArgeoUser.setPassword(password); securityDao.updateUser(simpleArgeoUser); @@ -116,6 +98,7 @@ public class DefaultSecurityService implements ArgeoSecurityService { securityDao.deleteRole(role); } + @Deprecated public TaskExecutor createSystemAuthenticatedTaskExecutor() { return new SimpleAsyncTaskExecutor() { private static final long serialVersionUID = -8126773862193265020L; @@ -133,6 +116,7 @@ public class DefaultSecurityService implements ArgeoSecurityService { * Wraps another runnable, adding security context
* TODO: secure the call to this method with Java Security */ + @Deprecated public Runnable wrapWithSystemAuthentication(final Runnable runnable) { return new Runnable() { @@ -162,11 +146,6 @@ public class DefaultSecurityService implements ArgeoSecurityService { return lst; } - public void updateCurrentUserNatures(Map userNatures) { - // TODO Auto-generated method stub - - } - public Set listUsers() { return securityDao.listUsers(); } @@ -182,6 +161,7 @@ public class DefaultSecurityService implements ArgeoSecurityService { public void setSecurityDao(ArgeoSecurityDao dao) { this.securityDao = dao; + setCurrentUserDao(dao); } public void setAuthenticationManager( diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java index 9b65ee042..f20f6805b 100644 --- a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/InternalAuthentication.java @@ -16,11 +16,13 @@ package org.argeo.security.core; +import org.argeo.security.SystemAuthentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.GrantedAuthorityImpl; import org.springframework.security.adapters.PrincipalSpringSecurityUserToken; -public class InternalAuthentication extends PrincipalSpringSecurityUserToken { +public class InternalAuthentication extends PrincipalSpringSecurityUserToken + implements SystemAuthentication { private static final long serialVersionUID = -6783376375615949315L; public final static String DEFAULT_SYSTEM_USERNAME = "system"; public final static String DEFAULT_SYSTEM_ROLE = "ROLE_SYSTEM"; diff --git a/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java new file mode 100644 index 000000000..d586d1178 --- /dev/null +++ b/security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/core/KeyBasedSystemExecutionService.java @@ -0,0 +1,57 @@ +package org.argeo.security.core; + +import org.argeo.security.SystemExecutionService; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.core.task.TaskExecutor; +import org.springframework.security.Authentication; +import org.springframework.security.AuthenticationManager; +import org.springframework.security.context.SecurityContext; +import org.springframework.security.context.SecurityContextHolder; + +public class KeyBasedSystemExecutionService implements SystemExecutionService { + private AuthenticationManager authenticationManager; + private String systemAuthenticationKey; + + public void executeAsSystem(Runnable runnable) { + wrapWithSystemAuthentication(runnable).run(); + } + + public TaskExecutor createSystemAuthenticatedTaskExecutor() { + return new SimpleAsyncTaskExecutor() { + private static final long serialVersionUID = -8126773862193265020L; + + @Override + public Thread createThread(Runnable runnable) { + return super + .createThread(wrapWithSystemAuthentication(runnable)); + } + + }; + } + + protected Runnable wrapWithSystemAuthentication(final Runnable runnable) { + return new Runnable() { + + public void run() { + SecurityContext securityContext = SecurityContextHolder + .getContext(); + Authentication auth = authenticationManager + .authenticate(new InternalAuthentication( + systemAuthenticationKey)); + securityContext.setAuthentication(auth); + + runnable.run(); + } + }; + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public void setSystemAuthenticationKey(String systemAuthenticationKey) { + this.systemAuthenticationKey = systemAuthenticationKey; + } + +} diff --git a/security/runtime/org.argeo.security.jackrabbit/.classpath b/security/runtime/org.argeo.security.jackrabbit/.classpath new file mode 100644 index 000000000..92f19d2ff --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/security/runtime/org.argeo.security.jackrabbit/.project b/security/runtime/org.argeo.security.jackrabbit/.project new file mode 100644 index 000000000..35bcca28f --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/.project @@ -0,0 +1,28 @@ + + + org.argeo.security.jackrabbit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.jdt.core.prefs b/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..fef3e9420 --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Tue Mar 01 09:49:47 CET 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.pde.core.prefs b/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..f99c55aaf --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Tue Mar 01 09:49:47 CET 2011 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/security/runtime/org.argeo.security.jackrabbit/build.properties b/security/runtime/org.argeo.security.jackrabbit/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/security/runtime/org.argeo.security.jackrabbit/pom.xml b/security/runtime/org.argeo.security.jackrabbit/pom.xml new file mode 100644 index 000000000..b676aef80 --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + + org.argeo.commons.security + runtime + 0.2.3-SNAPSHOT + .. + + org.argeo.security.jackrabbit + Commons Security Jackrabbit + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + ${version.maven-bundle-plugin} + + + org.argeo.dep.osgi.jackrabbit + org.argeo.security.jackrabbit.* + + + + + + + + org.argeo.commons.security + org.argeo.security.core + ${version.argeo-commons} + + + org.argeo.dep.osgi + org.argeo.dep.osgi.jcr + + + org.argeo.dep.osgi + org.argeo.dep.osgi.jackrabbit + + + org.springframework.security + org.springframework.security.core + + + diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/GrantedAuthorityPrincipal.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/GrantedAuthorityPrincipal.java new file mode 100644 index 000000000..ec6152edb --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/GrantedAuthorityPrincipal.java @@ -0,0 +1,20 @@ +package org.argeo.security.jackrabbit.spring; + +import java.security.Principal; + +import org.springframework.security.GrantedAuthority; + +/** Wraps a {@link GrantedAuthority} as a prin,cipal. */ +public class GrantedAuthorityPrincipal implements Principal { + private final GrantedAuthority grantedAuthority; + + public GrantedAuthorityPrincipal(GrantedAuthority grantedAuthority) { + super(); + this.grantedAuthority = grantedAuthority; + } + + public String getName() { + return grantedAuthority.getAuthority(); + } + +} diff --git a/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/SpringLoginModule.java b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/SpringLoginModule.java new file mode 100644 index 000000000..c6b456d62 --- /dev/null +++ b/security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/spring/SpringLoginModule.java @@ -0,0 +1,85 @@ +package org.argeo.security.jackrabbit.spring; + +import java.security.Principal; +import java.security.acl.Group; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import javax.jcr.Credentials; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; + +import org.apache.jackrabbit.core.security.AnonymousPrincipal; +import org.apache.jackrabbit.core.security.authentication.AbstractLoginModule; +import org.apache.jackrabbit.core.security.authentication.Authentication; +import org.apache.jackrabbit.core.security.principal.AdminPrincipal; +import org.argeo.security.SystemAuthentication; +import org.springframework.security.GrantedAuthority; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; + +public class SpringLoginModule extends AbstractLoginModule { + + /** + * Returns the Spring {@link org.springframework.security.Authentication} + * (which can be null) + */ + @Override + protected Principal getPrincipal(Credentials credentials) { + return SecurityContextHolder.getContext().getAuthentication(); + } + + protected Set getPrincipals() { + // use linked HashSet instead of HashSet in order to maintain the order + // of principals (as in the Subject). + Set principals = new LinkedHashSet(); + principals.add(principal); + + org.springframework.security.Authentication authen = (org.springframework.security.Authentication) principal; + + if (authen instanceof AnonymousAuthenticationToken) + principals.add(new AnonymousPrincipal()); + if (authen instanceof SystemAuthentication) + principals.add(new AdminPrincipal(authen.getName())); + + for (GrantedAuthority authority : authen.getAuthorities()) + principals.add(new GrantedAuthorityPrincipal(authority)); + + return principals; + } + + @SuppressWarnings("rawtypes") + @Override + protected void doInit(CallbackHandler callbackHandler, Session session, + Map options) throws LoginException { + } + + @Override + protected boolean impersonate(Principal principal, Credentials credentials) + throws RepositoryException, LoginException { + throw new UnsupportedOperationException( + "Impersonation is not yet supported"); + } + + @Override + protected Authentication getAuthentication(Principal principal, + Credentials creds) throws RepositoryException { + if (principal instanceof Group) { + return null; + } + return new Authentication() { + public boolean canHandle(Credentials credentials) { + return true; + } + + public boolean authenticate(Credentials credentials) + throws RepositoryException { + return true; + } + }; + } + +} diff --git a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java index 838a3cb97..f5e41232e 100644 --- a/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java +++ b/security/runtime/org.argeo.security.ldap/src/main/java/org/argeo/security/ldap/ArgeoSecurityDaoLdap.java @@ -18,11 +18,8 @@ package org.argeo.security.ldap; import static org.argeo.security.core.ArgeoUserDetails.createSimpleArgeoUser; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; import java.util.Collections; import java.util.List; -import java.util.Random; import java.util.Set; import java.util.TreeSet; @@ -32,7 +29,9 @@ import javax.naming.directory.DirContext; import org.argeo.security.ArgeoSecurityDao; import org.argeo.security.ArgeoUser; +import org.argeo.security.CurrentUserDao; import org.argeo.security.SimpleArgeoUser; +import org.argeo.security.UserAdminDao; import org.argeo.security.core.ArgeoUserDetails; import org.springframework.beans.factory.InitializingBean; import org.springframework.ldap.core.ContextExecutor; @@ -49,7 +48,6 @@ import org.springframework.security.ldap.LdapUtils; import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator; import org.springframework.security.ldap.search.FilterBasedLdapUserSearch; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; -import org.springframework.security.providers.ldap.authenticator.LdapShaPasswordEncoder; import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.UserDetailsManager; import org.springframework.security.userdetails.UserDetailsService; @@ -57,7 +55,8 @@ import org.springframework.security.userdetails.ldap.LdapUserDetailsManager; import org.springframework.security.userdetails.ldap.LdapUserDetailsService; import org.springframework.security.userdetails.ldap.UserDetailsContextMapper; -public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean { +public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, CurrentUserDao, + UserAdminDao, InitializingBean { // private final static Log log = LogFactory.getLog(UserDaoLdap.class); private UserDetailsManager userDetailsManager; @@ -80,17 +79,9 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean private LdapUserDetailsService ldapUserDetailsService; private List userNatureMappers; - private LdapShaPasswordEncoder ldapShaPasswordEncoder = new LdapShaPasswordEncoder(); - private Random random; - public ArgeoSecurityDaoLdap(BaseLdapPathContextSource contextSource) { this.contextSource = contextSource; ldapTemplate = new LdapTemplate(this.contextSource); - try { - random = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - random = new Random(System.currentTimeMillis()); - } } public void afterPropertiesSet() throws Exception { @@ -254,17 +245,6 @@ public class ArgeoSecurityDaoLdap implements ArgeoSecurityDao, InitializingBean ldapTemplate.unbind(dn); } - public Boolean isPasswordValid(String encoded, String raw) { - return ldapShaPasswordEncoder.isPasswordValid(encoded, raw, null); - } - - public String encodePassword(String raw) { - byte[] salt = null; - // byte[] salt = new byte[16]; - // random.nextBytes(salt); - return ldapShaPasswordEncoder.encodePassword(raw, salt); - } - protected String convertRoleToGroup(String role) { String group = role; if (group.startsWith(rolePrefix)) { diff --git a/security/runtime/pom.xml b/security/runtime/pom.xml index c04649e6f..641ca066a 100644 --- a/security/runtime/pom.xml +++ b/security/runtime/pom.xml @@ -16,6 +16,7 @@ org.argeo.security.mvc org.argeo.security.ldap org.argeo.security.activemq + org.argeo.security.jackrabbit diff --git a/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml b/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml index cc63f5a76..927608a18 100644 --- a/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml +++ b/server/dep/org.argeo.server.dep.jackrabbit.server/pom.xml @@ -20,6 +20,11 @@ org.argeo.server.tika.jackrabbit ${version.argeo-commons}
+ + org.argeo.commons.server + org.argeo.server.ext.jackrabbit + ${version.argeo-commons} + org.apache.xalan com.springsource.org.apache.xalan diff --git a/server/modules/org.argeo.server.ext.jackrabbit/META-INF/MANIFEST.MF b/server/modules/org.argeo.server.ext.jackrabbit/META-INF/MANIFEST.MF index e1c13f3b1..271e52de8 100644 --- a/server/modules/org.argeo.server.ext.jackrabbit/META-INF/MANIFEST.MF +++ b/server/modules/org.argeo.server.ext.jackrabbit/META-INF/MANIFEST.MF @@ -2,6 +2,6 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Jackrabbit Bundle-SymbolicName: org.argeo.server.ext.jackrabbit -Bundle-Description: provides additional DLLs to Jackrabbit +Bundle-Description: provides additional DLLs and imports to Jackrabbit Bundle-Version: 0.2.3.SNAPSHOT Fragment-Host: org.argeo.dep.osgi.jackrabbit diff --git a/server/runtime/org.argeo.server.jackrabbit/pom.xml b/server/runtime/org.argeo.server.jackrabbit/pom.xml index cce683335..756e0787d 100644 --- a/server/runtime/org.argeo.server.jackrabbit/pom.xml +++ b/server/runtime/org.argeo.server.jackrabbit/pom.xml @@ -38,8 +38,6 @@ org.springframework.web.context, org.xml.sax;version="0.0.0", org.apache.jackrabbit.webdav.jcr, - org.springframework.security.providers.jaas;resolution:="optional", - junit.framework;resolution:="optional", * @@ -51,25 +49,25 @@ org.argeo.commons.basic org.argeo.basic.nodeps - 0.2.3-SNAPSHOT + ${version.argeo-commons} org.argeo.commons.server org.argeo.server.core - 0.2.3-SNAPSHOT + ${version.argeo-commons} org.argeo.commons.server org.argeo.server.jcr.mvc - 0.2.3-SNAPSHOT + ${version.argeo-commons} org.argeo.commons.server org.argeo.server.dep.jackrabbit.server - 0.2.3-SNAPSHOT + ${version.argeo-commons} pom @@ -94,11 +92,6 @@ org.springframework.web.servlet - - org.springframework.security - org.springframework.security.core - - org.springframework.ws org.springframework.xml @@ -119,13 +112,13 @@ org.argeo.commons.basic org.argeo.support.junit - 0.2.3-SNAPSHOT + ${version.argeo-commons} test org.argeo.commons.basic org.argeo.basic.dep.log4j - 0.2.3-SNAPSHOT + ${version.argeo-commons} pom test diff --git a/server/runtime/org.argeo.server.jcr/build.properties b/server/runtime/org.argeo.server.jcr/build.properties index a9dd55a1d..a4f357883 100644 --- a/server/runtime/org.argeo.server.jcr/build.properties +++ b/server/runtime/org.argeo.server.jcr/build.properties @@ -1,7 +1,9 @@ source.. = src/main/java/,\ src/test/java/,\ - src/test/resources/ -output.. = target/classes/ + src/test/resources/,\ + src/main/resources/ +output.. = target/classes/,\ + target/test-classes/ bin.includes = META-INF/,\ . additional.bundles = com.springsource.slf4j.api,\ diff --git a/server/runtime/org.argeo.server.jcr/pom.xml b/server/runtime/org.argeo.server.jcr/pom.xml index 415c4fd05..0177d1d55 100644 --- a/server/runtime/org.argeo.server.jcr/pom.xml +++ b/server/runtime/org.argeo.server.jcr/pom.xml @@ -30,6 +30,7 @@ org.argeo.jcr.* + junit.framework;resolution:=optional,* @@ -55,7 +56,7 @@ org.argeo.commons.basic org.argeo.basic.nodeps - 0.2.3-SNAPSHOT + ${version.argeo-commons} @@ -98,7 +99,7 @@ org.argeo.commons.server org.argeo.server.dep.jackrabbit.server - 0.2.3-SNAPSHOT + ${version.argeo-commons} pom test @@ -109,20 +110,20 @@ org.argeo.commons.basic org.argeo.support.junit - 0.2.3-SNAPSHOT + ${version.argeo-commons} test org.argeo.commons.basic org.argeo.basic.dep.log4j - 0.2.3-SNAPSHOT + ${version.argeo-commons} pom test org.argeo.commons.osgi org.argeo.osgi.boot - 0.2.3-SNAPSHOT + ${version.argeo-commons} test
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java index 554e9f34c..59778556a 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -486,4 +486,12 @@ public class JcrUtils { else return baseRelPath + '/' + propertyName; } + + /** + * Normalize a name so taht it can be stores in contexts not supporting + * names with ':' (typically databases). Replaces ':' by '_'. + */ + public static String normalize(String name) { + return name.replace(':', '_'); + } } diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisNames.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisNames.java new file mode 100644 index 000000000..3a97f7b76 --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisNames.java @@ -0,0 +1,12 @@ +package org.argeo.jcr.gis; + +/** JCR names in the http://www.argeo.org/gis namespace */ +public interface GisNames { + public final static String GIS_NAMESPACE = "http://www.argeo.org/gis"; + public final static String GIS_ = "gis:"; + + public final static String GIS_SRS = "gis:srs"; + public final static String GIS_X = "gis:x"; + public final static String GIS_Y = "gis:y"; + public final static String GIS_Z = "gis:z"; +} diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisTypes.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisTypes.java new file mode 100644 index 000000000..83ebe6f8b --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/gis/GisTypes.java @@ -0,0 +1,8 @@ +package org.argeo.jcr.gis; + +/** JCR types in the http://www.argeo.org/gis namespace */ +public interface GisTypes { + public final static String GIS_COORDINATE = "gis:coordinate"; + public final static String GIS_GEOMETRY = "gis:geometry"; + public final static String GIS_POINT = "gis:point"; +} diff --git a/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/gis/argeo_gis.cnd b/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/gis/argeo_gis.cnd new file mode 100644 index 000000000..43e3b574c --- /dev/null +++ b/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/gis/argeo_gis.cnd @@ -0,0 +1,16 @@ + + +// GEOMETRIES (based on JTS http://www.vividsolutions.com/jts/JTSHome.htm) +[gis:coordinate] > nt:base +mixin +- gis:x (DOUBLE) m +- gis:y (DOUBLE) m +- gis:z (DOUBLE) + +[gis:geometry] > mix:created, mix:lastModified +mixin +// either an EPSG code (EPSG:4326 for WGS 84) or a WKT representation +- gis:srs (STRING) + +[gis:point] > gis:geometry, gis:coordinate +mixin -- 2.30.2