Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiple, successive connections using AKV provider #1594

Merged
merged 3 commits into from Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 19 additions & 25 deletions src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java
Expand Up @@ -1576,8 +1576,11 @@ private void registerKeyStoreProviderOnConnection(String keyStoreAuth, String ke
// need a secret to use the secret method
if (null == keyStoreSecret) {
throw new SQLServerException(SQLServerException.getErrString("R_keyStoreSecretNotSet"), null);
} else {
SQLServerColumnEncryptionAzureKeyVaultProvider provider = new SQLServerColumnEncryptionAzureKeyVaultProvider(
keyStorePrincipalId, keyStoreSecret);
systemColumnEncryptionKeyStoreProvider.put(provider.getName(), provider);
}
registerKeyVaultProvider(keyStorePrincipalId, keyStoreSecret);
break;
case KeyVaultManagedIdentity:
SQLServerColumnEncryptionAzureKeyVaultProvider provider;
Expand All @@ -1586,9 +1589,7 @@ private void registerKeyStoreProviderOnConnection(String keyStoreAuth, String ke
} else {
provider = new SQLServerColumnEncryptionAzureKeyVaultProvider();
}
Map<String, SQLServerColumnEncryptionKeyStoreProvider> keyStoreMap = new HashMap<>();
keyStoreMap.put(provider.getName(), provider);
registerColumnEncryptionKeyStoreProviders(keyStoreMap);
systemColumnEncryptionKeyStoreProvider.put(provider.getName(), provider);
break;
default:
// valueOfString would throw an exception if the keyStoreAuthentication is not valid.
Expand All @@ -1597,15 +1598,6 @@ private void registerKeyStoreProviderOnConnection(String keyStoreAuth, String ke
}
}

private void registerKeyVaultProvider(String clientId, String clientKey) throws SQLServerException {
// need a secret to use the secret method
SQLServerColumnEncryptionAzureKeyVaultProvider provider = new SQLServerColumnEncryptionAzureKeyVaultProvider(
clientId, clientKey);
Map<String, SQLServerColumnEncryptionKeyStoreProvider> keyStoreMap = new HashMap<>();
keyStoreMap.put(provider.getName(), provider);
registerColumnEncryptionKeyStoreProviders(keyStoreMap);
}

// Helper to check if timeout value is valid
int validateTimeout(SQLServerDriverIntProperty property) throws SQLServerException {
int timeout = property.getDefaultValue();
Expand Down Expand Up @@ -1843,20 +1835,22 @@ Connection connectInternal(Properties propsIn,

registerKeyStoreProviderOnConnection(keyStoreAuthentication, keyStoreSecret, keyStoreLocation);

if (null == globalCustomColumnEncryptionKeyStoreProviders) {
sPropKey = SQLServerDriverStringProperty.KEY_VAULT_PROVIDER_CLIENT_ID.toString();
sPropKey = SQLServerDriverStringProperty.KEY_VAULT_PROVIDER_CLIENT_ID.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null != sPropValue) {
if (null != keyStoreAuthentication) {
throw new SQLServerException(SQLServerException.getErrString("R_keyVaultProviderNotSupportedWithKeyStoreAuthentication"), null);
}
String keyVaultColumnEncryptionProviderClientId = sPropValue;
sPropKey = SQLServerDriverStringProperty.KEY_VAULT_PROVIDER_CLIENT_KEY.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null != sPropValue) {
String keyVaultColumnEncryptionProviderClientId = sPropValue;
sPropKey = SQLServerDriverStringProperty.KEY_VAULT_PROVIDER_CLIENT_KEY.toString();
sPropValue = activeConnectionProperties.getProperty(sPropKey);
if (null != sPropValue) {
String keyVaultColumnEncryptionProviderClientKey = sPropValue;

registerKeyVaultProvider(keyVaultColumnEncryptionProviderClientId,
keyVaultColumnEncryptionProviderClientKey);
}
if (null == sPropValue) {
throw new SQLServerException(SQLServerException.getErrString("R_keyVaultProviderNotSupportedWithKeyStoreAuthentication"), null);
David-Engel marked this conversation as resolved.
Show resolved Hide resolved
}
String keyVaultColumnEncryptionProviderClientKey = sPropValue;
SQLServerColumnEncryptionAzureKeyVaultProvider provider = new SQLServerColumnEncryptionAzureKeyVaultProvider(
keyVaultColumnEncryptionProviderClientId, keyVaultColumnEncryptionProviderClientKey);
systemColumnEncryptionKeyStoreProvider.put(provider.getName(), provider);
}

sPropKey = SQLServerDriverBooleanProperty.MULTI_SUBNET_FAILOVER.toString();
Expand Down
Expand Up @@ -550,6 +550,8 @@ protected Object[][] getContents() {
"Both \"keyStoreSecret\" and \"keyStoreLocation\" must be set, if \"keyStoreAuthentication=JavaKeyStorePassword\" has been specified in the connection string."},
{"R_keyStoreSecretNotSet",
"\"keyStoreSecret\" must be set, if \"keyStoreAuthentication=KeyVaultClientSecret\" has been specified in the connection string."},
{"R_keyVaultProviderNotSupportedWithKeyStoreAuthentication",
"\"keyStoreAuthentication\" cannot be used with \"keyVaultProviderClientId\" or \"keyVaultProviderClientKey\" in the connection string."},
{"R_certificateStoreInvalidKeyword",
"Cannot set \"keyStoreSecret\", if \"keyStoreAuthentication=CertificateStore\" has been specified in the connection string."},
{"R_certificateStoreLocationNotSet",
Expand Down
@@ -0,0 +1,38 @@
/*
* Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
* available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc.connection;

import java.sql.Connection;
import java.sql.SQLException;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.microsoft.sqlserver.testframework.AbstractTest;

/*
* This test is for testing various connection options
*/
@RunWith(JUnitPlatform.class)
public class ConnectionTest extends AbstractTest {

@Test
public void testConnections() throws SQLException {
SQLServerDataSource ds = new SQLServerDataSource();
ds.setURL(connectionString);
ds.setKeyStoreAuthentication("KeyVaultClientSecret");
ds.setKeyStorePrincipalId("placeholder");
ds.setKeyStoreSecret("placeholder");

// Multiple, successive connections should not fail
try (Connection con = ds.getConnection()) {
}

try (Connection con = ds.getConnection()) {
}
}
}