001 /** 002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved. 003 * Licensed under the Apache License, Version 2.0 (the "License"); 004 * you may not use this file except in compliance with the License. 005 * You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software 010 * distributed under the License is distributed on an "AS IS" BASIS, 011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 * See the License for the specific language governing permissions and 013 * limitations under the License. See accompanying LICENSE file. 014 */ 015 package org.apache.oozie.servlet; 016 017 import org.apache.hadoop.security.authentication.server.AuthenticationFilter; 018 import org.apache.hadoop.conf.Configuration; 019 import org.apache.oozie.service.Services; 020 021 import javax.servlet.FilterChain; 022 import javax.servlet.FilterConfig; 023 import javax.servlet.ServletException; 024 import javax.servlet.ServletRequest; 025 import javax.servlet.ServletResponse; 026 import javax.servlet.http.HttpServlet; 027 import javax.servlet.http.HttpServletRequest; 028 import java.io.IOException; 029 import java.util.Map; 030 import java.util.Properties; 031 032 /** 033 * Authentication filter that extends Alfredo AuthenticationFilter to override 034 * the configuration loading. 035 */ 036 public class AuthFilter extends AuthenticationFilter { 037 private static final String OOZIE_PREFIX = "oozie.authentication."; 038 039 private HttpServlet optionsServlet; 040 041 /** 042 * Initialize the filter. 043 * 044 * @param filterConfig filter configuration. 045 * @throws ServletException thrown if the filter could not be initialized. 046 */ 047 @Override 048 public void init(FilterConfig filterConfig) throws ServletException { 049 super.init(filterConfig); 050 optionsServlet = new HttpServlet() {}; 051 optionsServlet.init(); 052 } 053 054 /** 055 * Destroy the filter. 056 */ 057 @Override 058 public void destroy() { 059 optionsServlet.destroy(); 060 super.destroy(); 061 } 062 063 /** 064 * Returns the configuration from Oozie configuration to be used by the authentication filter. 065 * <p/> 066 * All properties from Oozie configuration which name starts with {@link #OOZIE_PREFIX} will 067 * be returned. The keys of the returned properties are trimmed from the {@link #OOZIE_PREFIX} 068 * prefix, for example the Oozie configuration property name 'oozie.authentication.type' will 069 * be just 'type'. 070 * 071 * @param configPrefix configuration prefix, this parameter is ignored by this implementation. 072 * @param filterConfig filter configuration, this parameter is ignored by this implementation. 073 * @return all Oozie configuration properties prefixed with {@link #OOZIE_PREFIX}, without the 074 * prefix. 075 */ 076 @Override 077 protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) { 078 Properties props = new Properties(); 079 Configuration conf = Services.get().getConf(); 080 081 //setting the cookie path to root '/' so it is used for all resources. 082 props.setProperty(AuthenticationFilter.COOKIE_PATH, "/"); 083 084 for (Map.Entry<String, String> entry : conf) { 085 String name = entry.getKey(); 086 if (name.startsWith(OOZIE_PREFIX)) { 087 String value = conf.get(name); 088 name = name.substring(OOZIE_PREFIX.length()); 089 props.setProperty(name, value); 090 } 091 } 092 093 return props; 094 } 095 096 /** 097 * Enforces authentication using Alfredo AuthenticationFilter. 098 * <p/> 099 * This method is overriden to respond to HTTP OPTIONS requests for authenticated calls, regardless 100 * of the target servlet supporting OPTIONS or not and to inject the authenticated user name as 101 * request attribute for Oozie to retrieve the user id. 102 * 103 * @param request http request. 104 * @param response http response. 105 * @param filterChain filter chain. 106 * @throws IOException thrown if an IO error occurs. 107 * @throws ServletException thrown if a servlet error occurs. 108 */ 109 @Override 110 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) 111 throws IOException, ServletException { 112 113 FilterChain filterChainWrapper = new FilterChain() { 114 @Override 115 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) 116 throws IOException, ServletException { 117 HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; 118 if (httpRequest.getMethod().equals("OPTIONS")) { 119 optionsServlet.service(request, response); 120 } 121 else { 122 httpRequest.setAttribute(JsonRestServlet.USER_NAME, httpRequest.getRemoteUser()); 123 filterChain.doFilter(servletRequest, servletResponse); 124 } 125 } 126 }; 127 128 super.doFilter(request, response, filterChainWrapper); 129 } 130 131 }