Skip to content

Commit d5c9519

Browse files
committed
Add static credentials support
1 parent d87feda commit d5c9519

File tree

7 files changed

+109
-31
lines changed

7 files changed

+109
-31
lines changed

src/main/java/tech/ydb/jdbc/YdbDriver.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public YdbConnection connect(String url, Properties info) throws SQLException {
5151
YdbConfig config = new YdbConfig(url, info);
5252
LOGGER.log(Level.INFO, "About to connect to [{0}] using properties {1}", new Object[] {
5353
config.getSafeUrl(),
54-
info
54+
config.getSafeProps()
5555
});
5656

5757
if (config.getOperationProperties().isCacheConnectionsInDriver()) {
@@ -69,15 +69,21 @@ public void close() throws SQLException {
6969
};
7070
}
7171

72-
public YdbContext getCachedContext(YdbConfig config) {
72+
public YdbContext getCachedContext(YdbConfig config) throws SQLException {
7373
// Workaround for https://bugs.openjdk.java.net/browse/JDK-8161372 to prevent unnecessary locks in Java 8
7474
// Was fixed in Java 9+
7575
YdbContext context = cache.get(config);
7676
if (context != null) {
7777
LOGGER.log(Level.FINE, "Reusing YDB connection to {0}", config.getConnectionProperties());
7878
return context;
7979
}
80-
return cache.computeIfAbsent(config, YdbContext::createContext);
80+
81+
context = YdbContext.createContext(config);
82+
YdbContext old = cache.put(config, context);
83+
if (old != null) {
84+
old.close();
85+
}
86+
return context;
8187
}
8288

8389
@Override

src/main/java/tech/ydb/jdbc/connection/YdbConfig.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import tech.ydb.jdbc.settings.YdbClientProperties;
88
import tech.ydb.jdbc.settings.YdbConnectionProperties;
9+
import tech.ydb.jdbc.settings.YdbConnectionProperty;
910
import tech.ydb.jdbc.settings.YdbJdbcTools;
1011
import tech.ydb.jdbc.settings.YdbOperationProperties;
1112
import tech.ydb.jdbc.settings.YdbProperties;
@@ -26,6 +27,23 @@ public YdbConfig(String url, Properties properties) throws SQLException {
2627
this.config = YdbJdbcTools.from(url, properties);
2728
}
2829

30+
public Properties getSafeProps() {
31+
Properties safe = new Properties();
32+
for (String key: properties.stringPropertyNames()) {
33+
if (isSensetive(key)) {
34+
safe.put(key, "***");
35+
} else {
36+
safe.put(key, properties.get(key));
37+
}
38+
}
39+
return safe;
40+
}
41+
42+
private static boolean isSensetive(String key) {
43+
return YdbConnectionProperty.TOKEN.getName().equalsIgnoreCase(key)
44+
|| "password".equalsIgnoreCase(key);
45+
}
46+
2947
@Override
3048
public boolean equals(Object o) {
3149
if (this == o) {

src/main/java/tech/ydb/jdbc/connection/YdbContext.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package tech.ydb.jdbc.connection;
22

3+
import java.sql.SQLException;
34
import java.util.Objects;
45
import java.util.logging.Level;
56
import java.util.logging.Logger;
67

78
import tech.ydb.core.grpc.GrpcTransport;
9+
import tech.ydb.jdbc.exception.YdbConfigurationException;
810
import tech.ydb.jdbc.settings.YdbClientProperties;
911
import tech.ydb.jdbc.settings.YdbConnectionProperties;
1012
import tech.ydb.jdbc.settings.YdbOperationProperties;
@@ -63,16 +65,20 @@ public void close() {
6365
}
6466
}
6567

66-
public static YdbContext createContext(YdbConfig config) {
67-
YdbConnectionProperties connProps = config.getConnectionProperties();
68-
YdbClientProperties clientProps = config.getClientProperties();
68+
public static YdbContext createContext(YdbConfig config) throws SQLException {
69+
try {
70+
YdbConnectionProperties connProps = config.getConnectionProperties();
71+
YdbClientProperties clientProps = config.getClientProperties();
6972

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

72-
GrpcTransport grpcTransport = connProps.toGrpcTransport();
75+
GrpcTransport grpcTransport = connProps.toGrpcTransport();
7376

74-
TableClient tableClient = clientProps.toTableClient(grpcTransport);
77+
TableClient tableClient = clientProps.toTableClient(grpcTransport);
7578

76-
return new YdbContext(config, grpcTransport, tableClient);
79+
return new YdbContext(config, grpcTransport, tableClient);
80+
} catch (Exception ex) {
81+
throw new YdbConfigurationException("Cannot connect to YDB", ex);
82+
}
7783
}
7884
}

src/main/java/tech/ydb/jdbc/settings/YdbConnectionProperties.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,23 @@
55

66
import javax.annotation.Nullable;
77

8+
import tech.ydb.core.auth.StaticCredentials;
89
import tech.ydb.core.grpc.GrpcTransport;
910
import tech.ydb.core.grpc.GrpcTransportBuilder;
1011

1112
public class YdbConnectionProperties {
1213
private final String safeURL;
1314
private final String connectionString;
15+
private final String username;
16+
private final String password;
1417
private final Map<YdbConnectionProperty<?>, ParsedProperty> params;
1518

16-
public YdbConnectionProperties(String safeURL, String connectionString,
19+
public YdbConnectionProperties(String safeURL, String connectionString, String username, String password,
1720
Map<YdbConnectionProperty<?>, ParsedProperty> params) {
1821
this.safeURL = safeURL;
1922
this.connectionString = Objects.requireNonNull(connectionString);
23+
this.username = username;
24+
this.password = password;
2025
this.params = Objects.requireNonNull(params);
2126
}
2227

@@ -44,6 +49,11 @@ public GrpcTransport toGrpcTransport() {
4449
entry.getKey().getSetter().accept(builder, entry.getValue().getParsedValue());
4550
}
4651
}
52+
53+
if (username != null && !username.isEmpty()) {
54+
builder = builder.withAuthProvider(new StaticCredentials(username, password));
55+
}
56+
4757
return builder.build();
4858
}
4959
}

src/main/java/tech/ydb/jdbc/settings/YdbJdbcTools.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,27 @@ public static YdbProperties from(String jdbcURL, Properties origProperties) thro
3939
String connectionString = ydbURL;
4040
String safeURL = ydbURL;
4141

42+
String username = origProperties.getProperty("user");
43+
String password = origProperties.getProperty("password");
44+
4245
Properties properties = new Properties();
4346
properties.putAll(origProperties);
4447

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

52+
String userInfo = url.getUserInfo();
53+
if (username == null && userInfo != null) {
54+
String[] parsed = userInfo.split(":", 2);
55+
if (parsed.length > 0) {
56+
username = parsed[0];
57+
}
58+
if (parsed.length > 1) {
59+
password = parsed[1];
60+
}
61+
}
62+
4963
String database = url.getPath();
5064

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

91-
YdbConnectionProperties ydbConnectionProps = new YdbConnectionProperties(
92-
safeURL, connectionString, parseProperties(properties, YdbConnectionProperty.properties()));
105+
YdbConnectionProperties ydbConnectionProps = new YdbConnectionProperties(safeURL, connectionString,
106+
username, password, parseProperties(properties, YdbConnectionProperty.properties()));
93107
YdbClientProperties ydbClientProperties = new YdbClientProperties(
94108
parseProperties(properties, YdbClientProperty.properties()));
95109
YdbOperationProperties ydbOperationProperties = new YdbOperationProperties(

src/test/java/tech/ydb/jdbc/YdbDriverStaticCredsTest.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ public static void createUsers() throws SQLException {
3131
try (Connection connection = DriverManager.getConnection(jdbcURL.build())) {
3232
try (Statement statement = connection.createStatement()) {
3333
statement.execute(QueryType.SCHEME_QUERY.getPrefix() + "\n"
34-
+ "CREATE USER user1 PASSWORD NULL;"
35-
+ "CREATE USER user2 PASSWORD 'pwss';"
34+
+ "CREATE USER user1 PASSWORD NULL;\n"
35+
+ "CREATE USER user2 PASSWORD 'pwss';\n"
36+
+ "CREATE USER user3 PASSWORD 'pw :ss;'\n;"
3637
);
3738
}
3839
}
@@ -43,7 +44,7 @@ public static void dropUsers() throws SQLException {
4344
try (Connection connection = DriverManager.getConnection(jdbcURL.build())) {
4445
try (Statement statement = connection.createStatement()) {
4546
statement.execute(QueryType.SCHEME_QUERY.getPrefix() + "\n"
46-
+ "DROP USER IF EXISTS user1, user2;"
47+
+ "DROP USER IF EXISTS user1, user2, user3;\n"
4748
);
4849
}
4950
}
@@ -70,25 +71,36 @@ private void testConnection(ConnectionSupplier connectionSupplier) throws SQLExc
7071
}
7172
}
7273

74+
private void wrongConnection(ConnectionSupplier connectionSupplier) {
75+
ExceptionAssert.ydbConfiguration("Cannot connect to YDB", () -> testConnection(connectionSupplier));
76+
}
77+
7378
@Test
7479
public void connectOK() throws SQLException {
75-
testConnection(connectByProperties("user1", "pwss"));
76-
testConnection(connectByAuthority("user1", "pwss"));
80+
testConnection(connectByProperties("user1", ""));
81+
testConnection(connectByAuthority("user1", ""));
7782

78-
testConnection(connectByProperties("user2", ""));
79-
testConnection(connectByAuthority("user2", ""));
83+
testConnection(connectByProperties("user1", null));
84+
testConnection(connectByAuthority("user1", null));
8085

81-
testConnection(connectByProperties("user2", null));
82-
testConnection(connectByAuthority("user2", null));
86+
testConnection(connectByProperties("user2", "pwss"));
87+
testConnection(connectByAuthority("user2", "pwss"));
88+
89+
testConnection(connectByProperties("user3", "pw :ss;"));
90+
testConnection(connectByAuthority("user3", "pw :ss;"));
8391
}
8492

8593
@Test
86-
public void connectWring() throws SQLException {
87-
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", "")));
88-
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", null)));
89-
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user1", "pass")));
94+
public void connectWrong() throws SQLException {
95+
wrongConnection(connectByProperties("user1", "a"));
96+
97+
wrongConnection(connectByProperties("user2", ""));
98+
wrongConnection(connectByProperties("user2", null));
99+
wrongConnection(connectByProperties("user2", "pass"));
90100

91-
ExceptionAssert.ydbConfiguration("can't connect", () -> testConnection(connectByProperties("user2", "a")));
101+
wrongConnection(connectByProperties("user3", ""));
102+
wrongConnection(connectByProperties("user3", null));
103+
wrongConnection(connectByProperties("user3", "pw:ss;"));
92104
}
93105

94106
interface ConnectionSupplier {

src/test/java/tech/ydb/jdbc/impl/helper/JdbcUrlHelper.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package tech.ydb.jdbc.impl.helper;
22

33

4+
import java.io.UnsupportedEncodingException;
5+
import java.net.URLEncoder;
6+
import java.nio.charset.StandardCharsets;
7+
48
import tech.ydb.test.junit5.YdbHelperExtension;
59

610
/**
@@ -31,17 +35,17 @@ public JdbcUrlHelper disableToken() {
3135
public JdbcUrlHelper withArg(String arg, String value) {
3236
String newExtra = new StringBuilder(extra)
3337
.append(extra.isEmpty() ? "" : "&")
34-
.append(arg)
38+
.append(encode(arg))
3539
.append("=")
36-
.append(value)
40+
.append(encode(value))
3741
.toString();
3842
return new JdbcUrlHelper(ydb, newExtra, authority, disableToken);
3943
}
4044

4145
public JdbcUrlHelper withAutority(String username, String password) {
42-
StringBuilder newAuthority = new StringBuilder(username);
46+
StringBuilder newAuthority = new StringBuilder(encode(username));
4347
if (password != null && !password.isEmpty()) {
44-
newAuthority = newAuthority.append(":").append(password);
48+
newAuthority = newAuthority.append(":").append(encode(password));
4549
}
4650
return new JdbcUrlHelper(ydb, extra, newAuthority.append("@").toString(), disableToken);
4751
}
@@ -64,4 +68,12 @@ public String build() {
6468

6569
return jdbc.toString();
6670
}
71+
72+
private static String encode(String raw) {
73+
try {
74+
return URLEncoder.encode(raw, StandardCharsets.UTF_8.name()).replace("+", "%20");
75+
} catch (UnsupportedEncodingException ex) {
76+
return raw;
77+
}
78+
}
6779
}

0 commit comments

Comments
 (0)