CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-dmetasoul--lakesoul-common

Core utilities and metadata management library for the LakeSoul lakehouse framework providing database connection management, RBAC authorization, protobuf serialization, and native library integration.

Pending
Overview
Eval results
Files

authorization-security.mddocs/

Authorization and Security

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.

Capabilities

AuthZEnforcer Class

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();
}

Authorization Annotations

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";
}

Authorization Exception

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);
}

Authorization Context

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();
}

AOP Authorization Components

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);
}

Authorization Parameter Fetchers

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.act

Policy 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=analytics

Security Best Practices:

  1. Principle of Least Privilege: Grant minimum necessary permissions
  2. Domain Isolation: Use domains to separate different business units or environments
  3. Role-Based Access: Use roles instead of direct user permissions where possible
  4. Audit Logging: Log all authorization decisions for security monitoring
  5. Regular Reviews: Periodically review and update authorization policies
  6. Secure Defaults: Default to deny access when authorization is enabled
  7. Error Handling: Don't expose sensitive information in authorization error messages

Thread Safety:

The authorization system is designed for concurrent usage:

  • Singleton Patterns: Thread-safe singleton initialization for global components
  • Context Management: Thread-local context storage for user sessions
  • Casbin Integration: SyncedEnforcer provides thread-safe policy enforcement
  • AOP Safety: AspectJ advice execution is thread-safe
  • Configuration: Global configuration is immutable after initialization

Install with Tessl CLI

npx tessl i tessl/maven-com-dmetasoul--lakesoul-common

docs

authorization-security.md

configuration-management.md

database-connection.md

entity-models.md

index.md

metadata-management.md

native-operations.md

scala-functional-api.md

tile.json