From bc252571d66531535f124f418856fb762089e7c1 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Mon, 12 May 2025 13:16:51 +0000 Subject: [PATCH 01/14] Add EnvVarIDTokenSource and FileIDTokenSource --- .../sdk/core/oauth/EnvVarIDTokenSource.java | 48 ++++++++++ .../sdk/core/oauth/FileIDTokenSource.java | 69 ++++++++++++++ .../core/oauth/EnvVarIDTokenSourceTest.java | 91 +++++++++++++++++++ .../sdk/core/oauth/FileIDTokenSourceTest.java | 72 +++++++++++++++ 4 files changed, 280 insertions(+) create mode 100644 databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java create mode 100644 databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java create mode 100644 databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java new file mode 100644 index 000000000..69781e105 --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -0,0 +1,48 @@ +package com.databricks.sdk.core.oauth; + +import com.databricks.sdk.core.DatabricksException; +import com.databricks.sdk.core.utils.Environment; +import com.google.common.base.Strings; + +/** Implementation of {@link IDTokenSource} that reads the ID token from an environment variable. */ +public class EnvVarIDTokenSource implements IDTokenSource { + private final String envVarName; + private final Environment env; + + /** + * Creates a new EnvVarIDTokenSource that reads from the specified environment variable. + * + * @param envVarName The name of the environment variable to read the ID token from. + * @param env The environment to read variables from. + */ + public EnvVarIDTokenSource(String envVarName, Environment env) { + this.envVarName = envVarName; + this.env = env; + } + + /** + * Retrieves an ID Token from the environment variable. + * + * @param audience The intended recipient of the ID Token (unused in this implementation). + * @return An {@link IDToken} containing the token value from the environment variable. + * @throws IllegalArgumentException if the environment variable name is null or empty, or the + * environment is null. + * @throws DatabricksException if the environment variable is not set or is empty. + */ + @Override + public IDToken getIDToken(String audience) { + if (Strings.isNullOrEmpty(envVarName)) { + throw new IllegalArgumentException("Environment variable name cannot be null or empty"); + } + + if (env == null) { + throw new IllegalArgumentException("Environment cannot be null"); + } + + String token = env.get(envVarName); + if (Strings.isNullOrEmpty(token)) { + throw new DatabricksException("Missing environment variable: " + envVarName); + } + return new IDToken(token); + } +} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java new file mode 100644 index 000000000..c23ee542a --- /dev/null +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -0,0 +1,69 @@ +package com.databricks.sdk.core.oauth; + +import com.databricks.sdk.core.DatabricksException; +import com.google.common.base.Strings; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +/** + * Implementation of {@link IDTokenSource} that reads the ID token from a file. The token is read + * using UTF-8 encoding and any leading/trailing whitespace is trimmed. + * + * @see IDTokenSource + */ +public class FileIDTokenSource implements IDTokenSource { + private final String filePath; + + /** + * Creates a new FileIDTokenSource that reads from the specified file. + * + * @param filePath Path to the file containing the ID token. The file should contain a single line + * with the token value. + * @throws IllegalArgumentException if the file path is null or empty. + */ + public FileIDTokenSource(String filePath) { + this.filePath = filePath; + } + + /** + * Retrieves an ID Token from the file. The file is read using UTF-8 encoding and the first line + * is used as the token value. + * + * @param audience The intended recipient of the ID Token (not used). + * @return An {@link IDToken} containing the token value from the file. + * @throws IllegalArgumentException if the file path is null or empty. + * @throws DatabricksException if the file does not exist, is empty, or contains only whitespace. + */ + @Override + public IDToken getIDToken(String audience) { + if (Strings.isNullOrEmpty(filePath)) { + throw new IllegalArgumentException("File path cannot be null or empty"); + } + + try { + Path path = Paths.get(filePath); + if (!Files.exists(path)) { + throw new DatabricksException("File " + filePath + " does not exist"); + } + + List lines = Files.readAllLines(path, StandardCharsets.UTF_8); + if (lines.isEmpty()) { + throw new DatabricksException("File " + filePath + " is empty"); + } + + String token = lines.get(0).trim(); + if (Strings.isNullOrEmpty(token)) { + throw new DatabricksException("File " + filePath + " is empty"); + } + + return new IDToken(token); + } catch (IOException e) { + throw new DatabricksException( + "Failed to read ID token from file " + filePath + ": " + e.getMessage(), e); + } + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java new file mode 100644 index 000000000..2349a7d86 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java @@ -0,0 +1,91 @@ +package com.databricks.sdk.core.oauth; + +import static org.junit.jupiter.api.Assertions.*; + +import com.databricks.sdk.core.DatabricksException; +import com.databricks.sdk.core.utils.Environment; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** Tests for EnvVarIDTokenSource. */ +public class EnvVarIDTokenSourceTest { + private static final String TEST_ENV_VAR_NAME = "TEST_ID_TOKEN"; + private static final String TEST_TOKEN = "test-id-token"; + private static final String TEST_AUDIENCE = "test-audience"; + + private Environment createTestEnvironment(Map envVars) { + return new Environment(envVars, new String[0], "test"); + } + + private static Stream provideTestCases() { + return Stream.of( + // Test case: Success case + Arguments.of( + "Success case", + TEST_ENV_VAR_NAME, + createEnvVars(TEST_ENV_VAR_NAME, TEST_TOKEN), + TEST_TOKEN, + null), + // Test case: Null environment variable name + Arguments.of( + "Null environment variable name", + null, + new HashMap<>(), + null, + IllegalArgumentException.class), + // Test case: Empty environment variable name + Arguments.of( + "Empty environment variable name", + "", + new HashMap<>(), + null, + IllegalArgumentException.class), + // Test case: Missing environment variable + Arguments.of( + "Missing environment variable", + TEST_ENV_VAR_NAME, + new HashMap<>(), + null, + DatabricksException.class), + // Test case: Empty token value + Arguments.of( + "Empty token value", + TEST_ENV_VAR_NAME, + createEnvVars(TEST_ENV_VAR_NAME, ""), + null, + DatabricksException.class), + // Test case: Null environment + Arguments.of( + "Null environment", TEST_ENV_VAR_NAME, null, null, IllegalArgumentException.class)); + } + + private static Map createEnvVars(String key, String value) { + Map envVars = new HashMap<>(); + envVars.put(key, value); + return envVars; + } + + @ParameterizedTest(name = "{0}") + @MethodSource("provideTestCases") + void testGetIDToken( + String testName, + String envVarName, + Map envVars, + String expectedToken, + Class expectedException) { + Environment env = envVars != null ? createTestEnvironment(envVars) : null; + EnvVarIDTokenSource source = new EnvVarIDTokenSource(envVarName, env); + + if (expectedException != null) { + assertThrows(expectedException, () -> source.getIDToken(TEST_AUDIENCE)); + } else { + IDToken token = source.getIDToken(TEST_AUDIENCE); + assertNotNull(token); + assertEquals(expectedToken, token.getValue()); + } + } +} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java new file mode 100644 index 000000000..4eb83a409 --- /dev/null +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java @@ -0,0 +1,72 @@ +package com.databricks.sdk.core.oauth; + +import static org.junit.jupiter.api.Assertions.*; + +import com.databricks.sdk.core.DatabricksException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Stream; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** Tests for FileIDTokenSource. */ +public class FileIDTokenSourceTest { + private static final String TEST_TOKEN = "test-id-token"; + private static final String TEST_AUDIENCE = "test-audience"; + + @TempDir Path tempDir; + + private Path createTestFile(String content) throws IOException { + Path file = tempDir.resolve("test-token.txt"); + Files.write(file, content.getBytes(StandardCharsets.UTF_8)); + return file; + } + + private static Stream provideTestCases() { + return Stream.of( + // Test case name, file path (null means create temp file), file content, expected token, + // expected exception + Arguments.of("Valid token file", null, TEST_TOKEN, TEST_TOKEN, null), + Arguments.of("Token with whitespace", null, " " + TEST_TOKEN + " ", TEST_TOKEN, null), + Arguments.of("Empty file", null, "", null, DatabricksException.class), + Arguments.of("File with only whitespace", null, " ", null, DatabricksException.class), + Arguments.of("Null file path", null, null, null, IllegalArgumentException.class), + Arguments.of("Empty file path", "", null, null, IllegalArgumentException.class), + Arguments.of( + "Non-existent file", + "/path/to/nonexistent/file.txt", + null, + null, + DatabricksException.class)); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("provideTestCases") + void testGetIDToken( + String testName, + String filePath, + String fileContent, + String expectedToken, + Class expectedException) + throws IOException { + // If filePath is null, create a temporary test file + String actualFilePath = filePath; + if (filePath == null && fileContent != null) { + actualFilePath = createTestFile(fileContent).toString(); + } + + FileIDTokenSource source = new FileIDTokenSource(actualFilePath); + + if (expectedException != null) { + assertThrows(expectedException, () -> source.getIDToken(TEST_AUDIENCE)); + } else { + IDToken token = source.getIDToken(TEST_AUDIENCE); + assertNotNull(token); + assertEquals(expectedToken, token.getValue()); + } + } +} From 7b107551e0b28e4ab7afa9bc58051de94f7d1a7c Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Mon, 12 May 2025 13:30:40 +0000 Subject: [PATCH 02/14] Minor comment change --- .../java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java | 2 ++ .../java/com/databricks/sdk/core/oauth/FileIDTokenSource.java | 1 + 2 files changed, 3 insertions(+) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index 69781e105..e8ac9c26e 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -6,7 +6,9 @@ /** Implementation of {@link IDTokenSource} that reads the ID token from an environment variable. */ public class EnvVarIDTokenSource implements IDTokenSource { + /* The name of the environment variable to read the ID token from. */ private final String envVarName; + /* The environment to read variables from. */ private final Environment env; /** diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index c23ee542a..fbca509be 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -16,6 +16,7 @@ * @see IDTokenSource */ public class FileIDTokenSource implements IDTokenSource { + /* The path to the file containing the ID token. */ private final String filePath; /** From ad003b073aa35708583576f490538daa84df0b38 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Mon, 12 May 2025 13:44:57 +0000 Subject: [PATCH 03/14] Catch exceptions of IDToken construction --- .../databricks/sdk/core/oauth/EnvVarIDTokenSource.java | 10 ++++++---- .../databricks/sdk/core/oauth/FileIDTokenSource.java | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index e8ac9c26e..4e2337283 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -41,10 +41,12 @@ public IDToken getIDToken(String audience) { throw new IllegalArgumentException("Environment cannot be null"); } - String token = env.get(envVarName); - if (Strings.isNullOrEmpty(token)) { - throw new DatabricksException("Missing environment variable: " + envVarName); + try { + String token = env.get(envVarName); + return new IDToken(token); + } catch (IllegalArgumentException e) { + throw new DatabricksException( + "Received empty ID token from environment variable " + envVarName); } - return new IDToken(token); } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index fbca509be..e613d8fa0 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -56,12 +56,13 @@ public IDToken getIDToken(String audience) { throw new DatabricksException("File " + filePath + " is empty"); } - String token = lines.get(0).trim(); - if (Strings.isNullOrEmpty(token)) { - throw new DatabricksException("File " + filePath + " is empty"); + try { + String token = lines.get(0).trim(); + return new IDToken(token); + } catch (IllegalArgumentException e) { + throw new DatabricksException("Received empty ID token from file " + filePath); } - return new IDToken(token); } catch (IOException e) { throw new DatabricksException( "Failed to read ID token from file " + filePath + ": " + e.getMessage(), e); From 757caae2205f84515c21ef38d816488700b0c955 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Mon, 12 May 2025 15:11:45 +0000 Subject: [PATCH 04/14] Add catches for exceptions --- .../sdk/core/oauth/EnvVarIDTokenSource.java | 3 ++ .../sdk/core/oauth/FileIDTokenSource.java | 46 ++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index 4e2337283..d905138ec 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -47,6 +47,9 @@ public IDToken getIDToken(String audience) { } catch (IllegalArgumentException e) { throw new DatabricksException( "Received empty ID token from environment variable " + envVarName); + } catch (RuntimeException e) { + throw new DatabricksException( + "Failed to read environment variable " + envVarName + ": " + e.getMessage(), e); } } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index e613d8fa0..a097286be 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; @@ -37,7 +38,8 @@ public FileIDTokenSource(String filePath) { * @param audience The intended recipient of the ID Token (not used). * @return An {@link IDToken} containing the token value from the file. * @throws IllegalArgumentException if the file path is null or empty. - * @throws DatabricksException if the file does not exist, is empty, or contains only whitespace. + * @throws DatabricksException if the file path is invalid, the file does not exist, is empty, or + * contains only whitespace. */ @Override public IDToken getIDToken(String audience) { @@ -45,27 +47,39 @@ public IDToken getIDToken(String audience) { throw new IllegalArgumentException("File path cannot be null or empty"); } + Path path; try { - Path path = Paths.get(filePath); - if (!Files.exists(path)) { - throw new DatabricksException("File " + filePath + " does not exist"); - } - - List lines = Files.readAllLines(path, StandardCharsets.UTF_8); - if (lines.isEmpty()) { - throw new DatabricksException("File " + filePath + " is empty"); - } + path = Paths.get(filePath); + } catch (InvalidPathException e) { + throw new DatabricksException("Invalid file path: " + filePath, e); + } - try { - String token = lines.get(0).trim(); - return new IDToken(token); - } catch (IllegalArgumentException e) { - throw new DatabricksException("Received empty ID token from file " + filePath); - } + if (!Files.exists(path)) { + throw new DatabricksException("File " + filePath + " does not exist"); + } + List lines; + try { + lines = Files.readAllLines(path, StandardCharsets.UTF_8); } catch (IOException e) { throw new DatabricksException( "Failed to read ID token from file " + filePath + ": " + e.getMessage(), e); } + + if (lines.isEmpty()) { + throw new DatabricksException("File " + filePath + " is empty"); + } + + try { + String token; + try { + token = lines.get(0).trim(); + } catch (IndexOutOfBoundsException | NullPointerException e) { + throw new DatabricksException("Invalid token format in file " + filePath); + } + return new IDToken(token); + } catch (IllegalArgumentException e) { + throw new DatabricksException("Received empty ID token from file " + filePath); + } } } From 7570061ec758a3fca53452f604710b8f55076e3c Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Mon, 12 May 2025 16:12:28 +0000 Subject: [PATCH 05/14] Exception handling --- .../sdk/core/oauth/EnvVarIDTokenSource.java | 5 +-- .../sdk/core/oauth/FileIDTokenSource.java | 34 +++++++++++++++---- .../databricks/sdk/core/oauth/IDToken.java | 1 + 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index d905138ec..ad587989d 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -30,6 +30,7 @@ public EnvVarIDTokenSource(String envVarName, Environment env) { * @throws IllegalArgumentException if the environment variable name is null or empty, or the * environment is null. * @throws DatabricksException if the environment variable is not set or is empty. + * @throws ClassCastException if the environment variable is not valid type. */ @Override public IDToken getIDToken(String audience) { @@ -47,9 +48,9 @@ public IDToken getIDToken(String audience) { } catch (IllegalArgumentException e) { throw new DatabricksException( "Received empty ID token from environment variable " + envVarName); - } catch (RuntimeException e) { + } catch (ClassCastException e) { throw new DatabricksException( - "Failed to read environment variable " + envVarName + ": " + e.getMessage(), e); + "Environment variable " + envVarName + " has invalid type: " + e.getMessage(), e); } } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index a097286be..6a4c2ebb6 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -33,13 +33,21 @@ public FileIDTokenSource(String filePath) { /** * Retrieves an ID Token from the file. The file is read using UTF-8 encoding and the first line - * is used as the token value. + * is used as the token value. Any leading or trailing whitespace in the token is trimmed. * - * @param audience The intended recipient of the ID Token (not used). + * @param audience The intended recipient of the ID Token. This parameter is not used in this + * implementation as the token is read directly from the file. * @return An {@link IDToken} containing the token value from the file. * @throws IllegalArgumentException if the file path is null or empty. - * @throws DatabricksException if the file path is invalid, the file does not exist, is empty, or - * contains only whitespace. + * @throws DatabricksException in the following cases: + *
    + *
  • If the file path is invalid or malformed + *
  • If the file does not exist + *
  • If there are security permission issues accessing the file + *
  • If the file is empty or contains only whitespace + *
  • If the file cannot be read due to I/O errors + *
  • If the token format in the file is invalid + *
*/ @Override public IDToken getIDToken(String audience) { @@ -54,8 +62,17 @@ public IDToken getIDToken(String audience) { throw new DatabricksException("Invalid file path: " + filePath, e); } - if (!Files.exists(path)) { - throw new DatabricksException("File " + filePath + " does not exist"); + try { + if (!Files.exists(path)) { + throw new DatabricksException("File " + filePath + " does not exist"); + } + } catch (SecurityException e) { + throw new DatabricksException( + "Security permission denied when checking if file " + + filePath + + " exists: " + + e.getMessage(), + e); } List lines; @@ -64,6 +81,9 @@ public IDToken getIDToken(String audience) { } catch (IOException e) { throw new DatabricksException( "Failed to read ID token from file " + filePath + ": " + e.getMessage(), e); + } catch (SecurityException e) { + throw new DatabricksException( + "Security permission denied when reading file " + filePath + ": " + e.getMessage(), e); } if (lines.isEmpty()) { @@ -74,7 +94,7 @@ public IDToken getIDToken(String audience) { String token; try { token = lines.get(0).trim(); - } catch (IndexOutOfBoundsException | NullPointerException e) { + } catch (IndexOutOfBoundsException e) { throw new DatabricksException("Invalid token format in file " + filePath); } return new IDToken(token); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/IDToken.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/IDToken.java index e9c3f1ac6..952fb6ed9 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/IDToken.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/IDToken.java @@ -12,6 +12,7 @@ public class IDToken { * Constructs an IDToken with a value. * * @param value The ID Token string. + * @throws IllegalArgumentException if the token value is null or empty. */ public IDToken(String value) { if (value == null || value.isEmpty()) { From b3f776f9d75d15e42edb7ed288b376155d8c47ad Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Tue, 13 May 2025 11:13:57 +0000 Subject: [PATCH 06/14] Add support for environment variable and file OIDC --- .../databricks/sdk/core/DatabricksConfig.java | 26 +++++++++++++++++++ .../sdk/core/DefaultCredentialsProvider.java | 15 +++++++++++ 2 files changed, 41 insertions(+) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java index fcb79c87b..98d75d4bc 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DatabricksConfig.java @@ -148,6 +148,14 @@ public class DatabricksConfig { @ConfigAttribute(env = "TOKEN_AUDIENCE") private String tokenAudience; + /** Path to the file containing an OIDC ID token. */ + @ConfigAttribute(env = "DATABRICKS_OIDC_TOKEN_FILEPATH", auth = "file-oidc") + private String oidcTokenFilepath; + + /** Environment variable name that contains an OIDC ID token. */ + @ConfigAttribute(env = "DATABRICKS_OIDC_TOKEN_ENV", auth = "env-oidc") + private String oidcTokenEnv; + public Environment getEnv() { return env; } @@ -528,6 +536,24 @@ public DatabricksConfig setTokenAudience(String tokenAudience) { return this; } + public String getOidcTokenFilepath() { + return oidcTokenFilepath; + } + + public DatabricksConfig setOidcTokenFilepath(String oidcTokenFilepath) { + this.oidcTokenFilepath = oidcTokenFilepath; + return this; + } + + public String getOidcTokenEnv() { + return oidcTokenEnv; + } + + public DatabricksConfig setOidcTokenEnv(String oidcTokenEnv) { + this.oidcTokenEnv = oidcTokenEnv; + return this; + } + public boolean isAzure() { if (azureWorkspaceResourceId != null) { return true; diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java index c3fc3b1e4..20bc0faf0 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java @@ -1,6 +1,7 @@ package com.databricks.sdk.core; import com.databricks.sdk.core.oauth.*; +import com.google.common.base.Strings; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; @@ -111,6 +112,20 @@ private void addOIDCCredentialsProviders(DatabricksConfig config) { } List namedIdTokenSources = new ArrayList<>(); + namedIdTokenSources.add( + new NamedIDTokenSource( + "env-oidc", + new EnvVarIDTokenSource( + // Use configured environment variable name if set, otherwise default to + // DATABRICKS_OIDC_TOKEN + (Strings.isNullOrEmpty(config.getOidcTokenEnv())) + ? "DATABRICKS_OIDC_TOKEN" + : config.getOidcTokenEnv(), + config.getEnv()))); + + namedIdTokenSources.add( + new NamedIDTokenSource("file-oidc", new FileIDTokenSource(config.getOidcTokenFilepath()))); + namedIdTokenSources.add( new NamedIDTokenSource( "github-oidc", From 391f822f3bcd73b6680f8820c09196f7a6d8b790 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Tue, 13 May 2025 12:57:15 +0000 Subject: [PATCH 07/14] Small change --- .../sdk/core/DefaultCredentialsProvider.java | 2 +- .../sdk/core/oauth/EnvVarIDTokenSource.java | 4 ---- .../sdk/core/oauth/FileIDTokenSource.java | 13 +++++++------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java index 20bc0faf0..0e4723f36 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/DefaultCredentialsProvider.java @@ -118,7 +118,7 @@ private void addOIDCCredentialsProviders(DatabricksConfig config) { new EnvVarIDTokenSource( // Use configured environment variable name if set, otherwise default to // DATABRICKS_OIDC_TOKEN - (Strings.isNullOrEmpty(config.getOidcTokenEnv())) + Strings.isNullOrEmpty(config.getOidcTokenEnv()) ? "DATABRICKS_OIDC_TOKEN" : config.getOidcTokenEnv(), config.getEnv()))); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index ad587989d..bc8756d11 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -38,10 +38,6 @@ public IDToken getIDToken(String audience) { throw new IllegalArgumentException("Environment variable name cannot be null or empty"); } - if (env == null) { - throw new IllegalArgumentException("Environment cannot be null"); - } - try { String token = env.get(envVarName); return new IDToken(token); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index 6a4c2ebb6..f85db2774 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -90,13 +90,14 @@ public IDToken getIDToken(String audience) { throw new DatabricksException("File " + filePath + " is empty"); } + String token; + try { + token = lines.get(0).trim(); + } catch (IndexOutOfBoundsException e) { + throw new DatabricksException("Invalid token format in file " + filePath); + } + try { - String token; - try { - token = lines.get(0).trim(); - } catch (IndexOutOfBoundsException e) { - throw new DatabricksException("Invalid token format in file " + filePath); - } return new IDToken(token); } catch (IllegalArgumentException e) { throw new DatabricksException("Received empty ID token from file " + filePath); From b3c7303367aec688ded79ee2a9313ec616204e7d Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Tue, 13 May 2025 13:51:29 +0000 Subject: [PATCH 08/14] Fix test --- .../databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java index 2349a7d86..49bf6536c 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSourceTest.java @@ -57,10 +57,7 @@ private static Stream provideTestCases() { TEST_ENV_VAR_NAME, createEnvVars(TEST_ENV_VAR_NAME, ""), null, - DatabricksException.class), - // Test case: Null environment - Arguments.of( - "Null environment", TEST_ENV_VAR_NAME, null, null, IllegalArgumentException.class)); + DatabricksException.class)); } private static Map createEnvVars(String key, String value) { From 92aaca15a30dff0f55d240f44bfe73e8af2c56f8 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Tue, 13 May 2025 14:52:19 +0000 Subject: [PATCH 09/14] Exception fixes --- .../sdk/core/oauth/EnvVarIDTokenSource.java | 14 ++--- .../sdk/core/oauth/FileIDTokenSource.java | 56 ++++++++++++------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index bc8756d11..6738b888b 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -6,6 +6,11 @@ /** Implementation of {@link IDTokenSource} that reads the ID token from an environment variable. */ public class EnvVarIDTokenSource implements IDTokenSource { + private static final String ERROR_ENV_VAR_NULL_OR_EMPTY = + "Environment variable name cannot be null or empty"; + private static final String ERROR_EMPTY_TOKEN = + "Received empty ID token from environment variable %s"; + /* The name of the environment variable to read the ID token from. */ private final String envVarName; /* The environment to read variables from. */ @@ -30,23 +35,18 @@ public EnvVarIDTokenSource(String envVarName, Environment env) { * @throws IllegalArgumentException if the environment variable name is null or empty, or the * environment is null. * @throws DatabricksException if the environment variable is not set or is empty. - * @throws ClassCastException if the environment variable is not valid type. */ @Override public IDToken getIDToken(String audience) { if (Strings.isNullOrEmpty(envVarName)) { - throw new IllegalArgumentException("Environment variable name cannot be null or empty"); + throw new IllegalArgumentException(ERROR_ENV_VAR_NULL_OR_EMPTY); } try { String token = env.get(envVarName); return new IDToken(token); } catch (IllegalArgumentException e) { - throw new DatabricksException( - "Received empty ID token from environment variable " + envVarName); - } catch (ClassCastException e) { - throw new DatabricksException( - "Environment variable " + envVarName + " has invalid type: " + e.getMessage(), e); + throw new DatabricksException(String.format(ERROR_EMPTY_TOKEN, envVarName), e); } } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index f85db2774..57a711f90 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -9,14 +9,28 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.stream.Collectors; /** * Implementation of {@link IDTokenSource} that reads the ID token from a file. The token is read - * using UTF-8 encoding and any leading/trailing whitespace is trimmed. + * using UTF-8 encoding and any leading/trailing whitespace is trimmed. The file should contain + * exactly one non-empty line with the token value. Files with multiple non-empty lines or only + * empty lines will result in an error. * * @see IDTokenSource */ public class FileIDTokenSource implements IDTokenSource { + private static final String ERROR_FILE_NOT_FOUND = "File %s does not exist"; + private static final String ERROR_SECURITY_CHECK = + "Security permission denied when checking if file %s exists: %s"; + private static final String ERROR_READ_FAILED = "Failed to read ID token from file %s: %s"; + private static final String ERROR_SECURITY_READ = + "Security permission denied when reading file %s: %s"; + private static final String ERROR_EMPTY_FILE = "File %s contains only empty lines"; + private static final String ERROR_MULTIPLE_LINES = + "The token should be a single line but the file %s contains %d non-empty lines"; + private static final String ERROR_EMPTY_TOKEN = "Received empty ID token from file %s"; + /* The path to the file containing the ID token. */ private final String filePath; @@ -64,43 +78,45 @@ public IDToken getIDToken(String audience) { try { if (!Files.exists(path)) { - throw new DatabricksException("File " + filePath + " does not exist"); + throw new DatabricksException(String.format(ERROR_FILE_NOT_FOUND, filePath)); } } catch (SecurityException e) { throw new DatabricksException( - "Security permission denied when checking if file " - + filePath - + " exists: " - + e.getMessage(), - e); + String.format(ERROR_SECURITY_CHECK, filePath, e.getMessage()), e); } - List lines; + List rawLines; try { - lines = Files.readAllLines(path, StandardCharsets.UTF_8); + rawLines = Files.readAllLines(path, StandardCharsets.UTF_8); } catch (IOException e) { - throw new DatabricksException( - "Failed to read ID token from file " + filePath + ": " + e.getMessage(), e); + throw new DatabricksException(String.format(ERROR_READ_FAILED, filePath, e.getMessage()), e); } catch (SecurityException e) { throw new DatabricksException( - "Security permission denied when reading file " + filePath + ": " + e.getMessage(), e); + String.format(ERROR_SECURITY_READ, filePath, e.getMessage()), e); } - if (lines.isEmpty()) { - throw new DatabricksException("File " + filePath + " is empty"); + // Filter out empty lines + List nonEmptyLines = + rawLines.stream() + .map(String::trim) + .filter(line -> !line.isEmpty()) + .collect(Collectors.toList()); + + if (nonEmptyLines.isEmpty()) { + throw new DatabricksException(String.format(ERROR_EMPTY_FILE, filePath)); } - String token; - try { - token = lines.get(0).trim(); - } catch (IndexOutOfBoundsException e) { - throw new DatabricksException("Invalid token format in file " + filePath); + if (nonEmptyLines.size() > 1) { + throw new DatabricksException( + String.format(ERROR_MULTIPLE_LINES, filePath, nonEmptyLines.size())); } + String token = nonEmptyLines.get(0); + try { return new IDToken(token); } catch (IllegalArgumentException e) { - throw new DatabricksException("Received empty ID token from file " + filePath); + throw new DatabricksException(String.format(ERROR_EMPTY_TOKEN, filePath)); } } } From e8c19814d9784d796fa5f8d3d69efbc4ae3799e5 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Wed, 14 May 2025 12:11:55 +0000 Subject: [PATCH 10/14] Fix JavaDoc --- .../databricks/sdk/core/oauth/EnvVarIDTokenSource.java | 2 ++ .../com/databricks/sdk/core/oauth/FileIDTokenSource.java | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index 6738b888b..24b2b1361 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -35,6 +35,8 @@ public EnvVarIDTokenSource(String envVarName, Environment env) { * @throws IllegalArgumentException if the environment variable name is null or empty, or the * environment is null. * @throws DatabricksException if the environment variable is not set or is empty. + * @throws NullPointerException if the environment variable name is null. + * @throws ClassCastException if the environment variable name is not a String. */ @Override public IDToken getIDToken(String audience) { diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index 57a711f90..ea5e55298 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -76,15 +76,18 @@ public IDToken getIDToken(String audience) { throw new DatabricksException("Invalid file path: " + filePath, e); } + boolean isFileExists; try { - if (!Files.exists(path)) { - throw new DatabricksException(String.format(ERROR_FILE_NOT_FOUND, filePath)); - } + isFileExists = Files.exists(path); } catch (SecurityException e) { throw new DatabricksException( String.format(ERROR_SECURITY_CHECK, filePath, e.getMessage()), e); } + if (!isFileExists) { + throw new DatabricksException(String.format(ERROR_FILE_NOT_FOUND, filePath)); + } + List rawLines; try { rawLines = Files.readAllLines(path, StandardCharsets.UTF_8); From 40505ad3b6b3dba8542a2a9f96c6a4cefd767f28 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Wed, 14 May 2025 12:30:41 +0000 Subject: [PATCH 11/14] Update JavaDoc --- .../com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index 24b2b1361..772411105 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -32,11 +32,8 @@ public EnvVarIDTokenSource(String envVarName, Environment env) { * * @param audience The intended recipient of the ID Token (unused in this implementation). * @return An {@link IDToken} containing the token value from the environment variable. - * @throws IllegalArgumentException if the environment variable name is null or empty, or the - * environment is null. + * @throws IllegalArgumentException if the environment variable name is null or empty. * @throws DatabricksException if the environment variable is not set or is empty. - * @throws NullPointerException if the environment variable name is null. - * @throws ClassCastException if the environment variable name is not a String. */ @Override public IDToken getIDToken(String audience) { From a09db93504baaf59f6571b42c37607072f2633bc Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Thu, 15 May 2025 09:06:04 +0000 Subject: [PATCH 12/14] Refactor tests --- .../sdk/core/oauth/FileIDTokenSourceTest.java | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java index 4eb83a409..d86c42f05 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java @@ -20,46 +20,49 @@ public class FileIDTokenSourceTest { @TempDir Path tempDir; - private Path createTestFile(String content) throws IOException { - Path file = tempDir.resolve("test-token.txt"); - Files.write(file, content.getBytes(StandardCharsets.UTF_8)); - return file; - } - private static Stream provideTestCases() { return Stream.of( - // Test case name, file path (null means create temp file), file content, expected token, - // expected exception - Arguments.of("Valid token file", null, TEST_TOKEN, TEST_TOKEN, null), - Arguments.of("Token with whitespace", null, " " + TEST_TOKEN + " ", TEST_TOKEN, null), - Arguments.of("Empty file", null, "", null, DatabricksException.class), - Arguments.of("File with only whitespace", null, " ", null, DatabricksException.class), - Arguments.of("Null file path", null, null, null, IllegalArgumentException.class), - Arguments.of("Empty file path", "", null, null, IllegalArgumentException.class), + // Test case name, fileContent, fileToReadFrom, expected token, expected exception + Arguments.of("Valid token file", TEST_TOKEN, "token.txt", TEST_TOKEN, null), + Arguments.of( + "Token with whitespace", " " + TEST_TOKEN + " ", "token.txt", TEST_TOKEN, null), + Arguments.of("Empty file", "", "token.txt", null, DatabricksException.class), Arguments.of( - "Non-existent file", - "/path/to/nonexistent/file.txt", - null, - null, - DatabricksException.class)); + "File with only whitespace", " ", "token.txt", null, DatabricksException.class), + Arguments.of("Null file path", TEST_TOKEN, null, null, IllegalArgumentException.class), + Arguments.of("Empty file path", TEST_TOKEN, "", null, IllegalArgumentException.class), + Arguments.of( + "Non-existent file", TEST_TOKEN, "nonexistent.txt", null, DatabricksException.class)); } @ParameterizedTest(name = "{0}") @MethodSource("provideTestCases") void testGetIDToken( String testName, - String filePath, String fileContent, + String fileToReadFrom, String expectedToken, Class expectedException) throws IOException { - // If filePath is null, create a temporary test file - String actualFilePath = filePath; - if (filePath == null && fileContent != null) { - actualFilePath = createTestFile(fileContent).toString(); + // Always create token.txt with the specified content + Path tokenFile = tempDir.resolve("token.txt"); + Files.write(tokenFile, fileContent.getBytes(StandardCharsets.UTF_8)); + + String filePathToRead = null; + // If fileToReadFrom is null, we want to simulate passing a null path to FileIDTokenSource (for + // error cases). + // If fileToReadFrom is an empty string, we want to simulate passing an empty path (also for + // error cases). + // Otherwise, resolve the file name relative to the temp directory to get the full path. + if (fileToReadFrom != null) { + if (fileToReadFrom.equals("")) { + filePathToRead = ""; + } else { + filePathToRead = tempDir.resolve(fileToReadFrom).toString(); + } } - FileIDTokenSource source = new FileIDTokenSource(actualFilePath); + FileIDTokenSource source = new FileIDTokenSource(filePathToRead); if (expectedException != null) { assertThrows(expectedException, () -> source.getIDToken(TEST_AUDIENCE)); From 72549457a59c6cb5e5e6130013919b3652b3f2b5 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Thu, 15 May 2025 09:24:24 +0000 Subject: [PATCH 13/14] Refactor tests --- .../databricks/sdk/core/oauth/FileIDTokenSourceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java index d86c42f05..4565aafac 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/FileIDTokenSourceTest.java @@ -48,7 +48,7 @@ void testGetIDToken( Path tokenFile = tempDir.resolve("token.txt"); Files.write(tokenFile, fileContent.getBytes(StandardCharsets.UTF_8)); - String filePathToRead = null; + String testPathToRead = null; // If fileToReadFrom is null, we want to simulate passing a null path to FileIDTokenSource (for // error cases). // If fileToReadFrom is an empty string, we want to simulate passing an empty path (also for @@ -56,13 +56,13 @@ void testGetIDToken( // Otherwise, resolve the file name relative to the temp directory to get the full path. if (fileToReadFrom != null) { if (fileToReadFrom.equals("")) { - filePathToRead = ""; + testPathToRead = ""; } else { - filePathToRead = tempDir.resolve(fileToReadFrom).toString(); + testPathToRead = tempDir.resolve(fileToReadFrom).toString(); } } - FileIDTokenSource source = new FileIDTokenSource(filePathToRead); + FileIDTokenSource source = new FileIDTokenSource(testPathToRead); if (expectedException != null) { assertThrows(expectedException, () -> source.getIDToken(TEST_AUDIENCE)); From eade1bac722c31030c206a5d79a7e3744e6c3f15 Mon Sep 17 00:00:00 2001 From: emmyzhou-db Date: Thu, 15 May 2025 12:00:32 +0000 Subject: [PATCH 14/14] Update exception messages --- .../sdk/core/oauth/EnvVarIDTokenSource.java | 10 ++---- .../sdk/core/oauth/FileIDTokenSource.java | 34 +++++++++---------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java index 772411105..5bbc1c4e2 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/EnvVarIDTokenSource.java @@ -6,11 +6,6 @@ /** Implementation of {@link IDTokenSource} that reads the ID token from an environment variable. */ public class EnvVarIDTokenSource implements IDTokenSource { - private static final String ERROR_ENV_VAR_NULL_OR_EMPTY = - "Environment variable name cannot be null or empty"; - private static final String ERROR_EMPTY_TOKEN = - "Received empty ID token from environment variable %s"; - /* The name of the environment variable to read the ID token from. */ private final String envVarName; /* The environment to read variables from. */ @@ -38,14 +33,15 @@ public EnvVarIDTokenSource(String envVarName, Environment env) { @Override public IDToken getIDToken(String audience) { if (Strings.isNullOrEmpty(envVarName)) { - throw new IllegalArgumentException(ERROR_ENV_VAR_NULL_OR_EMPTY); + throw new IllegalArgumentException("Environment variable name cannot be null or empty"); } try { String token = env.get(envVarName); return new IDToken(token); } catch (IllegalArgumentException e) { - throw new DatabricksException(String.format(ERROR_EMPTY_TOKEN, envVarName), e); + throw new DatabricksException( + String.format("Received empty ID token from environment variable %s", envVarName), e); } } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java index ea5e55298..b503d454c 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/oauth/FileIDTokenSource.java @@ -20,17 +20,6 @@ * @see IDTokenSource */ public class FileIDTokenSource implements IDTokenSource { - private static final String ERROR_FILE_NOT_FOUND = "File %s does not exist"; - private static final String ERROR_SECURITY_CHECK = - "Security permission denied when checking if file %s exists: %s"; - private static final String ERROR_READ_FAILED = "Failed to read ID token from file %s: %s"; - private static final String ERROR_SECURITY_READ = - "Security permission denied when reading file %s: %s"; - private static final String ERROR_EMPTY_FILE = "File %s contains only empty lines"; - private static final String ERROR_MULTIPLE_LINES = - "The token should be a single line but the file %s contains %d non-empty lines"; - private static final String ERROR_EMPTY_TOKEN = "Received empty ID token from file %s"; - /* The path to the file containing the ID token. */ private final String filePath; @@ -81,21 +70,27 @@ public IDToken getIDToken(String audience) { isFileExists = Files.exists(path); } catch (SecurityException e) { throw new DatabricksException( - String.format(ERROR_SECURITY_CHECK, filePath, e.getMessage()), e); + String.format( + "Security permission denied when checking if file %s exists: %s", + filePath, e.getMessage()), + e); } if (!isFileExists) { - throw new DatabricksException(String.format(ERROR_FILE_NOT_FOUND, filePath)); + throw new DatabricksException(String.format("File %s does not exist", filePath)); } List rawLines; try { rawLines = Files.readAllLines(path, StandardCharsets.UTF_8); } catch (IOException e) { - throw new DatabricksException(String.format(ERROR_READ_FAILED, filePath, e.getMessage()), e); + throw new DatabricksException( + String.format("Failed to read ID token from file %s: %s", filePath, e.getMessage()), e); } catch (SecurityException e) { throw new DatabricksException( - String.format(ERROR_SECURITY_READ, filePath, e.getMessage()), e); + String.format( + "Security permission denied when reading file %s: %s", filePath, e.getMessage()), + e); } // Filter out empty lines @@ -106,12 +101,14 @@ public IDToken getIDToken(String audience) { .collect(Collectors.toList()); if (nonEmptyLines.isEmpty()) { - throw new DatabricksException(String.format(ERROR_EMPTY_FILE, filePath)); + throw new DatabricksException(String.format("File %s contains only empty lines", filePath)); } if (nonEmptyLines.size() > 1) { throw new DatabricksException( - String.format(ERROR_MULTIPLE_LINES, filePath, nonEmptyLines.size())); + String.format( + "The token should be a single line but the file %s contains %d non-empty lines", + filePath, nonEmptyLines.size())); } String token = nonEmptyLines.get(0); @@ -119,7 +116,8 @@ public IDToken getIDToken(String audience) { try { return new IDToken(token); } catch (IllegalArgumentException e) { - throw new DatabricksException(String.format(ERROR_EMPTY_TOKEN, filePath)); + throw new DatabricksException( + String.format("Received empty ID token from file %s", filePath)); } } }