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 019package org.apache.oozie.util; 020 021import java.io.BufferedReader; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.InputStreamReader; 025import java.net.HttpURLConnection; 026import java.net.URL; 027import java.security.PrivilegedExceptionAction; 028import java.util.Map; 029 030import org.apache.hadoop.security.UserGroupInformation; 031import org.apache.hadoop.security.authentication.client.AuthenticatedURL; 032import org.apache.hadoop.security.authentication.client.AuthenticationException; 033import org.apache.hadoop.security.authentication.client.Authenticator; 034import org.apache.hadoop.security.authentication.client.KerberosAuthenticator; 035import org.apache.hadoop.security.authentication.client.PseudoAuthenticator; 036import org.apache.oozie.service.Services; 037 038public class AuthUrlClient { 039 040 static private Class<? extends Authenticator> AuthenticatorClass = null; 041 042 static private String errorMsg = null; 043 044 static { 045 try { 046 AuthenticatorClass = determineAuthenticatorClassType(); 047 } 048 catch (Exception e) { 049 errorMsg = e.getMessage(); 050 } 051 } 052 053 private static HttpURLConnection getConnection(URL url) throws IOException { 054 AuthenticatedURL.Token token = new AuthenticatedURL.Token(); 055 HttpURLConnection conn; 056 try { 057 conn = new AuthenticatedURL(AuthenticatorClass.newInstance()).openConnection(url, token); 058 } 059 catch (AuthenticationException ex) { 060 throw new IOException("Could not authenticate, " + ex.getMessage(), ex); 061 } 062 catch (InstantiationException ex) { 063 throw new IOException("Could not authenticate, " + ex.getMessage(), ex); 064 } 065 catch (IllegalAccessException ex) { 066 throw new IOException("Could not authenticate, " + ex.getMessage(), ex); 067 } 068 if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { 069 throw new IOException("Unexpected response code [" + conn.getResponseCode() + "], message [" 070 + conn.getResponseMessage() + "]"); 071 } 072 return conn; 073 } 074 075 @SuppressWarnings("unchecked") 076 private static Class<? extends Authenticator> determineAuthenticatorClassType() throws Exception { 077 // Adapted from 078 // org.apache.hadoop.security.authentication.server.AuthenticationFilter#init 079 Class<? extends Authenticator> authClass; 080 String authName = Services.get().getConf().get("oozie.authentication.type"); 081 String authClassName; 082 if (authName == null) { 083 throw new IOException("Authentication type must be specified: simple|kerberos|<class>"); 084 } 085 authName = authName.trim(); 086 if (authName.equals("simple")) { 087 authClassName = PseudoAuthenticator.class.getName(); 088 } 089 else if (authName.equals("kerberos")) { 090 authClassName = KerberosAuthenticator.class.getName(); 091 } 092 else { 093 authClassName = authName; 094 } 095 096 authClass = (Class<? extends Authenticator>) Thread.currentThread().getContextClassLoader() 097 .loadClass(authClassName); 098 return authClass; 099 } 100 101 /** 102 * Calls other Oozie server over HTTP. 103 * 104 * @param server The URL of the other Oozie server 105 * @return BufferedReader of inputstream. 106 * @throws IOException Signals that an I/O exception has occurred. 107 */ 108 public static BufferedReader callServer(String server) throws IOException { 109 110 if (AuthenticatorClass == null) { 111 throw new IOException(errorMsg); 112 } 113 114 final URL url = new URL(server); 115 BufferedReader reader = null; 116 try { 117 reader = UserGroupInformation.getLoginUser().doAs(new PrivilegedExceptionAction<BufferedReader>() { 118 @Override 119 public BufferedReader run() throws IOException { 120 HttpURLConnection conn = getConnection(url); 121 BufferedReader reader = null; 122 if ((conn.getResponseCode() == HttpURLConnection.HTTP_OK)) { 123 InputStream is = conn.getInputStream(); 124 reader = new BufferedReader(new InputStreamReader(is)); 125 } 126 return reader; 127 } 128 }); 129 } 130 catch (InterruptedException ie) { 131 throw new IOException(ie); 132 } 133 return reader; 134 } 135 136 public static String getQueryParamString(Map<String, String[]> params) { 137 StringBuilder stringBuilder = new StringBuilder(); 138 if (params == null || params.isEmpty()) { 139 return ""; 140 } 141 for (String key : params.keySet()) { 142 if (!key.isEmpty() && params.get(key).length > 0) { 143 stringBuilder.append("&"); 144 String value = params.get(key)[0]; // We don't support multi value. 145 stringBuilder.append(key); 146 stringBuilder.append("="); 147 stringBuilder.append(value); 148 } 149 } 150 return stringBuilder.toString(); 151 } 152 153}