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 java.io.IOException; 021import java.net.HttpURLConnection; 022import java.net.URL; 023import org.apache.commons.codec.binary.Base64; 024import org.apache.directory.server.core.integ.CreateLdapServerRule; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.http.resource.JerseyResource; 027import org.junit.AfterClass; 028import org.junit.BeforeClass; 029import org.junit.ClassRule; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033/** 034 * Base class for setting up and testing an HTTP server with LDAP authentication. 035 */ 036public class LdapServerTestBase extends HttpServerFunctionalTest { 037 private static final Logger LOG = LoggerFactory.getLogger(LdapServerTestBase.class); 038 039 @ClassRule 040 public static CreateLdapServerRule ldapRule = new CreateLdapServerRule(); 041 042 protected static HttpServer server; 043 protected static URL baseUrl; 044 045 private static final String AUTH_TYPE = "Basic "; 046 047 /** 048 * Sets up the HTTP server with LDAP authentication before any tests are run. 049 * @throws Exception if an error occurs during server setup 050 */ 051 @BeforeClass 052 public static void setupServer() throws Exception { 053 Configuration conf = new Configuration(); 054 setLdapConfigurations(conf); 055 056 server = createTestServer(conf); 057 server.addUnprivilegedServlet("echo", "/echo", TestHttpServer.EchoServlet.class); 058 server.addJerseyResourcePackage(JerseyResource.class.getPackage().getName(), "/jersey/*"); 059 server.start(); 060 061 baseUrl = getServerURL(server); 062 LOG.info("HTTP server started: " + baseUrl); 063 } 064 065 /** 066 * Stops the HTTP server after all tests are completed. 067 * @throws Exception if an error occurs during server shutdown 068 */ 069 @AfterClass 070 public static void stopServer() throws Exception { 071 try { 072 if (null != server) { 073 server.stop(); 074 } 075 } catch (Exception e) { 076 LOG.info("Failed to stop info server", e); 077 } 078 } 079 080 /** 081 * Configures the provided Configuration object for LDAP authentication. 082 * @param conf the Configuration object to set LDAP properties on 083 * @return the configured Configuration object 084 */ 085 protected static void setLdapConfigurations(Configuration conf) { 086 conf.setInt(HttpServer.HTTP_MAX_THREADS, TestHttpServer.MAX_THREADS); 087 088 // Enable LDAP (pre-req) 089 conf.set(HttpServer.HTTP_UI_AUTHENTICATION, "ldap"); 090 conf.set(HttpServer.FILTER_INITIALIZERS_PROPERTY, 091 "org.apache.hadoop.hbase.http.lib.AuthenticationFilterInitializer"); 092 conf.set("hadoop.http.authentication.type", "ldap"); 093 conf.set("hadoop.http.authentication.ldap.providerurl", String.format("ldap://%s:%s", 094 LdapConstants.LDAP_SERVER_ADDR, ldapRule.getLdapServer().getPort())); 095 conf.set("hadoop.http.authentication.ldap.enablestarttls", "false"); 096 conf.set("hadoop.http.authentication.ldap.basedn", LdapConstants.LDAP_BASE_DN); 097 } 098 099 /** 100 * Generates a Basic Authentication header from the provided credentials. 101 * @param credentials the credentials to encode 102 * @return the Basic Authentication header 103 */ 104 private String getBasicAuthHeader(String credentials) { 105 return AUTH_TYPE + new Base64(0).encodeToString(credentials.getBytes()); 106 } 107 108 /** 109 * Opens an HTTP connection to the specified endpoint with optional Basic Authentication. 110 * @param endpoint the endpoint to connect to 111 * @param credentials the credentials for Basic Authentication (optional) 112 * @return the opened HttpURLConnection 113 * @throws IOException if an error occurs while opening the connection 114 */ 115 protected HttpURLConnection openConnection(String endpoint, String credentials) 116 throws IOException { 117 URL url = new URL(getServerURL(server) + endpoint); 118 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 119 if (credentials != null) { 120 conn.setRequestProperty("Authorization", getBasicAuthHeader(credentials)); 121 } 122 return conn; 123 } 124}