CDAP Java Client library providing programmatic APIs for interacting with the CDAP platform
—
Security and administrative operations including namespace management, secure key storage, metadata management, authorization, and various utility functions for managing CDAP resources.
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)
}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);
}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)
}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
}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();
}// 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());
}// 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");// 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());// 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);// 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());// 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");
}// 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"
));// 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);// 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");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)
}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)
}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)
}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)
}public class MetaClient {
// Constructors
public MetaClient(ClientConfig config);
public MetaClient(ClientConfig config, RESTClient restClient);
// Meta information operations
// Common operations include:
// - getVersion()
// - ping()
// - getConfiguration()
}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);
}
}Security and administrative operations may throw these exceptions:
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());
}// 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