Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id BE5A0200B9A for ; Fri, 7 Oct 2016 22:47:13 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id BCF7E160AC6; Fri, 7 Oct 2016 20:47:13 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A3CDF160AE8 for ; Fri, 7 Oct 2016 22:47:12 +0200 (CEST) Received: (qmail 89349 invoked by uid 500); 7 Oct 2016 20:47:11 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 89340 invoked by uid 99); 7 Oct 2016 20:47:11 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 07 Oct 2016 20:47:11 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 98BFAE055E; Fri, 7 Oct 2016 20:47:11 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: xiao@apache.org To: common-commits@hadoop.apache.org Message-Id: <2120aa81d9864ef1b19bd201e6dc4903@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: hadoop git commit: HADOOP-13627. Have an explicit KerberosAuthException for UGI to throw, text from public constants. Contributed by Xiao Chen. Date: Fri, 7 Oct 2016 20:47:11 +0000 (UTC) archived-at: Fri, 07 Oct 2016 20:47:13 -0000 Repository: hadoop Updated Branches: refs/heads/branch-2 5ea87e4ae -> b9761f2fc HADOOP-13627. Have an explicit KerberosAuthException for UGI to throw, text from public constants. Contributed by Xiao Chen. (cherry picked from commit 2e853be6577a5b98fd860e6d64f89ca6d160514a) Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/b9761f2f Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/b9761f2f Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/b9761f2f Branch: refs/heads/branch-2 Commit: b9761f2fc917059522b593ee693af3defd264739 Parents: 5ea87e4 Author: Xiao Chen Authored: Fri Oct 7 13:46:27 2016 -0700 Committer: Xiao Chen Committed: Fri Oct 7 13:46:45 2016 -0700 ---------------------------------------------------------------------- .../hadoop/security/KerberosAuthException.java | 118 +++++++++++++++++++ .../hadoop/security/UGIExceptionMessages.java | 46 ++++++++ .../hadoop/security/UserGroupInformation.java | 74 +++++++----- 3 files changed, 209 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/b9761f2f/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/KerberosAuthException.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/KerberosAuthException.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/KerberosAuthException.java new file mode 100644 index 0000000..811c7c9 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/KerberosAuthException.java @@ -0,0 +1,118 @@ +/** + * 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; + +import static org.apache.hadoop.security.UGIExceptionMessages.*; + +import java.io.IOException; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + +/** + * Thrown when {@link UserGroupInformation} failed with an unrecoverable error, + * such as failure in kerberos login/logout, invalid subject etc. + * + * Caller should not retry when catching this exception. + */ +@InterfaceAudience.Public +@InterfaceStability.Unstable +public class KerberosAuthException extends IOException { + static final long serialVersionUID = 31L; + + private String user; + private String principal; + private String keytabFile; + private String ticketCacheFile; + private String initialMessage; + + public KerberosAuthException(String msg) { + super(msg); + } + + public KerberosAuthException(Throwable cause) { + super(cause); + } + + public KerberosAuthException(String initialMsg, Throwable cause) { + this(cause); + initialMessage = initialMsg; + } + + public void setUser(final String u) { + user = u; + } + + public void setPrincipal(final String p) { + principal = p; + } + + public void setKeytabFile(final String k) { + keytabFile = k; + } + + public void setTicketCacheFile(final String t) { + ticketCacheFile = t; + } + + /** @return The initial message, or null if not set. */ + public String getInitialMessage() { + return initialMessage; + } + + /** @return The keytab file path, or null if not set. */ + public String getKeytabFile() { + return keytabFile; + } + + /** @return The principal, or null if not set. */ + public String getPrincipal() { + return principal; + } + + /** @return The ticket cache file path, or null if not set. */ + public String getTicketCacheFile() { + return ticketCacheFile; + } + + /** @return The user, or null if not set. */ + public String getUser() { + return user; + } + + @Override + public String getMessage() { + final StringBuilder sb = new StringBuilder(); + if (initialMessage != null) { + sb.append(initialMessage); + } + if (user != null) { + sb.append(FOR_USER + user); + } + if (principal != null) { + sb.append(FOR_PRINCIPAL + principal); + } + if (keytabFile != null) { + sb.append(FROM_KEYTAB + keytabFile); + } + if (ticketCacheFile != null) { + sb.append(USING_TICKET_CACHE_FILE+ ticketCacheFile); + } + sb.append(" " + super.getMessage()); + return sb.toString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/hadoop/blob/b9761f2f/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UGIExceptionMessages.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UGIExceptionMessages.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UGIExceptionMessages.java new file mode 100644 index 0000000..c4d30e5 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UGIExceptionMessages.java @@ -0,0 +1,46 @@ +/* + * 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; + +/** + * Standard strings to use in exception messages + * in {@link KerberosAuthException} when throwing. + */ +final class UGIExceptionMessages { + + public static final String FAILURE_TO_LOGIN = "failure to login:"; + public static final String FOR_USER = " for user: "; + public static final String FOR_PRINCIPAL = " for principal: "; + public static final String FROM_KEYTAB = " from keytab "; + public static final String LOGIN_FAILURE = "Login failure"; + public static final String LOGOUT_FAILURE = "Logout failure"; + public static final String MUST_FIRST_LOGIN = + "login must be done first"; + public static final String MUST_FIRST_LOGIN_FROM_KEYTAB = + "loginUserFromKeyTab must be done first"; + public static final String SUBJECT_MUST_CONTAIN_PRINCIPAL = + "Provided Subject must contain a KerberosPrincipal"; + public static final String SUBJECT_MUST_NOT_BE_NULL = + "Subject must not be null"; + public static final String USING_TICKET_CACHE_FILE = + " using ticket cache file: "; + + //checkstyle: Utility classes should not have a public or default constructor. + private UGIExceptionMessages() { + } +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/b9761f2f/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java index f47012f..e69bb1e 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java @@ -19,6 +19,7 @@ package org.apache.hadoop.security; import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS; import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_TOKEN_FILES; +import static org.apache.hadoop.security.UGIExceptionMessages.*; import static org.apache.hadoop.util.PlatformName.IBM_JAVA; import java.io.File; @@ -743,8 +744,11 @@ public class UserGroupInformation { ugi.setAuthenticationMethod(AuthenticationMethod.KERBEROS); return ugi; } catch (LoginException le) { - throw new IOException("failure to login using ticket cache file " + - ticketCache, le); + KerberosAuthException kae = + new KerberosAuthException(FAILURE_TO_LOGIN, le); + kae.setUser(user); + kae.setTicketCacheFile(ticketCache); + throw kae; } } @@ -753,16 +757,17 @@ public class UserGroupInformation { * * @param user The KerberosPrincipal to use in UGI * - * @throws IOException if the kerberos login fails + * @throws IOException + * @throws KerberosAuthException if the kerberos login fails */ public static UserGroupInformation getUGIFromSubject(Subject subject) throws IOException { if (subject == null) { - throw new IOException("Subject must not be null"); + throw new KerberosAuthException(SUBJECT_MUST_NOT_BE_NULL); } if (subject.getPrincipals(KerberosPrincipal.class).isEmpty()) { - throw new IOException("Provided Subject must contain a KerberosPrincipal"); + throw new KerberosAuthException(SUBJECT_MUST_CONTAIN_PRINCIPAL); } KerberosPrincipal principal = @@ -882,7 +887,7 @@ public class UserGroupInformation { loginUser.spawnAutoRenewalThreadForUserCreds(); } catch (LoginException le) { LOG.debug("failure to login", le); - throw new IOException("failure to login: " + le, le); + throw new KerberosAuthException(FAILURE_TO_LOGIN, le); } if (LOG.isDebugEnabled()) { LOG.debug("UGI loginUser:"+loginUser); @@ -989,7 +994,8 @@ public class UserGroupInformation { * file and logs them in. They become the currently logged-in user. * @param user the principal name to load from the keytab * @param path the path to the keytab file - * @throws IOException if the keytab file can't be read + * @throws IOException + * @throws KerberosAuthException if it's a kerberos login exception. */ @InterfaceAudience.Public @InterfaceStability.Evolving @@ -1018,8 +1024,10 @@ public class UserGroupInformation { if (start > 0) { metrics.loginFailure.add(Time.now() - start); } - throw new IOException("Login failure for " + user + " from keytab " + - path+ ": " + le, le); + KerberosAuthException kae = new KerberosAuthException(LOGIN_FAILURE, le); + kae.setUser(user); + kae.setKeytabFile(path); + throw kae; } LOG.info("Login successful for user " + keytabPrincipal + " using keytab file " + keytabFile); @@ -1030,8 +1038,9 @@ public class UserGroupInformation { * This method assumes that the user logged in by calling * {@link #loginUserFromKeytab(String, String)}. * - * @throws IOException if a failure occurred in logout, or if the user did - * not log in by invoking loginUserFromKeyTab() before. + * @throws IOException + * @throws KerberosAuthException if a failure occurred in logout, + * or if the user did not log in by invoking loginUserFromKeyTab() before. */ @InterfaceAudience.Public @InterfaceStability.Evolving @@ -1042,7 +1051,7 @@ public class UserGroupInformation { } LoginContext login = getLogin(); if (login == null || keytabFile == null) { - throw new IOException("loginUserFromKeytab must be done first"); + throw new KerberosAuthException(MUST_FIRST_LOGIN_FROM_KEYTAB); } try { @@ -1053,9 +1062,10 @@ public class UserGroupInformation { login.logout(); } } catch (LoginException le) { - throw new IOException("Logout failure for " + user + " from keytab " + - keytabFile + ": " + le, - le); + KerberosAuthException kae = new KerberosAuthException(LOGOUT_FAILURE, le); + kae.setUser(user.toString()); + kae.setKeytabFile(keytabFile); + throw kae; } LOG.info("Logout successful for user " + keytabPrincipal @@ -1066,6 +1076,7 @@ public class UserGroupInformation { * Re-login a user from keytab if TGT is expired or is close to expiry. * * @throws IOException + * @throws KerberosAuthException if it's a kerberos login exception. */ public synchronized void checkTGTAndReloginFromKeytab() throws IOException { if (!isSecurityEnabled() @@ -1087,12 +1098,12 @@ public class UserGroupInformation { * happened already. * The Subject field of this UserGroupInformation object is updated to have * the new credentials. - * @throws IOException on a failure + * @throws IOException + * @throws KerberosAuthException on a failure */ @InterfaceAudience.Public @InterfaceStability.Evolving - public synchronized void reloginFromKeytab() - throws IOException { + public synchronized void reloginFromKeytab() throws IOException { if (!isSecurityEnabled() || user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS || !isKeytab) @@ -1112,7 +1123,7 @@ public class UserGroupInformation { LoginContext login = getLogin(); if (login == null || keytabFile == null) { - throw new IOException("loginUserFromKeyTab must be done first"); + throw new KerberosAuthException(MUST_FIRST_LOGIN_FROM_KEYTAB); } long start = 0; @@ -1144,8 +1155,10 @@ public class UserGroupInformation { if (start > 0) { metrics.loginFailure.add(Time.now() - start); } - throw new IOException("Login failure for " + keytabPrincipal + - " from keytab " + keytabFile + ": " + le, le); + KerberosAuthException kae = new KerberosAuthException(LOGIN_FAILURE, le); + kae.setPrincipal(keytabPrincipal); + kae.setKeytabFile(keytabFile); + throw kae; } } @@ -1154,19 +1167,19 @@ public class UserGroupInformation { * method assumes that login had happened already. * The Subject field of this UserGroupInformation object is updated to have * the new credentials. - * @throws IOException on a failure + * @throws IOException + * @throws KerberosAuthException on a failure */ @InterfaceAudience.Public @InterfaceStability.Evolving - public synchronized void reloginFromTicketCache() - throws IOException { + public synchronized void reloginFromTicketCache() throws IOException { if (!isSecurityEnabled() || user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS || !isKrbTkt) return; LoginContext login = getLogin(); if (login == null) { - throw new IOException("login must be done first"); + throw new KerberosAuthException(MUST_FIRST_LOGIN); } long now = Time.now(); if (!hasSufficientTimeElapsed(now)) { @@ -1193,8 +1206,9 @@ public class UserGroupInformation { login.login(); setLogin(login); } catch (LoginException le) { - throw new IOException("Login failure for " + getUserName() + ": " + le, - le); + KerberosAuthException kae = new KerberosAuthException(LOGIN_FAILURE, le); + kae.setUser(getUserName()); + throw kae; } } @@ -1240,8 +1254,10 @@ public class UserGroupInformation { if (start > 0) { metrics.loginFailure.add(Time.now() - start); } - throw new IOException("Login failure for " + user + " from keytab " + - path + ": " + le, le); + KerberosAuthException kae = new KerberosAuthException(LOGIN_FAILURE, le); + kae.setUser(user); + kae.setKeytabFile(path); + throw kae; } finally { if(oldKeytabFile != null) keytabFile = oldKeytabFile; if(oldKeytabPrincipal != null) keytabPrincipal = oldKeytabPrincipal; --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org For additional commands, e-mail: common-commits-help@hadoop.apache.org