use of com.mysql.cj.xdevapi.Session in project aws-mysql-jdbc by awslabs.
the class SecureSessionTest method testSecureSessionVerifyServerCertificateUsingSystemProps.
/**
* Tests secure {@link Session}s created via URL and properties map combined with SSL system properties, verifying server certificate.
*/
@Test
public void testSecureSessionVerifyServerCertificateUsingSystemProps() {
assumeTrue(supportsTestCertificates(this.session), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
System.setProperty("javax.net.ssl.trustStore", this.trustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", this.trustStorePassword);
Session testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiSslMode, XdevapiSslMode.VERIFY_CA));
assertSecureSession(testSession);
testSession.close();
Properties props = new Properties(this.sslFreeTestProperties);
props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), XdevapiSslMode.VERIFY_CA.toString());
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
testSession.close();
}
use of com.mysql.cj.xdevapi.Session in project aws-mysql-jdbc by awslabs.
the class SecureSessionTest method testSecureSessionDefaultAndRequired.
/**
* Tests secure {@link Session}s created via URL and properties map. This is the default if no ssl-mode is provided.
*/
@Test
public void testSecureSessionDefaultAndRequired() {
Session testSession = this.fact.getSession(this.sslFreeBaseUrl);
assertSecureSession(testSession);
testSession.close();
testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiSslMode, XdevapiSslMode.REQUIRED));
assertSecureSession(testSession);
testSession.close();
testSession = this.fact.getSession(this.sslFreeTestProperties);
assertSecureSession(testSession);
testSession.close();
Properties props = new Properties(this.sslFreeTestProperties);
props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), XdevapiSslMode.REQUIRED.toString());
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
testSession.close();
}
use of com.mysql.cj.xdevapi.Session in project aws-mysql-jdbc by awslabs.
the class SecureSessionTest method testAuthMechanisms.
/**
* Tests that PLAIN, MYSQL41, SHA256_MEMORY, and EXTERNAL authentication mechanisms.
*
* @throws Throwable
*/
@Test
public void testAuthMechanisms() throws Throwable {
try {
this.session.sql("CREATE USER IF NOT EXISTS 'testAuthMechNative'@'%' IDENTIFIED WITH mysql_native_password BY 'mysqlnative'").execute();
this.session.sql("GRANT SELECT ON *.* TO 'testAuthMechNative'@'%'").execute();
this.session.sql("CREATE USER IF NOT EXISTS 'testAuthMechSha256'@'%' IDENTIFIED WITH sha256_password BY 'sha256'").execute();
this.session.sql("GRANT SELECT ON *.* TO 'testAuthMechSha256'@'%'").execute();
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
this.session.sql("CREATE USER IF NOT EXISTS 'testAuthMechCachingSha2'@'%' IDENTIFIED WITH caching_sha2_password BY 'cachingsha2'").execute();
this.session.sql("GRANT SELECT ON *.* TO 'testAuthMechCachingSha2'@'%'").execute();
}
final Field sf = SessionImpl.class.getDeclaredField("session");
sf.setAccessible(true);
final Field pf = CoreSession.class.getDeclaredField("protocol");
pf.setAccessible(true);
final Field mf = XAuthenticationProvider.class.getDeclaredField("authMech");
mf.setAccessible(true);
Function<Session, AuthMech> getAuthMech = s -> {
try {
return (AuthMech) mf.get(((XProtocol) pf.get(sf.get(s))).getAuthenticationProvider());
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
};
/*
* Access denied (ER_ACCESS_DENIED_ERROR) error message from servers up to version 8.0.11.
* In MySQL 8.0.12 this message changed due to fix for Bug#27675699 - FAILED AUTHENTICATION AT X PLUGIN ALWAYS RETURNS ER_ACCESS_DENIED_ERROR.
* This variable may be redefined as needed along the test.
*/
String accessDeniedErrMsg = "ERROR 1045 \\(HY000\\) Invalid user or password";
/*
* Authenticate using (default) TLS first. As per MySQL 8.0.4 X Plugin this is required so that SHA2[56] logins get cached in SHA2_MEMORY.
*/
Session testSession = null;
Properties props = new Properties(this.sslFreeTestProperties);
// With default auth mechanism for secure connections (PLAIN).
// *** User: mysqlnative; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechNative");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "mysqlnative");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe & account gets cached.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechSha256; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechSha256");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "sha256");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe & account gets cached.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechSha256", testSession);
testSession.close();
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechCachingSha2; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechCachingSha2");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "cachingsha2");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe & account gets cached.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechCachingSha2", testSession);
testSession.close();
}
// Forcing an auth mechanism.
// *** User: testAuthMechNative; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechNative");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "mysqlnative");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
// *** User: testAuthMechNative; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Matching auth mechanism.
assertEquals(AuthMech.MYSQL41, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// *** User: testAuthMechNative; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechSha256; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechSha256");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "sha256");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechSha256", testSession);
testSession.close();
// *** User: testAuthMechSha256; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.12"))) {
accessDeniedErrMsg = "ERROR 1045 \\(HY000\\) Access denied for user 'testAuthMechSha256'@.*";
}
// Auth mech mismatch.
assertThrows(XProtocolError.class, accessDeniedErrMsg, () -> this.fact.getSession(props));
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// *** User: testAuthMechSha256; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechSha256", testSession);
testSession.close();
}
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechCachingSha2; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechCachingSha2");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "cachingsha2");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Connection is secure, passwords are safe.
assertEquals(AuthMech.PLAIN, getAuthMech.apply(testSession));
assertUser("testAuthMechCachingSha2", testSession);
testSession.close();
// *** User: testAuthMechCachingSha2; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.12"))) {
accessDeniedErrMsg = "ERROR 1045 \\(HY000\\) Access denied for user 'testAuthMechCachingSha2'@.*";
}
// Auth mech mismatch.
assertThrows(XProtocolError.class, accessDeniedErrMsg, () -> this.fact.getSession(props));
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// User: testAuthMechCachingSha2; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechCachingSha2", testSession);
testSession.close();
}
}
// *** User: external; Auth: EXTERNAL.
props.setProperty(PropertyKey.USER.getKeyName(), "external");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "external");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "EXTERNAL");
assertThrows(XProtocolError.class, "ERROR 1251 \\(HY000\\) Invalid authentication method EXTERNAL", () -> this.fact.getSession(props));
props.remove(PropertyKey.xdevapiAuth.getKeyName());
/*
* Authenticate using non-secure connections.
*/
props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), PropertyDefinitions.XdevapiSslMode.DISABLED.toString());
// With default auth mechanism for non-secure connections (MYSQL41|SHA2_MEMORY).
// *** User: testAuthMechNative; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechNative");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "mysqlnative");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Matching auth mechanism.
assertEquals(AuthMech.MYSQL41, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_PASSWORD requires secure connections in MySQL 8.0.3 and below.
// *** User: testAuthMechSha256; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechSha256");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "sha256");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechSha256", testSession);
testSession.close();
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// CACHING_SHA2_PASSWORD requires secure connections in MySQL 8.0.3 and below.
// *** User: testAuthMechCachingSha2; Auth: default.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechCachingSha2");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "cachingsha2");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechCachingSha2", testSession);
testSession.close();
}
// Forcing an auth mechanism.
// *** User: testAuthMechNative; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechNative");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "mysqlnative");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
assertThrows(XProtocolError.class, "PLAIN authentication is not allowed via unencrypted connection\\.", () -> this.fact.getSession(props));
// *** User: testAuthMechNative; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Matching auth mechanism.
assertEquals(AuthMech.MYSQL41, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// *** User: testAuthMechNative; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechNative", testSession);
testSession.close();
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechSha256; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechSha256");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "sha256");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
assertThrows(XProtocolError.class, "PLAIN authentication is not allowed via unencrypted connection\\.", () -> this.fact.getSession(props));
// *** User: testAuthMechSha256; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.12"))) {
accessDeniedErrMsg = "ERROR 1045 \\(HY000\\) Access denied for user 'testAuthMechSha256'@.*";
}
// Auth mech mismatch.
assertThrows(XProtocolError.class, accessDeniedErrMsg, () -> this.fact.getSession(props));
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// *** User: testAuthMechSha256; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechSha256", testSession);
testSession.close();
}
}
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.3"))) {
// *** User: testAuthMechCachingSha2; Auth: PLAIN.
props.setProperty(PropertyKey.USER.getKeyName(), "testAuthMechCachingSha2");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "cachingsha2");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "PLAIN");
assertThrows(XProtocolError.class, "PLAIN authentication is not allowed via unencrypted connection\\.", () -> this.fact.getSession(props));
// *** User: testAuthMechCachingSha2; Auth: MYSQL41.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "MYSQL41");
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.12"))) {
accessDeniedErrMsg = "ERROR 1045 \\(HY000\\) Access denied for user 'testAuthMechCachingSha2'@.*";
}
// Auth mech mismatch.
assertThrows(XProtocolError.class, accessDeniedErrMsg, () -> this.fact.getSession(props));
if (mysqlVersionMeetsMinimum(ServerVersion.parseVersion("8.0.4"))) {
// SHA256_MEMORY support added in MySQL 8.0.4.
// *** User: testAuthMechCachingSha2; Auth: SHA256_MEMORY.
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "SHA256_MEMORY");
testSession = this.fact.getSession(props);
assertNonSecureSession(testSession);
// Account is cached by now.
assertEquals(AuthMech.SHA256_MEMORY, getAuthMech.apply(testSession));
assertUser("testAuthMechCachingSha2", testSession);
testSession.close();
}
}
// *** User: external; Auth: EXTERNAL.
props.setProperty(PropertyKey.USER.getKeyName(), "external");
props.setProperty(PropertyKey.PASSWORD.getKeyName(), "external");
props.setProperty(PropertyKey.xdevapiAuth.getKeyName(), "EXTERNAL");
assertThrows(XProtocolError.class, "ERROR 1251 \\(HY000\\) Invalid authentication method EXTERNAL", () -> this.fact.getSession(props));
props.remove(PropertyKey.xdevapiAuth.getKeyName());
} finally {
this.session.sql("DROP USER IF EXISTS testAuthMechNative").execute();
this.session.sql("DROP USER IF EXISTS testAuthMechSha256").execute();
this.session.sql("DROP USER IF EXISTS testAuthMechCachingSha2").execute();
}
}
use of com.mysql.cj.xdevapi.Session in project aws-mysql-jdbc by awslabs.
the class SecureSessionTest method testBug26227653.
/**
* Tests fix for Bug#26227653, WL#10528 DIFF BEHAVIOUR WHEN SYSTEM PROP JAVAX.NET.SSL.TRUSTSTORETYPE IS SET
*
* The actual bug is: if wrong system-wide SSL settings are provided, the session should not fail if 'xdevapi.ssl-mode=REQUIRED'.
*/
@Test
public void testBug26227653() {
System.setProperty("javax.net.ssl.trustStore", "dummy_truststore");
System.setProperty("javax.net.ssl.trustStorePassword", "some_password");
System.setProperty("javax.net.ssl.trustStoreType", "wrong_type");
Session testSession = this.fact.getSession(this.sslFreeBaseUrl);
assertSecureSession(testSession);
testSession.close();
testSession = this.fact.getSession(this.sslFreeBaseUrl + makeParam(PropertyKey.xdevapiSslMode, PropertyDefinitions.XdevapiSslMode.REQUIRED));
assertSecureSession(testSession);
testSession.close();
testSession = this.fact.getSession(this.sslFreeTestProperties);
assertSecureSession(testSession);
testSession.close();
Properties props = new Properties(this.sslFreeTestProperties);
props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), PropertyDefinitions.XdevapiSslMode.REQUIRED.toString());
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
testSession.close();
}
use of com.mysql.cj.xdevapi.Session in project aws-mysql-jdbc by awslabs.
the class SecureSessionTest method testTLSv1_2.
/**
* Tests TLSv1.2
*
* @throws Exception
*/
@Test
public void testTLSv1_2() throws Exception {
assumeTrue(supportsTestCertificates(this.session), "This test requires the server configured with SSL certificates from ConnectorJ/src/test/config/ssl-test-certs");
// newer GPL servers, like 8.0.4+, are using OpenSSL and can use RSA encryption, while old ones compiled with yaSSL cannot
Session sess = this.fact.getSession(this.sslFreeBaseUrl);
boolean gplWithRSA = allowsRsa(sess);
String highestCommonTlsVersion = getHighestCommonTlsVersion(sess);
sess.close();
Properties props = new Properties(this.sslFreeTestProperties);
props.setProperty(PropertyKey.xdevapiSslMode.getKeyName(), PropertyDefinitions.XdevapiSslMode.VERIFY_CA.toString());
props.setProperty(PropertyKey.xdevapiSslTrustStoreUrl.getKeyName(), this.trustStoreUrl);
props.setProperty(PropertyKey.xdevapiSslTrustStorePassword.getKeyName(), this.trustStorePassword);
// defaults to TLSv1.1
Session testSession = this.fact.getSession(props);
assertSecureSession(testSession);
assertTlsVersion(testSession, highestCommonTlsVersion);
testSession.close();
// restricted to TLSv1
props.setProperty(PropertyKey.tlsVersions.getKeyName(), "TLSv1");
assertThrows(CJCommunicationsException.class, ".+TLS protocols TLSv1 and TLSv1.1 are not supported. Accepted values are TLSv1.2 and TLSv1.3.", () -> this.fact.getSession(props));
// TLSv1.2 should fail with servers compiled with yaSSL
props.setProperty(PropertyKey.tlsVersions.getKeyName(), "TLSv1.2,TLSv1.1,TLSv1");
if (gplWithRSA) {
testSession = this.fact.getSession(props);
assertSecureSession(testSession);
assertTlsVersion(testSession, "TLSv1.2");
testSession.close();
} else {
assertThrows(CJCommunicationsException.class, "javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake", () -> this.fact.getSession(props));
}
}
Aggregations