Skip to content

Commit 48bf294

Browse files
SK-2071: Merge branch 'v2' into saileshwar-skyflow/SK-2071-deidentify-file
2 parents 2584322 + f656d60 commit 48bf294

File tree

16 files changed

+642
-397
lines changed

16 files changed

+642
-397
lines changed

README.md

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ The Skyflow Java SDK is designed to help with integrating Skyflow into a Java ba
4444
- [Generate bearer tokens with context](#generate-bearer-tokens-with-context)
4545
- [Generate scoped bearer tokens](#generate-scoped-bearer-tokens)
4646
- [Generate signed data tokens](#generate-signed-data-tokens)
47+
- [Bearer token expiry edge case](#bearer-token-expiry-edge-case)
4748
- [Logging](#logging)
4849
- [Reporting a Vulnerability](#reporting-a-vulnerability)
4950

@@ -2147,7 +2148,7 @@ Notes:
21472148
- If both a file path and a string are provided, the last method used takes precedence.
21482149
- To generate multiple bearer tokens concurrently using threads, refer to the following [example](https://github.com/skyflowapi/skyflow-java/blob/main/samples/src/main/java/com/example/serviceaccount/BearerTokenGenerationUsingThreadsExample.java).
21492150

2150-
## Signed Data Tokens Generation
2151+
## Generate Signed Data Tokens
21512152

21522153
Skyflow generates data tokens when sensitive data is inserted into the vault. These data tokens can be digitally signed
21532154
with the private key of the service account credentials, which adds an additional layer of protection. Signed tokens can
@@ -2225,6 +2226,106 @@ Notes:
22252226
- The `time-to-live` (TTL) value should be specified in seconds.
22262227
- By default, the TTL value is set to 60 seconds.
22272228

2229+
## Bearer token expiry edge case
2230+
When you use bearer tokens for authentication and API requests in SDKs, there's the potential for a token to expire after the token is verified as valid but before the actual API call is made, causing the request to fail unexpectedly due to the token's expiration. An error from this edge case would look something like this:
2231+
2232+
```txt
2233+
message: Authentication failed. Bearer token is expired. Use a valid bearer token. See https://docs.skyflow.com/api-authentication/
2234+
```
2235+
2236+
If you encounter this kind of error, retry the request. During the retry, the SDK detects that the previous bearer token has expired and generates a new one for the current and subsequent requests.
2237+
2238+
#### [Example](https://github.com/skyflowapi/skyflow-java/blob/v2/samples/src/main/java/com/example/serviceaccount/BearerTokenExpiryExample.java):
2239+
2240+
```java
2241+
package com.example.serviceaccount;
2242+
2243+
import com.skyflow.Skyflow;
2244+
import com.skyflow.config.Credentials;
2245+
import com.skyflow.config.VaultConfig;
2246+
import com.skyflow.enums.Env;
2247+
import com.skyflow.enums.LogLevel;
2248+
import com.skyflow.enums.RedactionType;
2249+
import com.skyflow.errors.SkyflowException;
2250+
import com.skyflow.vault.tokens.DetokenizeRequest;
2251+
import com.skyflow.vault.tokens.DetokenizeResponse;
2252+
import io.github.cdimascio.dotenv.Dotenv;
2253+
import java.util.ArrayList;
2254+
2255+
/**
2256+
* This example demonstrates how to configure and use the Skyflow SDK
2257+
* to detokenize sensitive data stored in a Skyflow vault.
2258+
* It includes setting up credentials, configuring the vault, and
2259+
* making a detokenization request. The code also implements a retry
2260+
* mechanism to handle unauthorized access errors (HTTP 401).
2261+
*/
2262+
public class DetokenizeExample {
2263+
public static void main(String[] args) {
2264+
try {
2265+
// Setting up credentials for accessing the Skyflow vault
2266+
Credentials vaultCredentials = new Credentials();
2267+
vaultCredentials.setCredentialsString("<YOUR_CREDENTIALS_STRING>");
2268+
2269+
// Configuring the Skyflow vault with necessary details
2270+
VaultConfig vaultConfig = new VaultConfig();
2271+
vaultConfig.setVaultId("<YOUR_VAULT_ID>"); // Vault ID
2272+
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>"); // Cluster ID
2273+
vaultConfig.setEnv(Env.PROD); // Environment (e.g., DEV, PROD)
2274+
vaultConfig.setCredentials(vaultCredentials); // Setting credentials
2275+
2276+
// Creating a Skyflow client instance with the configured vault
2277+
Skyflow skyflowClient = Skyflow.builder()
2278+
.setLogLevel(LogLevel.ERROR) // Setting log level to ERROR
2279+
.addVaultConfig(vaultConfig) // Adding vault configuration
2280+
.build();
2281+
2282+
// Attempting to detokenize data using the Skyflow client
2283+
try {
2284+
detokenizeData(skyflowClient);
2285+
} catch (SkyflowException e) {
2286+
// Retry detokenization if the error is due to unauthorized access (HTTP 401)
2287+
if (e.getHttpCode() == 401) {
2288+
detokenizeData(skyflowClient);
2289+
} else {
2290+
// Rethrow the exception for other error codes
2291+
throw e;
2292+
}
2293+
}
2294+
} catch (SkyflowException e) {
2295+
// Handling any exceptions that occur during the process
2296+
System.out.println("An error occurred: " + e.getMessage());
2297+
}
2298+
}
2299+
2300+
/**
2301+
* Method to detokenize data using the Skyflow client.
2302+
* It sends a detokenization request with a list of tokens and prints the response.
2303+
*
2304+
* @param skyflowClient The Skyflow client instance used for detokenization.
2305+
* @throws SkyflowException If an error occurs during the detokenization process.
2306+
*/
2307+
public static void detokenizeData(Skyflow skyflowClient) throws SkyflowException {
2308+
// Creating a list of tokens to be detokenized
2309+
ArrayList<String> tokenList = new ArrayList<>();
2310+
tokenList.add("<YOUR_TOKEN_VALUE_1>"); // First token
2311+
tokenList.add("<YOUR_TOKEN_VALUE_2>"); // Second token
2312+
2313+
// Building a detokenization request with the token list and configuration
2314+
DetokenizeRequest detokenizeRequest = DetokenizeRequest.builder()
2315+
.tokens(tokenList) // Adding tokens to the request
2316+
.continueOnError(false) // Stop on error
2317+
.redactionType(RedactionType.PLAIN_TEXT) // Redaction type (e.g., PLAIN_TEXT)
2318+
.build();
2319+
2320+
// Sending the detokenization request and receiving the response
2321+
DetokenizeResponse detokenizeResponse = skyflowClient.vault().detokenize(detokenizeRequest);
2322+
2323+
// Printing the detokenized response
2324+
System.out.println(detokenizeResponse);
2325+
}
2326+
}
2327+
```
2328+
22282329
# Logging
22292330

22302331
The SDK provides logging with Java's built-in logging library. By default, the SDK's logging level is set to `LogLevel.ERROR`. This can be changed using the `setLogLevel(logLevel)` method, as shown below:

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.skyflow</groupId>
88
<artifactId>skyflow-java</artifactId>
9-
<version>2.0.0-beta.1-dev.ea71c1d</version>
9+
<version>2.0.0-beta.1-dev.ec349a9</version>
1010
<packaging>jar</packaging>
1111

1212
<name>${project.groupId}:${project.artifactId}</name>

samples/src/main/java/com/example/connection/InvokeConnectionExample.java

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,92 +13,89 @@
1313
import java.util.Map;
1414

1515
/**
16-
* This example demonstrates how to use the Skyflow SDK to invoke connections for different endpoints with different configurations.
16+
* This example demonstrates how to use the Skyflow SDK to invoke API connections.
1717
* It includes:
18-
* 1. Setting up connection configurations.
19-
* 2. Creating a Skyflow client.
20-
* 3. Sending POST and GET requests to connections.
18+
* 1. Setting up credentials and connection configurations.
19+
* 2. Creating a Skyflow client with multiple connections.
20+
* 3. Sending a POST request with request body and headers.
21+
* 4. Sending a GET request with path and query parameters.
2122
*/
2223
public class InvokeConnectionExample {
2324
public static void main(String[] args) throws SkyflowException {
24-
// Step 1: Set up credentials for the first connection configuration
25+
// Step 1: Set up credentials for API authentication
2526
Credentials credentials = new Credentials();
26-
credentials.setPath("<YOUR_CREDENTIALS_FILE_PATH_1>"); // Replace with the path to the credentials file
27+
credentials.setApiKey("<YOUR_API_KEY>"); // Replace with the actual API key
2728

28-
// Step 2: Configure the first connection (Connection 1)
29-
ConnectionConfig connectionConfig1 = new ConnectionConfig();
30-
connectionConfig1.setConnectionId("<YOUR_CONNECTION_ID_1>"); // Replace with the ID of the first connection
31-
connectionConfig1.setConnectionUrl("<YOUR_CONNECTION_URL_1>"); // Replace with the URL of the first connection
32-
connectionConfig1.setCredentials(credentials); // Associate credentials for the first connection
29+
// Step 2: Configure the first connection
30+
ConnectionConfig primaryConnectionConfig = new ConnectionConfig();
31+
primaryConnectionConfig.setConnectionId("<YOUR_CONNECTION_ID_1>"); // Replace with first connection ID
32+
primaryConnectionConfig.setConnectionUrl("<YOUR_CONNECTION_URL_1>"); // Replace with first connection URL
33+
primaryConnectionConfig.setCredentials(credentials); // Assign credentials
3334

34-
// Step 3: Configure the second connection (Connection 2)
35-
ConnectionConfig connectionConfig2 = new ConnectionConfig();
36-
connectionConfig2.setConnectionId("<YOUR_CONNECTION_ID_2>"); // Replace with the ID of the second connection
37-
connectionConfig2.setConnectionUrl("<YOUR_CONNECTION_URL_2>"); // Replace with the URL of the second connection
35+
// Step 3: Configure the second connection
36+
ConnectionConfig secondaryConnectionConfig = new ConnectionConfig();
37+
secondaryConnectionConfig.setConnectionId("<YOUR_CONNECTION_ID_2>"); // Replace with second connection ID
38+
secondaryConnectionConfig.setConnectionUrl("<YOUR_CONNECTION_URL_2>"); // Replace with second connection URL
3839

3940
// Step 4: Set up credentials for the Skyflow client
4041
Credentials skyflowCredentials = new Credentials();
41-
skyflowCredentials.setPath("<YOUR_CREDENTIALS_FILE_PATH_2>"); // Replace with the path to another credentials file
42+
skyflowCredentials.setCredentialsString("<YOUR_CREDENTIALS_STRING>"); // Replace with the credentials string
4243

43-
// Step 5: Create a Skyflow client and add connection configurations
44+
// Step 5: Create a Skyflow client with connection configurations
4445
Skyflow skyflowClient = Skyflow.builder()
45-
.setLogLevel(LogLevel.DEBUG) // Enable debugging for detailed logs
46-
.addConnectionConfig(connectionConfig1) // Add the first connection configuration
47-
.addConnectionConfig(connectionConfig2) // Add the second connection configuration
48-
.addSkyflowCredentials(skyflowCredentials) // Add general Skyflow credentials
46+
.setLogLevel(LogLevel.ERROR) // Set log level to ERROR
47+
.addConnectionConfig(primaryConnectionConfig) // Add the first connection
48+
.addConnectionConfig(secondaryConnectionConfig) // Add the second connection
49+
.addSkyflowCredentials(skyflowCredentials) // Provide Skyflow credentials
4950
.build();
5051

5152
// Example 1: Sending a POST request to the first connection
5253
try {
53-
// Set up the request body and headers for the POST request
54+
// Set up request body and headers
5455
Map<String, String> requestBody = new HashMap<>();
55-
requestBody.put("<COLUMN_NAME_1>", "<COLUMN_VALUE_1>"); // Replace with the actual column name and value
56+
requestBody.put("<COLUMN_NAME_1>", "<COLUMN_VALUE_1>"); // Replace with actual column name and value
5657
requestBody.put("<COLUMN_NAME_2>", "<COLUMN_VALUE_2>"); // Replace with another column name and value
5758

5859
Map<String, String> requestHeaders = new HashMap<>();
59-
requestHeaders.put("<HEADER_NAME_1>", "<HEADER_VALUE_1>"); // Replace with header name and value
60+
requestHeaders.put("<HEADER_NAME_1>", "<HEADER_VALUE_1>"); // Replace with actual header name and value
6061
requestHeaders.put("<HEADER_NAME_2>", "<HEADER_VALUE_2>"); // Replace with another header name and value
6162

62-
// Build the POST request to invoke the connection
63+
// Build and send the POST request
6364
InvokeConnectionRequest invokeConnectionRequest1 = InvokeConnectionRequest.builder()
64-
.methodName(RequestMethod.POST) // Set the HTTP method to POST
65-
.requestBody(requestBody) // Set the request body
66-
.requestHeaders(requestHeaders) // Set the request headers
65+
.method(RequestMethod.POST) // HTTP method set to POST
66+
.requestBody(requestBody) // Include request body
67+
.requestHeaders(requestHeaders) // Include request headers
6768
.build();
6869

69-
// Execute the POST request to the first connection
7070
InvokeConnectionResponse invokeConnectionResponse1 = skyflowClient.connection().invoke(invokeConnectionRequest1);
71-
System.out.println("Invoke Connection Response (POST): " + invokeConnectionResponse1); // Print the response
71+
System.out.println("Invoke Connection Response (POST): " + invokeConnectionResponse1);
7272
} catch (SkyflowException e) {
73-
System.out.println("Error while invoking connection (POST):");
74-
e.printStackTrace();
73+
System.out.println("Error while invoking connection (POST):" + e);
7574
}
7675

7776
// Example 2: Sending a GET request to the second connection
7877
try {
79-
// Set up path parameters and query parameters for the GET request
78+
// Set up path and query parameters
8079
Map<String, String> pathParams = new HashMap<>();
81-
pathParams.put("<YOUR_PATH_PARAM_KEY_1>", "<YOUR_PATH_PARAM_VALUE_1>"); // Replace with path parameters
80+
pathParams.put("<YOUR_PATH_PARAM_KEY_1>", "<YOUR_PATH_PARAM_VALUE_1>"); // Replace with actual path parameter
8281
pathParams.put("<YOUR_PATH_PARAM_KEY_2>", "<YOUR_PATH_PARAM_VALUE_2>"); // Replace with another path parameter
8382

8483
Map<String, String> queryParams = new HashMap<>();
85-
queryParams.put("<YOUR_QUERY_PARAM_KEY_1>", "<YOUR_QUERY_PARAM_VALUE_1>"); // Replace with query parameters
84+
queryParams.put("<YOUR_QUERY_PARAM_KEY_1>", "<YOUR_QUERY_PARAM_VALUE_1>"); // Replace with actual query parameter
8685
queryParams.put("<YOUR_QUERY_PARAM_KEY_2>", "<YOUR_QUERY_PARAM_VALUE_2>"); // Replace with another query parameter
8786

88-
// Build the GET request to invoke the connection
87+
// Build and send the GET request
8988
InvokeConnectionRequest invokeConnectionRequest2 = InvokeConnectionRequest.builder()
90-
.methodName(RequestMethod.GET) // Set the HTTP method to GET
91-
.pathParams(pathParams) // Set the path parameters
92-
.queryParams(queryParams) // Set the query parameters
89+
.method(RequestMethod.GET) // HTTP method set to GET
90+
.pathParams(pathParams) // Include path parameters
91+
.queryParams(queryParams) // Include query parameters
9392
.build();
9493

95-
// Execute the GET request to the second connection
9694
InvokeConnectionResponse invokeConnectionResponse2 = skyflowClient
97-
.connection("<YOUR_CONNECTION_ID_2>").invoke(invokeConnectionRequest2); // Invoke connection with ID 2
98-
System.out.println("Invoke Connection Response (GET): " + invokeConnectionResponse2); // Print the response
95+
.connection("<YOUR_CONNECTION_ID_2>").invoke(invokeConnectionRequest2);
96+
System.out.println("Invoke Connection Response (GET): " + invokeConnectionResponse2);
9997
} catch (SkyflowException e) {
100-
System.out.println("Error while invoking connection (GET):");
101-
e.printStackTrace();
98+
System.out.println("Error while invoking connection (GET):" + e);
10299
}
103100
}
104101
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.example.serviceaccount;
2+
3+
import com.skyflow.Skyflow;
4+
import com.skyflow.config.Credentials;
5+
import com.skyflow.config.VaultConfig;
6+
import com.skyflow.enums.Env;
7+
import com.skyflow.enums.LogLevel;
8+
import com.skyflow.enums.RedactionType;
9+
import com.skyflow.errors.SkyflowException;
10+
import com.skyflow.vault.tokens.DetokenizeRequest;
11+
import com.skyflow.vault.tokens.DetokenizeResponse;
12+
import io.github.cdimascio.dotenv.Dotenv;
13+
import java.util.ArrayList;
14+
15+
/**
16+
* This example demonstrates how to configure and use the Skyflow SDK
17+
* to detokenize sensitive data stored in a Skyflow vault.
18+
* It includes setting up credentials, configuring the vault, and
19+
* making a detokenization request. The code also implements a retry
20+
* mechanism to handle unauthorized access errors (HTTP 401).
21+
*/
22+
public class BearerTokenExpiryExample {
23+
public static void main(String[] args) {
24+
try {
25+
// Setting up credentials for accessing the Skyflow vault
26+
Credentials vaultCredentials = new Credentials();
27+
vaultCredentials.setCredentialsString("<YOUR_CREDENTIALS_STRING>");
28+
29+
// Configuring the Skyflow vault with necessary details
30+
VaultConfig vaultConfig = new VaultConfig();
31+
vaultConfig.setVaultId("<YOUR_VAULT_ID>"); // Vault ID
32+
vaultConfig.setClusterId("<YOUR_CLUSTER_ID>"); // Cluster ID
33+
vaultConfig.setEnv(Env.PROD); // Environment (e.g., DEV, PROD)
34+
vaultConfig.setCredentials(vaultCredentials); // Setting credentials
35+
36+
// Creating a Skyflow client instance with the configured vault
37+
Skyflow skyflowClient = Skyflow.builder()
38+
.setLogLevel(LogLevel.ERROR) // Setting log level to ERROR
39+
.addVaultConfig(vaultConfig) // Adding vault configuration
40+
.build();
41+
42+
// Attempting to detokenize data using the Skyflow client
43+
try {
44+
detokenizeData(skyflowClient);
45+
} catch (SkyflowException e) {
46+
// Retry detokenization if the error is due to unauthorized access (HTTP 401)
47+
if (e.getHttpCode() == 401) {
48+
detokenizeData(skyflowClient);
49+
} else {
50+
// Rethrow the exception for other error codes
51+
throw e;
52+
}
53+
}
54+
} catch (SkyflowException e) {
55+
// Handling any exceptions that occur during the process
56+
System.out.println("An error occurred: " + e.getMessage());
57+
}
58+
}
59+
60+
/**
61+
* Method to detokenize data using the Skyflow client.
62+
* It sends a detokenization request with a list of tokens and prints the response.
63+
*
64+
* @param skyflowClient The Skyflow client instance used for detokenization.
65+
* @throws SkyflowException If an error occurs during the detokenization process.
66+
*/
67+
public static void detokenizeData(Skyflow skyflowClient) throws SkyflowException {
68+
// Creating a list of tokens to be detokenized
69+
ArrayList<String> tokenList = new ArrayList<>();
70+
tokenList.add("<YOUR_TOKEN_VALUE_1>"); // First token
71+
tokenList.add("<YOUR_TOKEN_VALUE_2>"); // Second token
72+
73+
// Building a detokenization request with the token list and configuration
74+
DetokenizeRequest detokenizeRequest = DetokenizeRequest.builder()
75+
.tokens(tokenList) // Adding tokens to the request
76+
.continueOnError(false) // Stop on error
77+
.redactionType(RedactionType.PLAIN_TEXT) // Redaction type (e.g., PLAIN_TEXT)
78+
.build();
79+
80+
// Sending the detokenization request and receiving the response
81+
DetokenizeResponse detokenizeResponse = skyflowClient.vault().detokenize(detokenizeRequest);
82+
83+
// Printing the detokenized response
84+
System.out.println(detokenizeResponse);
85+
}
86+
}

0 commit comments

Comments
 (0)