Skip to content

Commit

Permalink
Add static credentials support
Browse files Browse the repository at this point in the history
  • Loading branch information
alex268 committed Apr 30, 2023
1 parent d87feda commit d5c9519
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 31 deletions.
12 changes: 9 additions & 3 deletions src/main/java/tech/ydb/jdbc/YdbDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public YdbConnection connect(String url, Properties info) throws SQLException {
YdbConfig config = new YdbConfig(url, info);
LOGGER.log(Level.INFO, "About to connect to [{0}] using properties {1}", new Object[] {
config.getSafeUrl(),
info
config.getSafeProps()
});

if (config.getOperationProperties().isCacheConnectionsInDriver()) {
Expand All @@ -69,15 +69,21 @@ public void close() throws SQLException {
};
}

public YdbContext getCachedContext(YdbConfig config) {
public YdbContext getCachedContext(YdbConfig config) throws SQLException {
// Workaround for https://bugs.openjdk.java.net/browse/JDK-8161372 to prevent unnecessary locks in Java 8
// Was fixed in Java 9+
YdbContext context = cache.get(config);
if (context != null) {
LOGGER.log(Level.FINE, "Reusing YDB connection to {0}", config.getConnectionProperties());
return context;
}
return cache.computeIfAbsent(config, YdbContext::createContext);

context = YdbContext.createContext(config);
YdbContext old = cache.put(config, context);
if (old != null) {
old.close();
}
return context;
}

@Override
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/tech/ydb/jdbc/connection/YdbConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import tech.ydb.jdbc.settings.YdbClientProperties;
import tech.ydb.jdbc.settings.YdbConnectionProperties;
import tech.ydb.jdbc.settings.YdbConnectionProperty;
import tech.ydb.jdbc.settings.YdbJdbcTools;
import tech.ydb.jdbc.settings.YdbOperationProperties;
import tech.ydb.jdbc.settings.YdbProperties;
Expand All @@ -26,6 +27,23 @@ public YdbConfig(String url, Properties properties) throws SQLException {
this.config = YdbJdbcTools.from(url, properties);
}

public Properties getSafeProps() {
Properties safe = new Properties();
for (String key: properties.stringPropertyNames()) {
if (isSensetive(key)) {
safe.put(key, "***");
} else {
safe.put(key, properties.get(key));
}
}
return safe;
}

private static boolean isSensetive(String key) {
return YdbConnectionProperty.TOKEN.getName().equalsIgnoreCase(key)
|| "password".equalsIgnoreCase(key);
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
20 changes: 13 additions & 7 deletions src/main/java/tech/ydb/jdbc/connection/YdbContext.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package tech.ydb.jdbc.connection;

import java.sql.SQLException;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;

import tech.ydb.core.grpc.GrpcTransport;
import tech.ydb.jdbc.exception.YdbConfigurationException;
import tech.ydb.jdbc.settings.YdbClientProperties;
import tech.ydb.jdbc.settings.YdbConnectionProperties;
import tech.ydb.jdbc.settings.YdbOperationProperties;
Expand Down Expand Up @@ -63,16 +65,20 @@ public void close() {
}
}

public static YdbContext createContext(YdbConfig config) {
YdbConnectionProperties connProps = config.getConnectionProperties();
YdbClientProperties clientProps = config.getClientProperties();
public static YdbContext createContext(YdbConfig config) throws SQLException {
try {
YdbConnectionProperties connProps = config.getConnectionProperties();
YdbClientProperties clientProps = config.getClientProperties();

LOGGER.log(Level.INFO, "Creating new YDB connection to {0}", connProps.getConnectionString());
LOGGER.log(Level.INFO, "Creating new YDB connection to {0}", connProps.getConnectionString());

GrpcTransport grpcTransport = connProps.toGrpcTransport();
GrpcTransport grpcTransport = connProps.toGrpcTransport();

TableClient tableClient = clientProps.toTableClient(grpcTransport);
TableClient tableClient = clientProps.toTableClient(grpcTransport);

return new YdbContext(config, grpcTransport, tableClient);
return new YdbContext(config, grpcTransport, tableClient);
} catch (Exception ex) {
throw new YdbConfigurationException("Cannot connect to YDB", ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@

import javax.annotation.Nullable;

import tech.ydb.core.auth.StaticCredentials;
import tech.ydb.core.grpc.GrpcTransport;
import tech.ydb.core.grpc.GrpcTransportBuilder;

public class YdbConnectionProperties {
private final String safeURL;
private final String connectionString;
private final String username;
private final String password;
private final Map<YdbConnectionProperty<?>, ParsedProperty> params;

public YdbConnectionProperties(String safeURL, String connectionString,
public YdbConnectionProperties(String safeURL, String connectionString, String username, String password,
Map<YdbConnectionProperty<?>, ParsedProperty> params) {
this.safeURL = safeURL;
this.connectionString = Objects.requireNonNull(connectionString);
this.username = username;
this.password = password;
this.params = Objects.requireNonNull(params);
}

Expand Down Expand Up @@ -44,6 +49,11 @@ public GrpcTransport toGrpcTransport() {
entry.getKey().getSetter().accept(builder, entry.getValue().getParsedValue());
}
}

if (username != null && !username.isEmpty()) {
builder = builder.withAuthProvider(new StaticCredentials(username, password));
}

return builder.build();
}
}
18 changes: 16 additions & 2 deletions src/main/java/tech/ydb/jdbc/settings/YdbJdbcTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,27 @@ public static YdbProperties from(String jdbcURL, Properties origProperties) thro
String connectionString = ydbURL;
String safeURL = ydbURL;

String username = origProperties.getProperty("user");
String password = origProperties.getProperty("password");

Properties properties = new Properties();
properties.putAll(origProperties);

if (!ydbURL.isEmpty()) {
URI url = new URI(ydbURL.contains("://") ? ydbURL : "grpc://" + ydbURL);
Map<String, List<String>> params = URITools.splitQuery(url);

String userInfo = url.getUserInfo();
if (username == null && userInfo != null) {
String[] parsed = userInfo.split(":", 2);
if (parsed.length > 0) {
username = parsed[0];
}
if (parsed.length > 1) {
password = parsed[1];
}
}

String database = url.getPath();

// merge properties and query params
Expand Down Expand Up @@ -88,8 +102,8 @@ public static YdbProperties from(String jdbcURL, Properties origProperties) thro
safeURL = sb.toString();
}

YdbConnectionProperties ydbConnectionProps = new YdbConnectionProperties(
safeURL, connectionString, parseProperties(properties, YdbConnectionProperty.properties()));
YdbConnectionProperties ydbConnectionProps = new YdbConnectionProperties(safeURL, connectionString,
username, password, parseProperties(properties, YdbConnectionProperty.properties()));
YdbClientProperties ydbClientProperties = new YdbClientProperties(
parseProperties(properties, YdbClientProperty.properties()));
YdbOperationProperties ydbOperationProperties = new YdbOperationProperties(
Expand Down
40 changes: 26 additions & 14 deletions src/test/java/tech/ydb/jdbc/YdbDriverStaticCredsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public static void createUsers() throws SQLException {
try (Connection connection = DriverManager.getConnection(jdbcURL.build())) {
try (Statement statement = connection.createStatement()) {
statement.execute(QueryType.SCHEME_QUERY.getPrefix() + "\n"
+ "CREATE USER user1 PASSWORD NULL;"
+ "CREATE USER user2 PASSWORD 'pwss';"
+ "CREATE USER user1 PASSWORD NULL;\n"
+ "CREATE USER user2 PASSWORD 'pwss';\n"
+ "CREATE USER user3 PASSWORD 'pw :ss;'\n;"
);
}
}
Expand All @@ -43,7 +44,7 @@ public static void dropUsers() throws SQLException {
try (Connection connection = DriverManager.getConnection(jdbcURL.build())) {
try (Statement statement = connection.createStatement()) {
statement.execute(QueryType.SCHEME_QUERY.getPrefix() + "\n"
+ "DROP USER IF EXISTS user1, user2;"
+ "DROP USER IF EXISTS user1, user2, user3;\n"
);
}
}
Expand All @@ -70,25 +71,36 @@ private void testConnection(ConnectionSupplier connectionSupplier) throws SQLExc
}
}

private void wrongConnection(ConnectionSupplier connectionSupplier) {
ExceptionAssert.ydbConfiguration("Cannot connect to YDB", () -> testConnection(connectionSupplier));
}

@Test
public void connectOK() throws SQLException {
testConnection(connectByProperties("user1", "pwss"));
testConnection(connectByAuthority("user1", "pwss"));
testConnection(connectByProperties("user1", ""));
testConnection(connectByAuthority("user1", ""));

testConnection(connectByProperties("user2", ""));
testConnection(connectByAuthority("user2", ""));
testConnection(connectByProperties("user1", null));
testConnection(connectByAuthority("user1", null));

testConnection(connectByProperties("user2", null));
testConnection(connectByAuthority("user2", null));
testConnection(connectByProperties("user2", "pwss"));
testConnection(connectByAuthority("user2", "pwss"));

testConnection(connectByProperties("user3", "pw :ss;"));
testConnection(connectByAuthority("user3", "pw :ss;"));
}

@Test
public void connectWring() throws SQLException {
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", "")));
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", null)));
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", "pass")));
public void connectWrong() throws SQLException {
wrongConnection(connectByProperties("user1", "a"));

wrongConnection(connectByProperties("user2", ""));
wrongConnection(connectByProperties("user2", null));
wrongConnection(connectByProperties("user2", "pass"));

ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user2", "a")));
wrongConnection(connectByProperties("user3", ""));
wrongConnection(connectByProperties("user3", null));
wrongConnection(connectByProperties("user3", "pw:ss;"));
}

interface ConnectionSupplier {
Expand Down
20 changes: 16 additions & 4 deletions src/test/java/tech/ydb/jdbc/impl/helper/JdbcUrlHelper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package tech.ydb.jdbc.impl.helper;


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import tech.ydb.test.junit5.YdbHelperExtension;

/**
Expand Down Expand Up @@ -31,17 +35,17 @@ public JdbcUrlHelper disableToken() {
public JdbcUrlHelper withArg(String arg, String value) {
String newExtra = new StringBuilder(extra)
.append(extra.isEmpty() ? "" : "&")
.append(arg)
.append(encode(arg))
.append("=")
.append(value)
.append(encode(value))
.toString();
return new JdbcUrlHelper(ydb, newExtra, authority, disableToken);
}

public JdbcUrlHelper withAutority(String username, String password) {
StringBuilder newAuthority = new StringBuilder(username);
StringBuilder newAuthority = new StringBuilder(encode(username));
if (password != null && !password.isEmpty()) {
newAuthority = newAuthority.append(":").append(password);
newAuthority = newAuthority.append(":").append(encode(password));
}
return new JdbcUrlHelper(ydb, extra, newAuthority.append("@").toString(), disableToken);
}
Expand All @@ -64,4 +68,12 @@ public String build() {

return jdbc.toString();
}

private static String encode(String raw) {
try {
return URLEncoder.encode(raw, StandardCharsets.UTF_8.name()).replace("+", "%20");
} catch (UnsupportedEncodingException ex) {
return raw;
}
}
}

0 comments on commit d5c9519

Please sign in to comment.