Core utilities and metadata management library for the LakeSoul lakehouse framework providing database connection management, RBAC authorization, protobuf serialization, and native library integration.
—
The authorization and security system provides comprehensive Role-Based Access Control (RBAC) using Casbin for fine-grained authorization policies. The system includes AOP-based enforcement, domain-based multi-tenancy, and flexible policy management for securing metadata operations across the LakeSoul ecosystem.
The central authorization enforcement class providing Casbin enforcer access and authorization status management.
/**
* Authorization enforcement using Casbin
* Provides singleton access to Casbin enforcer and authorization status
*/
public class AuthZEnforcer {
/**
* Get Casbin SyncedEnforcer instance
* Returns null if authorization is disabled
* @return SyncedEnforcer instance or null
*/
public static SyncedEnforcer get();
/**
* Check if authorization is globally enabled
* @return boolean true if authorization is enabled, false otherwise
*/
public static boolean authZEnabled();
}Annotation-based authorization for method-level access control with AOP enforcement.
/**
* Method-level authorization annotation
* Applied to methods requiring authorization checks
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthZ {
/**
* Authorization value/policy identifier
* @return String authorization policy identifier
*/
String value() default "";
/**
* Object parameter name for authorization
* Specifies which method parameter represents the object being accessed
* @return String parameter name (default "object")
*/
String object() default "object";
/**
* Action parameter name for authorization
* Specifies which method parameter represents the action being performed
* @return String parameter name (default "action")
*/
String action() default "action";
}
/**
* Pre-method authorization annotation
* Executed before method invocation
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthZBefore {
/**
* Authorization policy identifier
* @return String policy identifier
*/
String value() default "";
/**
* Object parameter specification
* @return String object parameter name
*/
String object() default "object";
/**
* Action parameter specification
* @return String action parameter name
*/
String action() default "action";
}
/**
* Post-method authorization annotation
* Executed after method invocation
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthZAfter {
/**
* Authorization policy identifier
* @return String policy identifier
*/
String value() default "";
/**
* Object parameter specification
* @return String object parameter name
*/
String object() default "object";
/**
* Action parameter specification
* @return String action parameter name
*/
String action() default "action";
}Exception class for authorization failures with standardized error handling.
/**
* Exception thrown when access is denied
* Extends RuntimeException for unchecked exception handling
*/
public class AuthZException extends RuntimeException {
/**
* Create AuthZException with default message
* Message: "lakesoul access denied!"
*/
public AuthZException();
/**
* Create AuthZException with custom message
* @param message Custom error message
*/
public AuthZException(String message);
/**
* Create AuthZException with message and cause
* @param message Custom error message
* @param cause Root cause exception
*/
public AuthZException(String message, Throwable cause);
}Context management for authorization information including domain and user context.
/**
* Context holder for authorization information
* Manages current user domain and authorization state
*/
public class AuthZContext {
/**
* Get singleton AuthZContext instance
* @return AuthZContext singleton instance
*/
public static AuthZContext getInstance();
/**
* Get current security domain
* @return String current domain name
*/
public String getDomain();
/**
* Set current security domain
* @param domain Domain name to set as current
*/
public void setDomain(String domain);
/**
* Get current user identifier
* @return String current user ID
*/
public String getUser();
/**
* Set current user identifier
* @param user User ID to set as current
*/
public void setUser(String user);
/**
* Get current user roles
* @return List<String> list of role names for current user
*/
public List<String> getRoles();
/**
* Set current user roles
* @param roles List of role names to assign to current user
*/
public void setRoles(List<String> roles);
/**
* Clear authorization context
* Resets user, domain, and roles to default values
*/
public void clear();
}AspectJ-based components for automatic authorization enforcement.
/**
* AOP aspect for authorization enforcement
* Intercepts methods annotated with authorization annotations
*/
public class AuthZAspect {
/**
* Around advice for @AuthZ annotation
* Executes authorization check before method execution
* @param joinPoint Method execution join point
* @param authZ Authorization annotation
* @return Object method result if authorized
* @throws AuthZException if access denied
*/
@Around("@annotation(authZ)")
public Object authorizeMethod(ProceedingJoinPoint joinPoint, AuthZ authZ) throws Throwable;
/**
* Before advice for @AuthZBefore annotation
* @param joinPoint Method execution join point
* @param authZBefore Authorization annotation
* @throws AuthZException if access denied
*/
@Before("@annotation(authZBefore)")
public void authorizeBeforeMethod(JoinPoint joinPoint, AuthZBefore authZBefore);
/**
* After advice for @AuthZAfter annotation
* @param joinPoint Method execution join point
* @param authZAfter Authorization annotation
* @throws AuthZException if access denied
*/
@After("@annotation(authZAfter)")
public void authorizeAfterMethod(JoinPoint joinPoint, AuthZAfter authZAfter);
}
/**
* AOP advice for authorization operations
* Provides common authorization logic for aspects
*/
public class AuthZAdvice {
/**
* Perform authorization check
* @param subject User or role performing the action
* @param object Resource being accessed
* @param action Action being performed
* @return boolean true if authorized, false otherwise
*/
public boolean authorize(String subject, String object, String action);
/**
* Extract authorization parameters from method arguments
* @param joinPoint Method execution join point
* @param authZ Authorization annotation
* @return AuthZParameters extracted parameters
*/
public AuthZParameters extractParameters(JoinPoint joinPoint, AuthZ authZ);
}Flexible parameter extraction system for authorization decisions.
/**
* Base interface for authorization parameter fetchers
* Extracts authorization parameters from method calls
*/
public interface AuthZFetcher {
/**
* Extract parameter value from method context
* @param joinPoint Method execution join point
* @param parameterName Name of parameter to extract
* @return Object parameter value
*/
Object fetchParameter(JoinPoint joinPoint, String parameterName);
/**
* Check if this fetcher supports the given parameter
* @param parameterName Name of parameter
* @return boolean true if supported, false otherwise
*/
boolean supports(String parameterName);
}
/**
* Identity-based authorization parameter fetcher
* Extracts user identity information
*/
public class AuthZIdentFetcher implements AuthZFetcher {
/**
* Fetch current user identity
* @param joinPoint Method execution join point
* @param parameterName Parameter name ("user", "subject", etc.)
* @return Object user identity
*/
public Object fetchParameter(JoinPoint joinPoint, String parameterName);
public boolean supports(String parameterName);
}
/**
* Parameter-based authorization fetcher
* Extracts values from method parameters
*/
public class AuthZParamFetcher implements AuthZFetcher {
/**
* Fetch parameter value from method arguments
* @param joinPoint Method execution join point
* @param parameterName Name of method parameter
* @return Object parameter value
*/
public Object fetchParameter(JoinPoint joinPoint, String parameterName);
public boolean supports(String parameterName);
}
/**
* Null fetcher for operations without parameters
* Returns null for all parameter requests
*/
public class AuthZNullFetcher implements AuthZFetcher {
public Object fetchParameter(JoinPoint joinPoint, String parameterName);
public boolean supports(String parameterName);
}
/**
* Table read operation parameter fetcher
* Specialized for table read authorization
*/
public class TableReadFetcher implements AuthZFetcher {
/**
* Extract table-specific parameters for read operations
* @param joinPoint Method execution join point
* @param parameterName Parameter name ("tableId", "tablePath", etc.)
* @return Object table-related parameter value
*/
public Object fetchParameter(JoinPoint joinPoint, String parameterName);
public boolean supports(String parameterName);
}
/**
* Table write operation parameter fetcher
* Specialized for table write authorization
*/
public class TableWriteFetcher implements AuthZFetcher {
/**
* Extract table-specific parameters for write operations
* @param joinPoint Method execution join point
* @param parameterName Parameter name ("tableId", "tablePath", etc.)
* @return Object table-related parameter value
*/
public Object fetchParameter(JoinPoint joinPoint, String parameterName);
public boolean supports(String parameterName);
}Usage Examples:
import com.dmetasoul.lakesoul.meta.rbac.*;
import com.dmetasoul.lakesoul.meta.entity.TableInfo;
import org.casbin.jcasbin.main.SyncedEnforcer;
public class AuthorizationExample {
// Method-level authorization using annotations
@AuthZ(value = "table_read", object = "tableId", action = "read")
public TableInfo getTableInfo(String tableId) {
// Method implementation - authorization checked automatically
// AuthZ aspect will verify user can read the specified table
return loadTableInfo(tableId);
}
@AuthZ(value = "table_write", object = "tableInfo", action = "create")
public void createTable(TableInfo tableInfo) {
// Authorization checked before table creation
// User must have create permission for the table
saveTableInfo(tableInfo);
}
@AuthZBefore(value = "namespace_admin", action = "delete")
public void deleteNamespace(String namespace) {
// Pre-method authorization check
// User must have admin permission for namespace operations
performNamespaceDeletion(namespace);
}
public void programmaticAuthorizationExample() {
// Check if authorization is enabled
if (AuthZEnforcer.authZEnabled()) {
// Get Casbin enforcer
SyncedEnforcer enforcer = AuthZEnforcer.get();
// Set current user context
AuthZContext context = AuthZContext.getInstance();
context.setUser("alice");
context.setDomain("analytics");
context.setRoles(Arrays.asList("analyst", "reader"));
// Perform authorization check
boolean canRead = enforcer.enforce(
"alice", // subject (user)
"table_001", // object (resource)
"read" // action
);
if (canRead) {
System.out.println("User authorized to read table");
// Proceed with operation
} else {
throw new AuthZException("Access denied: cannot read table_001");
}
// Check with role-based access
boolean canWrite = enforcer.enforce(
"analyst", // subject (role)
"table_001", // object (resource)
"write" // action
);
if (canWrite) {
System.out.println("Analyst role authorized to write table");
}
} else {
System.out.println("Authorization disabled - allowing all operations");
}
}
public void domainBasedAuthorizationExample() {
AuthZContext context = AuthZContext.getInstance();
// Set up analytics domain context
context.setUser("data_scientist");
context.setDomain("analytics");
context.setRoles(Arrays.asList("analyst", "viewer"));
try {
// This will be authorized within analytics domain
TableInfo analyticsTable = getTableInfo("analytics_table_001");
System.out.println("Access granted to analytics table");
// Switch to different domain
context.setDomain("finance");
// This may be denied if user doesn't have cross-domain access
TableInfo financeTable = getTableInfo("finance_table_001");
System.out.println("Access granted to finance table");
} catch (AuthZException e) {
System.err.println("Authorization failed: " + e.getMessage());
} finally {
// Clear context when done
context.clear();
}
}
public void configurationExample() {
// Check global authorization configuration
GlobalConfig config = GlobalConfig.get();
if (config.isAuthZEnabled()) {
System.out.println("Authorization is enabled");
System.out.println("Casbin model: " + config.getAuthZCasbinModel());
// Initialize authorization system
initializeAuthorizationPolicies();
} else {
System.out.println("Authorization is disabled");
// Skip authorization setup
}
}
public void customAuthorizationExample() {
SyncedEnforcer enforcer = AuthZEnforcer.get();
if (enforcer != null) {
// Add custom policy rules
enforcer.addPolicy("alice", "table_analytics", "read");
enforcer.addPolicy("alice", "table_analytics", "write");
enforcer.addPolicy("bob", "table_finance", "read");
// Add role-based policies
enforcer.addRoleForUser("alice", "analyst");
enforcer.addRoleForUser("bob", "viewer");
enforcer.addPolicy("analyst", "analytics_domain", "read");
enforcer.addPolicy("analyst", "analytics_domain", "write");
enforcer.addPolicy("viewer", "all_domains", "read");
// Save policies (if using file or database adapter)
enforcer.savePolicy();
System.out.println("Custom policies added successfully");
}
}
public void errorHandlingExample() {
try {
// Operation that might fail authorization
createTable(buildTableInfo());
} catch (AuthZException e) {
// Handle authorization failure
System.err.println("Access denied: " + e.getMessage());
// Log security event
logSecurityEvent("AUTHORIZATION_DENIED",
AuthZContext.getInstance().getUser(),
"table_create",
"table_001");
// Optionally redirect to access request page
redirectToAccessRequest();
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
e.printStackTrace();
}
}
// Helper methods
private TableInfo loadTableInfo(String tableId) {
// Implementation
return null;
}
private void saveTableInfo(TableInfo tableInfo) {
// Implementation
}
private void performNamespaceDeletion(String namespace) {
// Implementation
}
private TableInfo buildTableInfo() {
// Implementation
return null;
}
private void initializeAuthorizationPolicies() {
// Implementation
}
private void logSecurityEvent(String event, String user, String action, String resource) {
// Implementation
}
private void redirectToAccessRequest() {
// Implementation
}
}Policy Configuration:
Authorization policies are configured using Casbin model and policy files:
Model Configuration (RBAC with domains):
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, dom, obj, act
[role_definition]
g = _, _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.actPolicy Configuration:
# User policies
p, alice, analytics, table_*, read
p, alice, analytics, table_*, write
p, bob, finance, table_finance_*, read
# Role policies
p, analyst, analytics, table_*, read
p, analyst, analytics, table_*, write
p, viewer, *, table_*, read
# Role assignments
g, alice, analyst, analytics
g, bob, viewer, finance
g, charlie, admin, *Configuration Properties:
# Enable/disable authorization
lakesoul.authz.enabled=true
# Casbin model configuration
lakesoul.authz.casbin.model=path/to/rbac_with_domains_model.conf
# Policy storage (file, database, etc.)
lakesoul.authz.casbin.policy=path/to/policy.csv
# Current domain (can be set per user/session)
lakesoul.current.domain=analyticsSecurity Best Practices:
Thread Safety:
The authorization system is designed for concurrent usage:
Install with Tessl CLI
npx tessl i tessl/maven-com-dmetasoul--lakesoul-common