Service Provider Interface for CDAP's security and authorization framework enabling pluggable authorization mechanisms.
npx @tessl/cli install tessl/maven-co-cask-cdap--cdap-security-spi@5.1.0CDAP Security SPI provides the Service Provider Interface for CDAP's security and authorization framework, enabling pluggable authorization mechanisms for the CDAP data platform. It defines core interfaces for authorization enforcement, privilege management, and access control that can be extended to integrate with enterprise security systems.
<dependency>
<groupId>co.cask.cdap</groupId>
<artifactId>cdap-security-spi</artifactId>
<version>5.1.2</version>
</dependency>// Core authorization interfaces
import co.cask.cdap.security.spi.authorization.Authorizer;
import co.cask.cdap.security.spi.authorization.AuthorizationEnforcer;
import co.cask.cdap.security.spi.authorization.AuthorizationContext;
import co.cask.cdap.security.spi.authorization.PrivilegesManager;
// Authentication context
import co.cask.cdap.security.spi.authentication.AuthenticationContext;
import co.cask.cdap.security.spi.authentication.SecurityRequestContext;
// Exception classes
import co.cask.cdap.security.spi.authorization.UnauthorizedException;
import co.cask.cdap.security.spi.authorization.AlreadyExistsException;
// Base implementations
import co.cask.cdap.security.spi.authorization.AbstractAuthorizer;
import co.cask.cdap.security.spi.authorization.NoOpAuthorizer;import co.cask.cdap.security.spi.authorization.AbstractAuthorizer;
import co.cask.cdap.security.spi.authorization.AuthorizationContext;
import co.cask.cdap.proto.security.Action;
import co.cask.cdap.proto.security.Principal;
import co.cask.cdap.proto.id.EntityId;
public class CustomAuthorizer extends AbstractAuthorizer {
@Override
public void initialize(AuthorizationContext context) throws Exception {
// Initialize your authorization backend
Properties config = context.getExtensionProperties();
// Setup connection to your authorization system
}
@Override
public void enforce(EntityId entity, Principal principal, Set<Action> actions)
throws Exception {
// Check if principal has permissions for actions on entity
// Throw UnauthorizedException if not authorized
if (!hasPermission(entity, principal, actions)) {
throw new UnauthorizedException(principal, actions, entity);
}
}
@Override
public void grant(Authorizable authorizable, Principal principal, Set<Action> actions)
throws Exception {
// Grant permissions to principal on authorizable
}
// Implement other required methods...
}import co.cask.cdap.security.spi.authentication.SecurityRequestContext;
import co.cask.cdap.proto.security.Principal;
// Set user context for current thread
SecurityRequestContext.setUserId("alice");
SecurityRequestContext.setUserIP("192.168.1.100");
// Get user information
String userId = SecurityRequestContext.getUserId();
String userIP = SecurityRequestContext.getUserIP();
// Convert to Principal
Principal principal = SecurityRequestContext.toPrincipal();The CDAP Security SPI follows a modular architecture with distinct responsibilities:
Core authorization interfaces for implementing custom authorization backends with role-based access control and privilege management.
@Beta
interface Authorizer extends PrivilegesFetcher, PrivilegesManager, AuthorizationEnforcer {
void initialize(AuthorizationContext context) throws Exception;
void createRole(Role role) throws Exception;
void dropRole(Role role) throws Exception;
Set<Role> listAllRoles() throws Exception;
void destroy() throws Exception;
}@Beta
interface AuthorizationEnforcer {
void enforce(EntityId entity, Principal principal, Action action) throws Exception;
void enforce(EntityId entity, Principal principal, Set<Action> actions) throws Exception;
Set<? extends EntityId> isVisible(Set<? extends EntityId> entityIds, Principal principal) throws Exception;
}Thread-local authentication context management and user identification for authorization requests.
interface AuthenticationContext {
Principal getPrincipal();
}class SecurityRequestContext {
static String getUserId();
static void setUserId(String userIdParam);
static Principal toPrincipal();
}Structured exception hierarchy with HTTP status codes for proper error handling in web contexts.
class UnauthorizedException extends RuntimeException implements HttpErrorStatusProvider {
UnauthorizedException(Principal principal, Action action, EntityId entityId);
UnauthorizedException(Principal principal, Set<Action> actions, EntityId entityId);
int getStatusCode(); // Returns 403
}// From cdap-proto dependency
class Principal {
Principal(String name, PrincipalType type);
String getName();
PrincipalType getType();
}
enum PrincipalType {
USER, GROUP, ROLE
}
class Role {
Role(String name);
String getName();
}
interface EntityId {
// Entity identifier for CDAP resources
}
enum Action {
READ, WRITE, EXECUTE, ADMIN
// Actions that can be performed on entities
}
class Privilege {
Privilege(Authorizable authorizable, Action action);
Authorizable getAuthorizable();
Action getAction();
}
interface Authorizable {
// Represents an entity that can have privileges granted on it
}
interface HttpErrorStatusProvider {
/**
* Get the HTTP status code for this error condition.
*
* @return HTTP status code (e.g., 403, 404, 409, 400)
*/
int getStatusCode();
}interface AuthorizationContext extends DatasetContext, Admin, Transactional,
AuthenticationContext, SecureStore {
Properties getExtensionProperties();
// Messaging methods throw UnsupportedOperationException
}