blob: ddc8b0061f1e67921933c6788dbf5316b006fd96 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 org.apache.impala.customcluster;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.google.common.collect.Range;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.annotations.CreatePartition;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.core.annotations.ApplyLdifFiles;
import org.apache.directory.server.core.integ.CreateLdapServerRule;
import org.apache.impala.testutil.ImpalaJdbcClient;
import org.apache.impala.util.Metrics;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.apache.impala.service.JdbcTestBase;
/**
* Tests for connecting to Impala when LDAP authentication is in use.
*/
@CreateDS(name = "myDS",
partitions = { @CreatePartition(name = "test", suffix = "dc=myorg,dc=com") })
@CreateLdapServer(
transports = { @CreateTransport(protocol = "LDAP", address = "localhost") })
@ApplyLdifFiles({"users.ldif"})
public class LdapJdbcTest extends JdbcTestBase {
@ClassRule
public static CreateLdapServerRule serverRule = new CreateLdapServerRule();
// These correspond to the values in fe/src/test/resources/users.ldif
private static final String testUser_ = "Test1Ldap";
private static final String testPassword_ = "12345";
private static final Range<Long> zero = Range.closed(0L, 0L);
private static final Range<Long> one = Range.closed(1L, 1L);
Metrics metrics = new Metrics();
public LdapJdbcTest(String connectionType) { super(connectionType); }
public void setUp(String extraArgs) throws Exception {
String uri =
String.format("ldap://localhost:%s", serverRule.getLdapServer().getPort());
String dn = "cn=#UID,ou=Users,dc=myorg,dc=com";
String impalaArgs = String.format("--enable_ldap_auth --ldap_uri='%s' "
+ "--ldap_bind_pattern='%s' --ldap_passwords_in_clear_ok %s", uri, dn, extraArgs);
int ret = CustomClusterRunner.StartImpalaCluster(impalaArgs);
assertEquals(ret, 0);
con_ = createConnection(
ImpalaJdbcClient.getLdapConnectionStr(connectionType_, testUser_, testPassword_));
if (connectionType_.equals("http")) {
// There should have been one successful connection auth to create the session.
verifyMetrics(one, zero, zero, zero);
}
}
private void verifyMetrics(Range<Long> expectedBasicSuccess,
Range<Long> expectedBasicFailure, Range<Long> expectedCookieSuccess,
Range<Long> expectedCookieFailure) throws Exception {
long actualBasicSuccess = (long) metrics.getMetric(
"impala.thrift-server.hiveserver2-http-frontend.total-basic-auth-success");
assertTrue("Expected: " + expectedBasicSuccess + ", Actual: " + actualBasicSuccess,
expectedBasicSuccess.contains(actualBasicSuccess));
long actualBasicFailure = (long) metrics.getMetric(
"impala.thrift-server.hiveserver2-http-frontend.total-basic-auth-failure");
assertTrue("Expected: " + expectedBasicFailure + ", Actual: " + actualBasicFailure,
expectedBasicFailure.contains(actualBasicFailure));
long actualCookieSuccess = (long) metrics.getMetric(
"impala.thrift-server.hiveserver2-http-frontend.total-cookie-auth-success");
assertTrue("Expected: " + expectedCookieSuccess + ", Actual: " + actualCookieSuccess,
expectedCookieSuccess.contains(actualCookieSuccess));
long actualCookieFailure = (long) metrics.getMetric(
"impala.thrift-server.hiveserver2-http-frontend.total-cookie-auth-failure");
assertTrue("Expected: " + expectedCookieFailure + ", Actual: " + actualCookieFailure,
expectedCookieFailure.contains(actualCookieFailure));
}
@Test
public void testLoggedInUser() throws Exception {
setUp("");
ResultSet rs = con_.createStatement().executeQuery("select logged_in_user() user");
if (connectionType_.equals("http")) {
// After the initial auth, the driver should use cookies for all other requests.
verifyMetrics(one, zero, Range.atLeast(1L), zero);
}
assertTrue(rs.next());
assertEquals(rs.getString("user"), testUser_);
assertFalse(rs.next());
}
@Test
public void testFailedConnection() throws Exception {
setUp("");
try {
Connection con = createConnection(ImpalaJdbcClient.getLdapConnectionStr(
connectionType_, testUser_, "invalid-password"));
fail("Connecting with an invalid password should throw an error.");
} catch (SQLException e) {
assertTrue(e.getMessage().contains("Could not open client transport"));
}
try {
Connection con = createConnection(ImpalaJdbcClient.getLdapConnectionStr(
connectionType_, "invalid-user", testPassword_));
fail("Connecting with an invalid user name should throw an error.");
} catch (SQLException e) {
assertTrue(e.getMessage().contains("Could not open client transport"));
}
}
@Test
public void testExpireCookies() throws Exception {
if (connectionType_.equals("http")) {
setUp("--max_cookie_lifetime_s=1");
// Sleep long enough for the cookie returned in the initial connection to expire.
Thread.sleep(2000);
ResultSet rs = con_.createStatement().executeQuery("select logged_in_user() user");
// The driver should have supplied an incorrect cookie at least once, requiring at
// least one more auth to LDAP. There may also have been some successful cookie
// attempts, depending on timing.
verifyMetrics(Range.atLeast(2L), zero, Range.atLeast(0L), Range.atLeast(1L));
assertTrue(rs.next());
assertEquals(rs.getString("user"), testUser_);
assertFalse(rs.next());
}
}
}