/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.tests.jdbc; import com.google.inject.Inject; import com.google.inject.name.Named; import com.teradata.tempto.BeforeTestWithContext; import com.teradata.tempto.ProductTest; import com.teradata.tempto.Requirement; import com.teradata.tempto.RequirementsProvider; import com.teradata.tempto.Requires; import com.teradata.tempto.configuration.Configuration; import com.teradata.tempto.fulfillment.ldap.LdapObjectRequirement; import com.teradata.tempto.fulfillment.table.hive.tpch.ImmutableTpchTablesRequirements.ImmutableNationTable; import com.teradata.tempto.query.QueryResult; import org.testng.annotations.Test; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.AMERICA_ORG; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.ASIA_ORG; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.CHILD_GROUP; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.CHILD_GROUP_USER; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.DEFAULT_GROUP; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.DEFAULT_GROUP_USER; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.ORPHAN_USER; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.PARENT_GROUP; import static com.facebook.presto.tests.ImmutableLdapObjectDefinitions.PARENT_GROUP_USER; import static com.facebook.presto.tests.TestGroups.LDAP; import static com.facebook.presto.tests.TestGroups.PROFILE_SPECIFIC_TESTS; import static com.facebook.presto.tests.TestGroups.SIMBA_JDBC; import static com.facebook.presto.tests.TpchTableResults.PRESTO_NATION_RESULT; import static com.teradata.tempto.assertions.QueryAssert.assertThat; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; public class LdapTests extends ProductTest implements RequirementsProvider { private static final long TIMEOUT = 300 * 1000; // 30 secs per test private static final String NATION_SELECT_ALL_QUERY = "select * from tpch.tiny.nation"; private static final String JDBC_URL_FORMAT = "jdbc:presto://%s;AuthenticationType=LDAP Authentication;" + "SSLTrustStorePath=%s;SSLTrustStorePwd=%s;AllowSelfSignedServerCert=1;AllowHostNameCNMismatch=1"; private static final String SSL_CERTIFICATE_ERROR = "[Teradata][Presto](100140) SSL certificate error: Keystore was tampered with, or password was incorrect."; private static final String INVALID_CREDENTIALS_ERROR = "[Teradata][Presto](100240) Authentication failed: Invalid credentials."; private static final String MALFORMED_CREDENTIALS_ERROR = "[Teradata][Presto](100240) Authentication failed: Malformed decoded credentials."; private static final String UNAUTHORIZED_USER_ERROR = "[Teradata][Presto](100240) Authentication failed: Unauthorized user."; private static final String INVALID_SSL_PROPERTY = "[Teradata][Presto](100200) Connection string is invalid: SSL value is not valid for given AuthenticationType."; @Inject @Named("databases.presto.cli_ldap_truststore_path") private String ldapTruststorePath; @Inject @Named("databases.presto.cli_ldap_truststore_password") private String ldapTruststorePassword; @Inject @Named("databases.presto.cli_ldap_user_name") private String ldapUserName; @Inject @Named("databases.presto.cli_ldap_user_password") private String ldapUserPassword; @Inject @Named("databases.presto.cli_ldap_server_address") private String prestoServer; @BeforeTestWithContext public void setup() throws SQLException { prestoServer = prestoServer.substring(8); } @Override public Requirement getRequirements(Configuration configuration) { return new LdapObjectRequirement( Arrays.asList( AMERICA_ORG, ASIA_ORG, DEFAULT_GROUP, PARENT_GROUP, CHILD_GROUP, DEFAULT_GROUP_USER, PARENT_GROUP_USER, CHILD_GROUP_USER, ORPHAN_USER )); } @Requires(ImmutableNationTable.class) @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldRunQueryWithLdap() throws InterruptedException, SQLException { assertThat(executeLdapQuery(NATION_SELECT_ALL_QUERY, ldapUserName, ldapUserPassword)).matches(PRESTO_NATION_RESULT); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForLdapUserInChildGroup() throws InterruptedException { String name = CHILD_GROUP_USER.getAttributes().get("cn"); expectQueryToFailForUserNotInGroup(name); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForLdapUserInParentGroup() throws InterruptedException { String name = PARENT_GROUP_USER.getAttributes().get("cn"); expectQueryToFailForUserNotInGroup(name); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForOrphanLdapUser() throws InterruptedException { String name = ORPHAN_USER.getAttributes().get("cn"); expectQueryToFailForUserNotInGroup(name); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForWrongLdapPassword() throws IOException, InterruptedException { expectQueryToFail(ldapUserName, "wrong_password", INVALID_CREDENTIALS_ERROR); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForWrongLdapUser() throws IOException, InterruptedException { expectQueryToFail("invalid_user", ldapUserPassword, INVALID_CREDENTIALS_ERROR); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForEmptyUser() throws IOException, InterruptedException { expectQueryToFail("", ldapUserPassword, MALFORMED_CREDENTIALS_ERROR); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForLdapWithoutPassword() throws IOException, InterruptedException { expectQueryToFail(ldapUserName, "", MALFORMED_CREDENTIALS_ERROR); } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailQueryForLdapWithoutSsl() throws IOException, InterruptedException { try { DriverManager.getConnection(getLdapUrl() + ";SSL=0", ldapUserName, ldapUserPassword); fail(); } catch (SQLException exception) { assertEquals(exception.getMessage(), INVALID_SSL_PROPERTY); } } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailForIncorrectTrustStore() throws IOException, InterruptedException { try { String url = String.format(JDBC_URL_FORMAT, prestoServer, ldapTruststorePath, "wrong_password"); Connection connection = DriverManager.getConnection(url, ldapUserName, ldapUserPassword); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(NATION_SELECT_ALL_QUERY); fail(); } catch (SQLException exception) { assertEquals(exception.getMessage(), SSL_CERTIFICATE_ERROR); } } @Test(groups = {LDAP, SIMBA_JDBC, PROFILE_SPECIFIC_TESTS}, timeOut = TIMEOUT) public void shouldFailForUserWithColon() throws SQLException, InterruptedException { expectQueryToFail("UserWith:Colon", ldapUserPassword, MALFORMED_CREDENTIALS_ERROR); } private void expectQueryToFailForUserNotInGroup(String user) { expectQueryToFail(user, ldapUserPassword, UNAUTHORIZED_USER_ERROR); } private void expectQueryToFail(String user, String password, String message) { try { executeLdapQuery(NATION_SELECT_ALL_QUERY, user, password); fail(); } catch (SQLException exception) { assertEquals(exception.getMessage(), message); } } private QueryResult executeLdapQuery(String query, String name, String password) throws SQLException { try (Connection connection = getLdapConnection(name, password)) { Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(query); return QueryResult.forResultSet(rs); } } private Connection getLdapConnection(String name, String password) throws SQLException { return DriverManager.getConnection(getLdapUrl(), name, password); } private String getLdapUrl() { return String.format(JDBC_URL_FORMAT, prestoServer, ldapTruststorePath, ldapTruststorePassword); } }