Skip to content

Commit 0eac38a

Browse files
authored
Enhance Error Handling in VSecMHttpClient with Custom Exceptions and refactoring Javadocs (#1240)
* Updated Javadoc comments in VSecMHttpClient * Updated Javadoc comments in service/FetchService * Improved exception handling for client * Javadoc refactored * Exception folder created
1 parent 0483b66 commit 0eac38a

File tree

4 files changed

+196
-16
lines changed

4 files changed

+196
-16
lines changed

sdk-java/src/main/java/org/vsecm/client/VSecMHttpClient.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,62 @@
2626
*/
2727
public class VSecMHttpClient {
2828
private static final Logger LOGGER = Logger.getLogger(VSecMHttpClient.class.getName());
29+
30+
/**
31+
* The path to the SPIFFE socket used to communicate with the SPIFFE Workload API.
32+
* This socket provides access to the X.509 SVID (SPIFFE Verifiable Identity Document)
33+
* used for mutual TLS authentication.
34+
*/
2935
private static final String SPIFFE_SOCKET_PATH = "unix:///spire-agent-socket/spire-agent.sock";
3036

3137
/**
32-
* Creates an instance of {@link HttpClient} with SPIFFE-based SSL context.
33-
* This client can be used for secure HTTP communication.
38+
* Creates and configures an {@link HttpClient} instance with SPIFFE-based mutual TLS.
39+
* This client is used for secure communication with SPIFFE-enabled services.
40+
*
41+
* @return An instance of {@link HttpClient} configured with mutual TLS using SPIFFE credentials.
3442
*
35-
* @return A configured {@link HttpClient} instance ready for secure communication.
36-
* @throws RuntimeException if there's an issue configuring the SSL context,
37-
* encapsulating any underlying exceptions.
43+
* @throws VSecMHttpClientException.SocketPathError If the SPIFFE socket path is inaccessible.
44+
* @throws VSecMHttpClientException.X509FetchError If fetching X.509 SVIDs fails.
45+
* @throws VSecMHttpClientException.SSLContextError If SSLContext configuration fails.
46+
* @throws RuntimeException If an unknown error occurs during client initialization.
47+
*
48+
* @see #configureSSLContext()
3849
*/
3950
public HttpClient client() {
4051
try {
4152
SSLContext sslContext = configureSSLContext();
4253
return HttpClient.newBuilder().sslContext(sslContext).build();
4354
} catch (Exception e) {
4455
LOGGER.log(Level.SEVERE, "Failed to fetch secrets", e);
45-
throw new RuntimeException(e);
56+
57+
if (e instanceof SocketEndpointAddressException) {
58+
throw VSecMHttpClientException.socketPathError("SPIFFE socket path is inaccessible: " + e.getMessage());
59+
} else if (e instanceof X509SourceException) {
60+
throw VSecMHttpClientException.x509FetchError("Failed to fetch X.509 SVIDs: " + e.getMessage());
61+
} else if (e instanceof NoSuchAlgorithmException || e instanceof KeyManagementException) {
62+
throw VSecMHttpClientException.sslContextError("SSLContext configuration failed: " + e.getMessage());
63+
} else {
64+
throw new RuntimeException("Unknown error occurred: " + e.getMessage(), e);
65+
}
4666
}
4767
}
4868

4969
/**
50-
* Configures and returns an {@link SSLContext} suitable for SPIFFE based secure communication.
70+
* Configures and returns an {@link SSLContext} instance using SPIFFE credentials.
71+
* This method creates a secure SSL context that is configured with X.509 SVIDs
72+
* obtained from the SPIFFE Workload API to enable mutual TLS for communication.
5173
*
52-
* @return An {@link SSLContext} configured with SPIFFE X.509 SVIDs for mutual TLS.
53-
* @throws SocketEndpointAddressException If the SPIFFE Workload API socket endpoint address is incorrect.
54-
* @throws X509SourceException If there's an issue fetching or processing the X.509 SVIDs.
55-
* @throws NoSuchAlgorithmException If the SSL context cannot be instantiated due to a missing algorithm.
56-
* @throws KeyManagementException If there's an issue initializing the {@link SSLContext} with SPIFFE SVIDs.
74+
* @return A configured {@link SSLContext} that supports mutual TLS using SPIFFE identities.
75+
* @throws SocketEndpointAddressException If there is an issue with the SPIFFE socket path,
76+
* typically indicating that the SPIFFE Workload API is inaccessible.
77+
* @throws X509SourceException If there is an error fetching or processing the X.509 SVIDs from the SPIFFE Workload API.
78+
* @throws NoSuchAlgorithmException If the SSLContext cannot be instantiated due to a missing or unsupported algorithm.
79+
* @throws KeyManagementException If there is an issue initializing the SSLContext, typically indicating a problem
80+
* with key management or protocol setup.
81+
* @see DefaultX509Source
82+
* @see SpiffeSslContextFactory
5783
*/
84+
5885
private SSLContext configureSSLContext() throws SocketEndpointAddressException, X509SourceException, NoSuchAlgorithmException, KeyManagementException {
5986
DefaultX509Source.X509SourceOptions sourceOptions = DefaultX509Source.X509SourceOptions
6087
.builder()
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.vsecm.client;
2+
3+
/**
4+
* Custom exception class for handling errors in the VSecMHttpClient class.
5+
* Each error code corresponds to a specific type of failure encountered during
6+
* the HTTP client setup and SSL context configuration.
7+
*/
8+
public class VSecMHttpClientException extends RuntimeException {
9+
10+
// Error codes for different failure cases
11+
public static final int ERROR_CODE_SOCKET_PATH = 1000;
12+
public static final int ERROR_CODE_X509_FETCH = 1001;
13+
public static final int ERROR_CODE_SSL_CONTEXT = 1002;
14+
public static final int ERROR_CODE_KEY_MANAGEMENT = 1003;
15+
16+
private final int errorCode;
17+
18+
/**
19+
* Constructor for the custom exception.
20+
*
21+
* @param errorCode The specific error code representing the type of failure.
22+
* @param message The detailed error message.
23+
*/
24+
public VSecMHttpClientException(int errorCode, String message) {
25+
super(message);
26+
this.errorCode = errorCode;
27+
}
28+
29+
/**
30+
* Returns the error code associated with this exception.
31+
*
32+
* @return The error code.
33+
*/
34+
public int getErrorCode() {
35+
return errorCode;
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return "VSecMHttpClientException{" +
41+
"errorCode=" + errorCode +
42+
", message=" + getMessage() +
43+
'}';
44+
}
45+
46+
// Convenience methods for specific error codes
47+
48+
public static VSecMHttpClientException socketPathError(String message) {
49+
return new VSecMHttpClientException(ERROR_CODE_SOCKET_PATH, message);
50+
}
51+
52+
public static VSecMHttpClientException x509FetchError(String message) {
53+
return new VSecMHttpClientException(ERROR_CODE_X509_FETCH, message);
54+
}
55+
56+
public static VSecMHttpClientException sslContextError(String message) {
57+
return new VSecMHttpClientException(ERROR_CODE_SSL_CONTEXT, message);
58+
}
59+
60+
public static VSecMHttpClientException keyManagementError(String message) {
61+
return new VSecMHttpClientException(ERROR_CODE_KEY_MANAGEMENT, message);
62+
}
63+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.vsecm.exception;
2+
3+
4+
5+
/**
6+
* Custom exception class for handling errors in the VSecMHttpClient class.
7+
* Each error code corresponds to a specific type of failure encountered during
8+
* the HTTP client setup and SSL context configuration.
9+
*/
10+
11+
public class VSecMHttpClientException extends RuntimeException {
12+
13+
// Error codes for different failure cases
14+
public static final int ERROR_CODE_SOCKET_PATH = 1000;
15+
public static final int ERROR_CODE_X509_FETCH = 1001;
16+
public static final int ERROR_CODE_SSL_CONTEXT = 1002;
17+
public static final int ERROR_CODE_KEY_MANAGEMENT = 1003;
18+
19+
private final int errorCode;
20+
21+
/**
22+
* Constructor for the custom exception.
23+
*
24+
* @param errorCode The specific error code representing the type of failure.
25+
* @param message The detailed error message.
26+
*/
27+
28+
29+
public VSecMHttpClientException(int errorCode, String message) {
30+
super(message);
31+
this.errorCode = errorCode;
32+
}
33+
34+
35+
/**
36+
* Returns the error code associated with this exception.
37+
*
38+
* @return The error code.
39+
*/
40+
41+
public int getErrorCode() {
42+
return errorCode;
43+
}
44+
45+
46+
@Override
47+
public String toString() {
48+
return "VSecMHttpClientException{" +
49+
"errorCode=" + errorCode +
50+
", message=" + getMessage() +
51+
'}';
52+
}
53+
54+
// Convenience methods for specific error codes
55+
public static VSecMHttpClientException socketPathError(String message) {
56+
return new VSecMHttpClientException(ERROR_CODE_SOCKET_PATH, message);
57+
}
58+
59+
60+
public static VSecMHttpClientException x509FetchError(String message) {
61+
return new VSecMHttpClientException(ERROR_CODE_X509_FETCH, message);
62+
}
63+
64+
65+
public static VSecMHttpClientException sslContextError(String message) {
66+
return new VSecMHttpClientException(ERROR_CODE_SSL_CONTEXT, message);
67+
}
68+
69+
70+
public static VSecMHttpClientException keyManagementError(String message) {
71+
return new VSecMHttpClientException(ERROR_CODE_KEY_MANAGEMENT, message);
72+
}
73+
74+
}

sdk-java/src/main/java/org/vsecm/service/FetchService.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,27 @@ public final class FetchService {
2525
private FetchService(){}
2626

2727
/**
28-
* Fetches data as a {@link String} from the specified URI using an HTTP GET request.
29-
* This method utilizes a SPIFFE-enabled HTTP client for secure communication.
28+
* Fetches data from the specified URI using an HTTP GET request.
29+
* The request is sent over a secure channel using a SPIFFE-enabled HTTP client,
30+
* which ensures mutual TLS authentication as part of the communication process.
3031
*
31-
* @param secretUri The URI from which to fetch data. Must be a valid URI string.
32-
* @return The body of the HTTP response as a {@link String}. Returns an empty string if the request fails.
32+
* <p>This method constructs an HTTP GET request to the provided URI, sends the request
33+
* using the {@link VSecMHttpClient} (which handles SPIFFE-based secure communication),
34+
* and returns the response body as a {@link String}. If any errors occur during
35+
* the request (such as invalid URI, network issues, or interrupted request), an empty string
36+
* is returned, and the error is logged.</p>
37+
*
38+
* @param secretUri The URI from which to fetch the data. This must be a well-formed URI string
39+
* that points to a resource to be fetched.
40+
* Example: "https://example.com/data".
41+
* @return The body of the HTTP response as a {@link String}. If the request fails or an error occurs,
42+
* an empty string is returned.
43+
* @throws IllegalArgumentException if the URI is not valid or cannot be parsed.
44+
* @throws URISyntaxException if the provided URI is malformed or invalid.
45+
* @throws IOException if an I/O error occurs during communication with the server.
46+
* @throws InterruptedException if the request is interrupted during execution.
47+
*
48+
* @see VSecMHttpClient
3349
*/
3450
public static String fetch(String secretUri) {
3551
try {

0 commit comments

Comments
 (0)