View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.http.lib;
19  
20  import java.io.IOException;
21  import java.security.Principal;
22  import java.util.HashMap;
23  
24  import javax.servlet.FilterChain;
25  import javax.servlet.FilterConfig;
26  import javax.servlet.ServletException;
27  import javax.servlet.ServletRequest;
28  import javax.servlet.ServletResponse;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletRequestWrapper;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.hbase.classification.InterfaceAudience;
35  import org.apache.hadoop.conf.Configuration;
36  import org.apache.hadoop.hbase.HBaseInterfaceAudience;
37  import org.apache.hadoop.hbase.http.FilterContainer;
38  import org.apache.hadoop.hbase.http.FilterInitializer;
39  
40  import javax.servlet.Filter;
41  
42  import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.HBASE_HTTP_STATIC_USER;
43  import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.DEFAULT_HBASE_HTTP_STATIC_USER;
44  
45  /**
46   * Provides a servlet filter that pretends to authenticate a fake user (Dr.Who)
47   * so that the web UI is usable for a secure cluster without authentication.
48   */
49  @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
50  public class StaticUserWebFilter extends FilterInitializer {
51    static final String DEPRECATED_UGI_KEY = "dfs.web.ugi";
52  
53    private static final Log LOG = LogFactory.getLog(StaticUserWebFilter.class);
54  
55    static class User implements Principal {
56      private final String name;
57      public User(String name) {
58        this.name = name;
59      }
60      @Override
61      public String getName() {
62        return name;
63      }
64      @Override
65      public int hashCode() {
66        return name.hashCode();
67      }
68      @Override
69      public boolean equals(Object other) {
70        if (other == this) {
71          return true;
72        } else if (other == null || other.getClass() != getClass()) {
73          return false;
74        }
75        return ((User) other).name.equals(name);
76      }
77      @Override
78      public String toString() {
79        return name;
80      }    
81    }
82  
83    @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
84    public static class StaticUserFilter implements Filter {
85      private User user;
86      private String username;
87  
88      @Override
89      public void destroy() {
90        // NOTHING
91      }
92  
93      @Override
94      public void doFilter(ServletRequest request, ServletResponse response,
95                           FilterChain chain
96                           ) throws IOException, ServletException {
97        HttpServletRequest httpRequest = (HttpServletRequest) request;
98        // if the user is already authenticated, don't override it
99        if (httpRequest.getRemoteUser() != null) {
100         chain.doFilter(request, response);
101       } else {
102         HttpServletRequestWrapper wrapper = 
103             new HttpServletRequestWrapper(httpRequest) {
104           @Override
105           public Principal getUserPrincipal() {
106             return user;
107           }
108           @Override
109           public String getRemoteUser() {
110             return username;
111           }
112         };
113         chain.doFilter(wrapper, response);
114       }
115     }
116 
117     @Override
118     public void init(FilterConfig conf) throws ServletException {
119       this.username = conf.getInitParameter(HBASE_HTTP_STATIC_USER);
120       this.user = new User(username);
121     }
122     
123   }
124 
125   @Override
126   public void initFilter(FilterContainer container, Configuration conf) {
127     HashMap<String, String> options = new HashMap<String, String>();
128     
129     String username = getUsernameFromConf(conf);
130     options.put(HBASE_HTTP_STATIC_USER, username);
131 
132     container.addFilter("static_user_filter", 
133                         StaticUserFilter.class.getName(), 
134                         options);
135   }
136 
137   /**
138    * Retrieve the static username from the configuration.
139    */
140   static String getUsernameFromConf(Configuration conf) {
141     String oldStyleUgi = conf.get(DEPRECATED_UGI_KEY);
142     if (oldStyleUgi != null) {
143       // We can't use the normal configuration deprecation mechanism here
144       // since we need to split out the username from the configured UGI.
145       LOG.warn(DEPRECATED_UGI_KEY + " should not be used. Instead, use " + 
146           HBASE_HTTP_STATIC_USER + ".");
147       String[] parts = oldStyleUgi.split(",");
148       return parts[0];
149     } else {
150       return conf.get(HBASE_HTTP_STATIC_USER,
151         DEFAULT_HBASE_HTTP_STATIC_USER);
152     }
153   }
154 
155 }