Describe the bug
I'm trying to use Spring Security in combination with ACLs. I use PostgreSQL as my database and have used the schema from the Spring Security docs.
create table acl_sid(
id bigserial not null primary key,
principal boolean not null,
sid varchar(100) not null,
constraint unique_uk_1 unique(sid,principal)
);
create table acl_class(
id bigserial not null primary key,
class varchar(100) not null,
constraint unique_uk_2 unique(class)
);
create table acl_object_identity(
id bigserial primary key,
object_id_class bigint not null,
object_id_identity varchar(36) not null,
parent_object bigint,
owner_sid bigint,
entries_inheriting boolean not null,
constraint unique_uk_3 unique(object_id_class,object_id_identity),
constraint foreign_fk_1 foreign key(parent_object)references acl_object_identity(id),
constraint foreign_fk_2 foreign key(object_id_class)references acl_class(id),
constraint foreign_fk_3 foreign key(owner_sid)references acl_sid(id)
);
create table acl_entry(
id bigserial primary key,
acl_object_identity bigint not null,
ace_order int not null,
sid bigint not null,
mask integer not null,
granting boolean not null,
audit_success boolean not null,
audit_failure boolean not null,
constraint unique_uk_4 unique(acl_object_identity,ace_order),
constraint foreign_fk_4 foreign key(acl_object_identity) references acl_object_identity(id),
constraint foreign_fk_5 foreign key(sid) references acl_sid(id)
);
I'm trying to create a new ACL.
var contact = new Contact();
contact.setName("John Doe");
contact.setId(1L);
var objectIdentity = new ObjectIdentityImpl(contact);
tt.execute(
status -> {
var acl = mutableAclService.createAcl(objectIdentity);
var sid = new PrincipalSid("john");
acl.insertAce(acl.getEntries().size(), BasePermission.READ, sid, true);
mutableAclService.updateAcl(acl);
return null;
});
At first I thought it works but then I enabled logging for Spring Security.
logging.level.org.springframework.security=TRACE
Afterwards I started seeing the following error message.
2024-12-07T08:54:52.074+01:00 DEBUG 53186 --- [demo] [ main] o.s.security.acls.jdbc.AclClassIdUtils : Unable to obtain the class id type
org.postgresql.util.PSQLException: The column name class_id_type was not found in this ResultSet.
at org.postgresql.jdbc.PgResultSet.findColumn(PgResultSet.java:3094) ~[postgresql-42.7.4.jar:42.7.4]
at org.postgresql.jdbc.PgResultSet.getString(PgResultSet.java:2930) ~[postgresql-42.7.4.jar:42.7.4]
at com.zaxxer.hikari.pool.HikariProxyResultSet.getString(HikariProxyResultSet.java) ~[HikariCP-5.1.0.jar:na]
at org.springframework.security.acls.jdbc.AclClassIdUtils.classIdTypeFrom(AclClassIdUtils.java:90) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.AclClassIdUtils.hasValidClassIdType(AclClassIdUtils.java:81) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.AclClassIdUtils.identifierFrom(AclClassIdUtils.java:71) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.convertCurrentResultIntoObject(BasicLookupStrategy.java:580) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:532) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:504) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:733) ~[spring-jdbc-6.2.0.jar:6.2.0]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:658) ~[spring-jdbc-6.2.0.jar:6.2.0]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:723) ~[spring-jdbc-6.2.0.jar:6.2.0]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:754) ~[spring-jdbc-6.2.0.jar:6.2.0]
at org.springframework.security.acls.jdbc.BasicLookupStrategy.lookupObjectIdentities(BasicLookupStrategy.java:335) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.BasicLookupStrategy.readAclsById(BasicLookupStrategy.java:300) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.JdbcAclService.readAclsById(JdbcAclService.java:136) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:117) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:125) ~[spring-security-acl-6.4.1.jar:6.4.1]
at org.springframework.security.acls.jdbc.JdbcMutableAclService.updateAcl(JdbcMutableAclService.java:357) ~[spring-security-acl-6.4.1.jar:6.4.1]
at com.example.demo.DataSourcePopulator.lambda$afterPropertiesSet$0(DataSourcePopulator.java:106) ~[main/:na]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-6.2.0.jar:6.2.0]
at com.example.demo.DataSourcePopulator.afterPropertiesSet(DataSourcePopulator.java:101) ~[main/:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1849) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:288) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:334) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1122) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1093) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1030) ~[spring-beans-6.2.0.jar:6.2.0]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987) ~[spring-context-6.2.0.jar:6.2.0]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) ~[spring-context-6.2.0.jar:6.2.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-3.4.0.jar:3.4.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.4.0.jar:3.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-3.4.0.jar:3.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1361) ~[spring-boot-3.4.0.jar:3.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1350) ~[spring-boot-3.4.0.jar:3.4.0]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[main/:na]
I was confused because I use a Long identifier for my Contact entity and tried everything on my side but in the end never achieved to get rid of the error message.
To Reproduce
I spent quite some time to find a solution and I believe this is related to the following GitHub issues and Stack Overflow questions - https://stackoverflow.com/questions/41706241/how-to-use-spring-security-acl-when-my-domain-identifiers-are-of-string-type - https://github.com/spring-projects/spring-security/issues/7598 - https://github.com/spring-projects/spring-security/issues/7978 - https://github.com/spring-projects/spring-security/issues/7621
Expected behavior
We should not see any error messages in the logs.
Sample
Here is a minimal, reproducible sample https://github.com/zemirco/spring-security-acl.
Thank you! You're awesome and we love Spring Boot 🥳