Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grant permission to existing object identities with Spring Security ACL

I'm using the Spring Security ACL implementation and am wondering what's the best way of granting a new permission to a role/user (security identity - SID) for existing object identities.

For example, let's say I have the following (I'm mostly omitting the primary keys and some other columns and simply reference by string values for readability):

  • ACL_SID: ROLE_TEST
  • ACL_CLASS: test_class
  • ACL_OBJECT_IDENTITY:
    • id: 1
    • object_id_class: test_class
    • object_id_identity: someObjectInstanceId
  • ACL_ENTRY:
    • acl_object_identity: 1
    • sid: ROLE_TEST
    • mask: CREATE (this would be an integer in the db)

Now, I want to grant the permission WRITE to the role ROLE_TEST for all future and existing objects of class test_class. For objects created in the future I will simply check the role for its permissions and grant them. But what about the existing objects?

Does Spring provide anything to easily do this or do I have to write my own custom code to do the following (which wouldn't be so bad but if Spring already provides this, I would rather not do it myself):

  1. Retrieve all ACL entries with the SID of the role/user I want to grant the new permission to and that reference an object identity which has the appropriate object_id_class.
  2. For each result, create a new ACL entry that is identical to the result except for the mask, which would reflect the new permission.
like image 489
JWK Avatar asked Dec 05 '25 13:12

JWK


1 Answers

Since I couldn't find any build-in Spring support for this, I ended up with the following custom code. Not the most efficient but it does what I need it to do.

If anyone knows of a better solution or has suggestions for improving the below code, please let me know.

Custom JDBC ACL Service to retrieve all existing object identities by type (acl_class):

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;

import javax.sql.DataSource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CustomJdbcAclService {

    private final JdbcTemplate jdbcTemplate;

    private final static String SELECT_EXISTING_BY_CLASS_AND_SID =
            "SELECT DISTINCT " +
            "acl_object_identity.object_id_identity " +
            "FROM acl_object_identity " +
            "LEFT JOIN acl_entry on acl_entry.acl_object_identity = acl_object_identity.id " +
            "LEFT JOIN acl_class on acl_class.id = acl_object_identity.object_id_class " +
            "LEFT JOIN acl_sid on acl_entry.sid = acl_sid.id " +
            "WHERE acl_class.class = ? && acl_sid.sid = ? && acl_entry.granting = 1";

    public CustomJdbcAclService(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public List<ObjectIdentity> getExistingObjectIdentities(String type, Sid sid) {
        String sidName = getSidName(sid);

        List<Map<String, Object>> results = jdbcTemplate.queryForList(SELECT_EXISTING_BY_CLASS_AND_SID, type, sidName);
        List<ObjectIdentity> oids = new ArrayList<>();

        for (Map<String, Object> result : results) {
            oids.add(new ObjectIdentityImpl(type, (Serializable) result.get("object_id_identity")));
        }

        return oids;
    }

    private String getSidName(Sid sid) {
        String sidName;

        if (sid instanceof PrincipalSid) {
            sidName = ((PrincipalSid) sid).getPrincipal();
        } else if (sid instanceof GrantedAuthoritySid) {
            sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
        } else {
            throw new IllegalArgumentException("Unsupported implementation of Sid");
        }
        return sidName;
    }

}

I call the above from another ACL service:

public class MyAclService {

public void grantPermissionsToExisting(String type, Sid securityIdentity, Permission... permissions) {
        List<ObjectIdentity> existingOids = customJdbcAclService.getExistingObjectIdentities(type, securityIdentity);
        for (ObjectIdentity oid : existingOids) {
            // grantPermissions() gets the ACL of the object identity and inserts the new ACEs
            grantPermissions(oid, securityIdentity, permissions);
        }
    }

}
like image 164
JWK Avatar answered Dec 08 '25 19:12

JWK



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!