CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-cdap-cdap--cdap-client

CDAP Java Client library providing programmatic APIs for interacting with the CDAP platform

Pending
Overview
Eval results
Files

security-administration.mddocs/

Security and Administration

Security and administrative operations including namespace management, secure key storage, metadata management, authorization, and various utility functions for managing CDAP resources.

NamespaceClient

public class NamespaceClient {
    // Constructors
    public NamespaceClient(ClientConfig config);
    public NamespaceClient(ClientConfig config, RESTClient restClient);
    
    // Inherits namespace CRUD operations from AbstractNamespaceClient
    // Common operations include:
    // - create(NamespaceMeta namespaceMeta)
    // - get(NamespaceId namespaceId) 
    // - list()
    // - delete(NamespaceId namespaceId)
    // - updateProperties(NamespaceId namespaceId, Map<String, String> properties)
}

SecureStoreClient

public class SecureStoreClient {
    // Constructors
    public SecureStoreClient(ClientConfig config);
    public SecureStoreClient(ClientConfig config, RESTClient restClient);
    
    // Secure key management methods
    public void createKey(SecureKeyId secureKeyId, SecureKeyCreateRequest keyCreateRequest);
    public String getData(SecureKeyId secureKeyId);
    public SecureStoreMetadata getKeyMetadata(SecureKeyId secureKeyId);
    public void deleteKey(SecureKeyId secureKeyId);
    public List<SecureStoreMetadata> listKeys(NamespaceId namespaceId);
}

MetadataClient

public class MetadataClient {
    // Constructors
    public MetadataClient(ClientConfig config);
    public MetadataClient(ClientConfig config, RESTClient restClient);
    
    // Inherits metadata CRUD and search operations from AbstractMetadataClient
    // Common operations include:
    // - addTags(MetadataEntity entity, Set<String> tags)
    // - getTags(MetadataEntity entity)
    // - addProperties(MetadataEntity entity, Map<String, String> properties)
    // - getProperties(MetadataEntity entity)
    // - removeMetadata(MetadataEntity entity)
    // - searchMetadata(NamespaceId namespace, String query)
}

AuthorizationClient

public class AuthorizationClient {
    // Constructors
    public AuthorizationClient(ClientConfig config);
    public AuthorizationClient(ClientConfig config, RESTClient restClient);
    
    // Authorization operations (specific methods depend on implementation)
    // Common operations include:
    // - grant permissions
    // - revoke permissions  
    // - list permissions
    // - check access
}

Security Types and Configuration

public class SecureKeyId {
    public static SecureKeyId of(NamespaceId namespace, String name);
    public NamespaceId getNamespace();
    public String getName();
}

public class SecureKeyCreateRequest {
    public SecureKeyCreateRequest(String description, String data, Map<String, String> properties);
    public String getDescription();
    public String getData();
    public Map<String, String> getProperties();
}

public class SecureStoreMetadata {
    public String getName();
    public String getDescription();
    public long getCreationTimeMs();
    public Map<String, String> getProperties();
}

public class NamespaceMeta {
    public NamespaceMeta(String name, String description, Map<String, String> config);
    public String getName();
    public String getDescription();
    public Map<String, String> getConfig();
}

Namespace Management

Namespace Operations

// List all namespaces
List<NamespaceMeta> namespaces = namespaceClient.list();
System.out.println("Available namespaces (" + namespaces.size() + "):");

for (NamespaceMeta namespace : namespaces) {
    System.out.println("- " + namespace.getName());
    System.out.println("  Description: " + namespace.getDescription());
    System.out.println("  Config: " + namespace.getConfig());
}

// Get specific namespace
NamespaceId namespaceId = NamespaceId.of("production");
try {
    NamespaceMeta namespaceMeta = namespaceClient.get(namespaceId);
    System.out.println("Namespace: " + namespaceMeta.getName());
    System.out.println("Description: " + namespaceMeta.getDescription());
    System.out.println("Configuration: " + namespaceMeta.getConfig());
} catch (NamespaceNotFoundException e) {
    System.err.println("Namespace not found: " + namespaceId.getId());
}

Namespace Creation

// Create development namespace
Map<String, String> devConfig = Map.of(
    "scheduler.queue.name", "dev-queue",
    "explore.as.principal", "dev-user",
    "security.impersonation.principal", "dev-service-account",
    "data.retention.days", "7"
);

NamespaceMeta devNamespace = new NamespaceMeta(
    "development",
    "Development environment for testing applications",
    devConfig
);

try {
    namespaceClient.create(devNamespace);
    System.out.println("Created development namespace");
} catch (NamespaceAlreadyExistsException e) {
    System.out.println("Development namespace already exists");
}

// Create production namespace with strict configuration
Map<String, String> prodConfig = Map.of(
    "scheduler.queue.name", "production-queue",
    "security.authorization.enabled", "true", 
    "security.authentication.required", "true",
    "data.retention.days", "365",
    "backup.enabled", "true",
    "monitoring.enabled", "true"
);

NamespaceMeta prodNamespace = new NamespaceMeta(
    "production",
    "Production environment with enhanced security",
    prodConfig
);

namespaceClient.create(prodNamespace);
System.out.println("Created production namespace");

Namespace Configuration Updates

// Update namespace properties
Map<String, String> updatedProperties = Map.of(
    "data.retention.days", "14", // Extended retention
    "backup.frequency", "daily",
    "monitoring.alerts.enabled", "true"
);

namespaceClient.updateProperties(namespaceId, updatedProperties);
System.out.println("Updated namespace properties");

// Get updated configuration
NamespaceMeta updated = namespaceClient.get(namespaceId);
System.out.println("Updated config: " + updated.getConfig());

Secure Key Management

Creating Secure Keys

// Create secure key for database password
SecureKeyId dbPasswordKey = SecureKeyId.of(namespaceId, "db-password");
Map<String, String> keyProperties = Map.of(
    "type", "database-credential",
    "database", "user-profiles",
    "environment", "production"
);

SecureKeyCreateRequest passwordRequest = new SecureKeyCreateRequest(
    "Database password for user profiles service",
    "super-secure-password-123", // In practice, this should come from secure input
    keyProperties
);

secureStoreClient.createKey(dbPasswordKey, passwordRequest);
System.out.println("Created secure key: " + dbPasswordKey.getName());

// Create API key
SecureKeyId apiKey = SecureKeyId.of(namespaceId, "external-api-key");
SecureKeyCreateRequest apiRequest = new SecureKeyCreateRequest(
    "API key for external service integration",
    "api-key-xyz789",
    Map.of(
        "type", "api-credential",
        "service", "external-analytics",
        "expires", "2024-12-31"
    )
);

secureStoreClient.createKey(apiKey, apiRequest);

// Create encryption key
SecureKeyId encryptionKey = SecureKeyId.of(namespaceId, "data-encryption-key");
SecureKeyCreateRequest encryptionRequest = new SecureKeyCreateRequest(
    "AES encryption key for sensitive data",
    generateSecureKey(), // Generate cryptographically secure key
    Map.of(
        "type", "encryption-key",
        "algorithm", "AES-256",
        "purpose", "data-encryption"
    )
);

secureStoreClient.createKey(encryptionKey, encryptionRequest);

Retrieving and Managing Secure Keys

// List all secure keys in namespace
List<SecureStoreMetadata> keys = secureStoreClient.listKeys(namespaceId);
System.out.println("Secure keys in namespace " + namespaceId.getId() + ":");

for (SecureStoreMetadata keyMeta : keys) {
    System.out.println("- " + keyMeta.getName());
    System.out.println("  Description: " + keyMeta.getDescription());
    System.out.println("  Created: " + new Date(keyMeta.getCreationTimeMs()));
    System.out.println("  Properties: " + keyMeta.getProperties());
}

// Get key metadata (without revealing the actual key)
SecureStoreMetadata metadata = secureStoreClient.getKeyMetadata(dbPasswordKey);
System.out.println("Key metadata: " + metadata.getName());
System.out.println("Description: " + metadata.getDescription());

// Retrieve key data (use with caution!)
try {
    String keyData = secureStoreClient.getData(dbPasswordKey);
    // Use the key data immediately and don't store it
    connectToDatabase(keyData);
    // Clear the key from memory
    keyData = null;
} catch (UnauthorizedException e) {
    System.err.println("Not authorized to access key: " + dbPasswordKey.getName());
}

// Delete expired or unused key
secureStoreClient.deleteKey(apiKey);
System.out.println("Deleted secure key: " + apiKey.getName());

Secure Key Rotation

// Key rotation example
public void rotateSecureKey(SecureKeyId keyId, String newKeyData) {
    try {
        // Get current key metadata
        SecureStoreMetadata currentMeta = secureStoreClient.getKeyMetadata(keyId);
        
        // Create new key request with updated timestamp
        Map<String, String> updatedProperties = new HashMap<>(currentMeta.getProperties());
        updatedProperties.put("rotated.timestamp", String.valueOf(System.currentTimeMillis()));
        updatedProperties.put("rotation.count", 
            String.valueOf(Integer.parseInt(updatedProperties.getOrDefault("rotation.count", "0")) + 1));
        
        SecureKeyCreateRequest rotatedRequest = new SecureKeyCreateRequest(
            currentMeta.getDescription() + " (rotated)",
            newKeyData,
            updatedProperties
        );
        
        // Delete old key and create new one
        secureStoreClient.deleteKey(keyId);
        secureStoreClient.createKey(keyId, rotatedRequest);
        
        System.out.println("Successfully rotated key: " + keyId.getName());
        
        // Notify applications that key has been rotated
        notifyApplicationsOfKeyRotation(keyId);
        
    } catch (Exception e) {
        System.err.println("Key rotation failed for " + keyId.getName() + ": " + e.getMessage());
        throw new RuntimeException("Key rotation failed", e);
    }
}

private String generateSecureKey() {
    // Generate cryptographically secure key (example implementation)
    SecureRandom random = new SecureRandom();
    byte[] keyBytes = new byte[32]; // 256-bit key
    random.nextBytes(keyBytes);
    return Base64.getEncoder().encodeToString(keyBytes);
}

private void notifyApplicationsOfKeyRotation(SecureKeyId keyId) {
    // Implement application notification logic
    System.out.println("Notifying applications of key rotation: " + keyId.getName());
}

private void connectToDatabase(String password) {
    // Database connection logic using the secure password
    System.out.println("Connecting to database with retrieved password");
}

Metadata Management

Adding and Managing Metadata

// Add tags to application
ApplicationId appId = ApplicationId.of(namespaceId, "user-analytics", "1.0.0");
MetadataEntity appEntity = MetadataEntity.ofApplication(appId);

Set<String> tags = Set.of(
    "analytics",
    "user-data", 
    "production",
    "gdpr-compliant",
    "high-priority"
);

metadataClient.addTags(appEntity, tags);
System.out.println("Added tags to application: " + appId.getApplication());

// Add properties to application
Map<String, String> properties = Map.of(
    "owner", "data-team@company.com",
    "cost-center", "engineering",
    "sla", "99.9%",
    "data-classification", "internal",
    "backup-required", "true",
    "monitoring-tier", "critical"
);

metadataClient.addProperties(appEntity, properties);
System.out.println("Added properties to application");

// Add metadata to dataset
DatasetId datasetId = DatasetId.of(namespaceId, "user-profiles");
MetadataEntity datasetEntity = MetadataEntity.ofDataset(datasetId);

metadataClient.addTags(datasetEntity, Set.of("pii", "user-data", "encrypted"));
metadataClient.addProperties(datasetEntity, Map.of(
    "schema-version", "2.1",
    "retention-policy", "7-years",
    "encryption-enabled", "true",
    "access-control", "restricted"
));

Retrieving Metadata

// Get tags for application
Set<String> appTags = metadataClient.getTags(appEntity);
System.out.println("Application tags: " + appTags);

// Get properties for application  
Map<String, String> appProperties = metadataClient.getProperties(appEntity);
System.out.println("Application properties: " + appProperties);

// Get all metadata for dataset
Set<String> datasetTags = metadataClient.getTags(datasetEntity);
Map<String, String> datasetProperties = metadataClient.getProperties(datasetEntity);

System.out.println("Dataset " + datasetId.getDataset() + ":");
System.out.println("  Tags: " + datasetTags);
System.out.println("  Properties: " + datasetProperties);

Metadata Search

// Search by tags
String tagQuery = "tags:analytics AND tags:production";
List<MetadataSearchResult> tagResults = metadataClient.searchMetadata(namespaceId, tagQuery);

System.out.println("Found " + tagResults.size() + " entities with analytics and production tags:");
for (MetadataSearchResult result : tagResults) {
    System.out.println("- " + result.getEntityId() + " (type: " + result.getEntityType() + ")");
}

// Search by properties
String propertyQuery = "properties.owner:data-team*";
List<MetadataSearchResult> ownerResults = metadataClient.searchMetadata(namespaceId, propertyQuery);

// Complex search query
String complexQuery = "(tags:user-data OR tags:analytics) AND properties.sla:99.9% AND type:application";
List<MetadataSearchResult> complexResults = metadataClient.searchMetadata(namespaceId, complexQuery);

System.out.println("Complex search results: " + complexResults.size() + " entities");

Data Operations and Utilities

LineageClient

public class LineageClient {
    // Constructors
    public LineageClient(ClientConfig config);
    public LineageClient(ClientConfig config, RESTClient restClient);
    
    // Data lineage operations
    // Common operations include:
    // - getLineage(DatasetId dataset, long startTime, long endTime, int levels)
    // - getFieldLineage(DatasetId dataset, String field, long startTime, long endTime)
}

PreferencesClient

public class PreferencesClient {
    // Constructors
    public PreferencesClient(ClientConfig config);
    public PreferencesClient(ClientConfig config, RESTClient restClient);
    
    // Preferences management operations
    // Common operations include:
    // - setPreferences(NamespaceId namespace, Map<String, String> preferences)
    // - getPreferences(NamespaceId namespace)
    // - setApplicationPreferences(ApplicationId application, Map<String, String> preferences)
    // - getProgramPreferences(ProgramId program)
}

DatasetModuleClient and DatasetTypeClient

public class DatasetModuleClient {
    // Constructors
    public DatasetModuleClient(ClientConfig config);
    public DatasetModuleClient(ClientConfig config, RESTClient restClient);
    
    // Dataset module management operations
    // Common operations include:
    // - deploy(NamespaceId namespace, String moduleName, String className, File jarFile)
    // - list(NamespaceId namespace)
    // - get(DatasetModuleId moduleId)
    // - delete(DatasetModuleId moduleId)
}

public class DatasetTypeClient {
    // Constructors  
    public DatasetTypeClient(ClientConfig config);
    public DatasetTypeClient(ClientConfig config, RESTClient restClient);
    
    // Dataset type operations
    // Common operations include:
    // - list(NamespaceId namespace)
    // - get(DatasetTypeId typeId)
}

WorkflowClient

public class WorkflowClient {
    // Constructors
    public WorkflowClient(ClientConfig config);
    public WorkflowClient(ClientConfig config, RESTClient restClient);
    
    // Workflow management operations
    // Common operations include:
    // - getWorkflowToken(ProgramRunId workflowRun)
    // - getWorkflowStatus(ProgramId workflow)
    // - getNodeStates(ProgramRunId workflowRun)
}

MetaClient

public class MetaClient {
    // Constructors
    public MetaClient(ClientConfig config);
    public MetaClient(ClientConfig config, RESTClient restClient);
    
    // Meta information operations
    // Common operations include:
    // - getVersion()
    // - ping()
    // - getConfiguration()
}

Advanced Administrative Operations

Comprehensive Environment Setup

public class EnvironmentSetup {
    private final NamespaceClient namespaceClient;
    private final SecureStoreClient secureStoreClient;
    private final MetadataClient metadataClient;
    
    public EnvironmentSetup(NamespaceClient namespaceClient, 
                           SecureStoreClient secureStoreClient,
                           MetadataClient metadataClient) {
        this.namespaceClient = namespaceClient;
        this.secureStoreClient = secureStoreClient;
        this.metadataClient = metadataClient;
    }
    
    public void setupProductionEnvironment() {
        try {
            // Create production namespace
            createProductionNamespace();
            
            // Set up secure keys
            setupSecureKeys();
            
            // Configure metadata policies
            setupMetadataPolicies();
            
            System.out.println("Production environment setup completed");
            
        } catch (Exception e) {
            System.err.println("Environment setup failed: " + e.getMessage());
            throw new RuntimeException("Failed to setup production environment", e);
        }
    }
    
    private void createProductionNamespace() {
        Map<String, String> prodConfig = Map.of(
            "security.authorization.enabled", "true",
            "security.authentication.required", "true",
            "audit.enabled", "true",
            "data.retention.days", "2555", // 7 years
            "backup.enabled", "true",
            "monitoring.enabled", "true",
            "scheduler.queue.name", "production"
        );
        
        NamespaceMeta prodNamespace = new NamespaceMeta(
            "production",
            "Production environment with enterprise security",
            prodConfig
        );
        
        try {
            namespaceClient.create(prodNamespace);
            System.out.println("Created production namespace");
        } catch (NamespaceAlreadyExistsException e) {
            System.out.println("Production namespace already exists");
        }
    }
    
    private void setupSecureKeys() {
        NamespaceId prodNamespace = NamespaceId.of("production");
        
        // Database credentials
        createSecureKey(prodNamespace, "db-primary-password", 
            "Primary database password", getSecureInput("database password"));
        
        // API keys
        createSecureKey(prodNamespace, "external-api-key",
            "External service API key", getSecureInput("API key"));
            
        // Encryption keys
        createSecureKey(prodNamespace, "data-encryption-key",
            "Data encryption key", generateEncryptionKey());
        
        System.out.println("Secure keys configured");
    }
    
    private void setupMetadataPolicies() {
        // Add metadata tags for governance
        NamespaceId prodNamespace = NamespaceId.of("production");
        MetadataEntity namespaceEntity = MetadataEntity.ofNamespace(prodNamespace);
        
        metadataClient.addTags(namespaceEntity, Set.of(
            "production", "enterprise", "audited", "secure"
        ));
        
        metadataClient.addProperties(namespaceEntity, Map.of(
            "environment", "production",
            "compliance", "sox-gdpr",
            "backup-policy", "daily",
            "retention-policy", "7-years",
            "access-policy", "restricted"
        ));
        
        System.out.println("Metadata policies configured");
    }
    
    private void createSecureKey(NamespaceId namespace, String keyName, String description, String keyData) {
        SecureKeyId keyId = SecureKeyId.of(namespace, keyName);
        SecureKeyCreateRequest request = new SecureKeyCreateRequest(description, keyData, Map.of(
            "created.by", "admin",
            "created.timestamp", String.valueOf(System.currentTimeMillis()),
            "environment", "production"
        ));
        
        try {
            secureStoreClient.createKey(keyId, request);
            System.out.println("Created secure key: " + keyName);
        } catch (Exception e) {
            System.err.println("Failed to create key " + keyName + ": " + e.getMessage());
        }
    }
    
    private String getSecureInput(String prompt) {
        // Implement secure input mechanism (e.g., read from environment, vault, etc.)
        return System.getenv("SECURE_" + prompt.toUpperCase().replace(" ", "_"));
    }
    
    private String generateEncryptionKey() {
        SecureRandom random = new SecureRandom();
        byte[] key = new byte[32]; // 256-bit key
        random.nextBytes(key);
        return Base64.getEncoder().encodeToString(key);
    }
}

Error Handling

Security and administrative operations may throw these exceptions:

  • NamespaceNotFoundException: Namespace does not exist
  • NamespaceAlreadyExistsException: Namespace already exists during creation
  • SecureKeyNotFoundException: Secure key does not exist
  • SecureKeyAlreadyExistsException: Secure key already exists during creation
  • UnauthorizedException: Insufficient permissions for security operations
  • UnauthenticatedException: Authentication required
try {
    NamespaceMeta namespace = namespaceClient.get(namespaceId);
    System.out.println("Namespace found: " + namespace.getName());
} catch (NamespaceNotFoundException e) {
    System.err.println("Namespace not found: " + namespaceId.getId());
} catch (UnauthorizedException e) {
    System.err.println("No permission to access namespace: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Network error: " + e.getMessage());
}

Best Practices

  1. Security First: Always use secure key storage for sensitive data
  2. Least Privilege: Grant minimum necessary permissions
  3. Metadata Governance: Implement consistent metadata tagging strategies
  4. Environment Separation: Use separate namespaces for different environments
  5. Key Rotation: Regularly rotate secure keys and credentials
  6. Audit Trail: Enable auditing for all security-related operations
// Good: Comprehensive security setup with proper error handling
public class SecurityManager {
    private final SecureStoreClient secureStoreClient;
    private final MetadataClient metadataClient;
    
    public SecurityManager(SecureStoreClient secureStoreClient, MetadataClient metadataClient) {
        this.secureStoreClient = secureStoreClient;
        this.metadataClient = metadataClient;
    }
    
    public void setupApplicationSecurity(ApplicationId appId, Map<String, String> credentials) {
        try {
            // Create secure keys for application
            for (Map.Entry<String, String> entry : credentials.entrySet()) {
                createApplicationSecureKey(appId, entry.getKey(), entry.getValue());
            }
            
            // Add security metadata
            addSecurityMetadata(appId);
            
            System.out.println("Security setup completed for application: " + appId.getApplication());
            
        } catch (Exception e) {
            System.err.println("Security setup failed for " + appId.getApplication() + ": " + e.getMessage());
            throw new SecurityException("Application security setup failed", e);
        }
    }
    
    private void createApplicationSecureKey(ApplicationId appId, String keyName, String keyValue) {
        SecureKeyId keyId = SecureKeyId.of(appId.getNamespace(), 
            appId.getApplication() + "-" + keyName);
        
        SecureKeyCreateRequest request = new SecureKeyCreateRequest(
            "Secure key for " + appId.getApplication() + " - " + keyName,
            keyValue,
            Map.of(
                "application", appId.getApplication(),
                "key-type", keyName,
                "created.timestamp", String.valueOf(System.currentTimeMillis())
            )
        );
        
        try {
            secureStoreClient.createKey(keyId, request);
            System.out.println("Created secure key: " + keyId.getName());
        } catch (SecureKeyAlreadyExistsException e) {
            System.out.println("Secure key already exists, skipping: " + keyId.getName());
        }
    }
    
    private void addSecurityMetadata(ApplicationId appId) {
        MetadataEntity entity = MetadataEntity.ofApplication(appId);
        
        metadataClient.addTags(entity, Set.of("secure", "credentials-managed"));
        metadataClient.addProperties(entity, Map.of(
            "security.credentials", "managed",
            "security.review.required", "true",
            "security.last.review", String.valueOf(System.currentTimeMillis())
        ));
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-cdap-cdap--cdap-client

docs

application-management.md

artifact-management.md

configuration.md

data-operations.md

dataset-operations.md

index.md

metrics-monitoring.md

program-control.md

schedule-management.md

security-administration.md

service-management.md

tile.json