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.crypto.key.kms.server;
19 
20 import org.apache.hadoop.classification.InterfaceAudience;
21 import org.apache.hadoop.security.UserGroupInformation;
22 import org.apache.hadoop.security.token.delegation.web.HttpUserGroupInformation;
23 
24 import javax.servlet.Filter;
25 import javax.servlet.FilterChain;
26 import javax.servlet.FilterConfig;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.http.HttpServletRequest;
31 import java.io.IOException;
32 
33 /**
34  * Servlet filter that captures context of the HTTP request to be use in the
35  * scope of KMS calls on the server side.
36  */
37 @InterfaceAudience.Private
38 public class KMSMDCFilter implements Filter {
39 
40   private static class Data {
41     private UserGroupInformation ugi;
42     private String method;
43     private StringBuffer url;
44 
Data(UserGroupInformation ugi, String method, StringBuffer url)45     private Data(UserGroupInformation ugi, String method, StringBuffer url) {
46       this.ugi = ugi;
47       this.method = method;
48       this.url = url;
49     }
50   }
51 
52   private static ThreadLocal<Data> DATA_TL = new ThreadLocal<Data>();
53 
getUgi()54   public static UserGroupInformation getUgi() {
55     return DATA_TL.get().ugi;
56   }
57 
getMethod()58   public static String getMethod() {
59     return DATA_TL.get().method;
60   }
61 
getURL()62   public static String getURL() {
63     return DATA_TL.get().url.toString();
64   }
65 
66   @Override
init(FilterConfig config)67   public void init(FilterConfig config) throws ServletException {
68   }
69 
70   @Override
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)71   public void doFilter(ServletRequest request, ServletResponse response,
72       FilterChain chain)
73       throws IOException, ServletException {
74     try {
75       DATA_TL.remove();
76       UserGroupInformation ugi = HttpUserGroupInformation.get();
77       String method = ((HttpServletRequest) request).getMethod();
78       StringBuffer requestURL = ((HttpServletRequest) request).getRequestURL();
79       String queryString = ((HttpServletRequest) request).getQueryString();
80       if (queryString != null) {
81         requestURL.append("?").append(queryString);
82       }
83       DATA_TL.set(new Data(ugi, method, requestURL));
84       chain.doFilter(request, response);
85     } finally {
86       DATA_TL.remove();
87     }
88   }
89 
90   @Override
destroy()91   public void destroy() {
92   }
93 }
94