001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.http;
019
020import static org.junit.Assert.assertEquals;
021
022import java.io.IOException;
023import java.net.HttpURLConnection;
024import org.apache.directory.server.annotations.CreateLdapServer;
025import org.apache.directory.server.annotations.CreateTransport;
026import org.apache.directory.server.core.annotations.ApplyLdifs;
027import org.apache.directory.server.core.annotations.ContextEntry;
028import org.apache.directory.server.core.annotations.CreateDS;
029import org.apache.directory.server.core.annotations.CreatePartition;
030import org.apache.hadoop.conf.Configuration;
031import org.apache.hadoop.fs.CommonConfigurationKeys;
032import org.apache.hadoop.hbase.HBaseClassTestRule;
033import org.apache.hadoop.hbase.http.resource.JerseyResource;
034import org.apache.hadoop.hbase.testclassification.MiscTests;
035import org.apache.hadoop.hbase.testclassification.SmallTests;
036import org.junit.BeforeClass;
037import org.junit.ClassRule;
038import org.junit.Test;
039import org.junit.experimental.categories.Category;
040import org.slf4j.Logger;
041import org.slf4j.LoggerFactory;
042
043/**
044 * Test class for admin ACLs with LDAP authentication on the HttpServer.
045 */
046@Category({ MiscTests.class, SmallTests.class })
047@CreateLdapServer(
048    transports = { @CreateTransport(protocol = "LDAP", address = LdapConstants.LDAP_SERVER_ADDR), })
049@CreateDS(name = "TestLdapAdminACL", allowAnonAccess = true,
050    partitions = { @CreatePartition(name = "Test_Partition", suffix = LdapConstants.LDAP_BASE_DN,
051        contextEntry = @ContextEntry(entryLdif = "dn: " + LdapConstants.LDAP_BASE_DN + " \n"
052          + "dc: example\n" + "objectClass: top\n" + "objectClass: domain\n\n")) })
053@ApplyLdifs({ "dn: uid=bjones," + LdapConstants.LDAP_BASE_DN, "cn: Bob Jones", "sn: Jones",
054  "objectClass: inetOrgPerson", "uid: bjones", "userPassword: p@ssw0rd",
055
056  "dn: uid=jdoe," + LdapConstants.LDAP_BASE_DN, "cn: John Doe", "sn: Doe",
057  "objectClass: inetOrgPerson", "uid: jdoe", "userPassword: secure123" })
058public class TestLdapAdminACL extends LdapServerTestBase {
059
060  @ClassRule
061  public static final HBaseClassTestRule CLASS_RULE =
062    HBaseClassTestRule.forClass(TestLdapAdminACL.class);
063  private static final Logger LOG = LoggerFactory.getLogger(TestLdapAdminACL.class);
064
065  private static final String ADMIN_CREDENTIALS = "bjones:p@ssw0rd";
066  private static final String NON_ADMIN_CREDENTIALS = "jdoe:secure123";
067  private static final String WRONG_CREDENTIALS = "bjones:password";
068
069  @BeforeClass
070  public static void setupServer() throws Exception {
071    Configuration conf = new Configuration();
072    setLdapConfigurationWithACLs(conf);
073
074    server = createTestServer(conf, InfoServer.buildAdminAcl(conf));
075    server.addUnprivilegedServlet("echo", "/echo", TestHttpServer.EchoServlet.class);
076    // we will reuse /jmx which is a privileged servlet
077    server.addJerseyResourcePackage(JerseyResource.class.getPackage().getName(), "/jersey/*");
078    server.start();
079
080    baseUrl = getServerURL(server);
081    LOG.info("HTTP server started: " + baseUrl);
082  }
083
084  private static void setLdapConfigurationWithACLs(Configuration conf) {
085    setLdapConfigurations(conf);
086
087    // Enable LDAP admin ACL
088    conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION, true);
089    conf.setBoolean(CommonConfigurationKeys.HADOOP_SECURITY_INSTRUMENTATION_REQUIRES_ADMIN, true);
090    conf.set(HttpServer.HTTP_LDAP_AUTHENTICATION_ADMIN_USERS_KEY, "bjones");
091  }
092
093  @Test
094  public void testAdminAllowedUnprivilegedServletAccess() throws IOException {
095    HttpURLConnection conn = openConnection("/echo?a=b", ADMIN_CREDENTIALS);
096    assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
097  }
098
099  @Test
100  public void testAdminAllowedPrivilegedServletAccess() throws IOException {
101    HttpURLConnection conn = openConnection("/jmx", ADMIN_CREDENTIALS);
102    assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
103  }
104
105  @Test
106  public void testNonAdminAllowedUnprivilegedServletAccess() throws IOException {
107    HttpURLConnection conn = openConnection("/echo?a=b", NON_ADMIN_CREDENTIALS);
108    assertEquals(HttpURLConnection.HTTP_OK, conn.getResponseCode());
109  }
110
111  @Test
112  public void testNonAdminDisallowedPrivilegedServletAccess() throws IOException {
113    HttpURLConnection conn = openConnection("/jmx", NON_ADMIN_CREDENTIALS);
114    assertEquals(HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode());
115  }
116
117  @Test
118  public void testWrongAuthDisallowedUnprivilegedServletAccess() throws IOException {
119    HttpURLConnection conn = openConnection("/echo?a=b", WRONG_CREDENTIALS);
120    assertEquals(HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode());
121  }
122
123  @Test
124  public void testWrongAuthDisallowedPrivilegedServletAccess() throws IOException {
125    HttpURLConnection conn = openConnection("/jmx", WRONG_CREDENTIALS);
126    assertEquals(HttpURLConnection.HTTP_FORBIDDEN, conn.getResponseCode());
127  }
128}