HHH-7462 - Make JACC service

This commit is contained in:
Steve Ebersole 2013-03-24 12:09:52 -05:00
parent e4c1db1e8f
commit d184cb3eb4
29 changed files with 865 additions and 479 deletions

View File

@ -417,11 +417,6 @@ public interface AvailableSettings {
*/
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 @@ public interface AvailableSettings {
* 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 File

@ -134,7 +134,8 @@ import org.hibernate.mapping.Table;
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,23 +2199,42 @@ public class Configuration implements Serializable {
}
}
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 );
Iterator grantElements = secNode.elementIterator();
while ( grantElements.hasNext() ) {
Element grantElement = (Element) grantElements.next();
String elementName = grantElement.getName();
if ( "grant".equals( elementName ) ) {
jcfg.addPermission(
grantElement.attributeValue( "role" ),
grantElement.attributeValue( "entity-name" ),
grantElement.attributeValue( "actions" )
);
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() ) {
final Element grantElement = (Element) grantElements.next();
final String elementName = grantElement.getName();
if ( "grant".equals( elementName ) ) {
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 {

View File

@ -26,13 +26,17 @@ package org.hibernate.event.spi;
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 abstract class AbstractPreDatabaseOperationEvent extends AbstractEvent {
*
* @return The entity.
*/
@Override
public Object getEntity() {
return entity;
}
@ -97,4 +102,14 @@ public abstract class AbstractPreDatabaseOperationEvent extends AbstractEvent {
public EventSource getSource() {
return getSession();
}
@Override
public String getEntityName() {
return persister.getEntityName();
}
@Override
public Serializable getIdentifier() {
return id;
}
}

View File

@ -26,6 +26,8 @@ package org.hibernate.event.spi;
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 @@ import org.hibernate.persister.entity.EntityPersister;
* @author Gavin King
* @author Steve Ebersole
*/
public class PreDeleteEvent extends AbstractPreDatabaseOperationEvent {
public class PreDeleteEvent
extends AbstractPreDatabaseOperationEvent
implements PermissionCheckEntityInformation{
private Object[] deletedState;
/**

View File

@ -26,14 +26,14 @@ package org.hibernate.event.spi;
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 class PreLoadEvent extends AbstractEvent {
super(session);
}
@Override
public Object getEntity() {
return entity;
}
@ -78,5 +79,14 @@ public class PreLoadEvent extends AbstractEvent {
this.state = state;
return this;
}
@Override
public String getEntityName() {
return persister.getEntityName();
}
@Override
public Serializable getIdentifier() {
return id;
}
}

View File

@ -31,6 +31,7 @@ import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
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 class IntegratorServiceImpl implements IntegratorService {
// 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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -0,0 +1,5 @@
package org.hibernate.secure;
/**
* Package defining support for declarative security of CRUD operations via JACC.
*/

View File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -509,9 +509,9 @@ public interface AvailableSettings {
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 File

@ -104,7 +104,8 @@ import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
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 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
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 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
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 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
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 class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
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 File

@ -30,7 +30,6 @@ import java.util.Map;
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.jpa.event.internal.jpa.StandardListenerFactory;
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 class JpaIntegrator implements Integrator {
}
};
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 class JpaIntegrator implements Integrator {
// 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 class JpaIntegrator implements Integrator {
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 class JpaIntegrator implements Integrator {
// 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 class JpaIntegrator implements Integrator {
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() );