Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

HHH-7462 - Make JACC service

  • Loading branch information...
commit d184cb3eb4b7721ac3e9729c2a38d85150e40d46 1 parent e4c1db1
@sebersole sebersole authored
Showing with 862 additions and 476 deletions.
  1. +4 −5 hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
  2. +32 −12 hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
  3. +16 −1 hibernate-core/src/main/java/org/hibernate/event/spi/AbstractPreDatabaseOperationEvent.java
  4. +6 −1 hibernate-core/src/main/java/org/hibernate/event/spi/PreDeleteEvent.java
  5. +14 −4 hibernate-core/src/main/java/org/hibernate/event/spi/PreLoadEvent.java
  6. +2 −0  hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java
  7. +53 −0 hibernate-core/src/main/java/org/hibernate/secure/internal/AbstractJaccSecurableEventListener.java
  8. +48 −0 hibernate-core/src/main/java/org/hibernate/secure/internal/DisabledJaccServiceImpl.java
  9. +0 −70 hibernate-core/src/main/java/org/hibernate/secure/internal/HibernatePermission.java
  10. +0 −88 hibernate-core/src/main/java/org/hibernate/secure/internal/JACCConfiguration.java
  11. +0 −144 hibernate-core/src/main/java/org/hibernate/secure/internal/JACCPermissions.java
  12. +5 −14 ...java/org/hibernate/secure/internal/{JACCPreDeleteEventListener.java → JaccPreDeleteEventListener.java}
  13. +5 −14 ...java/org/hibernate/secure/internal/{JACCPreInsertEventListener.java → JaccPreInsertEventListener.java}
  14. +5 −14 ...ain/java/org/hibernate/secure/internal/{JACCPreLoadEventListener.java → JaccPreLoadEventListener.java}
  15. +5 −14 ...java/org/hibernate/secure/internal/{JACCPreUpdateEventListener.java → JaccPreUpdateEventListener.java}
  16. +3 −2 ...re/src/main/java/org/hibernate/secure/internal/{JACCSecurityListener.java → JaccSecurityListener.java}
  17. +221 −0 hibernate-core/src/main/java/org/hibernate/secure/internal/StandardJaccServiceImpl.java
  18. +5 −0 hibernate-core/src/main/java/org/hibernate/secure/package-info.java
  19. +0 −33 hibernate-core/src/main/java/org/hibernate/secure/package.html
  20. +53 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/GrantedPermission.java
  21. +39 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/IntegrationException.java
  22. +132 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java
  23. +50 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java
  24. +36 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccService.java
  25. +80 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/PermissibleAction.java
  26. +35 −0 hibernate-core/src/main/java/org/hibernate/secure/spi/PermissionCheckEntityInformation.java
  27. +3 −3 hibernate-entitymanager/src/main/java/org/hibernate/jpa/AvailableSettings.java
  28. +10 −14 hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
  29. +0 −43 hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java
View
9 hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java
@@ -417,11 +417,6 @@
*/
public static final String DEFAULT_ENTITY_MODE = "hibernate.default_entity_mode";
- /**
- * The jacc context id of the deployment
- */
- public static final String JACC_CONTEXTID = "hibernate.jacc_context_id";
-
/**
* Should all database identifiers be quoted.
*/
@@ -639,4 +634,8 @@
* Default is <code>true</code> (enabled).
*/
public static final String JTA_TRACK_BY_THREAD = "hibernate.jta.track_by_thread";
+
+ public static final String JACC_CONTEXT_ID = "hibernate.jacc_context_id";
+ public static final String JACC_PREFIX = "hibernate.jacc";
+ public static final String JACC_ENABLED = "hibernate.jacc.enabled";
}
View
44 hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java
@@ -134,7 +134,8 @@
import org.hibernate.mapping.TypeDef;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.proxy.EntityNotFoundDelegate;
-import org.hibernate.secure.internal.JACCConfiguration;
+import org.hibernate.secure.spi.GrantedPermission;
+import org.hibernate.secure.spi.JaccPermissionDeclarations;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.hibernate.tool.hbm2ddl.IndexMetadata;
@@ -2198,25 +2199,44 @@ else if ( classAttribute != null ) {
}
}
+ private JaccPermissionDeclarations jaccPermissionDeclarations;
+
private void parseSecurity(Element secNode) {
- String contextId = secNode.attributeValue( "context" );
- setProperty( Environment.JACC_CONTEXTID, contextId );
- LOG.jaccContextId( contextId );
- JACCConfiguration jcfg = new JACCConfiguration( contextId );
+ final String nodeContextId = secNode.attributeValue( "context" );
+
+ final String explicitContextId = getProperty( AvailableSettings.JACC_CONTEXT_ID );
+ if ( explicitContextId == null ) {
+ setProperty( AvailableSettings.JACC_CONTEXT_ID, nodeContextId );
+ LOG.jaccContextId( nodeContextId );
+ }
+ else {
+ // if they dont match, throw an error
+ if ( ! nodeContextId.equals( explicitContextId ) ) {
+ throw new HibernateException( "Non-matching JACC context ids" );
+ }
+ }
+ jaccPermissionDeclarations = new JaccPermissionDeclarations( nodeContextId );
+
Iterator grantElements = secNode.elementIterator();
while ( grantElements.hasNext() ) {
- Element grantElement = (Element) grantElements.next();
- String elementName = grantElement.getName();
+ final Element grantElement = (Element) grantElements.next();
+ final String elementName = grantElement.getName();
if ( "grant".equals( elementName ) ) {
- jcfg.addPermission(
- grantElement.attributeValue( "role" ),
- grantElement.attributeValue( "entity-name" ),
- grantElement.attributeValue( "actions" )
- );
+ jaccPermissionDeclarations.addPermissionDeclaration(
+ new GrantedPermission(
+ grantElement.attributeValue( "role" ),
+ grantElement.attributeValue( "entity-name" ),
+ grantElement.attributeValue( "actions" )
+ )
+ );
}
}
}
+ public JaccPermissionDeclarations getJaccPermissionDeclarations() {
+ return jaccPermissionDeclarations;
+ }
+
RootClass getRootClassMapping(String clazz) throws MappingException {
try {
return (RootClass) getClassMapping( clazz );
View
17 hibernate-core/src/main/java/org/hibernate/event/spi/AbstractPreDatabaseOperationEvent.java
@@ -26,13 +26,17 @@
import java.io.Serializable;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
/**
* Represents an operation we are about to perform against the database.
*
* @author Steve Ebersole
*/
-public abstract class AbstractPreDatabaseOperationEvent extends AbstractEvent {
+public abstract class AbstractPreDatabaseOperationEvent
+ extends AbstractEvent
+ implements PermissionCheckEntityInformation {
+
private final Object entity;
private final Serializable id;
private final EntityPersister persister;
@@ -61,6 +65,7 @@ public AbstractPreDatabaseOperationEvent(
*
* @return The entity.
*/
+ @Override
public Object getEntity() {
return entity;
}
@@ -97,4 +102,14 @@ public EntityPersister getPersister() {
public EventSource getSource() {
return getSession();
}
+
+ @Override
+ public String getEntityName() {
+ return persister.getEntityName();
+ }
+
+ @Override
+ public Serializable getIdentifier() {
+ return id;
+ }
}
View
7 hibernate-core/src/main/java/org/hibernate/event/spi/PreDeleteEvent.java
@@ -26,6 +26,8 @@
import java.io.Serializable;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
+
/**
* Represents a <tt>pre-delete</tt> event, which occurs just prior to
@@ -34,7 +36,10 @@
* @author Gavin King
* @author Steve Ebersole
*/
-public class PreDeleteEvent extends AbstractPreDatabaseOperationEvent {
+public class PreDeleteEvent
+ extends AbstractPreDatabaseOperationEvent
+ implements PermissionCheckEntityInformation{
+
private Object[] deletedState;
/**
View
18 hibernate-core/src/main/java/org/hibernate/event/spi/PreLoadEvent.java
@@ -26,14 +26,14 @@
import java.io.Serializable;
import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
/**
- * Called before injecting property values into a newly
- * loaded entity instance.
+ * Called before injecting property values into a newly loaded entity instance.
*
* @author Gavin King
*/
-public class PreLoadEvent extends AbstractEvent {
+public class PreLoadEvent extends AbstractEvent implements PermissionCheckEntityInformation {
private Object entity;
private Object[] state;
private Serializable id;
@@ -43,6 +43,7 @@ public PreLoadEvent(EventSource session) {
super(session);
}
+ @Override
public Object getEntity() {
return entity;
}
@@ -78,5 +79,14 @@ public PreLoadEvent setState(Object[] state) {
this.state = state;
return this;
}
-
+
+ @Override
+ public String getEntityName() {
+ return persister.getEntityName();
+ }
+
+ @Override
+ public Serializable getIdentifier() {
+ return id;
+ }
}
View
2  hibernate-core/src/main/java/org/hibernate/integrator/internal/IntegratorServiceImpl.java
@@ -31,6 +31,7 @@
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.integrator.spi.IntegratorService;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
+import org.hibernate.secure.spi.JaccIntegrator;
/**
* @author Steve Ebersole
@@ -44,6 +45,7 @@ public IntegratorServiceImpl(LinkedHashSet<Integrator> providedIntegrators, Clas
// register standard integrators. Envers and JPA, for example, need to be handled by discovery because in
// separate project/jars.
addIntegrator( new BeanValidationIntegrator() );
+ addIntegrator( new JaccIntegrator() );
// register provided integrators
for ( Integrator integrator : providedIntegrators ) {
View
53 hibernate-core/src/main/java/org/hibernate/secure/internal/AbstractJaccSecurableEventListener.java
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.internal;
+
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.event.spi.AbstractPreDatabaseOperationEvent;
+import org.hibernate.secure.spi.JaccService;
+import org.hibernate.secure.spi.PermissibleAction;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
+
+/**
+ * Base class for JACC-securable event listeners
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractJaccSecurableEventListener implements JaccSecurityListener {
+ private JaccService jaccService;
+
+ protected void performSecurityCheck(AbstractPreDatabaseOperationEvent event, PermissibleAction action) {
+ performSecurityCheck( event.getSession(), event, action );
+ }
+
+ protected void performSecurityCheck(
+ SessionImplementor session,
+ PermissionCheckEntityInformation entityInformation,
+ PermissibleAction action) {
+ if ( jaccService == null ) {
+ jaccService = session.getFactory().getServiceRegistry().getService( JaccService.class );
+ }
+ jaccService.checkPermission( entityInformation, action );
+ }
+}
View
48 hibernate-core/src/main/java/org/hibernate/secure/internal/DisabledJaccServiceImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.internal;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.secure.spi.GrantedPermission;
+import org.hibernate.secure.spi.JaccService;
+import org.hibernate.secure.spi.PermissibleAction;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
+
+/**
+ * @author Steve Ebersole
+ */
+public class DisabledJaccServiceImpl implements JaccService {
+ private static final Logger log = Logger.getLogger( DisabledJaccServiceImpl.class );
+
+ @Override
+ public void addPermission(GrantedPermission permissionDeclaration) {
+ log.debug( "Ignoring call to addPermission on disabled JACC service" );
+ }
+
+ @Override
+ public void checkPermission(PermissionCheckEntityInformation entityInformation, PermissibleAction action) {
+ log.debug( "Ignoring call to checkPermission on disabled JACC service" );
+ }
+}
View
70 hibernate-core/src/main/java/org/hibernate/secure/internal/HibernatePermission.java
@@ -1,70 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- */
-package org.hibernate.secure.internal;
-
-import java.security.Permission;
-
-/**
- * @author Gavin King
- */
-public class HibernatePermission extends Permission {
- public static final String INSERT = "insert";
- public static final String UPDATE = "update";
- public static final String DELETE = "delete";
- public static final String READ = "read";
- public static final String ANY = "*";
-
- private final String actions;
-
- public HibernatePermission(String entityName, String actions) {
- super(entityName);
- this.actions = actions;
- }
-
- public boolean implies(Permission permission) {
- //TODO!
- return ( "*".equals( getName() ) || getName().equals( permission.getName() ) ) &&
- ( "*".equals(actions) || actions.indexOf( permission.getActions() ) >= 0 );
- }
-
- public boolean equals(Object obj) {
- if ( !(obj instanceof HibernatePermission) ) return false;
- HibernatePermission permission = (HibernatePermission) obj;
- return permission.getName().equals( getName() ) &&
- permission.getActions().equals(actions);
- }
-
- public int hashCode() {
- return getName().hashCode() * 37 + actions.hashCode();
- }
-
- public String getActions() {
- return actions;
- }
-
- public String toString() {
- return "HibernatePermission(" + getName() + ':' + actions + ')';
- }
-
-}
View
88 hibernate-core/src/main/java/org/hibernate/secure/internal/JACCConfiguration.java
@@ -1,88 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- */
-package org.hibernate.secure.internal;
-
-import java.util.StringTokenizer;
-import javax.security.jacc.EJBMethodPermission;
-import javax.security.jacc.PolicyConfiguration;
-import javax.security.jacc.PolicyConfigurationFactory;
-import javax.security.jacc.PolicyContextException;
-
-import org.jboss.logging.Logger;
-
-import org.hibernate.HibernateException;
-import org.hibernate.internal.CoreMessageLogger;
-
-/**
- * Adds Hibernate permissions to roles via JACC
- *
- * @author Gavin King
- */
-public class JACCConfiguration {
-
- private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JACCConfiguration.class.getName());
-
- private final PolicyConfiguration policyConfiguration;
-
- public JACCConfiguration(String contextId) throws HibernateException {
- try {
- policyConfiguration = PolicyConfigurationFactory
- .getPolicyConfigurationFactory()
- .getPolicyConfiguration( contextId, false );
- }
- catch (ClassNotFoundException cnfe) {
- throw new HibernateException( "JACC provider class not found", cnfe );
- }
- catch (PolicyContextException pce) {
- throw new HibernateException( "policy context exception occurred", pce );
- }
- }
-
- public void addPermission(String role, String entityName, String action) {
-
- if ( action.equals( "*" ) ) {
- action = "insert,read,update,delete";
- }
-
- StringTokenizer tok = new StringTokenizer( action, "," );
-
- while ( tok.hasMoreTokens() ) {
- String methodName = tok.nextToken().trim();
- EJBMethodPermission permission = new EJBMethodPermission(
- entityName,
- methodName,
- null, // interfaces
- null // arguments
- );
-
- LOG.debugf("Adding permission to role %s: %s", role, permission);
- try {
- policyConfiguration.addToRole( role, permission );
- }
- catch (PolicyContextException pce) {
- throw new HibernateException( "policy context exception occurred", pce );
- }
- }
- }
-}
View
144 hibernate-core/src/main/java/org/hibernate/secure/internal/JACCPermissions.java
@@ -1,144 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors. All third-party contributions are
- * distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02110-1301 USA
- */
-package org.hibernate.secure.internal;
-
-import java.lang.reflect.UndeclaredThrowableException;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Policy;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.util.Set;
-import javax.security.auth.Subject;
-import javax.security.jacc.EJBMethodPermission;
-import javax.security.jacc.PolicyContext;
-import javax.security.jacc.PolicyContextException;
-
-/**
- * Copied from JBoss org.jboss.ejb3.security.JaccHelper and org.jboss.ejb3.security.SecurityActions
- *
- * @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
- */
-public class JACCPermissions {
-
- public static void checkPermission(Class clazz, String contextID, EJBMethodPermission methodPerm)
- throws SecurityException {
- CodeSource ejbCS = clazz.getProtectionDomain().getCodeSource();
-
- try {
- setContextID( contextID );
-
- Policy policy = Policy.getPolicy();
- // Get the caller
- Subject caller = getContextSubject();
-
- Principal[] principals = null;
- if ( caller != null ) {
- // Get the caller principals
- Set principalsSet = caller.getPrincipals();
- principals = new Principal[ principalsSet.size() ];
- principalsSet.toArray( principals );
- }
-
- ProtectionDomain pd = new ProtectionDomain( ejbCS, null, null, principals );
- if ( policy.implies( pd, methodPerm ) == false ) {
- String msg = "Denied: " + methodPerm + ", caller=" + caller;
- SecurityException e = new SecurityException( msg );
- throw e;
- }
- }
- catch (PolicyContextException e) {
- throw new RuntimeException( e );
- }
- }
-
- interface PolicyContextActions {
- /**
- * The JACC PolicyContext key for the current Subject
- */
- static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
- PolicyContextActions PRIVILEGED = new PolicyContextActions() {
- private final PrivilegedExceptionAction exAction = new PrivilegedExceptionAction() {
- public Object run() throws Exception {
- return PolicyContext.getContext( SUBJECT_CONTEXT_KEY );
- }
- };
-
- public Subject getContextSubject() throws PolicyContextException {
- try {
- return (Subject) AccessController.doPrivileged( exAction );
- }
- catch (PrivilegedActionException e) {
- Exception ex = e.getException();
- if ( ex instanceof PolicyContextException ) {
- throw (PolicyContextException) ex;
- }
- else {
- throw new UndeclaredThrowableException( ex );
- }
- }
- }
- };
-
- PolicyContextActions NON_PRIVILEGED = new PolicyContextActions() {
- public Subject getContextSubject() throws PolicyContextException {
- return (Subject) PolicyContext.getContext( SUBJECT_CONTEXT_KEY );
- }
- };
-
- Subject getContextSubject() throws PolicyContextException;
- }
-
- static Subject getContextSubject() throws PolicyContextException {
- if ( System.getSecurityManager() == null ) {
- return PolicyContextActions.NON_PRIVILEGED.getContextSubject();
- }
- else {
- return PolicyContextActions.PRIVILEGED.getContextSubject();
- }
- }
-
- private static class SetContextID implements PrivilegedAction {
- String contextID;
-
- SetContextID(String contextID) {
- this.contextID = contextID;
- }
-
- public Object run() {
- String previousID = PolicyContext.getContextID();
- PolicyContext.setContextID( contextID );
- return previousID;
- }
- }
-
- static String setContextID(String contextID) {
- PrivilegedAction action = new SetContextID( contextID );
- String previousID = (String) AccessController.doPrivileged( action );
- return previousID;
- }
-}
View
19 ...e/secure/internal/JACCPreDeleteEventListener.java → ...e/secure/internal/JaccPreDeleteEventListener.java
@@ -23,31 +23,22 @@
*/
package org.hibernate.secure.internal;
-import javax.security.jacc.EJBMethodPermission;
-
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
+import org.hibernate.secure.spi.PermissibleAction;
/**
* Check security before any deletion
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
+ * @author Steve Ebersole
*/
-public class JACCPreDeleteEventListener implements PreDeleteEventListener, JACCSecurityListener {
- private final String contextId;
-
- public JACCPreDeleteEventListener(String contextId) {
- this.contextId = contextId;
+public class JaccPreDeleteEventListener extends AbstractJaccSecurableEventListener implements PreDeleteEventListener {
+ public JaccPreDeleteEventListener() {
}
public boolean onPreDelete(PreDeleteEvent event) {
- final EJBMethodPermission deletePermission = new EJBMethodPermission(
- event.getPersister().getEntityName(),
- HibernatePermission.DELETE,
- null,
- null
- );
- JACCPermissions.checkPermission( event.getEntity().getClass(), contextId, deletePermission );
+ performSecurityCheck( event, PermissibleAction.DELETE );
return false;
}
View
19 ...e/secure/internal/JACCPreInsertEventListener.java → ...e/secure/internal/JaccPreInsertEventListener.java
@@ -23,31 +23,22 @@
*/
package org.hibernate.secure.internal;
-import javax.security.jacc.EJBMethodPermission;
-
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
+import org.hibernate.secure.spi.PermissibleAction;
/**
* Check security before an insertion
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
+ * @author Steve Ebersole
*/
-public class JACCPreInsertEventListener implements PreInsertEventListener, JACCSecurityListener {
- private final String contextId;
-
- public JACCPreInsertEventListener(String contextId) {
- this.contextId = contextId;
+public class JaccPreInsertEventListener extends AbstractJaccSecurableEventListener implements PreInsertEventListener {
+ public JaccPreInsertEventListener() {
}
public boolean onPreInsert(PreInsertEvent event) {
- final EJBMethodPermission insertPermission = new EJBMethodPermission(
- event.getPersister().getEntityName(),
- HibernatePermission.INSERT,
- null,
- null
- );
- JACCPermissions.checkPermission( event.getEntity().getClass(), contextId, insertPermission );
+ performSecurityCheck( event, PermissibleAction.INSERT );
return false;
}
}
View
19 ...ate/secure/internal/JACCPreLoadEventListener.java → ...ate/secure/internal/JaccPreLoadEventListener.java
@@ -23,30 +23,21 @@
*/
package org.hibernate.secure.internal;
-import javax.security.jacc.EJBMethodPermission;
-
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
+import org.hibernate.secure.spi.PermissibleAction;
/**
* Check security before any load
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
+ * @author Steve Ebersole
*/
-public class JACCPreLoadEventListener implements PreLoadEventListener, JACCSecurityListener {
- private final String contextId;
-
- public JACCPreLoadEventListener(String contextId) {
- this.contextId = contextId;
+public class JaccPreLoadEventListener extends AbstractJaccSecurableEventListener implements PreLoadEventListener {
+ public JaccPreLoadEventListener() {
}
public void onPreLoad(PreLoadEvent event) {
- final EJBMethodPermission loadPermission = new EJBMethodPermission(
- event.getPersister().getEntityName(),
- HibernatePermission.READ,
- null,
- null
- );
- JACCPermissions.checkPermission( event.getEntity().getClass(), contextId, loadPermission );
+ performSecurityCheck( event.getSession(), event, PermissibleAction.READ );
}
}
View
19 ...e/secure/internal/JACCPreUpdateEventListener.java → ...e/secure/internal/JaccPreUpdateEventListener.java
@@ -23,31 +23,22 @@
*/
package org.hibernate.secure.internal;
-import javax.security.jacc.EJBMethodPermission;
-
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
+import org.hibernate.secure.spi.PermissibleAction;
/**
* Check security before any update
*
* @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
+ * @author Steve Ebersole
*/
-public class JACCPreUpdateEventListener implements PreUpdateEventListener, JACCSecurityListener {
- private final String contextId;
-
- public JACCPreUpdateEventListener(String contextId) {
- this.contextId = contextId;
+public class JaccPreUpdateEventListener extends AbstractJaccSecurableEventListener implements PreUpdateEventListener {
+ public JaccPreUpdateEventListener() {
}
public boolean onPreUpdate(PreUpdateEvent event) {
- final EJBMethodPermission updatePermission = new EJBMethodPermission(
- event.getPersister().getEntityName(),
- HibernatePermission.UPDATE,
- null,
- null
- );
- JACCPermissions.checkPermission( event.getEntity().getClass(), contextId, updatePermission );
+ performSecurityCheck( event, PermissibleAction.UPDATE );
return false;
}
}
View
5 ...bernate/secure/internal/JACCSecurityListener.java → ...bernate/secure/internal/JaccSecurityListener.java
@@ -24,9 +24,10 @@
package org.hibernate.secure.internal;
/**
- * Marker interface for JACC event listeners
+ * Marker interface for JACC event listeners. Used in event listener duplication strategy checks; see
+ * {@link org.hibernate.secure.spi.JaccIntegrator} for details.
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
*/
-public interface JACCSecurityListener {
+public interface JaccSecurityListener {
}
View
221 hibernate-core/src/main/java/org/hibernate/secure/internal/StandardJaccServiceImpl.java
@@ -0,0 +1,221 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.internal;
+
+import javax.security.auth.Subject;
+import javax.security.jacc.EJBMethodPermission;
+import javax.security.jacc.PolicyConfiguration;
+import javax.security.jacc.PolicyConfigurationFactory;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Policy;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.secure.spi.GrantedPermission;
+import org.hibernate.secure.spi.IntegrationException;
+import org.hibernate.secure.spi.JaccService;
+import org.hibernate.secure.spi.PermissibleAction;
+import org.hibernate.secure.spi.PermissionCheckEntityInformation;
+import org.hibernate.service.spi.Configurable;
+
+/**
+ * @author Steve Ebersole
+ */
+public class StandardJaccServiceImpl implements JaccService, Configurable {
+ private static final Logger log = Logger.getLogger( StandardJaccServiceImpl.class );
+
+ private String contextId;
+ private PolicyConfiguration policyConfiguration;
+
+ @Override
+ public void configure(Map configurationValues) {
+ this.contextId = (String) configurationValues.get( AvailableSettings.JACC_CONTEXT_ID );
+ }
+
+ @Override
+ public void addPermission(GrantedPermission permissionDeclaration) {
+ // todo : do we need to wrap these PolicyConfiguration calls in privileged actions like we do during permission checks?
+
+ if ( policyConfiguration == null ) {
+ policyConfiguration = locatePolicyConfiguration( contextId );
+ }
+
+ for ( String grantedAction : permissionDeclaration.getPermissibleAction().getImpliedActions() ) {
+ final EJBMethodPermission permission = new EJBMethodPermission(
+ permissionDeclaration.getEntityName(),
+ grantedAction,
+ null, // interfaces
+ null // arguments
+ );
+
+ log.debugf( "Adding permission [%s] to role [%s]", grantedAction, permissionDeclaration.getRole() );
+ try {
+ policyConfiguration.addToRole( permissionDeclaration.getRole(), permission );
+ }
+ catch (PolicyContextException pce) {
+ throw new HibernateException( "policy context exception occurred", pce );
+ }
+ }
+ }
+
+ private PolicyConfiguration locatePolicyConfiguration(String contextId) {
+ try {
+ return PolicyConfigurationFactory
+ .getPolicyConfigurationFactory()
+ .getPolicyConfiguration( contextId, false );
+ }
+ catch (Exception e) {
+ throw new IntegrationException( "Unable to access JACC PolicyConfiguration" );
+ }
+ }
+
+ @Override
+ public void checkPermission(PermissionCheckEntityInformation entityInformation, PermissibleAction action) {
+ if ( action == PermissibleAction.ANY ) {
+ throw new HibernateException( "ANY action (*) is not legal for permission check, only for configuration" );
+ }
+
+ final String originalContextId = AccessController.doPrivileged( new ContextIdSetAction( contextId ) );
+ try {
+ doPermissionCheckInContext( entityInformation, action );
+ }
+ finally {
+ AccessController.doPrivileged( new ContextIdSetAction( originalContextId ) );
+ }
+ }
+
+ private static class ContextIdSetAction implements PrivilegedAction<String> {
+ private final String contextId;
+
+ private ContextIdSetAction(String contextId) {
+ this.contextId = contextId;
+ }
+
+ @Override
+ public String run() {
+ String previousID = PolicyContext.getContextID();
+ PolicyContext.setContextID( contextId );
+ return previousID;
+ }
+ }
+
+ private void doPermissionCheckInContext(PermissionCheckEntityInformation entityInformation, PermissibleAction action) {
+ final Policy policy = Policy.getPolicy();
+ final Principal[] principals = getCallerPrincipals();
+
+ final CodeSource codeSource = entityInformation.getEntity().getClass().getProtectionDomain().getCodeSource();
+ final ProtectionDomain pd = new ProtectionDomain( codeSource, null, null, principals );
+
+ // the action is known as 'method name' in JACC
+ final EJBMethodPermission jaccPermission = new EJBMethodPermission(
+ entityInformation.getEntityName(),
+ action.getImpliedActions()[0],
+ null,
+ null
+ );
+
+ if ( ! policy.implies( pd, jaccPermission) ) {
+ throw new SecurityException(
+ String.format(
+ "JACC denied permission to [%s.%s] for [%s]",
+ entityInformation.getEntityName(),
+ action.getImpliedActions()[0],
+ join( principals )
+ )
+ );
+ }
+ }
+
+ private String join(Principal[] principals) {
+ String separator = "";
+ final StringBuilder buffer = new StringBuilder();
+ for ( Principal principal : principals ) {
+ buffer.append( separator ).append( principal.getName() );
+ separator = ", ";
+ }
+ return buffer.toString();
+ }
+
+ protected Principal[] getCallerPrincipals() {
+ final Subject caller = getContextSubjectAccess().getContextSubject();
+ if ( caller == null ) {
+ return new Principal[0];
+ }
+
+ final Set<Principal> principalsSet = caller.getPrincipals();
+ return principalsSet.toArray( new Principal[ principalsSet.size()] );
+ }
+
+ private ContextSubjectAccess getContextSubjectAccess() {
+ return ( System.getSecurityManager() == null )
+ ? NonPrivilegedContextSubjectAccess.INSTANCE
+ : PrivilegedContextSubjectAccess.INSTANCE;
+ }
+
+ protected static interface ContextSubjectAccess {
+ public static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
+
+ public Subject getContextSubject();
+ }
+
+ protected static class PrivilegedContextSubjectAccess implements ContextSubjectAccess {
+ public static final PrivilegedContextSubjectAccess INSTANCE = new PrivilegedContextSubjectAccess();
+
+ private final PrivilegedAction<Subject> privilegedAction = new PrivilegedAction<Subject>() {
+ public Subject run() {
+ return NonPrivilegedContextSubjectAccess.INSTANCE.getContextSubject();
+ }
+ };
+
+ @Override
+ public Subject getContextSubject() {
+ return AccessController.doPrivileged( privilegedAction );
+ }
+ }
+
+ protected static class NonPrivilegedContextSubjectAccess implements ContextSubjectAccess {
+ public static final NonPrivilegedContextSubjectAccess INSTANCE = new NonPrivilegedContextSubjectAccess();
+
+ @Override
+ public Subject getContextSubject() {
+ try {
+ return (Subject) PolicyContext.getContext( SUBJECT_CONTEXT_KEY );
+ }
+ catch (PolicyContextException e) {
+ throw new HibernateException( "Unable to access JACC PolicyContext in order to locate calling Subject", e );
+ }
+ }
+ }
+
+}
View
5 hibernate-core/src/main/java/org/hibernate/secure/package-info.java
@@ -0,0 +1,5 @@
+package org.hibernate.secure;
+
+/**
+ * Package defining support for declarative security of CRUD operations via JACC.
+ */
View
33 hibernate-core/src/main/java/org/hibernate/secure/package.html
@@ -1,33 +0,0 @@
-<!--
- ~ Hibernate, Relational Persistence for Idiomatic Java
- ~
- ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
- ~ indicated by the @author tags or express copyright attribution
- ~ statements applied by the authors. All third-party contributions are
- ~ distributed under license by Red Hat Middleware LLC.
- ~
- ~ This copyrighted material is made available to anyone wishing to use, modify,
- ~ copy, or redistribute it subject to the terms and conditions of the GNU
- ~ Lesser General Public License, as published by the Free Software Foundation.
- ~
- ~ 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.
- ~
- ~ You should have received a copy of the GNU Lesser General Public License
- ~ along with this distribution; if not, write to:
- ~ Free Software Foundation, Inc.
- ~ 51 Franklin Street, Fifth Floor
- ~ Boston, MA 02110-1301 USA
- ~
- -->
-
-<html>
-<head></head>
-<body>
-<p>
- Declarative security for CRUD operations on entities.
-</p>
-</body>
-</html>
View
53 hibernate-core/src/main/java/org/hibernate/secure/spi/GrantedPermission.java
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+/**
+ * Describes a Hibernate (persistence) permission.
+ *
+ * @author Steve Ebersole
+ */
+public class GrantedPermission {
+ private final String role;
+ private final String entityName;
+ private final PermissibleAction action;
+
+ public GrantedPermission(String role, String entityName, String action) {
+ this.role = role;
+ this.entityName = entityName;
+ this.action = PermissibleAction.interpret( action );
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public String getEntityName() {
+ return entityName;
+ }
+
+ public PermissibleAction getPermissibleAction() {
+ return action;
+ }
+}
View
39 hibernate-core/src/main/java/org/hibernate/secure/spi/IntegrationException.java
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+import org.hibernate.HibernateException;
+
+/**
+ * @author Steve Ebersole
+ */
+public class IntegrationException extends HibernateException {
+ public IntegrationException(String message) {
+ super( message );
+ }
+
+ public IntegrationException(String message, Throwable root) {
+ super( message, root );
+ }
+}
View
132 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccIntegrator.java
@@ -0,0 +1,132 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.AvailableSettings;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.event.service.spi.DuplicationStrategy;
+import org.hibernate.event.service.spi.EventListenerRegistry;
+import org.hibernate.event.spi.EventType;
+import org.hibernate.integrator.spi.Integrator;
+import org.hibernate.integrator.spi.ServiceContributingIntegrator;
+import org.hibernate.metamodel.source.MetadataImplementor;
+import org.hibernate.secure.internal.DisabledJaccServiceImpl;
+import org.hibernate.secure.internal.JaccPreDeleteEventListener;
+import org.hibernate.secure.internal.JaccPreInsertEventListener;
+import org.hibernate.secure.internal.JaccPreLoadEventListener;
+import org.hibernate.secure.internal.JaccPreUpdateEventListener;
+import org.hibernate.secure.internal.JaccSecurityListener;
+import org.hibernate.secure.internal.StandardJaccServiceImpl;
+import org.hibernate.service.spi.SessionFactoryServiceRegistry;
+
+/**
+ * Integrator for setting up JACC integration
+ *
+ * @author Steve Ebersole
+ */
+public class JaccIntegrator implements ServiceContributingIntegrator {
+ private static final Logger log = Logger.getLogger( JaccIntegrator.class );
+
+ private static final DuplicationStrategy DUPLICATION_STRATEGY = new DuplicationStrategy() {
+ @Override
+ public boolean areMatch(Object listener, Object original) {
+ return listener.getClass().equals( original.getClass() ) &&
+ JaccSecurityListener.class.isInstance( original );
+ }
+
+ @Override
+ public Action getAction() {
+ return Action.KEEP_ORIGINAL;
+ }
+ };
+
+ @Override
+ public void prepareServices(StandardServiceRegistryBuilder serviceRegistryBuilder) {
+ boolean isSecurityEnabled = serviceRegistryBuilder.getSettings().containsKey( AvailableSettings.JACC_ENABLED );
+ final JaccService jaccService = isSecurityEnabled ? new StandardJaccServiceImpl() : new DisabledJaccServiceImpl();
+ serviceRegistryBuilder.addService( JaccService.class, jaccService );
+ }
+
+ @Override
+ public void integrate(
+ Configuration configuration,
+ SessionFactoryImplementor sessionFactory,
+ SessionFactoryServiceRegistry serviceRegistry) {
+ doIntegration( configuration.getProperties(), configuration.getJaccPermissionDeclarations(), serviceRegistry );
+ }
+
+ private void doIntegration(
+ Map properties,
+ JaccPermissionDeclarations permissionDeclarations,
+ SessionFactoryServiceRegistry serviceRegistry) {
+ boolean isSecurityEnabled = properties.containsKey( AvailableSettings.JACC_ENABLED );
+ if ( ! isSecurityEnabled ) {
+ log.debug( "Skipping JACC integration as it was not enabled" );
+ return;
+ }
+
+ final String contextId = (String) properties.get( AvailableSettings.JACC_CONTEXT_ID );
+ if ( contextId == null ) {
+ throw new IntegrationException( "JACC context id must be specified" );
+ }
+
+ final JaccService jaccService = serviceRegistry.getService( JaccService.class );
+ if ( jaccService == null ) {
+ throw new IntegrationException( "JaccService was not set up" );
+ }
+
+ if ( permissionDeclarations != null ) {
+ for ( GrantedPermission declaration : permissionDeclarations.getPermissionDeclarations() ) {
+ jaccService.addPermission( declaration );
+ }
+ }
+
+ final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
+ eventListenerRegistry.addDuplicationStrategy( DUPLICATION_STRATEGY );
+
+ eventListenerRegistry.prependListeners( EventType.PRE_DELETE, new JaccPreDeleteEventListener() );
+ eventListenerRegistry.prependListeners( EventType.PRE_INSERT, new JaccPreInsertEventListener() );
+ eventListenerRegistry.prependListeners( EventType.PRE_UPDATE, new JaccPreUpdateEventListener() );
+ eventListenerRegistry.prependListeners( EventType.PRE_LOAD, new JaccPreLoadEventListener() );
+ }
+
+ @Override
+ public void integrate(
+ MetadataImplementor metadata,
+ SessionFactoryImplementor sessionFactory,
+ SessionFactoryServiceRegistry serviceRegistry) {
+ doIntegration( sessionFactory.getProperties(), null, serviceRegistry );
+ }
+
+ @Override
+ public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
+ // nothing to do
+ }
+}
View
50 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccPermissionDeclarations.java
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Steve Ebersole
+ */
+public class JaccPermissionDeclarations {
+ private final String contextId;
+ private List<GrantedPermission> permissionDeclarations;
+
+ public JaccPermissionDeclarations(String contextId) {
+ this.contextId = contextId;
+ }
+
+ public void addPermissionDeclaration(GrantedPermission permissionDeclaration) {
+ if ( permissionDeclarations == null ) {
+ permissionDeclarations = new ArrayList<GrantedPermission>();
+ }
+ permissionDeclarations.add( permissionDeclaration );
+ }
+
+ public Iterable<GrantedPermission> getPermissionDeclarations() {
+ return permissionDeclarations;
+ }
+}
View
36 hibernate-core/src/main/java/org/hibernate/secure/spi/JaccService.java
@@ -0,0 +1,36 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+import org.hibernate.service.Service;
+
+/**
+ * Service describing Hibernate integration with JACC for security service.
+ *
+ * @author Steve Ebersole
+ */
+public interface JaccService extends Service {
+ public void addPermission(GrantedPermission permissionDeclaration);
+ public void checkPermission(PermissionCheckEntityInformation entityInformation, PermissibleAction action);
+}
View
80 hibernate-core/src/main/java/org/hibernate/secure/spi/PermissibleAction.java
@@ -0,0 +1,80 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+/**
+ * @author Steve Ebersole
+ */
+public enum PermissibleAction {
+ INSERT( "insert" ),
+ UPDATE( "update" ),
+ DELETE( "delete" ),
+ READ( "read" ),
+ ANY( "*" ) {
+ @Override
+ public String[] getImpliedActions() {
+ return new String[] { INSERT.externalName, UPDATE.externalName, DELETE.externalName, READ.externalName };
+ }
+ };
+
+ private final String externalName;
+ private final String[] impliedActions;
+
+ private PermissibleAction(String externalName) {
+ this.externalName = externalName;
+ this.impliedActions = buildImpliedActions( externalName );
+ }
+
+ private String[] buildImpliedActions(String externalName) {
+ return new String[] { externalName };
+ }
+
+ public String getExternalName() {
+ return externalName;
+ }
+
+ public String[] getImpliedActions() {
+ return impliedActions;
+ }
+
+ public static PermissibleAction interpret(String action) {
+ if ( INSERT.externalName.equals( action ) ) {
+ return INSERT;
+ }
+ else if ( UPDATE.externalName.equals( action ) ) {
+ return UPDATE;
+ }
+ else if ( DELETE.externalName.equals( action ) ) {
+ return DELETE;
+ }
+ else if ( READ.externalName.equals( action ) ) {
+ return READ;
+ }
+ else if ( ANY.externalName.equals( action ) ) {
+ return ANY;
+ }
+
+ throw new IllegalArgumentException( "Unrecognized action : " + action );
+ }
+}
View
35 hibernate-core/src/main/java/org/hibernate/secure/spi/PermissionCheckEntityInformation.java
@@ -0,0 +1,35 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2013, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.secure.spi;
+
+import java.io.Serializable;
+
+/**
+ * @author Steve Ebersole
+ */
+public interface PermissionCheckEntityInformation {
+ public Object getEntity();
+ public String getEntityName();
+ public Serializable getIdentifier();
+}
View
6 hibernate-entitymanager/src/main/java/org/hibernate/jpa/AvailableSettings.java
@@ -509,9 +509,9 @@
public static final String XML_FILE_NAMES = "hibernate.ejb.xml_files";
public static final String HBXML_FILES = "hibernate.hbmxml.files";
public static final String LOADED_CLASSES = "hibernate.ejb.loaded.classes";
- public static final String JACC_CONTEXT_ID = "hibernate.jacc.ctx.id";
- public static final String JACC_PREFIX = "hibernate.jacc";
- public static final String JACC_ENABLED = "hibernate.jacc.enabled";
+ public static final String JACC_CONTEXT_ID = org.hibernate.cfg.AvailableSettings.JACC_CONTEXT_ID;
+ public static final String JACC_PREFIX = org.hibernate.cfg.AvailableSettings.JACC_PREFIX;
+ public static final String JACC_ENABLED = org.hibernate.cfg.AvailableSettings.JACC_ENABLED;
public static final String PERSISTENCE_UNIT_NAME = "hibernate.ejb.persistenceUnitName";
}
View
24 hibernate-entitymanager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
@@ -104,7 +104,8 @@
import org.hibernate.metamodel.source.annotations.JPADotNames;
import org.hibernate.metamodel.source.annotations.JandexHelper;
import org.hibernate.proxy.EntityNotFoundDelegate;
-import org.hibernate.secure.internal.JACCConfiguration;
+import org.hibernate.secure.spi.GrantedPermission;
+import org.hibernate.secure.spi.JaccService;
import org.hibernate.service.ConfigLoader;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor;
@@ -147,7 +148,7 @@
private final StandardServiceRegistryBuilder serviceRegistryBuilder;
private final Map configurationValues;
- private final List<JaccDefinition> jaccDefinitions = new ArrayList<JaccDefinition>();
+ private final List<GrantedPermission> grantedJaccPermissions = new ArrayList<GrantedPermission>();
private final List<CacheRegionDefinition> cacheRegionDefinitions = new ArrayList<CacheRegionDefinition>();
// todo : would much prefer this as a local variable...
private final List<JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping> cfgXmlNamedMappings = new ArrayList<JaxbHibernateConfiguration.JaxbSessionFactory.JaxbMapping>();
@@ -618,11 +619,9 @@ private void processHibernateConfigurationElement(
}
if ( configurationElement.getSecurity() != null ) {
- final String contextId = configurationElement.getSecurity().getContext();
for ( JaxbHibernateConfiguration.JaxbSecurity.JaxbGrant grant : configurationElement.getSecurity().getGrant() ) {
- jaccDefinitions.add(
- new JaccDefinition(
- contextId,
+ grantedJaccPermissions.add(
+ new GrantedPermission(
grant.getRole(),
grant.getEntityName(),
grant.getActions()
@@ -651,10 +650,7 @@ private void addJaccDefinition(String key, Object value) {
final int classStart = roleStart + role.length() + 1;
final String clazz = key.substring( classStart, key.length() );
- final JaccDefinition def = new JaccDefinition( jaccContextId, role, clazz, (String) value );
-
- jaccDefinitions.add( def );
-
+ grantedJaccPermissions.add( new GrantedPermission( role, clazz, (String) value ) );
}
catch ( IndexOutOfBoundsException e ) {
throw persistenceException( "Illegal usage of " + AvailableSettings.JACC_PREFIX + ": " + key );
@@ -1006,10 +1002,10 @@ public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry
}
}
- if ( jaccDefinitions != null ) {
- for ( JaccDefinition jaccDefinition : jaccDefinitions ) {
- JACCConfiguration jaccCfg = new JACCConfiguration( jaccDefinition.contextId );
- jaccCfg.addPermission( jaccDefinition.role, jaccDefinition.clazz, jaccDefinition.actions );
+ if ( grantedJaccPermissions != null ) {
+ final JaccService jaccService = serviceRegistry.getService( JaccService.class );
+ for ( GrantedPermission grantedPermission : grantedJaccPermissions ) {
+ jaccService.addPermission( grantedPermission );
}
}
View
43 hibernate-entitymanager/src/main/java/org/hibernate/jpa/event/spi/JpaIntegrator.java
@@ -30,7 +30,6 @@
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
-import org.hibernate.cfg.Environment;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CascadingActions;
@@ -65,11 +64,6 @@
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.source.MetadataImplementor;
-import org.hibernate.secure.internal.JACCPreDeleteEventListener;
-import org.hibernate.secure.internal.JACCPreInsertEventListener;
-import org.hibernate.secure.internal.JACCPreLoadEventListener;
-import org.hibernate.secure.internal.JACCPreUpdateEventListener;
-import org.hibernate.secure.internal.JACCSecurityListener;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
@@ -97,19 +91,6 @@ public Action getAction() {
}
};
- private static final DuplicationStrategy JACC_DUPLICATION_STRATEGY = new DuplicationStrategy() {
- @Override
- public boolean areMatch(Object listener, Object original) {
- return listener.getClass().equals( original.getClass() ) &&
- JACCSecurityListener.class.isInstance( original );
- }
-
- @Override
- public Action getAction() {
- return Action.KEEP_ORIGINAL;
- }
- };
-
@Override
@SuppressWarnings( {"unchecked"})
public void integrate(
@@ -137,10 +118,7 @@ public String toString() {
// then prepare listeners
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
- boolean isSecurityEnabled = configuration.getProperties().containsKey( AvailableSettings.JACC_ENABLED );
-
eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY );
- eventListenerRegistry.addDuplicationStrategy( JACC_DUPLICATION_STRATEGY );
// op listeners
eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE );
@@ -153,15 +131,6 @@ public String toString() {
eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() );
- // pre op listeners
- if ( isSecurityEnabled ) {
- final String jaccContextId = configuration.getProperty( Environment.JACC_CONTEXTID );
- eventListenerRegistry.prependListeners( EventType.PRE_DELETE, new JACCPreDeleteEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_INSERT, new JACCPreInsertEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_UPDATE, new JACCPreUpdateEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_LOAD, new JACCPreLoadEventListener(jaccContextId) );
- }
-
// post op listeners
eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() );
@@ -268,10 +237,7 @@ public String toString() {
// then prepare listeners
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
- boolean isSecurityEnabled = sessionFactory.getProperties().containsKey( AvailableSettings.JACC_ENABLED );
-
eventListenerRegistry.addDuplicationStrategy( JPA_DUPLICATION_STRATEGY );
- eventListenerRegistry.addDuplicationStrategy( JACC_DUPLICATION_STRATEGY );
// op listeners
eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, JpaAutoFlushEventListener.INSTANCE );
@@ -284,15 +250,6 @@ public String toString() {
eventListenerRegistry.setListeners( EventType.SAVE, new JpaSaveEventListener() );
eventListenerRegistry.setListeners( EventType.SAVE_UPDATE, new JpaSaveOrUpdateEventListener() );
- // pre op listeners
- if ( isSecurityEnabled ) {
- final String jaccContextId = sessionFactory.getProperties().getProperty( Environment.JACC_CONTEXTID );
- eventListenerRegistry.prependListeners( EventType.PRE_DELETE, new JACCPreDeleteEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_INSERT, new JACCPreInsertEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_UPDATE, new JACCPreUpdateEventListener(jaccContextId) );
- eventListenerRegistry.prependListeners( EventType.PRE_LOAD, new JACCPreLoadEventListener(jaccContextId) );
- }
-
// post op listeners
eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener() );
eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener() );
Please sign in to comment.
Something went wrong with that request. Please try again.