/**
* POST TITLE: CyberArk Conjur Secrets Management in Java
*
* Complete implementation of CyberArk Conjur for secrets management in Java applications
*/
import com.cyberark.conjur.api.Conjur;
import com.cyberark.conjur.api.Variables;
import com.cyberark.conjur.sdk.ApiException;
import com.cyberark.conjur.sdk.Configuration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.vault.annotation.VaultPropertySource;
import java.io.*;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.security.KeyStore;
import javax.net.ssl.*;
public class ConjurJavaIntegration {
/**
* Conjur Configuration Manager
*/
public static class ConjurConfigManager {
private final Path configPath;
private final Properties properties;
public ConjurConfigManager(Path configPath) {
this.configPath = configPath;
this.properties = new Properties();
}
/**
* Conjur Configuration
*/
public static class ConjurConfiguration {
private String applianceUrl;
private String account;
private String username;
private String password;
private String apiKey;
private String certFile;
private String authnUrl;
private boolean sslVerification = true;
private int timeout = 30;
public ConjurConfiguration(String applianceUrl, String account) {
this.applianceUrl = applianceUrl;
this.account = account;
}
// Builder methods
public ConjurConfiguration withUsername(String username) {
this.username = username;
return this;
}
public ConjurConfiguration withPassword(String password) {
this.password = password;
return this;
}
public ConjurConfiguration withApiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
public ConjurConfiguration withCertFile(String certFile) {
this.certFile = certFile;
return this;
}
public ConjurConfiguration withAuthnUrl(String authnUrl) {
this.authnUrl = authnUrl;
return this;
}
public ConjurConfiguration withSslVerification(boolean sslVerification) {
this.sslVerification = sslVerification;
return this;
}
public ConjurConfiguration withTimeout(int timeout) {
this.timeout = timeout;
return this;
}
// Getters
public String getApplianceUrl() { return applianceUrl; }
public String getAccount() { return account; }
public String getUsername() { return username; }
public String getPassword() { return password; }
public String getApiKey() { return apiKey; }
public String getCertFile() { return certFile; }
public String getAuthnUrl() { return authnUrl; }
public boolean isSslVerification() { return sslVerification; }
public int getTimeout() { return timeout; }
}
/**
* Create Conjur configuration file
*/
public void createConfiguration(ConjurConfiguration config) throws IOException {
properties.setProperty("CONJUR_APPLIANCE_URL", config.getApplianceUrl());
properties.setProperty("CONJUR_ACCOUNT", config.getAccount());
properties.setProperty("CONJUR_AUTHN_URL",
config.getAuthnUrl() != null ? config.getAuthnUrl() : config.getApplianceUrl() + "/authn");
if (config.getUsername() != null) {
properties.setProperty("CONJUR_AUTHN_LOGIN", config.getUsername());
}
if (config.getApiKey() != null) {
properties.setProperty("CONJUR_AUTHN_API_KEY", config.getApiKey());
}
if (config.getCertFile() != null) {
properties.setProperty("CONJUR_CERT_FILE", config.getCertFile());
}
properties.setProperty("CONJUR_SSL_CERTIFICATE",
config.isSslVerification() ? config.getCertFile() : "");
properties.setProperty("CONJUR_VERIFY_SSL",
String.valueOf(config.isSslVerification()));
try (FileOutputStream out = new FileOutputStream(configPath.toFile())) {
properties.store(out, "Conjur Configuration");
}
System.out.println("β
Conjur configuration created: " + configPath);
}
/**
* Load configuration from file
*/
public ConjurConfiguration loadConfiguration() throws IOException {
try (FileInputStream in = new FileInputStream(configPath.toFile())) {
properties.load(in);
}
return new ConjurConfiguration(
properties.getProperty("CONJUR_APPLIANCE_URL"),
properties.getProperty("CONJUR_ACCOUNT")
)
.withUsername(properties.getProperty("CONJUR_AUTHN_LOGIN"))
.withApiKey(properties.getProperty("CONJUR_AUTHN_API_KEY"))
.withCertFile(properties.getProperty("CONJUR_CERT_FILE"))
.withAuthnUrl(properties.getProperty("CONJUR_AUTHN_URL"))
.withSslVerification(Boolean.parseBoolean(properties.getProperty("CONJUR_VERIFY_SSL", "true")));
}
/**
* Create sample configuration for development
*/
public void createDevelopmentConfig() throws IOException {
ConjurConfiguration config = new ConjurConfiguration(
"https://conjur.example.com",
"my-account"
)
.withUsername("admin@my-account")
.withApiKey("your-api-key-here")
.withCertFile("/etc/conjur/conjur.pem")
.withSslVerification(true)
.withTimeout(30);
createConfiguration(config);
}
}
/**
* Conjur Client Wrapper
*/
public static class ConjurClient {
private final Conjur conjur;
private final Variables variables;
private final HttpClient httpClient;
private final ConjurConfigManager.ConjurConfiguration config;
public ConjurClient(ConjurConfigManager.ConjurConfiguration config) {
this.config = config;
configureConjurSDK(config);
this.conjur = new Conjur();
this.variables = conjur.variables();
this.httpClient = createHttpClient(config);
}
private void configureConjurSDK(ConjurConfigManager.ConjurConfiguration config) {
// Configure Conjur SDK
Configuration.setApplianceUrl(config.getApplianceUrl());
Configuration.setAccount(config.getAccount());
Configuration.setUsername(config.getUsername());
Configuration.setApiKey(config.getApiKey());
Configuration.setCertFile(config.getCertFile());
Configuration.setSslVerification(config.isSslVerification());
}
private HttpClient createHttpClient(ConjurConfigManager.ConjurConfiguration config) {
HttpClient.Builder builder = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(config.getTimeout()));
if (!config.isSslVerification() && config.getCertFile() != null) {
builder.sslContext(createSSLContext(config.getCertFile()));
}
return builder.build();
}
private SSLContext createSSLContext(String certFile) {
try {
// Load custom trust store with Conjur certificate
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
// Load Conjur certificate
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (FileInputStream fis = new FileInputStream(certFile)) {
Collection<? extends Certificate> certificates = cf.generateCertificates(fis);
int i = 0;
for (Certificate cert : certificates) {
trustStore.setCertificateEntry("conjur-cert-" + i++, cert);
}
}
// Create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext;
} catch (Exception e) {
throw new RuntimeException("Failed to create SSL context", e);
}
}
/**
* Retrieve secret by variable ID
*/
public String getSecret(String variableId) {
try {
System.out.println("π Retrieving secret: " + variableId);
String secret = variables.getVariable(variableId).retrieve();
System.out.println("β
Secret retrieved successfully");
return secret;
} catch (ApiException e) {
System.err.println("β Failed to retrieve secret: " + e.getMessage());
throw new RuntimeException("Secret retrieval failed", e);
}
}
/**
* Retrieve secret with retry logic
*/
public String getSecretWithRetry(String variableId, int maxRetries) {
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
return getSecret(variableId);
} catch (Exception e) {
if (attempt == maxRetries) {
throw e;
}
System.out.println("π Retry attempt " + attempt + " for: " + variableId);
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Retry interrupted", ie);
}
}
}
throw new RuntimeException("All retry attempts failed");
}
/**
* Retrieve multiple secrets
*/
public Map<String, String> getSecrets(List<String> variableIds) {
Map<String, String> secrets = new HashMap<>();
for (String variableId : variableIds) {
try {
secrets.put(variableId, getSecret(variableId));
} catch (Exception e) {
System.err.println("β Failed to retrieve secret: " + variableId);
// Continue with other secrets
}
}
return secrets;
}
/**
* Retrieve secrets in batch (parallel)
*/
public Map<String, String> getSecretsParallel(List<String> variableIds) {
ExecutorService executor = Executors.newFixedThreadPool(10);
Map<String, String> secrets = new ConcurrentHashMap<>();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (String variableId : variableIds) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
String secret = getSecret(variableId);
secrets.put(variableId, secret);
} catch (Exception e) {
System.err.println("β Failed to retrieve secret: " + variableId);
}
}, executor);
futures.add(future);
}
// Wait for all completions
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
executor.shutdown();
return secrets;
}
/**
* Add secret to Conjur
*/
public void addSecret(String variableId, String secretValue) {
try {
System.out.println("π Adding secret: " + variableId);
variables.getVariable(variableId).addSecret(secretValue);
System.out.println("β
Secret added successfully");
} catch (ApiException e) {
System.err.println("β Failed to add secret: " + e.getMessage());
throw new RuntimeException("Secret addition failed", e);
}
}
/**
* Check if secret exists
*/
public boolean secretExists(String variableId) {
try {
variables.getVariable(variableId).retrieve();
return true;
} catch (ApiException e) {
return false;
}
}
/**
* List all variables (requires appropriate permissions)
*/
public List<String> listVariables() {
try {
// This is a simplified implementation
// In reality, you'd use the appropriate Conjur API endpoint
return Collections.emptyList();
} catch (Exception e) {
System.err.println("β Failed to list variables: " + e.getMessage());
return Collections.emptyList();
}
}
/**
* Test connection to Conjur
*/
public boolean testConnection() {
try {
// Try to retrieve a known variable or use health check
conjur.variables().getVariable("test").retrieve();
return true;
} catch (Exception e) {
return false;
}
}
}
/**
* Secrets Management Service
*/
public static class SecretsManagementService {
private final ConjurClient conjurClient;
private final ScheduledExecutorService scheduler;
private final Map<String, String> secretCache;
private final long cacheRefreshInterval;
public SecretsManagementService(ConjurClient conjurClient) {
this.conjurClient = conjurClient;
this.scheduler = Executors.newScheduledThreadPool(1);
this.secretCache = new ConcurrentHashMap<>();
this.cacheRefreshInterval = 300000; // 5 minutes
startCacheRefresher();
}
/**
* Get secret with caching
*/
public String getSecret(String variableId) {
return getSecret(variableId, false);
}
public String getSecret(String variableId, boolean forceRefresh) {
if (forceRefresh || !secretCache.containsKey(variableId)) {
String secret = conjurClient.getSecret(variableId);
secretCache.put(variableId, secret);
return secret;
}
return secretCache.get(variableId);
}
/**
* Get database configuration secrets
*/
public DatabaseConfig getDatabaseConfig(String dbVariablePrefix) {
Map<String, String> secrets = conjurClient.getSecrets(Arrays.asList(
dbVariablePrefix + "/username",
dbVariablePrefix + "/password",
dbVariablePrefix + "/url",
dbVariablePrefix + "/port"
));
return new DatabaseConfig(
secrets.get(dbVariablePrefix + "/username"),
secrets.get(dbVariablePrefix + "/password"),
secrets.get(dbVariablePrefix + "/url"),
secrets.get(dbVariablePrefix + "/port")
);
}
/**
* Get API configuration secrets
*/
public ApiConfig getApiConfig(String apiVariablePrefix) {
Map<String, String> secrets = conjurClient.getSecrets(Arrays.asList(
apiVariablePrefix + "/key",
apiVariablePrefix + "/secret",
apiVariablePrefix + "/endpoint"
));
return new ApiConfig(
secrets.get(apiVariablePrefix + "/key"),
secrets.get(apiVariablePrefix + "/secret"),
secrets.get(apiVariablePrefix + "/endpoint")
);
}
/**
* Get SSL/TLS configuration
*/
public SSLConfig getSSLConfig(String sslVariablePrefix) {
Map<String, String> secrets = conjurClient.getSecrets(Arrays.asList(
sslVariablePrefix + "/keystore-password",
sslVariablePrefix + "/truststore-password",
sslVariablePrefix + "/key-alias"
));
return new SSLConfig(
secrets.get(sslVariablePrefix + "/keystore-password"),
secrets.get(sslVariablePrefix + "/truststore-password"),
secrets.get(sslVariablePrefix + "/key-alias")
);
}
/**
* Start background cache refresher
*/
private void startCacheRefresher() {
scheduler.scheduleAtFixedRate(() -> {
try {
refreshCache();
} catch (Exception e) {
System.err.println("β Cache refresh failed: " + e.getMessage());
}
}, cacheRefreshInterval, cacheRefreshInterval, TimeUnit.MILLISECONDS);
}
private void refreshCache() {
System.out.println("π Refreshing secret cache...");
List<String> keys = new ArrayList<>(secretCache.keySet());
for (String key : keys) {
try {
String newSecret = conjurClient.getSecret(key);
secretCache.put(key, newSecret);
} catch (Exception e) {
System.err.println("β Failed to refresh secret: " + key);
// Keep old value for now
}
}
}
/**
* Clear cache
*/
public void clearCache() {
secretCache.clear();
System.out.println("π§Ή Secret cache cleared");
}
/**
* Get cache statistics
*/
public CacheStats getCacheStats() {
return new CacheStats(
secretCache.size(),
System.currentTimeMillis()
);
}
/**
* Shutdown service
*/
public void shutdown() {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* Configuration Classes
*/
public static class DatabaseConfig {
private final String username;
private final String password;
private final String url;
private final String port;
public DatabaseConfig(String username, String password, String url, String port) {
this.username = username;
this.password = password;
this.url = url;
this.port = port;
}
// Getters
public String getUsername() { return username; }
public String getPassword() { return password; }
public String getUrl() { return url; }
public String getPort() { return port; }
public String getConnectionString() {
return String.format("jdbc:postgresql://%s:%s/mydb", url, port);
}
}
public static class ApiConfig {
private final String apiKey;
private final String apiSecret;
private final String endpoint;
public ApiConfig(String apiKey, String apiSecret, String endpoint) {
this.apiKey = apiKey;
this.apiSecret = apiSecret;
this.endpoint = endpoint;
}
// Getters
public String getApiKey() { return apiKey; }
public String getApiSecret() { return apiSecret; }
public String getEndpoint() { return endpoint; }
}
public static class SSLConfig {
private final String keystorePassword;
private final String truststorePassword;
private final String keyAlias;
public SSLConfig(String keystorePassword, String truststorePassword, String keyAlias) {
this.keystorePassword = keystorePassword;
this.truststorePassword = truststorePassword;
this.keyAlias = keyAlias;
}
// Getters
public String getKeystorePassword() { return keystorePassword; }
public String getTruststorePassword() { return truststorePassword; }
public String getKeyAlias() { return keyAlias; }
}
public static class CacheStats {
private final int cacheSize;
private final long lastRefresh;
public CacheStats(int cacheSize, long lastRefresh) {
this.cacheSize = cacheSize;
this.lastRefresh = lastRefresh;
}
// Getters
public int getCacheSize() { return cacheSize; }
public long getLastRefresh() { return lastRefresh; }
}
/**
* Spring Boot Integration
*/
@Configuration
@ConfigurationProperties(prefix = "conjur")
public static class ConjurProperties {
private String applianceUrl;
private String account;
private String username;
private String apiKey;
private String certFile;
private boolean sslVerification = true;
// Getters and setters
public String getApplianceUrl() { return applianceUrl; }
public void setApplianceUrl(String applianceUrl) { this.applianceUrl = applianceUrl; }
public String getAccount() { return account; }
public void setAccount(String account) { this.account = account; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getApiKey() { return apiKey; }
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
public String getCertFile() { return certFile; }
public void setCertFile(String certFile) { this.certFile = certFile; }
public boolean isSslVerification() { return sslVerification; }
public void setSslVerification(boolean sslVerification) { this.sslVerification = sslVerification; }
}
@SpringBootApplication
public static class ConjurIntegrationApplication {
@Bean
public ConjurConfigManager conjurConfigManager(@Value("${conjur.config.path:./conjur.properties}") String configPath) {
return new ConjurConfigManager(Paths.get(configPath));
}
@Bean
public ConjurClient conjurClient(ConjurProperties properties) {
ConjurConfigManager.ConjurConfiguration config =
new ConjurConfigManager.ConjurConfiguration(
properties.getApplianceUrl(),
properties.getAccount()
)
.withUsername(properties.getUsername())
.withApiKey(properties.getApiKey())
.withCertFile(properties.getCertFile())
.withSslVerification(properties.isSslVerification());
return new ConjurClient(config);
}
@Bean
public SecretsManagementService secretsManagementService(ConjurClient conjurClient) {
return new SecretsManagementService(conjurClient);
}
}
@RestController
@RequestMapping("/api/secrets")
public static class SecretsController {
private final SecretsManagementService secretsService;
private final ConjurClient conjurClient;
public SecretsController(SecretsManagementService secretsService,
ConjurClient conjurClient) {
this.secretsService = secretsService;
this.conjurClient = conjurClient;
}
@GetMapping("/{variableId}")
public ResponseEntity<Map<String, String>> getSecret(@PathVariable String variableId) {
try {
String secret = secretsService.getSecret(variableId);
return ResponseEntity.ok(Map.of(
"variableId", variableId,
"secret", "***" // Don't expose actual secret in response
));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", "Failed to retrieve secret: " + e.getMessage()));
}
}
@PostMapping("/{variableId}")
public ResponseEntity<String> addSecret(@PathVariable String variableId,
@RequestBody Map<String, String> request) {
try {
String secretValue = request.get("value");
conjurClient.addSecret(variableId, secretValue);
return ResponseEntity.ok("Secret added successfully");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Failed to add secret: " + e.getMessage());
}
}
@GetMapping("/database/{prefix}")
public ResponseEntity<DatabaseConfig> getDatabaseConfig(@PathVariable String prefix) {
try {
DatabaseConfig config = secretsService.getDatabaseConfig(prefix);
return ResponseEntity.ok(config);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@GetMapping("/api/{prefix}")
public ResponseEntity<ApiConfig> getApiConfig(@PathVariable String prefix) {
try {
ApiConfig config = secretsService.getApiConfig(prefix);
return ResponseEntity.ok(config);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@GetMapping("/cache/stats")
public ResponseEntity<CacheStats> getCacheStats() {
try {
CacheStats stats = secretsService.getCacheStats();
return ResponseEntity.ok(stats);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@PostMapping("/cache/clear")
public ResponseEntity<String> clearCache() {
try {
secretsService.clearCache();
return ResponseEntity.ok("Cache cleared successfully");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Failed to clear cache: " + e.getMessage());
}
}
@GetMapping("/health")
public ResponseEntity<Map<String, String>> healthCheck() {
try {
boolean healthy = conjurClient.testConnection();
Map<String, String> response = new HashMap<>();
response.put("status", healthy ? "healthy" : "unhealthy");
response.put("timestamp", new Date().toString());
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("status", "error", "error", e.getMessage()));
}
}
}
/**
* Kubernetes Integration for Conjur
*/
public static class KubernetesConjurIntegration {
private final KubernetesClient k8sClient;
public KubernetesConjurIntegration(KubernetesClient k8sClient) {
this.k8sClient = k8sClient;
}
/**
* Create Kubernetes secret from Conjur variables
*/
public void createK8sSecretFromConjur(String secretName, String namespace,
Map<String, String> conjurVariables,
ConjurClient conjurClient) {
try {
Map<String, String> secrets = conjurClient.getSecrets(
new ArrayList<>(conjurVariables.keySet())
);
Map<String, String> data = new HashMap<>();
for (Map.Entry<String, String> entry : conjurVariables.entrySet()) {
String conjurVar = entry.getKey();
String k8sKey = entry.getValue();
data.put(k8sKey, secrets.get(conjurVar));
}
Secret secret = new SecretBuilder()
.withNewMetadata()
.withName(secretName)
.withNamespace(namespace)
.endMetadata()
.withStringData(data)
.build();
k8sClient.secrets().inNamespace(namespace).createOrReplace(secret);
System.out.println("β
Kubernetes secret created: " + secretName);
} catch (Exception e) {
System.err.println("β Failed to create Kubernetes secret: " + e.getMessage());
throw new RuntimeException("Kubernetes secret creation failed", e);
}
}
/**
* Create Conjur-authenticated deployment
*/
public void createConjurAuthenticatedDeployment(String name, String namespace,
String conjurAccount,
String conjurAuthnUrl) {
try {
Deployment deployment = new DeploymentBuilder()
.withNewMetadata()
.withName(name)
.withNamespace(namespace)
.endMetadata()
.withNewSpec()
.withReplicas(1)
.withNewSelector()
.addToMatchLabels("app", name)
.endSelector()
.withNewTemplate()
.withNewMetadata()
.withLabels(Map.of("app", name))
.endMetadata()
.withNewSpec()
.withContainers(createConjurContainer(name))
.withVolumes(createConjurVolumes())
.endSpec()
.endTemplate()
.endSpec()
.build();
k8sClient.apps().deployments().inNamespace(namespace).createOrReplace(deployment);
System.out.println("β
Conjur-authenticated deployment created: " + name);
} catch (Exception e) {
System.err.println("β Failed to create deployment: " + e.getMessage());
throw new RuntimeException("Deployment creation failed", e);
}
}
private List<Container> createConjurContainer(String name) {
Container container = new ContainerBuilder()
.withName(name)
.withImage("my-app:latest")
.withEnv(Arrays.asList(
new EnvVarBuilder()
.withName("CONJUR_APPLIANCE_URL")
.withValueFrom(new EnvVarSourceBuilder()
.withSecretKeyRef(new SecretKeySelectorBuilder()
.withName("conjur-config")
.withKey("appliance-url")
.build())
.build())
.build(),
new EnvVarBuilder()
.withName("CONJUR_ACCOUNT")
.withValueFrom(new EnvVarSourceBuilder()
.withSecretKeyRef(new SecretKeySelectorBuilder()
.withName("conjur-config")
.withKey("account")
.build())
.build())
.build(),
new EnvVarBuilder()
.withName("CONJUR_AUTHN_URL")
.withValueFrom(new EnvVarSourceBuilder()
.withSecretKeyRef(new SecretKeySelectorBuilder()
.withName("conjur-config")
.withKey("authn-url")
.build())
.build())
.build()
))
.withVolumeMounts(Arrays.asList(
new VolumeMountBuilder()
.withName("conjur-cert")
.withMountPath("/etc/conjur")
.withReadOnly(true)
.build()
))
.build();
return Arrays.asList(container);
}
private List<Volume> createConjurVolumes() {
return Arrays.asList(
new VolumeBuilder()
.withName("conjur-cert")
.withSecret(new SecretVolumeSourceBuilder()
.withSecretName("conjur-certificate")
.build())
.build()
);
}
}
/**
* Demo and Usage Examples
*/
public static void main(String[] args) {
System.out.println("π CyberArk Conjur Java Integration");
System.out.println("===================================\n");
try {
// Demo 1: Configuration Management
System.out.println("1. βοΈ Configuration Management");
Path tempDir = Files.createTempDirectory("conjur-demo");
ConjurConfigManager configManager = new ConjurConfigManager(
tempDir.resolve("conjur.properties"));
configManager.createDevelopmentConfig();
System.out.println(" Configuration file created");
// Demo 2: Conjur Client
System.out.println("\n2. π Conjur Client Operations");
ConjurConfigManager.ConjurConfiguration config = configManager.loadConfiguration();
ConjurClient conjurClient = new ConjurClient(config);
System.out.println(" Conjur client initialized");
System.out.println(" Connection test: " + conjurClient.testConnection());
// Demo 3: Secrets Management
System.out.println("\n3. ποΈ Secrets Management");
SecretsManagementService secretsService = new SecretsManagementService(conjurClient);
// Example secret operations (commented out as they require actual Conjur instance)
/*
String dbPassword = secretsService.getSecret("myapp/database/password");
DatabaseConfig dbConfig = secretsService.getDatabaseConfig("myapp/database");
ApiConfig apiConfig = secretsService.getApiConfig("myapp/external-api");
*/
System.out.println(" Secrets management service initialized");
System.out.println(" Automatic cache refresh enabled");
// Demo 4: Cache Management
System.out.println("\n4. πΎ Cache Management");
CacheStats stats = secretsService.getCacheStats();
System.out.println(" Cache size: " + stats.getCacheSize());
System.out.println(" Last refresh: " + new Date(stats.getLastRefresh()));
// Demo 5: Kubernetes Integration
System.out.println("\n5. βΈοΈ Kubernetes Integration");
try (KubernetesClient k8sClient = new KubernetesClientBuilder().build()) {
KubernetesConjurIntegration k8sIntegration =
new KubernetesConjurIntegration(k8sClient);
System.out.println(" Kubernetes integration ready");
System.out.println(" Can create Conjur-authenticated deployments");
}
// Cleanup
secretsService.shutdown();
deleteDirectory(tempDir);
System.out.println("\nβ
Conjur Java Integration Demo Completed");
System.out.println("\nπ Key Features:");
System.out.println(" - Secure secrets retrieval and management");
System.out.println(" - Automatic secret caching with refresh");
System.out.println(" - Kubernetes integration for secret injection");
System.out.println(" - SSL/TLS configuration support");
System.out.println(" - Spring Boot auto-configuration");
System.out.println(" - Health checks and monitoring");
} catch (Exception e) {
System.err.println("β Demo failed: " + e.getMessage());
e.printStackTrace();
}
}
private static void deleteDirectory(Path path) throws IOException {
Files.walk(path)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
}
}
Maven Dependencies
<!-- pom.xml --> <dependencies> <!-- CyberArk Conjur SDK --> <dependency> <groupId>com.cyberark</groupId> <artifactId>conjur-api</artifactId> <version>2.0.0</version> </dependency> <!-- Kubernetes Client --> <dependency> <groupId>io.fabric8</groupId> <artifactId>kubernetes-client</artifactId> <version>6.8.0</version> </dependency> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.7.0</version> </dependency> <!-- HTTP Client --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.20</version> </dependency> </dependencies>
Configuration Examples
application.yml
conjur:
appliance-url: https://conjur.example.com
account: my-account
username: admin@my-account
api-key: ${CONJUR_API_KEY}
cert-file: /etc/conjur/conjur.pem
ssl-verification: true
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: ${db.username}
password: ${db.password}
management:
endpoints:
web:
exposure:
include: health,info,metrics
conjur.properties
CONJUR_APPLIANCE_URL=https://conjur.example.com CONJUR_ACCOUNT=my-account CONJUR_AUTHN_LOGIN=admin@my-account CONJUR_AUTHN_API_KEY=your-api-key-here CONJUR_CERT_FILE=/etc/conjur/conjur.pem CONJUR_VERIFY_SSL=true
Kubernetes Manifest Example
apiVersion: v1 kind: Secret metadata: name: conjur-config namespace: default stringData: appliance-url: https://conjur.example.com account: my-account authn-url: https://conjur.example.com/authn --- apiVersion: apps/v1 kind: Deployment metadata: name: my-app namespace: default spec: replicas: 1 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-app image: my-app:latest env: - name: CONJUR_APPLIANCE_URL valueFrom: secretKeyRef: name: conjur-config key: appliance-url - name: CONJUR_ACCOUNT valueFrom: secretKeyRef: name: conjur-config key: account - name: CONJUR_AUTHN_URL valueFrom: secretKeyRef: name: conjur-config key: authn-url volumeMounts: - name: conjur-cert mountPath: /etc/conjur readOnly: true volumes: - name: conjur-cert secret: secretName: conjur-certificate
Usage Examples
// Initialize Conjur client
ConjurConfigManager.ConjurConfiguration config = new ConjurConfigManager.ConjurConfiguration(
"https://conjur.example.com", "my-account")
.withUsername("admin@my-account")
.withApiKey("your-api-key")
.withCertFile("/etc/conjur/conjur.pem");
ConjurClient conjurClient = new ConjurClient(config);
// Create secrets management service
SecretsManagementService secretsService = new SecretsManagementService(conjurClient);
// Retrieve secrets
String dbPassword = secretsService.getSecret("myapp/database/password");
DatabaseConfig dbConfig = secretsService.getDatabaseConfig("myapp/database");
// Use in application
DataSource dataSource = DataSourceBuilder.create()
.url(dbConfig.getConnectionString())
.username(dbConfig.getUsername())
.password(dbConfig.getPassword())
.build();
This CyberArk Conjur integration provides:
- Complete Conjur Client implementation with proper authentication
- Secrets Management Service with caching and automatic refresh
- Configuration Management for different environments
- Kubernetes Integration for secret injection and deployments
- Spring Boot Auto-configuration for easy setup
- SSL/TLS Support with custom certificate handling
- Health Monitoring and connection testing
- Batch Operations for efficient secret retrieval
- Error Handling with retry mechanisms
- Security Best Practices for secrets management
The solution enables Java applications to securely manage secrets using CyberArk Conjur while providing enterprise-grade features for production environments.
Java Logistics, Shipping Integration & Enterprise Inventory Automation (Tracking, ERP, RFID & Billing Systems)
https://macronepal.com/blog/aftership-tracking-in-java-enterprise-package-visibility/
Explains how to integrate AfterShip tracking services into Java applications to provide real-time shipment visibility, delivery status updates, and centralized tracking across multiple courier services.
https://macronepal.com/blog/shipping-integration-using-fedex-api-with-java-for-logistics-automation/
Explains how to integrate the FedEx API into Java systems to automate shipping tasks such as creating shipments, calculating delivery costs, generating shipping labels, and tracking packages.
https://macronepal.com/blog/shipping-and-logistics-integrating-ups-apis-with-java-applications/
Explains UPS API integration in Java to enable automated shipping operations including rate calculation, shipment scheduling, tracking, and delivery confirmation management.
https://macronepal.com/blog/generating-and-reading-qr-codes-for-products-in-java/
Explains how Java applications generate and read QR codes for product identification, tracking, and authentication, supporting faster inventory handling and product verification processes.
https://macronepal.com/blog/designing-a-robust-pick-and-pack-workflow-in-java/
Explains how to design an efficient pick-and-pack workflow in Java warehouse systems, covering order processing, item selection, packaging steps, and logistics preparation to improve fulfillment efficiency.
https://macronepal.com/blog/rfid-inventory-management-system-in-java-a-complete-guide/
Explains how RFID technology integrates with Java applications to automate inventory tracking, reduce manual errors, and enable real-time stock monitoring in warehouses and retail environments.
https://macronepal.com/blog/erp-integration-with-odoo-in-java/
Explains how Java applications connect with Odoo ERP systems to synchronize inventory, orders, customer records, and financial data across enterprise systems.
https://macronepal.com/blog/automated-invoice-generation-creating-professional-excel-invoices-with-apache-poi-in-java/
Explains how to automatically generate professional Excel invoices in Java using Apache POI, enabling structured billing documents and automated financial record creation.
https://macronepal.com/blog/enterprise-financial-integration-using-quickbooks-api-in-java-applications/
Explains QuickBooks API integration in Java to automate financial workflows such as invoice management, payment tracking, accounting synchronization, and financial reporting.