Skip to content

Commit

Permalink
SNOW-1689931 Adding flag to skip token file permission verification
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-pmotacki committed Nov 25, 2024
1 parent 1286a3e commit 120f492
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.snowflake.client.config;

import static net.snowflake.client.jdbc.SnowflakeUtil.convertSystemGetEnvToBooleanValue;
import static net.snowflake.client.jdbc.SnowflakeUtil.systemGetEnv;

import com.fasterxml.jackson.dataformat.toml.TomlMapper;
Expand Down Expand Up @@ -34,6 +35,50 @@ public class SFConnectionConfigParser {
"SNOWFLAKE_DEFAULT_CONNECTION_NAME";
public static final String DEFAULT = "default";
public static final String SNOWFLAKE_TOKEN_FILE_PATH = "/snowflake/session/token";
public static final String SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION =
"SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION";

public static ConnectionParameters buildConnectionParameters() throws SnowflakeSQLException {
String defaultConnectionName =
Optional.ofNullable(systemGetEnv(SNOWFLAKE_DEFAULT_CONNECTION_NAME_KEY)).orElse(DEFAULT);
Map<String, String> fileConnectionConfiguration =
loadDefaultConnectionConfiguration(defaultConnectionName);

if (fileConnectionConfiguration != null && !fileConnectionConfiguration.isEmpty()) {
Properties conectionProperties = new Properties();
conectionProperties.putAll(fileConnectionConfiguration);

String url = createUrl(fileConnectionConfiguration);
logger.debug("Url created using parameters from connection configuration file: {}", url);

if ("oauth".equals(fileConnectionConfiguration.get("authenticator"))
&& fileConnectionConfiguration.get("token") == null) {
Path path =
Paths.get(
Optional.ofNullable(fileConnectionConfiguration.get("token_file_path"))
.orElse(SNOWFLAKE_TOKEN_FILE_PATH));
logger.debug("Token used in connect is read from file: {}", path);
try {
boolean shouldSkipTokenFilePermissionsVerification =
convertSystemGetEnvToBooleanValue(SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION, false);
if (!shouldSkipTokenFilePermissionsVerification) {
verifyFilePermissionSecure(path);
}
String token = new String(Files.readAllBytes(path), Charset.defaultCharset());
if (!token.isEmpty()) {
putPropertyIfNotNull(conectionProperties, "token", token.trim());
} else {
logger.warn("The token has empty value");
}
} catch (Exception ex) {
throw new SnowflakeSQLException(ex, "There is a problem during reading token from file");
}
}
return new ConnectionParameters(url, conectionProperties);
} else {
return null;
}
}

private static Map<String, String> loadDefaultConnectionConfiguration(
String defaultConnectionName) throws SnowflakeSQLException {
Expand Down Expand Up @@ -88,44 +133,6 @@ private static void verifyFilePermissionSecure(Path configFilePath)
}
}

public static ConnectionParameters buildConnectionParameters() throws SnowflakeSQLException {
String defaultConnectionName =
Optional.ofNullable(systemGetEnv(SNOWFLAKE_DEFAULT_CONNECTION_NAME_KEY)).orElse(DEFAULT);
Map<String, String> fileConnectionConfiguration =
loadDefaultConnectionConfiguration(defaultConnectionName);

if (fileConnectionConfiguration != null && !fileConnectionConfiguration.isEmpty()) {
Properties conectionProperties = new Properties();
conectionProperties.putAll(fileConnectionConfiguration);

String url = createUrl(fileConnectionConfiguration);
logger.debug("Url created using parameters from connection configuration file: {}", url);

if ("oauth".equals(fileConnectionConfiguration.get("authenticator"))
&& fileConnectionConfiguration.get("token") == null) {
Path path =
Paths.get(
Optional.ofNullable(fileConnectionConfiguration.get("token_file_path"))
.orElse(SNOWFLAKE_TOKEN_FILE_PATH));
logger.debug("Token used in connect is read from file: {}", path);
try {
verifyFilePermissionSecure(path);
String token = new String(Files.readAllBytes(path), Charset.defaultCharset());
if (!token.isEmpty()) {
putPropertyIfNotNull(conectionProperties, "token", token.trim());
} else {
logger.warn("The token has empty value");
}
} catch (Exception ex) {
throw new SnowflakeSQLException(ex, "There is a problem during reading token from file");
}
}
return new ConnectionParameters(url, conectionProperties);
} else {
return null;
}
}

private static String createUrl(Map<String, String> fileConnectionConfiguration)
throws SnowflakeSQLException {
Optional<String> maybeAccount = Optional.ofNullable(fileConnectionConfiguration.get("account"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ public enum SFSessionProperty {

HTTP_CLIENT_CONNECTION_TIMEOUT("HTTP_CLIENT_CONNECTION_TIMEOUT", false, Integer.class),

HTTP_CLIENT_SOCKET_TIMEOUT("HTTP_CLIENT_SOCKET_TIMEOUT", false, Integer.class);
HTTP_CLIENT_SOCKET_TIMEOUT("HTTP_CLIENT_SOCKET_TIMEOUT", false, Integer.class),

SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION(
"SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION", false, Boolean.class);

// property key in string
private String propertyKey;
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,22 @@ public static boolean convertSystemPropertyToBooleanValue(
}
return defaultValue;
}
/**
* Helper function to convert environment variable to boolean
*
* @param envVariableKey property name of the environment variable
* @param defaultValue default value used
* @return the value of the environment variable as boolean, else the default value
*/
@SnowflakeJdbcInternalApi
public static boolean convertSystemGetEnvToBooleanValue(
String envVariableKey, boolean defaultValue) {
String environmentVariableValue = systemGetEnv(envVariableKey);
if (environmentVariableValue != null) {
return Boolean.parseBoolean(environmentVariableValue);
}
return defaultValue;
}

@SnowflakeJdbcInternalApi
public static <T> T mapSFExceptionToSQLException(ThrowingCallable<T, SFException> action)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.snowflake.client.config;

import static net.snowflake.client.config.SFConnectionConfigParser.SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION;
import static net.snowflake.client.config.SFConnectionConfigParser.SNOWFLAKE_DEFAULT_CONNECTION_NAME_KEY;
import static net.snowflake.client.config.SFConnectionConfigParser.SNOWFLAKE_HOME_KEY;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -44,6 +45,7 @@ public void setUp() throws IOException {
public void close() throws IOException {
SnowflakeUtil.systemUnsetEnv(SNOWFLAKE_HOME_KEY);
SnowflakeUtil.systemUnsetEnv(SNOWFLAKE_DEFAULT_CONNECTION_NAME_KEY);
SnowflakeUtil.systemUnsetEnv(SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION);
Files.walk(tempPath).map(Path::toFile).forEach(File::delete);
Files.delete(tempPath);
}
Expand Down Expand Up @@ -103,6 +105,21 @@ public void testThrowErrorWhenWrongPermissionsForTokenFile() throws IOException
SnowflakeSQLException.class, () -> SFConnectionConfigParser.buildConnectionParameters());
}

@Test
public void testNoThrowErrorWhenWrongPermissionsForTokenFileButSkippingFlagIsEnabled()
throws SnowflakeSQLException, IOException {
SnowflakeUtil.systemSetEnv(SNOWFLAKE_HOME_KEY, tempPath.toString());
SnowflakeUtil.systemSetEnv(SNOWFLAKE_DEFAULT_CONNECTION_NAME_KEY, "default");
SnowflakeUtil.systemSetEnv(SKIP_TOKEN_FILE_PERMISSIONS_VERIFICATION, "true");
File tokenFile = new File(Paths.get(tempPath.toString(), "token").toUri());
prepareConnectionConfigurationTomlFile(
Collections.singletonMap("token_file_path", tokenFile.toString()), true, false);

ConnectionParameters data = SFConnectionConfigParser.buildConnectionParameters();
assertNotNull(data);
assertEquals(tokenFile.toString(), data.getParams().get("token_file_path"));
}

@Test
public void testLoadSFConnectionConfigWithHostConfigured()
throws SnowflakeSQLException, IOException {
Expand Down

0 comments on commit 120f492

Please sign in to comment.