-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ✨ feat(VSecM): 448 Java SDK Create Java SDK poc Signed-off-by: sahinakyol <akyolsahinn@gmail.com> * ✨ feat(VSecM): 448 Remove unnecessary classes Signed-off-by: sahinakyol <akyolsahinn@gmail.com> * 📚 docs(VSecM): 448 Add simple doc Signed-off-by: sahinakyol <akyolsahinn@gmail.com> * 🐛 fix(VSecM): 448 Revert go changes Signed-off-by: sahinakyol <akyolsahinn@gmail.com> --------- Signed-off-by: sahinakyol <akyolsahinn@gmail.com>
- Loading branch information
1 parent
4b6521b
commit 564db67
Showing
14 changed files
with
527 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
target/ | ||
!.mvn/wrapper/maven-wrapper.jar | ||
!**/src/main/**/target/ | ||
!**/src/test/**/target/ | ||
|
||
### IntelliJ IDEA ### | ||
.idea/modules.xml | ||
.idea/jarRepositories.xml | ||
.idea/compiler.xml | ||
.idea/libraries/ | ||
*.iws | ||
*.iml | ||
*.ipr | ||
|
||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
build/ | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
### VS Code ### | ||
.vscode/ | ||
|
||
### Mac OS ### | ||
.DS_Store | ||
|
||
dependency-reduced-pom.xml | ||
|
||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# How to implement to your project | ||
|
||
``` | ||
<dependency> | ||
<groupId>org.wsecm</groupId> | ||
<artifactId>sdk-java</artifactId> | ||
<version>1.0.0</version> | ||
</dependency> | ||
``` | ||
|
||
``` | ||
public void start() { | ||
LOGGER.info("START...."); | ||
String fetch = fetch("https://vsecm-safe.vsecm-system.svc.cluster.local:8443/sentinel/v1/secrets?reveal=true"); | ||
LOGGER.info("RESULT .... " + fetch); | ||
TaskFactory taskFactory = new FetchSecretsTaskFactory(); | ||
Future<String> watchedData = watch(taskFactory, "https://vsecm-safe.vsecm-system.svc.cluster.local:8443/sentinel/v1/secrets?reveal=true"); | ||
if (watchedData.isDone()) { | ||
try { | ||
saveData(watchedData.get(), "/opt/vsecm/secrets.json"); | ||
} catch (InterruptedException | ExecutionException e) { | ||
LOGGER.info("ERROR .... " + e.getMessage()); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
# TEST INSTRUCTIONS | ||
- If you want to test properly you should revert changes to this **[commit](https://github.com/vmware-tanzu/secrets-manager/pull/732/commits/caa16943b6e2aeac714486b5e73b2aa13f1515c1)** | ||
- Check README |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>org.vsecm</groupId> | ||
<artifactId>sdk-java</artifactId> | ||
<version>1.0.0</version> | ||
<name>sdk-java</name> | ||
|
||
<properties> | ||
<maven.compiler.source>11</maven.compiler.source> | ||
<maven.compiler.target>11</maven.compiler.target> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.spiffe</groupId> | ||
<artifactId>java-spiffe-provider</artifactId> | ||
<version>0.8.6</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.spiffe</groupId> | ||
<artifactId>grpc-netty-linux</artifactId> | ||
<version>0.8.6</version> | ||
<scope>runtime</scope> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.13.0</version> | ||
<configuration> | ||
<release>11</release> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
76 changes: 76 additions & 0 deletions
76
sdk-java/src/main/java/org/vsecm/client/VSecMHttpClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/** | ||
* Provides an HTTP client configured with SPIFFE based SSL context for secure communication. | ||
* This client is specifically designed for environments that utilize SPIFFE for workload identification | ||
* and secure communication. | ||
* | ||
* <p>This implementation leverages the SPIFFE Workload API to fetch X.509 SVIDs for establishing TLS connections, | ||
* ensuring that the communication is both secure and aligned with the SPIFFE standards.</p> | ||
*/ | ||
package org.vsecm.client; | ||
|
||
import io.spiffe.exception.SocketEndpointAddressException; | ||
import io.spiffe.exception.X509SourceException; | ||
import io.spiffe.provider.SpiffeSslContextFactory; | ||
import io.spiffe.workloadapi.DefaultX509Source; | ||
|
||
import javax.net.ssl.SSLContext; | ||
import java.net.http.HttpClient; | ||
import java.security.KeyManagementException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* Represents a HTTP client that is secured with SPIFFE-based mutual TLS, | ||
* utilizing the SPIFFE Workload API for fetching SVIDs. | ||
*/ | ||
public class VSecMHttpClient { | ||
private static final Logger LOGGER = Logger.getLogger(VSecMHttpClient.class.getName()); | ||
private static final String SPIFFE_SOCKET_PATH = "unix:///spire-agent-socket/agent.sock"; | ||
|
||
/** | ||
* Creates an instance of {@link HttpClient} with SPIFFE-based SSL context. | ||
* This client can be used for secure HTTP communication. | ||
* | ||
* @return A configured {@link HttpClient} instance ready for secure communication. | ||
* @throws RuntimeException if there's an issue configuring the SSL context, | ||
* encapsulating any underlying exceptions. | ||
*/ | ||
public HttpClient client() { | ||
try { | ||
SSLContext sslContext = configureSSLContext(); | ||
return HttpClient.newBuilder().sslContext(sslContext).build(); | ||
} catch (Exception e) { | ||
LOGGER.log(Level.SEVERE, "Failed to fetch secrets", e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Configures and returns an {@link SSLContext} suitable for SPIFFE based secure communication. | ||
* | ||
* @return An {@link SSLContext} configured with SPIFFE X.509 SVIDs for mutual TLS. | ||
* @throws SocketEndpointAddressException If the SPIFFE Workload API socket endpoint address is incorrect. | ||
* @throws X509SourceException If there's an issue fetching or processing the X.509 SVIDs. | ||
* @throws NoSuchAlgorithmException If the SSL context cannot be instantiated due to a missing algorithm. | ||
* @throws KeyManagementException If there's an issue initializing the {@link SSLContext} with SPIFFE SVIDs. | ||
*/ | ||
private SSLContext configureSSLContext() throws SocketEndpointAddressException, X509SourceException, NoSuchAlgorithmException, KeyManagementException { | ||
DefaultX509Source.X509SourceOptions sourceOptions = DefaultX509Source.X509SourceOptions | ||
.builder() | ||
.spiffeSocketPath(SPIFFE_SOCKET_PATH) | ||
.build(); | ||
|
||
DefaultX509Source x509Source = DefaultX509Source.newSource(sourceOptions); | ||
LOGGER.info("SPIFFE_ID: " + x509Source.getX509Svid().getSpiffeId()); | ||
|
||
SpiffeSslContextFactory.SslContextOptions sslContextOptions = SpiffeSslContextFactory.SslContextOptions | ||
.builder() | ||
.acceptAnySpiffeId() | ||
.x509Source(x509Source) | ||
.build(); | ||
|
||
return SpiffeSslContextFactory.getSslContext(sslContextOptions); | ||
} | ||
|
||
} |
47 changes: 47 additions & 0 deletions
47
sdk-java/src/main/java/org/vsecm/service/FetchService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* A service class for fetching data from specified URIs using a SPIFFE-enabled HTTP client. | ||
* This service leverages {@link org.vsecm.client.VSecMHttpClient} for secure HTTP requests, | ||
* ensuring communication adheres to the SPIFFE standard for secure and authenticated connections. | ||
*/ | ||
package org.vsecm.service; | ||
|
||
import org.vsecm.client.VSecMHttpClient; | ||
|
||
import java.io.IOException; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* Provides static utility methods for fetching data from a specified URI. | ||
* This class cannot be instantiated and serves purely as a utility class. | ||
*/ | ||
public final class FetchService { | ||
private static final Logger LOGGER = Logger.getLogger(FetchService.class.getName()); | ||
|
||
private FetchService(){} | ||
|
||
/** | ||
* Fetches data as a {@link String} from the specified URI using an HTTP GET request. | ||
* This method utilizes a SPIFFE-enabled HTTP client for secure communication. | ||
* | ||
* @param secretUri The URI from which to fetch data. Must be a valid URI string. | ||
* @return The body of the HTTP response as a {@link String}. Returns an empty string if the request fails. | ||
*/ | ||
public static String fetch(String secretUri) { | ||
try { | ||
HttpRequest request = HttpRequest.newBuilder(new URI(secretUri)).GET().build(); | ||
VSecMHttpClient vSecMHttpClient = new VSecMHttpClient(); | ||
HttpResponse<String> response = vSecMHttpClient.client().send(request, HttpResponse.BodyHandlers.ofString()); | ||
LOGGER.info("Response status code: " + response.statusCode()); | ||
LOGGER.info("Response body: " + response.body()); | ||
return response.body(); | ||
} catch (URISyntaxException | IOException | InterruptedException e) { | ||
LOGGER.log(Level.SEVERE, "Failed processes when request to URI : " + secretUri, e); | ||
return ""; | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
sdk-java/src/main/java/org/vsecm/service/SaveToFileService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* Provides functionality to save data to a file, creating the necessary directories if they do not exist. | ||
* This service is designed to facilitate the saving of data to the file system, ensuring that the file | ||
* path's parent directories are created if necessary. | ||
*/ | ||
package org.vsecm.service; | ||
|
||
import java.io.BufferedWriter; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
/** | ||
* Utility class for saving data to a file. It ensures that the parent directories of the specified | ||
* file path are created before writing the data. This class cannot be instantiated. | ||
*/ | ||
public class SaveToFileService { | ||
private static final Logger LOGGER = Logger.getLogger(SaveToFileService.class.getName()); | ||
|
||
/** | ||
* Saves the provided data to a file at the specified path. If the file's parent directories do not exist, | ||
* they are created. If writing to the file fails, an error is logged. | ||
* | ||
* @param data The string data to be saved to the file. | ||
* @param pathStr The file system path where the data should be saved. Must be a valid path string. | ||
*/ | ||
public static void saveData(String data, String pathStr) { | ||
Path path = Paths.get(pathStr); | ||
|
||
// Attempt to create the directory(ies) if they don't exist | ||
try { | ||
Files.createDirectories(path.getParent()); | ||
} catch (IOException e) { | ||
LOGGER.log(Level.SEVERE, "Failed to create directory for secrets", e); | ||
return; | ||
} | ||
|
||
// Attempt to write the data to the file | ||
try (BufferedWriter writer = Files.newBufferedWriter(path)) { | ||
writer.write(data); | ||
} catch (IOException e) { | ||
LOGGER.log(Level.SEVERE, "Error saving data to " + pathStr, e); | ||
} | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
sdk-java/src/main/java/org/vsecm/service/WatchService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/** | ||
* Provides a scheduling service for executing tasks that monitor or interact with specified resources, such as URIs. | ||
* Utilizes a {@link TaskFactory} to create tasks that can be scheduled for execution. | ||
* This service is designed to be flexible, allowing for different types of tasks to be executed based on the implementation | ||
* provided by the {@link TaskFactory}. | ||
*/ | ||
package org.vsecm.service; | ||
|
||
import org.vsecm.task.Task; | ||
import org.vsecm.task.TaskFactory; | ||
|
||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
|
||
/** | ||
* A utility class for scheduling and executing tasks. This class cannot be instantiated and is used | ||
* to schedule tasks provided by a {@link TaskFactory}. The tasks can perform any operations defined | ||
* by their implementation, such as monitoring changes to a resource or processing data. | ||
*/ | ||
public final class WatchService { | ||
private WatchService() {} | ||
|
||
/** | ||
* Schedules and executes a task created by the provided {@link TaskFactory}. The task is executed | ||
* using a single-threaded {@link ScheduledExecutorService}. | ||
* | ||
* @param taskFactory The factory to create a task for execution. | ||
* @param secretUri The URI or resource identifier that the task will operate on or monitor. | ||
* @return A {@link Future} representing pending completion of the task. The future's get method will | ||
* return the task's result upon completion. | ||
*/ | ||
public static Future<String> watch(TaskFactory taskFactory, String secretUri) { | ||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); | ||
Task task = taskFactory.createTask(scheduler); | ||
return task.execute(secretUri); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
sdk-java/src/main/java/org/vsecm/task/FetchSecretsTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.vsecm.task; | ||
|
||
import org.vsecm.task.backoff.BackoffStrategy; | ||
|
||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import static org.vsecm.service.FetchService.fetch; | ||
|
||
/** | ||
* A task for fetching secrets from a specified URI, with retry logic based on a backoff strategy. | ||
* This task is designed to periodically fetch data, adjusting its retry interval based on the success | ||
* and failure outcomes of each attempt. | ||
*/ | ||
public class FetchSecretsTask implements Task { | ||
|
||
private static final Logger LOGGER = Logger.getLogger(FetchSecretsTask.class.getName()); | ||
private final ScheduledExecutorService scheduler; | ||
private final BackoffStrategy backoffStrategy; | ||
private long interval; | ||
private long successCount = 0; | ||
private long errorCount = 0; | ||
|
||
/** | ||
* Constructs a new {@code FetchSecretsTask} with the specified scheduler, backoff strategy, and initial interval. | ||
* | ||
* @param scheduler The {@link ScheduledExecutorService} to schedule task execution. | ||
* @param backoffStrategy The {@link BackoffStrategy} to determine the interval between retries. | ||
* @param initialInterval The initial interval (in milliseconds) before the first execution or retry. | ||
*/ | ||
public FetchSecretsTask(ScheduledExecutorService scheduler, BackoffStrategy backoffStrategy, long initialInterval) { | ||
this.scheduler = scheduler; | ||
this.backoffStrategy = backoffStrategy; | ||
this.interval = initialInterval; | ||
} | ||
|
||
/** | ||
* Schedules and executes the task of fetching secrets from the provided URI. If the fetch fails, | ||
* the task will retry based on the backoff strategy provided during construction. | ||
* | ||
* @param secretUri The URI from which to fetch secrets. | ||
* @return A {@link Future} representing pending completion of the task, containing the fetched data as a {@link String} | ||
* upon success, or {@code null} if an error occurs. | ||
*/ | ||
@Override | ||
public Future<String> execute(String secretUri) { | ||
Callable<String> task = () -> { | ||
try { | ||
String result = fetch(secretUri); | ||
successCount++; | ||
return result; | ||
} catch (Exception e) { | ||
errorCount++; | ||
interval = backoffStrategy.calculateBackoff(interval, successCount, errorCount); | ||
LOGGER.log(Level.WARNING, "Could not fetch secrets. Will retry in " + interval + "ms.", e); | ||
return null; | ||
} | ||
}; | ||
return scheduler.schedule(task, interval, TimeUnit.MILLISECONDS); | ||
} | ||
} |
Oops, something went wrong.