|
|
|
@ -14,9 +14,11 @@
|
|
|
|
|
* See the License for the specific language governing permissions and |
|
|
|
|
* limitations under the License. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
package org.apache.dolphinscheduler.common.utils; |
|
|
|
|
|
|
|
|
|
import org.apache.dolphinscheduler.common.Constants; |
|
|
|
|
|
|
|
|
|
import org.apache.http.auth.AuthSchemeProvider; |
|
|
|
|
import org.apache.http.auth.AuthScope; |
|
|
|
|
import org.apache.http.auth.Credentials; |
|
|
|
@ -28,15 +30,7 @@ import org.apache.http.impl.auth.SPNegoSchemeFactory;
|
|
|
|
|
import org.apache.http.impl.client.BasicCredentialsProvider; |
|
|
|
|
import org.apache.http.impl.client.CloseableHttpClient; |
|
|
|
|
import org.apache.http.impl.client.HttpClientBuilder; |
|
|
|
|
import org.slf4j.Logger; |
|
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
|
|
import javax.security.auth.Subject; |
|
|
|
|
import javax.security.auth.kerberos.KerberosPrincipal; |
|
|
|
|
import javax.security.auth.login.AppConfigurationEntry; |
|
|
|
|
import javax.security.auth.login.Configuration; |
|
|
|
|
import javax.security.auth.login.LoginContext; |
|
|
|
|
import javax.security.auth.login.LoginException; |
|
|
|
|
import java.security.Principal; |
|
|
|
|
import java.security.PrivilegedAction; |
|
|
|
|
import java.util.HashMap; |
|
|
|
@ -44,95 +38,103 @@ import java.util.HashSet;
|
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
import javax.security.auth.Subject; |
|
|
|
|
import javax.security.auth.kerberos.KerberosPrincipal; |
|
|
|
|
import javax.security.auth.login.AppConfigurationEntry; |
|
|
|
|
import javax.security.auth.login.Configuration; |
|
|
|
|
import javax.security.auth.login.LoginContext; |
|
|
|
|
import javax.security.auth.login.LoginException; |
|
|
|
|
|
|
|
|
|
import org.slf4j.Logger; |
|
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* kerberos http client |
|
|
|
|
*/ |
|
|
|
|
public class KerberosHttpClient { |
|
|
|
|
|
|
|
|
|
public static final Logger logger = LoggerFactory.getLogger(KerberosHttpClient.class); |
|
|
|
|
|
|
|
|
|
private String principal; |
|
|
|
|
private String keyTabLocation; |
|
|
|
|
|
|
|
|
|
public KerberosHttpClient(String principal, String keyTabLocation) { |
|
|
|
|
super(); |
|
|
|
|
this.principal = principal; |
|
|
|
|
this.keyTabLocation = keyTabLocation; |
|
|
|
|
super(); |
|
|
|
|
this.principal = principal; |
|
|
|
|
this.keyTabLocation = keyTabLocation; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public KerberosHttpClient(String principal, String keyTabLocation, boolean isDebug) { |
|
|
|
|
this(principal, keyTabLocation); |
|
|
|
|
if (isDebug) { |
|
|
|
|
System.setProperty("sun.security.spnego.debug", "true"); |
|
|
|
|
System.setProperty("sun.security.krb5.debug", "true"); |
|
|
|
|
} |
|
|
|
|
this(principal, keyTabLocation); |
|
|
|
|
if (isDebug) { |
|
|
|
|
System.setProperty("sun.security.spnego.debug", "true"); |
|
|
|
|
System.setProperty("sun.security.krb5.debug", "true"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public KerberosHttpClient(String principal, String keyTabLocation, String krb5Location, boolean isDebug) { |
|
|
|
|
this(principal, keyTabLocation, isDebug); |
|
|
|
|
System.setProperty("java.security.krb5.conf", krb5Location); |
|
|
|
|
this(principal, keyTabLocation, isDebug); |
|
|
|
|
System.setProperty("java.security.krb5.conf", krb5Location); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static CloseableHttpClient buildSpengoHttpClient() { |
|
|
|
|
HttpClientBuilder builder = HttpClientBuilder.create(); |
|
|
|
|
Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create() |
|
|
|
|
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build(); |
|
|
|
|
builder.setDefaultAuthSchemeRegistry(authSchemeRegistry); |
|
|
|
|
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); |
|
|
|
|
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() { |
|
|
|
|
@Override |
|
|
|
|
public Principal getUserPrincipal() { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String getPassword() { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
builder.setDefaultCredentialsProvider(credentialsProvider); |
|
|
|
|
return builder.build(); |
|
|
|
|
HttpClientBuilder builder = HttpClientBuilder.create(); |
|
|
|
|
Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create() |
|
|
|
|
.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build(); |
|
|
|
|
builder.setDefaultAuthSchemeRegistry(authSchemeRegistry); |
|
|
|
|
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); |
|
|
|
|
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() { |
|
|
|
|
@Override |
|
|
|
|
public Principal getUserPrincipal() { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String getPassword() { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
builder.setDefaultCredentialsProvider(credentialsProvider); |
|
|
|
|
return builder.build(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String get(final String url, final String userId) { |
|
|
|
|
logger.info("Calling KerberosHttpClient {} {} {}", this.principal, this.keyTabLocation, url); |
|
|
|
|
Configuration config = new Configuration() { |
|
|
|
|
@SuppressWarnings("serial") |
|
|
|
|
@Override |
|
|
|
|
public AppConfigurationEntry[] getAppConfigurationEntry(String name) { |
|
|
|
|
Map<String, Object> options = new HashMap<>(9); |
|
|
|
|
options.put("useTicketCache", "false"); |
|
|
|
|
options.put("useKeyTab", "true"); |
|
|
|
|
options.put("keyTab", keyTabLocation); |
|
|
|
|
options.put("refreshKrb5Config", "true"); |
|
|
|
|
options.put("principal", principal); |
|
|
|
|
options.put("storeKey", "true"); |
|
|
|
|
options.put("doNotPrompt", "true"); |
|
|
|
|
options.put("isInitiator", "true"); |
|
|
|
|
options.put("debug", "true"); |
|
|
|
|
return new AppConfigurationEntry[] { |
|
|
|
|
new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", |
|
|
|
|
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
Set<Principal> princ = new HashSet<>(1); |
|
|
|
|
princ.add(new KerberosPrincipal(userId)); |
|
|
|
|
Subject sub = new Subject(false, princ, new HashSet<>(), new HashSet<>()); |
|
|
|
|
|
|
|
|
|
LoginContext lc; |
|
|
|
|
try { |
|
|
|
|
lc = new LoginContext("", sub, null, config); |
|
|
|
|
lc.login(); |
|
|
|
|
Subject serviceSubject = lc.getSubject(); |
|
|
|
|
return Subject.doAs(serviceSubject, (PrivilegedAction<String>) () -> { |
|
|
|
|
CloseableHttpClient httpClient = buildSpengoHttpClient(); |
|
|
|
|
HttpGet httpget = new HttpGet(url); |
|
|
|
|
return HttpUtils.getResponseContentString(httpget, httpClient); |
|
|
|
|
}); |
|
|
|
|
} catch (LoginException le) { |
|
|
|
|
logger.error("Kerberos authentication failed ", le); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
logger.info("Calling KerberosHttpClient {} {} {}", this.principal, this.keyTabLocation, url); |
|
|
|
|
Configuration config = new Configuration() { |
|
|
|
|
@SuppressWarnings("serial") |
|
|
|
|
@Override |
|
|
|
|
public AppConfigurationEntry[] getAppConfigurationEntry(String name) { |
|
|
|
|
Map<String, Object> options = new HashMap<>(9); |
|
|
|
|
options.put("useTicketCache", "false"); |
|
|
|
|
options.put("useKeyTab", "true"); |
|
|
|
|
options.put("keyTab", keyTabLocation); |
|
|
|
|
options.put("refreshKrb5Config", "true"); |
|
|
|
|
options.put("principal", principal); |
|
|
|
|
options.put("storeKey", "true"); |
|
|
|
|
options.put("doNotPrompt", "true"); |
|
|
|
|
options.put("isInitiator", "true"); |
|
|
|
|
options.put("debug", "true"); |
|
|
|
|
return new AppConfigurationEntry[] { |
|
|
|
|
new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", |
|
|
|
|
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options) }; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
Set<Principal> princ = new HashSet<>(1); |
|
|
|
|
princ.add(new KerberosPrincipal(userId)); |
|
|
|
|
Subject sub = new Subject(false, princ, new HashSet<>(), new HashSet<>()); |
|
|
|
|
|
|
|
|
|
LoginContext lc; |
|
|
|
|
try { |
|
|
|
|
lc = new LoginContext("", sub, null, config); |
|
|
|
|
lc.login(); |
|
|
|
|
Subject serviceSubject = lc.getSubject(); |
|
|
|
|
return Subject.doAs(serviceSubject, (PrivilegedAction<String>) () -> { |
|
|
|
|
CloseableHttpClient httpClient = buildSpengoHttpClient(); |
|
|
|
|
HttpGet httpget = new HttpGet(url); |
|
|
|
|
return HttpUtils.getResponseContentString(httpget, httpClient); |
|
|
|
|
}); |
|
|
|
|
} catch (LoginException le) { |
|
|
|
|
logger.error("Kerberos authentication failed ", le); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -143,14 +145,13 @@ public class KerberosHttpClient {
|
|
|
|
|
*/ |
|
|
|
|
public static String get(String url) { |
|
|
|
|
|
|
|
|
|
String responseContent; |
|
|
|
|
KerberosHttpClient kerberosHttpClient = new KerberosHttpClient( |
|
|
|
|
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_USERNAME), |
|
|
|
|
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_PATH), |
|
|
|
|
PropertyUtils.getString(Constants.JAVA_SECURITY_KRB5_CONF_PATH), true); |
|
|
|
|
responseContent = kerberosHttpClient.get(url, PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_USERNAME)); |
|
|
|
|
return responseContent; |
|
|
|
|
String responseContent; |
|
|
|
|
KerberosHttpClient kerberosHttpClient = new KerberosHttpClient( |
|
|
|
|
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_USERNAME), |
|
|
|
|
PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_PATH), |
|
|
|
|
PropertyUtils.getString(Constants.JAVA_SECURITY_KRB5_CONF_PATH), true); |
|
|
|
|
responseContent = kerberosHttpClient.get(url, PropertyUtils.getString(Constants.LOGIN_USER_KEY_TAB_USERNAME)); |
|
|
|
|
return responseContent; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|