spring-projects / spring-projects/spring-security

ACL: acl_class class vs class_id_type for BasicLookupStrategy conflict

Open
#7,598 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: acl status: ideal-for-contribution type: enhancement
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Summary

Hi! I'm trying to use ACL with Spring Boot.

Actual Behavior

I used the schemas as specified here (in this case H2) and I try to use the BasicLookupStrategy. I tried both names, class and class_id_type for the table acl_class, neither work out of the box because BasicLookupStrategy tries to use class_id_type AND class, but the schema above specifies class for the column name. Now here's where the strategy tries to actually use both column names:

https://github.com/spring-projects/spring-security/blob/c1db1aad91837d571ab3d621c8e470d67c7635c6/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java#L96

https://github.com/spring-projects/spring-security/blob/c1db1aad91837d571ab3d621c8e470d67c7635c6/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java#L110

Is the schema missing something? Am I supposed to implement something else? I don't want to implement my own LookupStrategy just for this.

Expected Behavior

No schema issues, both calls should succeed (see sample).

Configuration
Version

5.2.0.RELEASE

Sample

Leaving the column named class causes:

org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "class_id_type" not found [42122-200]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:453) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.jdbc.JdbcResultSet.getColumnIndex(JdbcResultSet.java:3169) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.jdbc.JdbcResultSet.get(JdbcResultSet.java:3268) ~[h2-1.4.200.jar:1.4.200]
	at org.h2.jdbc.JdbcResultSet.getString(JdbcResultSet.java:316) ~[h2-1.4.200.jar:1.4.200]
	at com.zaxxer.hikari.pool.HikariProxyResultSet.getString(HikariProxyResultSet.java) ~[HikariCP-3.4.1.jar:na]
	at org.springframework.security.acls.jdbc.AclClassIdUtils.classIdTypeFrom(AclClassIdUtils.java:88) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.AclClassIdUtils.hasValidClassIdType(AclClassIdUtils.java:80) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.AclClassIdUtils.identifierFrom(AclClassIdUtils.java:65) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.convertCurrentResultIntoObject(BasicLookupStrategy.java:634) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:583) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:558) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:679) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700) ~[spring-jdbc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.BasicLookupStrategy.lookupObjectIdentities(BasicLookupStrategy.java:381) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.BasicLookupStrategy.readAclsById(BasicLookupStrategy.java:336) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.JdbcAclService.readAclsById(JdbcAclService.java:129) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:111) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:119) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.security.acls.jdbc.JdbcMutableAclService.createAcl(JdbcMutableAclService.java:122) ~[spring-security-acl-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at de.redacted.data.service.PermissionService.mutableAclFactory(PermissionService.java:33) ~[classes/:na]

schema:

create table acl_class
(
    id    bigint generated by default as identity (start with 100) not null primary key,
    class varchar_ignorecase(100)                                  not null,
    constraint unique_uk_2 unique (class)
);

Renaming column to class_id_type causes:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select acl_object_identity.object_id_identity, acl_entry.ace_order,  acl_object_identity.id as acl_id, acl_object_identity.parent_object, acl_object_identity.entries_inheriting, acl_entry.id as ace_id, acl_entry.mask,  acl_entry.granting,  acl_entry.audit_success, acl_entry.audit_failure,  acl_sid.principal as ace_principal, acl_sid.sid as ace_sid,  acli_sid.principal as acl_principal, acli_sid.sid as acl_sid, acl_class.class from acl_object_identity left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid left join acl_class on acl_class.id = acl_object_identity.object_id_class   left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity left join acl_sid on acl_entry.sid = acl_sid.id  where ( (acl_object_identity.object_id_identity = ? and acl_class.class = ?)) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc]; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "ACL_CLASS.CLASS" not found; SQL statement:
select acl_object_identity.object_id_identity, acl_entry.ace_order,  acl_object_identity.id as acl_id, acl_object_identity.parent_object, acl_object_identity.entries_inheriting, acl_entry.id as ace_id, acl_entry.mask,  acl_entry.granting,  acl_entry.audit_success, acl_entry.audit_failure,  acl_sid.principal as ace_principal, acl_sid.sid as ace_sid,  acli_sid.principal as acl_principal, acli_sid.sid as acl_sid, acl_class.class from acl_object_identity left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid left join acl_class on acl_class.id = acl_object_identity.object_id_class   left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity left join acl_sid on acl_entry.sid = acl_sid.id  where ( (acl_object_identity.object_id_identity = ? and acl_class.class = ?)) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc [42122-200]

with code:

final ObjectIdentity objectIdentity = new ObjectIdentityImpl(targetObj.getClass(), targetObj.getId());
final MutableAcl acl = mutableAclFactory(objectIdentity);
    public MutableAcl mutableAclFactory(ObjectIdentity objectIdentity) {
        try {
            return (MutableAcl) aclService.readAclById(objectIdentity);
        } catch (final NotFoundException e) {
            return aclService.createAcl(objectIdentity);
        }
    }

schema:

create table acl_class
(
    id    bigint generated by default as identity (start with 100) not null primary key,
    class_id_type varchar_ignorecase(100)                                  not null,
    constraint unique_uk_2 unique (class_id_type)
);

That being said, AclClassIdUtils also uses class_id_type:
https://github.com/spring-projects/spring-security/blob/c1db1aad91837d571ab3d621c8e470d67c7635c6/acl/src/main/java/org/springframework/security/acls/jdbc/AclClassIdUtils.java#L39

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java and AclClassIdUtils.java, especially the referenced query and column lookups. Reproduce the failure with the two supplied H2 acl_class schemas and the sample ACL operations. Done means the documented schema and BasicLookupStrategy use consistent column names without the reported SQL errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.