[ 
https://issues.apache.org/jira/browse/HADOOP-12333?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14703189#comment-14703189
 ] 

john lilley commented on HADOOP-12333:
--------------------------------------

Yes, exactly.  Our software, while running as a service, is a client as far as 
Hadoop is concerned, until we launch YARN tasks (but those are taken care of 
separately via delegation tokens).  The software allows each user to log in 
independently using their own credentials.  This can be either keytab or 
login/password.  If login/password, we use this to both authenticate the OS 
login and the Hadoop login, assuming there is Active Directory integration for 
the KDC.  It spawns processes under the users validated credentials, but they 
are still running in a service context.  So when the user logs in a provides a 
password, we authenticate and get a ticket.  We cannot use kinit because there 
is no command-line context.  This leads to the first issue -- in order to do 
the equivalent of kinit we have to breach UGI via reflection to gain access to 
setLogin().  The second issue is renewing the ticket.  I think we can mimic the 
reloginFromKeytab() code by doing a user.logout() followed by a new round of 
login, but to make this safe we also have to do things like lock UGI.class.  
While all of this is feasible, I am concerned about compatibility with future 
versions because we are not using the API.  it seems like an oversight that 
Hadoop doesn't support this.

> UserGroupInformation method to log in and relogin with password
> ---------------------------------------------------------------
>
>                 Key: HADOOP-12333
>                 URL: https://issues.apache.org/jira/browse/HADOOP-12333
>             Project: Hadoop Common
>          Issue Type: Improvement
>          Components: security
>    Affects Versions: 2.6.0
>         Environment: all
>            Reporter: john lilley
>
> UserGroupInformation lacks a simple method to login using a password, and 
> also makes an important method private.  While many people seem to believe 
> that kinit should be used for passwords, it is unworkable in many cases (such 
> as when software is running as a service).
> Currently to workaround we must do all of this:
>     // create a dynamic configuration for the LoginContext
>     Map<String,String> krbOptions = new HashMap<String,String>();
>     krbOptions.put("doNotPrompt", "false");
>     krbOptions.put("useTicketCache", "false");
>     krbOptions.put("useKeyTab", "false");
>     krbOptions.put("renewTGT", "false");
>     AppConfigurationEntry ace = new AppConfigurationEntry(
>         KerberosUtil.getKrb5LoginModuleName(), 
> LoginModuleControlFlag.REQUIRED,
>         krbOptions);
>     DynamicConfiguration dynConf = new DynamicConfiguration(
>         new AppConfigurationEntry[] {ace});
>     // create LoginContext with login callback handler
>     LoginContext loginContext = 
> newLoginContext(USER_PASSWORD_LOGIN_KERBEROS_CONFIG_NAME, 
>       null, new LoginHandler(userPrincipal, password), dynConf);
>     loginContext.login();
>     // get Subject and Principal for logged in user
>     Subject loginSubject = loginContext.getSubject();
>     Set<Principal> loginPrincipals = loginSubject.getPrincipals();
>     if (loginPrincipals.isEmpty()) {
>       throw new LoginException("No login principals in loginSubject: " + 
> loginSubject);
>     }
>     String username = loginPrincipals.iterator().next().getName();
>     Principal ugiUser = newUser(username, AuthenticationMethod.KERBEROS, 
> loginContext);
>     // update Hadoop security details
>     loginSubject.getPrincipals().add(ugiUser);
>     UserGroupInformation loginUser = newUserGroupInformation(loginSubject);
>     UserGroupInformation.setLoginUser(loginUser);
>     setUGILogin(loginUser, loginContext); // do 
> loginUser.setLogin(loginContext)
>     loginUser.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
> Note the method setUGILogin() uses reflection to overcome private method that 
> we need:
> private static void setUGILogin(UserGroupInformation loginUser, LoginContext 
> loginContext) 
>             throws SecurityException, NoSuchMethodException, 
> IllegalArgumentException, 
>             IllegalAccessException, InvocationTargetException 
>   {
>     Class<UserGroupInformation> cls = UserGroupInformation.class;
>     Method mtd = cls.getDeclaredMethod("setLogin", LoginContext.class);
>     mtd.setAccessible(true);
>     mtd.invoke(loginUser, loginContext);
>   }
>   
> Finally there is no method reloginFromPassword().  While we can use 
> reflection to access the private methods needed for this, it should simply be 
> supported.  
> PS: I really hope I've just missed something obvious and you can just call me 
> an idiot ;-)



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to