hadoop KerberosName 源码
haddop KerberosName 代码
文件路径:/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/KerberosName.java
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.security.authentication.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.hadoop.classification.VisibleForTesting;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class implements parsing and handling of Kerberos principal names. In
* particular, it splits them apart and translates them down into local
* operating system names.
*/
@SuppressWarnings("all")
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce"})
@InterfaceStability.Evolving
public class KerberosName {
private static final Logger LOG = LoggerFactory.getLogger(KerberosName.class);
/**
* Constant that defines auth_to_local legacy hadoop evaluation
*/
public static final String MECHANISM_HADOOP = "hadoop";
/**
* Constant that defines auth_to_local MIT evaluation
*/
public static final String MECHANISM_MIT = "mit";
/** Constant that defines the default behavior of the rule mechanism */
public static final String DEFAULT_MECHANISM = MECHANISM_HADOOP;
/** The first component of the name */
private final String serviceName;
/** The second component of the name. It may be null. */
private final String hostName;
/** The realm of the name. */
private final String realm;
/**
* A pattern that matches a Kerberos name with at most 2 components.
*/
private static final Pattern nameParser =
Pattern.compile("([^/@]+)(/([^/@]+))?(@([^/@]+))?");
/**
* A pattern that matches a string with out '$' and then a single
* parameter with $n.
*/
private static Pattern parameterPattern =
Pattern.compile("([^$]*)(\\$(\\d*))?");
/**
* A pattern for parsing a auth_to_local rule.
*/
private static final Pattern ruleParser =
Pattern.compile("\\s*((DEFAULT)|(RULE:\\[(\\d*):([^\\]]*)](\\(([^)]*)\\))?"+
"(s/([^/]*)/([^/]*)/(g)?)?))/?(L)?");
/**
* A pattern that recognizes simple/non-simple names.
*/
private static final Pattern nonSimplePattern = Pattern.compile("[/@]");
/**
* The list of translation rules.
*/
private static List<Rule> rules;
/**
* How to evaluate auth_to_local rules
*/
private static String ruleMechanism = null;
private static String defaultRealm = null;
@VisibleForTesting
public static void resetDefaultRealm() {
try {
defaultRealm = KerberosUtil.getDefaultRealm();
} catch (Exception ke) {
LOG.debug("resetting default realm failed, "
+ "current default realm will still be used.", ke);
}
}
/**
* Create a name from the full Kerberos principal name.
* @param name full Kerberos principal name.
*/
public KerberosName(String name) {
Matcher match = nameParser.matcher(name);
if (!match.matches()) {
if (name.contains("@")) {
throw new IllegalArgumentException("Malformed Kerberos name: " + name);
} else {
serviceName = name;
hostName = null;
realm = null;
}
} else {
serviceName = match.group(1);
hostName = match.group(3);
realm = match.group(5);
}
}
/**
* Get the configured default realm.
* Used syncronized method here, because double-check locking is overhead.
* @return the default realm from the krb5.conf
*/
public static synchronized String getDefaultRealm() {
if (defaultRealm == null) {
try {
defaultRealm = KerberosUtil.getDefaultRealm();
} catch (Exception ke) {
LOG.debug("Kerberos krb5 configuration not found, setting default realm to empty");
defaultRealm = "";
}
}
return defaultRealm;
}
/**
* Put the name back together from the parts.
*/
@Override
public String toString() {
StringBuilder result = new StringBuilder();
result.append(serviceName);
if (hostName != null) {
result.append('/');
result.append(hostName);
}
if (realm != null) {
result.append('@');
result.append(realm);
}
return result.toString();
}
/**
* Get the first component of the name.
* @return the first section of the Kerberos principal name
*/
public String getServiceName() {
return serviceName;
}
/**
* Get the second component of the name.
* @return the second section of the Kerberos principal name, and may be null
*/
public String getHostName() {
return hostName;
}
/**
* Get the realm of the name.
* @return the realm of the name, may be null
*/
public String getRealm() {
return realm;
}
/**
* An encoding of a rule for translating kerberos names.
*/
private static class Rule {
private final boolean isDefault;
private final int numOfComponents;
private final String format;
private final Pattern match;
private final Pattern fromPattern;
private final String toPattern;
private final boolean repeat;
private final boolean toLowerCase;
Rule() {
isDefault = true;
numOfComponents = 0;
format = null;
match = null;
fromPattern = null;
toPattern = null;
repeat = false;
toLowerCase = false;
}
Rule(int numOfComponents, String format, String match, String fromPattern,
String toPattern, boolean repeat, boolean toLowerCase) {
isDefault = false;
this.numOfComponents = numOfComponents;
this.format = format;
this.match = match == null ? null : Pattern.compile(match);
this.fromPattern =
fromPattern == null ? null : Pattern.compile(fromPattern);
this.toPattern = toPattern;
this.repeat = repeat;
this.toLowerCase = toLowerCase;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
if (isDefault) {
buf.append("DEFAULT");
} else {
buf.append("RULE:[");
buf.append(numOfComponents);
buf.append(':');
buf.append(format);
buf.append(']');
if (match != null) {
buf.append('(');
buf.append(match);
buf.append(')');
}
if (fromPattern != null) {
buf.append("s/");
buf.append(fromPattern);
buf.append('/');
buf.append(toPattern);
buf.append('/');
if (repeat) {
buf.append('g');
}
}
if (toLowerCase) {
buf.append("/L");
}
}
return buf.toString();
}
/**
* Replace the numbered parameters of the form $n where n is from 1 to
* the length of params. Normal text is copied directly and $n is replaced
* by the corresponding parameter.
* @param format the string to replace parameters again
* @param params the list of parameters
* @return the generated string with the parameter references replaced.
* @throws BadFormatString
*/
static String replaceParameters(String format,
String[] params) throws BadFormatString {
Matcher match = parameterPattern.matcher(format);
int start = 0;
StringBuilder result = new StringBuilder();
while (start < format.length() && match.find(start)) {
result.append(match.group(1));
String paramNum = match.group(3);
if (paramNum != null) {
try {
int num = Integer.parseInt(paramNum);
if (num < 0 || num >= params.length) {
throw new BadFormatString("index " + num + " from " + format +
" is outside of the valid range 0 to " +
(params.length - 1));
}
result.append(params[num]);
} catch (NumberFormatException nfe) {
throw new BadFormatString("bad format in username mapping in " +
paramNum, nfe);
}
}
start = match.end();
}
return result.toString();
}
/**
* Replace the matches of the from pattern in the base string with the value
* of the to string.
* @param base the string to transform
* @param from the pattern to look for in the base string
* @param to the string to replace matches of the pattern with
* @param repeat whether the substitution should be repeated
* @return
*/
static String replaceSubstitution(String base, Pattern from, String to,
boolean repeat) {
Matcher match = from.matcher(base);
if (repeat) {
return match.replaceAll(to);
} else {
return match.replaceFirst(to);
}
}
/**
* Try to apply this rule to the given name represented as a parameter
* array.
* @param params first element is the realm, second and later elements are
* are the components of the name "a/b@FOO" -> {"FOO", "a", "b"}
* @param ruleMechanism defines the rule evaluation mechanism
* @return the short name if this rule applies or null
* @throws IOException throws if something is wrong with the rules
*/
String apply(String[] params, String ruleMechanism) throws IOException {
String result = null;
if (isDefault) {
if (getDefaultRealm().equals(params[0])) {
result = params[1];
}
} else if (params.length - 1 == numOfComponents) {
String base = replaceParameters(format, params);
if (match == null || match.matcher(base).matches()) {
if (fromPattern == null) {
result = base;
} else {
result = replaceSubstitution(base, fromPattern, toPattern, repeat);
}
}
}
if (result != null
&& nonSimplePattern.matcher(result).find()
&& ruleMechanism.equalsIgnoreCase(MECHANISM_HADOOP)) {
throw new NoMatchingRule("Non-simple name " + result +
" after auth_to_local rule " + this);
}
if (toLowerCase && result != null) {
result = result.toLowerCase(Locale.ENGLISH);
}
return result;
}
}
static List<Rule> parseRules(String rules) {
List<Rule> result = new ArrayList<Rule>();
String remaining = rules.trim();
while (remaining.length() > 0) {
Matcher matcher = ruleParser.matcher(remaining);
if (!matcher.lookingAt()) {
throw new IllegalArgumentException("Invalid rule: " + remaining);
}
if (matcher.group(2) != null) {
result.add(new Rule());
} else {
result.add(new Rule(Integer.parseInt(matcher.group(4)),
matcher.group(5),
matcher.group(7),
matcher.group(9),
matcher.group(10),
"g".equals(matcher.group(11)),
"L".equals(matcher.group(12))));
}
remaining = remaining.substring(matcher.end());
}
return result;
}
@SuppressWarnings("serial")
public static class BadFormatString extends IOException {
BadFormatString(String msg) {
super(msg);
}
BadFormatString(String msg, Throwable err) {
super(msg, err);
}
}
@SuppressWarnings("serial")
public static class NoMatchingRule extends IOException {
NoMatchingRule(String msg) {
super(msg);
}
}
/**
* Get the translation of the principal name into an operating system
* user name.
* @return the short name
* @throws IOException throws if something is wrong with the rules
*/
public String getShortName() throws IOException {
String[] params;
if (hostName == null) {
// if it is already simple, just return it
if (realm == null) {
return serviceName;
}
params = new String[]{realm, serviceName};
} else {
params = new String[]{realm, serviceName, hostName};
}
String ruleMechanism = this.ruleMechanism;
if (ruleMechanism == null && rules != null) {
LOG.warn("auth_to_local rule mechanism not set."
+ "Using default of " + DEFAULT_MECHANISM);
ruleMechanism = DEFAULT_MECHANISM;
}
for(Rule r: rules) {
String result = r.apply(params, ruleMechanism);
if (result != null) {
return result;
}
}
if (ruleMechanism.equalsIgnoreCase(MECHANISM_HADOOP)) {
throw new NoMatchingRule("No rules applied to " + toString());
}
return toString();
}
/**
* Get the rules.
* @return String of configured rules, or null if not yet configured
*/
public static String getRules() {
String ruleString = null;
if (rules != null) {
StringBuilder sb = new StringBuilder();
for (Rule rule : rules) {
sb.append(rule.toString()).append("\n");
}
ruleString = sb.toString().trim();
}
return ruleString;
}
/**
* Indicates if the name rules have been set.
*
* @return if the name rules have been set.
*/
public static boolean hasRulesBeenSet() {
return rules != null;
}
/**
* Indicates of the rule mechanism has been set
*
* @return if the rule mechanism has been set.
*/
public static boolean hasRuleMechanismBeenSet() {
return ruleMechanism != null;
}
/**
* Set the rules.
* @param ruleString the rules string.
*/
public static void setRules(String ruleString) {
rules = (ruleString != null) ? parseRules(ruleString) : null;
}
/**
*
* @param ruleMech the evaluation type: hadoop, mit
* 'hadoop' indicates '@' or '/' are not allowed the result
* evaluation. 'MIT' indicates that auth_to_local
* rules follow MIT Kerberos evaluation.
*/
public static void setRuleMechanism(String ruleMech) {
if (ruleMech != null
&& (!ruleMech.equalsIgnoreCase(MECHANISM_HADOOP)
&& !ruleMech.equalsIgnoreCase(MECHANISM_MIT))) {
throw new IllegalArgumentException("Invalid rule mechanism: " + ruleMech);
}
ruleMechanism = ruleMech;
}
/**
* Get the rule evaluation mechanism
* @return the rule evaluation mechanism
*/
public static String getRuleMechanism() {
return ruleMechanism;
}
static void printRules() throws IOException {
int i = 0;
for(Rule r: rules) {
System.out.println(++i + " " + r);
}
}
}
相关信息
相关文章
hadoop FileSignerSecretProvider 源码
hadoop RandomSignerSecretProvider 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦