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 */ 018 package org.apache.oozie.servlet; 019 020 import org.apache.hadoop.security.authentication.server.AuthenticationFilter; 021 import org.apache.hadoop.conf.Configuration; 022 import org.apache.oozie.service.Services; 023 024 import javax.servlet.FilterChain; 025 import javax.servlet.FilterConfig; 026 import javax.servlet.ServletException; 027 import javax.servlet.ServletRequest; 028 import javax.servlet.ServletResponse; 029 import javax.servlet.http.HttpServlet; 030 import javax.servlet.http.HttpServletRequest; 031 import java.io.IOException; 032 import java.util.Map; 033 import java.util.Properties; 034 035 /** 036 * Authentication filter that extends Hadoop-auth AuthenticationFilter to override 037 * the configuration loading. 038 */ 039 public class AuthFilter extends AuthenticationFilter { 040 private static final String OOZIE_PREFIX = "oozie.authentication."; 041 042 private HttpServlet optionsServlet; 043 044 /** 045 * Initialize the filter. 046 * 047 * @param filterConfig filter configuration. 048 * @throws ServletException thrown if the filter could not be initialized. 049 */ 050 @Override 051 public void init(FilterConfig filterConfig) throws ServletException { 052 super.init(filterConfig); 053 optionsServlet = new HttpServlet() {}; 054 optionsServlet.init(); 055 } 056 057 /** 058 * Destroy the filter. 059 */ 060 @Override 061 public void destroy() { 062 optionsServlet.destroy(); 063 super.destroy(); 064 } 065 066 /** 067 * Returns the configuration from Oozie configuration to be used by the authentication filter. 068 * <p/> 069 * All properties from Oozie configuration which name starts with {@link #OOZIE_PREFIX} will 070 * be returned. The keys of the returned properties are trimmed from the {@link #OOZIE_PREFIX} 071 * prefix, for example the Oozie configuration property name 'oozie.authentication.type' will 072 * be just 'type'. 073 * 074 * @param configPrefix configuration prefix, this parameter is ignored by this implementation. 075 * @param filterConfig filter configuration, this parameter is ignored by this implementation. 076 * @return all Oozie configuration properties prefixed with {@link #OOZIE_PREFIX}, without the 077 * prefix. 078 */ 079 @Override 080 protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) { 081 Properties props = new Properties(); 082 Configuration conf = Services.get().getConf(); 083 084 //setting the cookie path to root '/' so it is used for all resources. 085 props.setProperty(AuthenticationFilter.COOKIE_PATH, "/"); 086 087 for (Map.Entry<String, String> entry : conf) { 088 String name = entry.getKey(); 089 if (name.startsWith(OOZIE_PREFIX)) { 090 String value = conf.get(name); 091 name = name.substring(OOZIE_PREFIX.length()); 092 props.setProperty(name, value); 093 } 094 } 095 096 return props; 097 } 098 099 /** 100 * Enforces authentication using Hadoop-auth AuthenticationFilter. 101 * <p/> 102 * This method is overriden to respond to HTTP OPTIONS requests for authenticated calls, regardless 103 * of the target servlet supporting OPTIONS or not and to inject the authenticated user name as 104 * request attribute for Oozie to retrieve the user id. 105 * 106 * @param request http request. 107 * @param response http response. 108 * @param filterChain filter chain. 109 * @throws IOException thrown if an IO error occurs. 110 * @throws ServletException thrown if a servlet error occurs. 111 */ 112 @Override 113 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) 114 throws IOException, ServletException { 115 116 FilterChain filterChainWrapper = new FilterChain() { 117 @Override 118 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) 119 throws IOException, ServletException { 120 HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; 121 if (httpRequest.getMethod().equals("OPTIONS")) { 122 optionsServlet.service(request, response); 123 } 124 else { 125 httpRequest.setAttribute(JsonRestServlet.USER_NAME, httpRequest.getRemoteUser()); 126 filterChain.doFilter(servletRequest, servletResponse); 127 } 128 } 129 }; 130 131 super.doFilter(request, response, filterChainWrapper); 132 } 133 134 }