HHH-14844 - Drop JACC integration
This commit is contained in:
parent
986d65a288
commit
8a8a92ca5e
|
@ -1,296 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.userguide.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.PostLoad;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
import jakarta.persistence.Transient;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
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.event.spi.LoadEvent;
|
||||
import org.hibernate.event.spi.LoadEventListener;
|
||||
import org.hibernate.integrator.spi.ServiceContributingIntegrator;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
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.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.IntegrationException;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.secure.spi.JaccService;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class ListenerTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Person.class,
|
||||
Customer.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test(expected = SecurityException.class)
|
||||
public void testLoadListener() {
|
||||
Serializable customerId = 1L;
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::events-interceptors-load-listener-example[]
|
||||
EntityManagerFactory entityManagerFactory = entityManagerFactory();
|
||||
SessionFactoryImplementor sessionFactory = entityManagerFactory.unwrap( SessionFactoryImplementor.class );
|
||||
sessionFactory
|
||||
.getServiceRegistry()
|
||||
.getService( EventListenerRegistry.class )
|
||||
.prependListeners( EventType.LOAD, new SecuredLoadEntityListener() );
|
||||
|
||||
Customer customer = entityManager.find( Customer.class, customerId );
|
||||
//end::events-interceptors-load-listener-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPACallback() {
|
||||
Long personId = 1L;
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Person person = new Person();
|
||||
person.id = personId;
|
||||
person.name = "John Doe";
|
||||
person.dateOfBirth = Timestamp.valueOf(LocalDateTime.of( 2000, 1, 1, 0, 0, 0 ));
|
||||
entityManager.persist( person );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Person person = entityManager.find( Person.class, personId );
|
||||
assertTrue(person.age > 0);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Customer")
|
||||
public static class Customer {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Customer() {
|
||||
}
|
||||
|
||||
public Customer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
//tag::events-jpa-callbacks-example[]
|
||||
@Entity(name = "Person")
|
||||
@EntityListeners( LastUpdateListener.class )
|
||||
public static class Person {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Date dateOfBirth;
|
||||
|
||||
@Transient
|
||||
private long age;
|
||||
|
||||
private Date lastUpdate;
|
||||
|
||||
public void setLastUpdate(Date lastUpdate) {
|
||||
this.lastUpdate = lastUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transient property at load time based on a calculation.
|
||||
* Note that a native Hibernate formula mapping is better for this purpose.
|
||||
*/
|
||||
@PostLoad
|
||||
public void calculateAge() {
|
||||
age = ChronoUnit.YEARS.between( LocalDateTime.ofInstant(
|
||||
Instant.ofEpochMilli( dateOfBirth.getTime()), ZoneOffset.UTC),
|
||||
LocalDateTime.now()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LastUpdateListener {
|
||||
|
||||
@PreUpdate
|
||||
@PrePersist
|
||||
public void setLastUpdate( Person p ) {
|
||||
p.setLastUpdate( new Date() );
|
||||
}
|
||||
}
|
||||
//end::events-jpa-callbacks-example[]
|
||||
|
||||
//tag::events-interceptors-example[]
|
||||
public static class SecuredLoadEntityListener implements LoadEventListener {
|
||||
// this is the single method defined by the LoadEventListener interface
|
||||
public void onLoad(LoadEvent event, LoadType loadType)
|
||||
throws HibernateException {
|
||||
if ( !Principal.isAuthorized( event.getEntityClassName(), event.getEntityId() ) ) {
|
||||
throw new SecurityException( "Unauthorized access" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//end::events-Principal-example[]
|
||||
public static class Principal {
|
||||
public static boolean isAuthorized(String clazz, Object id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//tag::events-declarative-security-jacc-example[]
|
||||
public static 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(
|
||||
Metadata metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
doIntegration(
|
||||
serviceRegistry
|
||||
.getService( ConfigurationService.class ).getSettings(),
|
||||
// pass no permissions here, because atm actually injecting the
|
||||
// permissions into the JaccService is handled on SessionFactoryImpl via
|
||||
// the org.hibernate.boot.cfgxml.spi.CfgXmlAccessService
|
||||
null,
|
||||
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 disintegrate(SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
//end::events-declarative-security-jacc-example[]
|
||||
}
|
|
@ -24,8 +24,6 @@ import org.hibernate.boot.jaxb.cfg.spi.JaxbCfgEventListenerType;
|
|||
import org.hibernate.boot.jaxb.cfg.spi.JaxbCfgHibernateConfiguration;
|
||||
import org.hibernate.boot.jaxb.cfg.spi.JaxbCfgMappingReferenceType;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -42,7 +40,6 @@ public class LoadedConfig {
|
|||
|
||||
private final Map configurationValues = new ConcurrentHashMap( 16, 0.75f, 1 );
|
||||
|
||||
private Map<String,JaccPermissionDeclarations> jaccPermissionsByContextId;
|
||||
private List<CacheRegionDefinition> cacheRegionDefinitions;
|
||||
private List<MappingReference> mappingReferences;
|
||||
private Map<EventType,Set<String>> eventListenerMap;
|
||||
|
@ -59,14 +56,6 @@ public class LoadedConfig {
|
|||
return configurationValues;
|
||||
}
|
||||
|
||||
public Map<String, JaccPermissionDeclarations> getJaccPermissionsByContextId() {
|
||||
return jaccPermissionsByContextId;
|
||||
}
|
||||
|
||||
public JaccPermissionDeclarations getJaccPermissions(String jaccContextId) {
|
||||
return jaccPermissionsByContextId.get( jaccContextId );
|
||||
}
|
||||
|
||||
public List<CacheRegionDefinition> getCacheRegionDefinitions() {
|
||||
return cacheRegionDefinitions == null ? Collections.emptyList() : cacheRegionDefinitions;
|
||||
}
|
||||
|
@ -102,22 +91,6 @@ public class LoadedConfig {
|
|||
cfg.addCacheRegionDefinition( parseCacheRegionDefinition( cacheDeclaration ) );
|
||||
}
|
||||
|
||||
if ( jaxbCfg.getSecurity() != null ) {
|
||||
for ( JaxbCfgHibernateConfiguration.JaxbCfgSecurity.JaxbCfgGrant grant : jaxbCfg.getSecurity().getGrant() ) {
|
||||
final JaccPermissionDeclarations jaccPermissions = cfg.getOrCreateJaccPermissions(
|
||||
jaxbCfg.getSecurity()
|
||||
.getContext()
|
||||
);
|
||||
jaccPermissions.addPermissionDeclaration(
|
||||
new GrantedPermission(
|
||||
grant.getRole(),
|
||||
grant.getEntityName(),
|
||||
grant.getActions()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !jaxbCfg.getSessionFactory().getListener().isEmpty() ) {
|
||||
for ( JaxbCfgEventListenerType listener : jaxbCfg.getSessionFactory().getListener() ) {
|
||||
final EventType eventType = EventType.resolveEventTypeByName( listener.getType().value() );
|
||||
|
@ -216,20 +189,6 @@ public class LoadedConfig {
|
|||
listenerClasses.add( listenerClass );
|
||||
}
|
||||
|
||||
public JaccPermissionDeclarations getOrCreateJaccPermissions(String contextId) {
|
||||
if ( jaccPermissionsByContextId == null ) {
|
||||
jaccPermissionsByContextId = new HashMap<>();
|
||||
}
|
||||
|
||||
JaccPermissionDeclarations jaccPermission = jaccPermissionsByContextId.get( contextId );
|
||||
if ( jaccPermission == null ) {
|
||||
jaccPermission = new JaccPermissionDeclarations( contextId );
|
||||
}
|
||||
jaccPermissionsByContextId.put( contextId, jaccPermission );
|
||||
|
||||
return jaccPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge information from loaded a {@code cfg.xml} represented by the incoming parameter
|
||||
* into this LoadedConfig representation
|
||||
|
@ -254,7 +213,6 @@ public class LoadedConfig {
|
|||
addConfigurationValues( incoming.getConfigurationValues() );
|
||||
addMappingReferences( incoming.getMappingReferences() );
|
||||
addCacheRegionDefinitions( incoming.getCacheRegionDefinitions() );
|
||||
addJaccPermissions( incoming.getJaccPermissionsByContextId() );
|
||||
addEventListeners( incoming.getEventListenerMap() );
|
||||
}
|
||||
|
||||
|
@ -289,26 +247,6 @@ public class LoadedConfig {
|
|||
this.cacheRegionDefinitions.addAll( cacheRegionDefinitions );
|
||||
}
|
||||
|
||||
private void addJaccPermissions(Map<String, JaccPermissionDeclarations> jaccPermissionsByContextId) {
|
||||
if ( jaccPermissionsByContextId == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.jaccPermissionsByContextId == null ) {
|
||||
this.jaccPermissionsByContextId = new HashMap<>();
|
||||
}
|
||||
|
||||
for ( Map.Entry<String, JaccPermissionDeclarations> incomingEntry : jaccPermissionsByContextId.entrySet() ) {
|
||||
JaccPermissionDeclarations permissions = jaccPermissionsByContextId.get( incomingEntry.getKey() );
|
||||
if ( permissions == null ) {
|
||||
permissions = new JaccPermissionDeclarations( incomingEntry.getKey() );
|
||||
this.jaccPermissionsByContextId.put( incomingEntry.getKey(), permissions );
|
||||
}
|
||||
|
||||
permissions.addPermissionDeclarations( incomingEntry.getValue().getPermissionDeclarations() );
|
||||
}
|
||||
}
|
||||
|
||||
private void addEventListeners(Map<EventType, Set<String>> eventListenerMap) {
|
||||
if ( eventListenerMap == null ) {
|
||||
return;
|
||||
|
|
|
@ -1997,10 +1997,6 @@ public interface AvailableSettings {
|
|||
*/
|
||||
String JTA_TRACK_BY_THREAD = "hibernate.jta.track_by_thread";
|
||||
|
||||
String JACC_CONTEXT_ID = "hibernate.jacc_context_id";
|
||||
String JACC_PREFIX = "hibernate.jacc";
|
||||
String JACC_ENABLED = "hibernate.jacc.enabled";
|
||||
|
||||
/**
|
||||
* If enabled, allows schema update and validation to support synonyms. Due
|
||||
* to the possibility that this would return duplicate tables (especially in
|
||||
|
|
|
@ -17,7 +17,6 @@ import jakarta.validation.Validation;
|
|||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -29,6 +28,7 @@ import org.hibernate.event.spi.PreUpdateEvent;
|
|||
import org.hibernate.event.spi.PreUpdateEventListener;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.RepresentationMode;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -78,31 +78,40 @@ public class BeanValidationEventListener
|
|||
|
||||
public boolean onPreInsert(PreInsertEvent event) {
|
||||
validate(
|
||||
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),
|
||||
event.getSession().getFactory(), GroupsPerOperation.Operation.INSERT
|
||||
event.getEntity(),
|
||||
event.getPersister().getRepresentationStrategy().getMode(),
|
||||
event.getPersister(),
|
||||
event.getSession().getFactory(),
|
||||
GroupsPerOperation.Operation.INSERT
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onPreUpdate(PreUpdateEvent event) {
|
||||
validate(
|
||||
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),
|
||||
event.getSession().getFactory(), GroupsPerOperation.Operation.UPDATE
|
||||
event.getEntity(),
|
||||
event.getPersister().getRepresentationStrategy().getMode(),
|
||||
event.getPersister(),
|
||||
event.getSession().getFactory(),
|
||||
GroupsPerOperation.Operation.UPDATE
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onPreDelete(PreDeleteEvent event) {
|
||||
validate(
|
||||
event.getEntity(), event.getPersister().getEntityMode(), event.getPersister(),
|
||||
event.getSession().getFactory(), GroupsPerOperation.Operation.DELETE
|
||||
event.getEntity(),
|
||||
event.getPersister().getRepresentationStrategy().getMode(),
|
||||
event.getPersister(),
|
||||
event.getSession().getFactory(),
|
||||
GroupsPerOperation.Operation.DELETE
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
private <T> void validate(T object, EntityMode mode, EntityPersister persister,
|
||||
SessionFactoryImplementor sessionFactory, GroupsPerOperation.Operation operation) {
|
||||
if ( object == null || mode != EntityMode.POJO ) {
|
||||
private <T> void validate(T object, RepresentationMode mode, EntityPersister persister,
|
||||
SessionFactoryImplementor sessionFactory, GroupsPerOperation.Operation operation) {
|
||||
if ( object == null || mode != RepresentationMode.POJO ) {
|
||||
return;
|
||||
}
|
||||
TraversableResolver tr = new HibernateTraversableResolver(
|
||||
|
|
|
@ -7,16 +7,13 @@
|
|||
package org.hibernate.event.spi;
|
||||
|
||||
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
|
||||
implements PermissionCheckEntityInformation {
|
||||
public abstract class AbstractPreDatabaseOperationEvent extends AbstractEvent {
|
||||
|
||||
private final Object entity;
|
||||
private final Object id;
|
||||
|
@ -46,7 +43,6 @@ public abstract class AbstractPreDatabaseOperationEvent
|
|||
*
|
||||
* @return The entity.
|
||||
*/
|
||||
@Override
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
@ -61,7 +57,7 @@ public abstract class AbstractPreDatabaseOperationEvent
|
|||
}
|
||||
|
||||
/**
|
||||
* The persister for the {@link #getEntity entity}.
|
||||
* The persister for the entity.
|
||||
*
|
||||
* @return The entity persister.
|
||||
*/
|
||||
|
@ -85,14 +81,4 @@ public abstract class AbstractPreDatabaseOperationEvent
|
|||
public EventSource getSource() {
|
||||
return getSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntityName() {
|
||||
return persister.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.event.spi;
|
||||
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.secure.spi.PermissionCheckEntityInformation;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,9 +16,7 @@ import org.hibernate.secure.spi.PermissionCheckEntityInformation;
|
|||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PreDeleteEvent
|
||||
extends AbstractPreDatabaseOperationEvent
|
||||
implements PermissionCheckEntityInformation {
|
||||
public class PreDeleteEvent extends AbstractPreDatabaseOperationEvent {
|
||||
|
||||
private Object[] deletedState;
|
||||
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
package org.hibernate.event.spi;
|
||||
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.secure.spi.PermissionCheckEntityInformation;
|
||||
|
||||
/**
|
||||
* Called before injecting property values into a newly loaded entity instance.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class PreLoadEvent extends AbstractEvent implements PermissionCheckEntityInformation {
|
||||
public class PreLoadEvent extends AbstractEvent {
|
||||
private Object entity;
|
||||
private Object[] state;
|
||||
private Object id;
|
||||
|
@ -31,7 +30,6 @@ public class PreLoadEvent extends AbstractEvent implements PermissionCheckEntity
|
|||
persister = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
@ -67,14 +65,4 @@ public class PreLoadEvent extends AbstractEvent implements PermissionCheckEntity
|
|||
this.state = state;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntityName() {
|
||||
return persister.getEntityName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.hibernate.cache.internal.CollectionCacheInvalidator;
|
|||
import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.secure.spi.JaccIntegrator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -29,7 +28,6 @@ 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() );
|
||||
addIntegrator( new CollectionCacheInvalidator() );
|
||||
|
||||
// register provided integrators
|
||||
|
|
|
@ -47,7 +47,6 @@ import org.hibernate.SessionFactoryObserver;
|
|||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.StatelessSessionBuilder;
|
||||
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
|
||||
import org.hibernate.boot.cfgxml.spi.LoadedConfig;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
|
@ -80,16 +79,12 @@ import org.hibernate.engine.spi.SessionBuilderImplementor;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionOwner;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||
import org.hibernate.event.spi.EventEngine;
|
||||
import org.hibernate.event.spi.EventType;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.integrator.spi.IntegratorService;
|
||||
import org.hibernate.internal.util.config.ConfigurationException;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.jpa.internal.AfterCompletionActionLegacyJpaImpl;
|
||||
import org.hibernate.jpa.internal.ExceptionMapperLegacyJpaImpl;
|
||||
|
@ -124,9 +119,6 @@ import org.hibernate.resource.transaction.backend.jta.internal.synchronization.A
|
|||
import org.hibernate.resource.transaction.backend.jta.internal.synchronization.ExceptionMapper;
|
||||
import org.hibernate.resource.transaction.backend.jta.internal.synchronization.ManagedFlushChecker;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.secure.spi.JaccService;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
|
||||
|
@ -226,7 +218,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
if ( sfName == null ) {
|
||||
sfName = cfgXmlAccessService.getAggregatedConfig().getSessionFactoryName();
|
||||
}
|
||||
applyCfgXmlValues( cfgXmlAccessService.getAggregatedConfig(), serviceRegistry );
|
||||
}
|
||||
|
||||
this.name = sfName;
|
||||
|
@ -494,34 +485,6 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyCfgXmlValues(LoadedConfig aggregatedConfig, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
final JaccService jaccService = serviceRegistry.getService( JaccService.class );
|
||||
if ( jaccService.getContextId() != null ) {
|
||||
final JaccPermissionDeclarations permissions = aggregatedConfig.getJaccPermissions( jaccService.getContextId() );
|
||||
if ( permissions != null ) {
|
||||
for ( GrantedPermission grantedPermission : permissions.getPermissionDeclarations() ) {
|
||||
jaccService.addPermission( grantedPermission );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( aggregatedConfig.getEventListenerMap() != null ) {
|
||||
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
|
||||
final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
for ( Map.Entry<EventType, Set<String>> entry : aggregatedConfig.getEventListenerMap().entrySet() ) {
|
||||
final EventListenerGroup group = eventListenerRegistry.getEventListenerGroup( entry.getKey() );
|
||||
for ( String listenerClassName : entry.getValue() ) {
|
||||
try {
|
||||
group.appendListener( cls.classForName( listenerClassName ).newInstance() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ConfigurationException( "Unable to instantiate event listener class : " + listenerClassName, e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JdbcConnectionAccess buildLocalConnectionAccess() {
|
||||
if ( settings.getMultiTenancyStrategy().requiresMultiTenantConnectionProvider() ) {
|
||||
final MultiTenantConnectionProvider mTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class );
|
||||
|
|
|
@ -73,8 +73,6 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
|
|||
import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl;
|
||||
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.spi.ServiceBinding;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
@ -98,9 +96,6 @@ import static org.hibernate.cfg.AvailableSettings.CLASS_CACHE_PREFIX;
|
|||
import static org.hibernate.cfg.AvailableSettings.COLLECTION_CACHE_PREFIX;
|
||||
import static org.hibernate.cfg.AvailableSettings.DATASOURCE;
|
||||
import static org.hibernate.cfg.AvailableSettings.DRIVER;
|
||||
import static org.hibernate.cfg.AvailableSettings.JACC_CONTEXT_ID;
|
||||
import static org.hibernate.cfg.AvailableSettings.JACC_ENABLED;
|
||||
import static org.hibernate.cfg.AvailableSettings.JACC_PREFIX;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_JDBC_DRIVER;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_JDBC_PASSWORD;
|
||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_JDBC_URL;
|
||||
|
@ -550,8 +545,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
|
||||
normalizeSettings( persistenceUnit, integrationSettings, mergedSettings );
|
||||
|
||||
final String jaccContextId = (String) mergedSettings.configurationValues.get( JACC_CONTEXT_ID );
|
||||
|
||||
// here we are going to iterate the merged config settings looking for:
|
||||
// 1) additional JACC permissions
|
||||
// 2) additional cache region declarations
|
||||
|
@ -570,22 +563,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
final String keyString = (String) entry.getKey();
|
||||
final String valueString = (String) entry.getValue();
|
||||
|
||||
if ( keyString.startsWith( JACC_PREFIX ) ) {
|
||||
if( !JACC_CONTEXT_ID.equals( keyString ) && !JACC_ENABLED.equals( keyString )) {
|
||||
if ( jaccContextId == null ) {
|
||||
LOG.debugf(
|
||||
"Found JACC permission grant [%s] in properties, but no JACC context id was specified; ignoring",
|
||||
keyString
|
||||
);
|
||||
}
|
||||
else {
|
||||
mergedSettings.getJaccPermissions( jaccContextId ).addPermissionDeclaration(
|
||||
parseJaccConfigEntry( keyString, valueString )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( keyString.startsWith( CLASS_CACHE_PREFIX ) ) {
|
||||
if ( keyString.startsWith( CLASS_CACHE_PREFIX ) ) {
|
||||
mergedSettings.addCacheRegionDefinition(
|
||||
parseCacheRegionDefinitionEntry(
|
||||
keyString.substring( CLASS_CACHE_PREFIX.length() + 1 ),
|
||||
|
@ -1204,19 +1182,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
ssrBuilder.getAggregatedCfgXml().merge( loadedConfig );
|
||||
}
|
||||
|
||||
private GrantedPermission parseJaccConfigEntry(String keyString, String valueString) {
|
||||
try {
|
||||
final int roleStart = JACC_PREFIX.length() + 1;
|
||||
final String role = keyString.substring( roleStart, keyString.indexOf( '.', roleStart ) );
|
||||
final int classStart = roleStart + role.length() + 1;
|
||||
final String clazz = keyString.substring( classStart );
|
||||
return new GrantedPermission( role, clazz, valueString );
|
||||
}
|
||||
catch ( IndexOutOfBoundsException e ) {
|
||||
throw persistenceException( "Illegal usage of " + JACC_PREFIX + ": " + keyString );
|
||||
}
|
||||
}
|
||||
|
||||
private CacheRegionDefinition parseCacheRegionDefinitionEntry(String role, String value, CacheRegionDefinition.CacheRegionType cacheType) {
|
||||
final StringTokenizer params = new StringTokenizer( value, ";, " );
|
||||
if ( !params.hasMoreTokens() ) {
|
||||
|
@ -1591,7 +1556,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
public static class MergedSettings {
|
||||
private final Map configurationValues = new ConcurrentHashMap( 16, 0.75f, 1 );
|
||||
|
||||
private Map<String, JaccPermissionDeclarations> jaccPermissionsByContextId;
|
||||
private List<CacheRegionDefinition> cacheRegionDefinitions;
|
||||
|
||||
/**
|
||||
|
@ -1630,19 +1594,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
return configurationValues;
|
||||
}
|
||||
|
||||
private JaccPermissionDeclarations getJaccPermissions(String jaccContextId) {
|
||||
if ( jaccPermissionsByContextId == null ) {
|
||||
jaccPermissionsByContextId = new HashMap<>();
|
||||
}
|
||||
|
||||
JaccPermissionDeclarations jaccPermissions = jaccPermissionsByContextId.get( jaccContextId );
|
||||
if ( jaccPermissions == null ) {
|
||||
jaccPermissions = new JaccPermissionDeclarations( jaccContextId );
|
||||
jaccPermissionsByContextId.put( jaccContextId, jaccPermissions );
|
||||
}
|
||||
return jaccPermissions;
|
||||
}
|
||||
|
||||
private void addCacheRegionDefinition(CacheRegionDefinition cacheRegionDefinition) {
|
||||
if ( this.cacheRegionDefinitions == null ) {
|
||||
this.cacheRegionDefinitions = new ArrayList<>();
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccService;
|
||||
import org.hibernate.secure.spi.PermissibleAction;
|
||||
import org.hibernate.secure.spi.PermissionCheckEntityInformation;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DisabledJaccServiceImpl implements JaccService {
|
||||
private static final Logger log = Logger.getLogger( DisabledJaccServiceImpl.class );
|
||||
|
||||
@Override
|
||||
public String getContextId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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" );
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
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 extends AbstractJaccSecurableEventListener implements PreDeleteEventListener {
|
||||
public JaccPreDeleteEventListener() {
|
||||
}
|
||||
|
||||
public boolean onPreDelete(PreDeleteEvent event) {
|
||||
performSecurityCheck( event, PermissibleAction.DELETE );
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
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 extends AbstractJaccSecurableEventListener implements PreInsertEventListener {
|
||||
public JaccPreInsertEventListener() {
|
||||
}
|
||||
|
||||
public boolean onPreInsert(PreInsertEvent event) {
|
||||
performSecurityCheck( event, PermissibleAction.INSERT );
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
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 extends AbstractJaccSecurableEventListener implements PreLoadEventListener {
|
||||
public JaccPreLoadEventListener() {
|
||||
}
|
||||
|
||||
public void onPreLoad(PreLoadEvent event) {
|
||||
performSecurityCheck( event.getSession(), event, PermissibleAction.READ );
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
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 extends AbstractJaccSecurableEventListener implements PreUpdateEventListener {
|
||||
public JaccPreUpdateEventListener() {
|
||||
}
|
||||
|
||||
public boolean onPreUpdate(PreUpdateEvent event) {
|
||||
performSecurityCheck( event, PermissibleAction.UPDATE );
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.internal;
|
||||
|
||||
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 javax.security.auth.Subject;
|
||||
import jakarta.security.jacc.EJBMethodPermission;
|
||||
import jakarta.security.jacc.PolicyConfiguration;
|
||||
import jakarta.security.jacc.PolicyConfigurationFactory;
|
||||
import jakarta.security.jacc.PolicyContext;
|
||||
import jakarta.security.jacc.PolicyContextException;
|
||||
|
||||
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;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @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 String getContextId() {
|
||||
return contextId;
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure;
|
||||
|
||||
/**
|
||||
* Package defining support for declarative security of CRUD operations via JACC.
|
||||
*/
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
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.ServiceContributingIntegrator;
|
||||
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;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* 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(
|
||||
Metadata metadata,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
doIntegration(
|
||||
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
|
||||
// pass no permissions here, because atm actually injecting the
|
||||
// permissions into the JaccService is handled on SessionFactoryImpl via
|
||||
// the org.hibernate.boot.cfgxml.spi.CfgXmlAccessService
|
||||
null,
|
||||
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 disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
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 String getContextId() {
|
||||
return contextId;
|
||||
}
|
||||
|
||||
public void addPermissionDeclaration(GrantedPermission permissionDeclaration) {
|
||||
if ( permissionDeclarations == null ) {
|
||||
permissionDeclarations = new ArrayList<>();
|
||||
}
|
||||
permissionDeclarations.add( permissionDeclaration );
|
||||
}
|
||||
|
||||
public void addPermissionDeclarations(Collection<GrantedPermission> permissionDeclarations) {
|
||||
if ( this.permissionDeclarations == null ) {
|
||||
this.permissionDeclarations = new ArrayList<>();
|
||||
}
|
||||
this.permissionDeclarations.addAll( permissionDeclarations );
|
||||
}
|
||||
|
||||
public Collection<GrantedPermission> getPermissionDeclarations() {
|
||||
return permissionDeclarations;
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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 {
|
||||
/**
|
||||
* Obtain the JACC context-id in effect for this service. {@code null} indicates no
|
||||
* context is in effect (service is disabled).
|
||||
*
|
||||
* @return The effective JACC context-id
|
||||
*/
|
||||
public String getContextId();
|
||||
|
||||
public void addPermission(GrantedPermission permissionDeclaration);
|
||||
public void checkPermission(PermissionCheckEntityInformation entityInformation, PermissibleAction action);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.secure.spi;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface PermissionCheckEntityInformation {
|
||||
public Object getEntity();
|
||||
public String getEntityName();
|
||||
public Object getIdentifier();
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.secure;
|
||||
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permission;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.Policy;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.Provider;
|
||||
import java.util.Collections;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import javax.security.auth.Subject;
|
||||
import jakarta.security.jacc.PolicyContext;
|
||||
import jakarta.security.jacc.PolicyContextException;
|
||||
import jakarta.security.jacc.PolicyContextHandler;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@Jpa(annotatedClasses = {
|
||||
JaccIntegratorTest.Person.class
|
||||
}, properties = {
|
||||
@Setting( name = AvailableSettings.JACC_ENABLED, value = "true"),
|
||||
@Setting( name = AvailableSettings.JACC_CONTEXT_ID, value = "JACC_CONTEXT_ID"),
|
||||
@Setting( name = "hibernate.jacc.allowed.org.hibernate.secure.Customer", value = "insert")
|
||||
})
|
||||
@TestForIssue( jiraKey = "HHH-11805" )
|
||||
public class JaccIntegratorTest {
|
||||
|
||||
@BeforeEach
|
||||
protected void afterEntityManagerFactoryBuilt(EntityManagerFactoryScope scope) {
|
||||
scope.getEntityManagerFactory();
|
||||
PolicyContextHandler policyContextHandler = new PolicyContextHandler() {
|
||||
@Override
|
||||
public Object getContext(String key, Object data) throws PolicyContextException {
|
||||
Subject subject = new Subject( true, Collections.singleton(new java.security.Principal() {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "org.hibernate.secure.JaccIntegratorTest$Person";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean implies(Subject subject) {
|
||||
return true;
|
||||
}
|
||||
}), Collections.emptySet(), Collections.emptySet());
|
||||
return subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getKeys() throws PolicyContextException {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String key) throws PolicyContextException {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
try {
|
||||
PolicyContext.registerHandler( "javax.security.auth.Subject.container", policyContextHandler, true);
|
||||
}
|
||||
catch (PolicyContextException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPolicy(boolean allow) {
|
||||
Policy.setPolicy( new Policy() {
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
return super.getProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return super.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parameters getParameters() {
|
||||
return super.getParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCollection getPermissions(CodeSource codesource) {
|
||||
return super.getPermissions( codesource );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionCollection getPermissions(ProtectionDomain domain) {
|
||||
return super.getPermissions( domain );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean implies(ProtectionDomain domain, Permission permission) {
|
||||
return allow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
super.refresh();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllow(EntityManagerFactoryScope scope) {
|
||||
setPolicy( true );
|
||||
|
||||
scope.inTransaction( entityManager -> {
|
||||
Person person = new Person();
|
||||
person.id = 1L;
|
||||
person.name = "John Doe";
|
||||
|
||||
entityManager.persist( person );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallow(EntityManagerFactoryScope scope) {
|
||||
setPolicy( false );
|
||||
|
||||
try {
|
||||
scope.inTransaction( entityManager -> {
|
||||
Person person = new Person();
|
||||
person.id = 1L;
|
||||
person.name = "John Doe";
|
||||
|
||||
entityManager.persist( person );
|
||||
} );
|
||||
|
||||
fail("Should have thrown SecurityException");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertTrue( e.getCause() instanceof SecurityException );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Person")
|
||||
public static class Person {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
}
|
|
@ -57,3 +57,8 @@ Multiple component mappings for the same java class with different property mapp
|
|||
* Functions
|
||||
* Multi-table bulk manipulation HQL/Criteria query handling
|
||||
|
||||
|
||||
=== Removal
|
||||
|
||||
* JMX integration
|
||||
* JACC integration
|
||||
|
|
Loading…
Reference in New Issue