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.lib; 019 020import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.DEFAULT_HBASE_HTTP_STATIC_USER; 021import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.HBASE_HTTP_STATIC_USER; 022 023import java.io.IOException; 024import java.security.Principal; 025import java.util.HashMap; 026 027import javax.servlet.Filter; 028import javax.servlet.FilterChain; 029import javax.servlet.FilterConfig; 030import javax.servlet.ServletException; 031import javax.servlet.ServletRequest; 032import javax.servlet.ServletResponse; 033import javax.servlet.http.HttpServletRequest; 034import javax.servlet.http.HttpServletRequestWrapper; 035 036import org.apache.hadoop.conf.Configuration; 037import org.apache.hadoop.hbase.HBaseInterfaceAudience; 038import org.apache.hadoop.hbase.http.FilterContainer; 039import org.apache.hadoop.hbase.http.FilterInitializer; 040import org.apache.yetus.audience.InterfaceAudience; 041import org.slf4j.Logger; 042import org.slf4j.LoggerFactory; 043 044/** 045 * Provides a servlet filter that pretends to authenticate a fake user (Dr.Who) 046 * so that the web UI is usable for a secure cluster without authentication. 047 */ 048@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) 049public class StaticUserWebFilter extends FilterInitializer { 050 static final String DEPRECATED_UGI_KEY = "dfs.web.ugi"; 051 052 private static final Logger LOG = LoggerFactory.getLogger(StaticUserWebFilter.class); 053 054 static class User implements Principal { 055 private final String name; 056 public User(String name) { 057 this.name = name; 058 } 059 @Override 060 public String getName() { 061 return name; 062 } 063 @Override 064 public int hashCode() { 065 return name.hashCode(); 066 } 067 @Override 068 public boolean equals(Object other) { 069 if (other == this) { 070 return true; 071 } else if (other == null || other.getClass() != getClass()) { 072 return false; 073 } 074 return ((User) other).name.equals(name); 075 } 076 @Override 077 public String toString() { 078 return name; 079 } 080 } 081 082 @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG) 083 public static class StaticUserFilter implements Filter { 084 private User user; 085 private String username; 086 087 @Override 088 public void destroy() { 089 // NOTHING 090 } 091 092 @Override 093 public void doFilter(ServletRequest request, ServletResponse response, 094 FilterChain chain 095 ) throws IOException, ServletException { 096 HttpServletRequest httpRequest = (HttpServletRequest) request; 097 // if the user is already authenticated, don't override it 098 if (httpRequest.getRemoteUser() != null) { 099 chain.doFilter(request, response); 100 } else { 101 HttpServletRequestWrapper wrapper = 102 new HttpServletRequestWrapper(httpRequest) { 103 @Override 104 public Principal getUserPrincipal() { 105 return user; 106 } 107 @Override 108 public String getRemoteUser() { 109 return username; 110 } 111 }; 112 chain.doFilter(wrapper, response); 113 } 114 } 115 116 @Override 117 public void init(FilterConfig conf) throws ServletException { 118 this.username = conf.getInitParameter(HBASE_HTTP_STATIC_USER); 119 this.user = new User(username); 120 } 121 122 } 123 124 @Override 125 public void initFilter(FilterContainer container, Configuration conf) { 126 HashMap<String, String> options = new HashMap<>(); 127 128 String username = getUsernameFromConf(conf); 129 options.put(HBASE_HTTP_STATIC_USER, username); 130 131 container.addFilter("static_user_filter", 132 StaticUserFilter.class.getName(), 133 options); 134 } 135 136 /** 137 * Retrieve the static username from the configuration. 138 */ 139 static String getUsernameFromConf(Configuration conf) { 140 String oldStyleUgi = conf.get(DEPRECATED_UGI_KEY); 141 if (oldStyleUgi != null) { 142 // We can't use the normal configuration deprecation mechanism here 143 // since we need to split out the username from the configured UGI. 144 LOG.warn(DEPRECATED_UGI_KEY + " should not be used. Instead, use " + 145 HBASE_HTTP_STATIC_USER + "."); 146 String[] parts = oldStyleUgi.split(","); 147 return parts[0]; 148 } else { 149 return conf.get(HBASE_HTTP_STATIC_USER, 150 DEFAULT_HBASE_HTTP_STATIC_USER); 151 } 152 } 153 154}