@Override public Optional<Subject> map(final Optional<Object> wrapper) { try { LOG.info("logging in user as {}", username); LoginContext lc = new LoginContext("PropertyFile", callbacks -> { LOG.info("Callback Handler invoked "); Stream.of(callbacks).forEach(cb -> { if (cb instanceof NameCallback) { ((NameCallback) cb).setName(username); } else if (cb instanceof PasswordCallback) { ((PasswordCallback) cb).setPassword(password.toCharArray()); } }); }); lc.login(); return Optional.of(lc.getSubject()); } catch (LoginException e) { LOG.error("Authentication failed", e); return Optional.empty(); } }
/** * * @param user * @param password * @param configuration * @throws LoginException * @throws IOException */ private void getKerberosToken(String user, char[] password, Configuration configuration) throws LoginException, IOException { LOG.trace("Entering method getKerberosToken() for user: " + user); URL url = HydrographService.class.getClassLoader().getResource("jaas.conf"); System.setProperty("java.security.auth.login.config", url.toExternalForm()); LOG.info("Generating Kerberos ticket for user: " + user); UserGroupInformation.setConfiguration(configuration); lc = new LoginContext("EntryName", new UserPassCallbackHandler(user, password)); lc.login(); Subject subject = lc.getSubject(); UserGroupInformation.loginUserFromSubject(subject); Subject.doAs(subject, this); LOG.info("Kerberos ticket successfully generated for user: " + user); }
private static LoginContext newLoginContext(String appName, Subject subject, javax.security.auth.login.Configuration loginConf) throws LoginException { // Temporarily switch the thread's ContextClassLoader to match this // class's classloader, so that we can properly load HadoopLoginModule // from the JAAS libraries. Thread t = Thread.currentThread(); ClassLoader oldCCL = t.getContextClassLoader(); t.setContextClassLoader(HadoopLoginModule.class.getClassLoader()); try { return new LoginContext(appName, subject, null, loginConf); } finally { t.setContextClassLoader(oldCCL); } }
@Test public void noPreviousContextOnLogin() throws Exception { KerberosConnection krbUtil = mock(KerberosConnection.class); Subject subject = new Subject(); Subject loggedInSubject = new Subject(); Configuration conf = mock(Configuration.class); LoginContext context = mock(LoginContext.class); // Call the real login(LoginContext, Configuration, Subject) method when(krbUtil.login(nullable(LoginContext.class), any(Configuration.class), any(Subject.class))) .thenCallRealMethod(); // Return a fake LoginContext when(krbUtil.createLoginContext(conf)).thenReturn(context); // Return a fake Subject from that fake LoginContext when(context.getSubject()).thenReturn(loggedInSubject); Entry<LoginContext, Subject> pair = krbUtil.login(null, conf, subject); // Verify we get the fake LoginContext and Subject assertEquals(context, pair.getKey()); assertEquals(loggedInSubject, pair.getValue()); // login should be called on the LoginContext verify(context).login(); }
static Subject getSubject() throws Exception { if (!secure) return new Subject(); /* * To authenticate the DemoClient, kinit should be invoked ahead. * Here we try to get the Kerberos credential from the ticket cache. */ LoginContext context = new LoginContext("", new Subject(), null, new Configuration() { @Override public AppConfigurationEntry[] getAppConfigurationEntry(String name) { Map<String, String> options = new HashMap<String, String>(); options.put("useKeyTab", "false"); options.put("storeKey", "false"); options.put("doNotPrompt", "true"); options.put("useTicketCache", "true"); options.put("renewTGT", "true"); options.put("refreshKrb5Config", "true"); options.put("isInitiator", "true"); String ticketCache = System.getenv("KRB5CCNAME"); if (ticketCache != null) { options.put("ticketCache", ticketCache); } options.put("debug", "true"); return new AppConfigurationEntry[]{ new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)}; } }); context.login(); return context.getSubject(); }
/** * Construct a new Principal, associated with the specified Realm, for the * specified username and password, with the specified role names * (as Strings). * * @param name The username of the user represented by this Principal * @param password Credentials used to authenticate this user * @param roles List of roles (must be Strings) possessed by this user * @param userPrincipal - the principal to be returned from the request * getUserPrincipal call if not null; if null, this will be returned * @param loginContext - If provided, this will be used to log out the user * at the appropriate time * @param gssCredential - If provided, the user's delegated credentials */ public GenericPrincipal(String name, String password, List<String> roles, Principal userPrincipal, LoginContext loginContext, GSSCredential gssCredential) { super(); this.name = name; this.password = password; this.userPrincipal = userPrincipal; if (roles != null) { this.roles = new String[roles.size()]; this.roles = roles.toArray(this.roles); if (this.roles.length > 1) Arrays.sort(this.roles); } this.loginContext = loginContext; this.gssCredential = gssCredential; }
@Override public final Subject authenticate(final Object credentials) { // Setup login context final LoginContext loginContext; try { loginContext = AccessController.doPrivileged( (PrivilegedExceptionAction<LoginContext>) () -> new LoginContext(name, null, new JMXCallbackHandler(credentials), configuration)); } catch (final PrivilegedActionException pae) { throw new SecurityException("Could not create loginContext", pae); } // Perform authentication try { loginContext.login(); final Subject subject = loginContext.getSubject(); AccessController.doPrivileged((PrivilegedAction<Void>) () -> { subject.setReadOnly(); return null; }); return subject; } catch (final LoginException le) { throw new SecurityException(le); } }
@Test public void testClientLogin() throws Throwable { LoginContext client = login(ALICE_LOCALHOST, ALICE_CLIENT_CONTEXT, keytab_alice); try { logLoginDetails(ALICE_LOCALHOST, client); String confFilename = System.getProperty(Environment.JAAS_CONF_KEY); assertNotNull("Unset: "+ Environment.JAAS_CONF_KEY, confFilename); String config = FileUtils.readFileToString(new File(confFilename)); LOG.info("{}=\n{}", confFilename, config); RegistrySecurity.setZKSaslClientProperties(ALICE, ALICE_CLIENT_CONTEXT); } finally { client.logout(); } }
/** * have the ZK user create the root dir. * This logs out the ZK user after and stops its curator instance, * to avoid contamination * @throws Throwable */ public void userZookeeperToCreateRoot() throws Throwable { System.setProperty("curator-log-events", "true"); CuratorService curator = null; LoginContext login = login(ZOOKEEPER_LOCALHOST, ZOOKEEPER_CLIENT_CONTEXT, keytab_zk); try { logLoginDetails(ZOOKEEPER, login); RegistrySecurity.setZKSaslClientProperties(ZOOKEEPER, ZOOKEEPER_CLIENT_CONTEXT); curator = startCuratorServiceInstance("ZK", true); LOG.info(curator.toString()); addToTeardown(curator); curator.zkMkPath("/", CreateMode.PERSISTENT, false, RegistrySecurity.WorldReadWriteACL); ZKPathDumper pathDumper = curator.dumpPath(true); LOG.info(pathDumper.toString()); } finally { logout(login); ServiceOperations.stop(curator); } }
private <T> T doAs(String user, final PrivilegedExceptionAction<T> action) throws Exception { Set<Principal> principals = new HashSet<Principal>(); principals.add(new KerberosPrincipal(user)); //client login Subject subject = new Subject(false, principals, new HashSet<Object>(), new HashSet<Object>()); LoginContext loginContext = new LoginContext("", subject, null, KerberosConfiguration.createClientConfig(user, keytab)); try { loginContext.login(); subject = loginContext.getSubject(); UserGroupInformation ugi = UserGroupInformation.getUGIFromSubject(subject); return ugi.doAs(action); } finally { loginContext.logout(); } }
private static void checkPrincipal(LoginContext loginContext, boolean principalShouldExist) { if (!principalShouldExist) { if (loginContext.getSubject().getPrincipals().size() != 0) { throw new RuntimeException("Test failed. Principal was not " + "cleared."); } } else { for (Principal p : loginContext.getSubject().getPrincipals()) { if (p instanceof UnixPrincipal && USER_NAME.equals(p.getName())) { //Proper principal was found, return. return; } } throw new RuntimeException("Test failed. UnixPrincipal " + USER_NAME + " expected."); } }
public static void testConfigName(String confName, boolean expectException) { String expectedMsg = "No LoginModules configured for " + confName; try { LoginContext lc = new LoginContext(confName, new Subject(), new MyCallbackHandler(), new MyConfiguration()); if (expectException) { throw new RuntimeException("Wrong Config Name Test failed: " + "expected LoginException not thrown."); } } catch (LoginException le) { if (!expectException || !le.getMessage().equals(expectedMsg)) { System.out.println("Wrong Config Name Test failed: " + "received Unexpected exception."); throw new RuntimeException(le); } } }
public static void testLogin(String confName, char[] passwd, Configuration cf, boolean expectException) { try { CallbackHandler ch = new MyCallbackHandler("testUser", passwd); LoginContext lc = new LoginContext(confName, new Subject(), ch, cf); lc.login(); if (expectException) { throw new RuntimeException("Login Test failed: " + "expected LoginException not thrown"); } } catch (LoginException le) { if (!expectException) { System.out.println("Login Test failed: " + "received Unexpected exception."); throw new RuntimeException(le); } } }
/** * Authenticate using the login module from the specified * configuration entry. * * @param caller the caller of JAAS Login * @param mech the mech to be used * @return the authenticated subject */ public static Subject login(GSSCaller caller, Oid mech) throws LoginException { CallbackHandler cb = null; if (caller instanceof HttpCaller) { cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler( ((HttpCaller)caller).info()); } else { String defaultHandler = java.security.Security.getProperty(DEFAULT_HANDLER); // get the default callback handler if ((defaultHandler != null) && (defaultHandler.length() != 0)) { cb = null; } else { cb = new ConsoleCallbackHandler(); } } // New instance of LoginConfigImpl must be created for each login, // since the entry name is not passed as the first argument, but // generated with caller and mech inside LoginConfigImpl LoginContext lc = new LoginContext("", null, cb, new LoginConfigImpl(caller, mech)); lc.login(); return lc.getSubject(); }
static void login(String test, String... conf) throws Exception { System.out.println("Testing " + test + "..."); StringBuilder sb = new StringBuilder(); sb.append("hello {\n"); for (int i=0; i<conf.length; i+=2) { sb.append(" com.sun.security.auth.module." + conf[i] + " " + conf[i+1] + ";\n"); } sb.append("};\n"); Files.write(Paths.get(test), sb.toString().getBytes()); // Must be called. Configuration has an internal static field. Configuration.setConfiguration(null); System.setProperty("java.security.auth.login.config", test); LoginContext lc = new LoginContext("hello"); lc.login(); System.out.println(lc.getSubject()); }
private static void checkPrincipal(LoginContext loginContext, boolean principalShouldExist) { if (!principalShouldExist) { if (loginContext.getSubject().getPrincipals().size() != 0) { throw new RuntimeException("Test failed. Principal was not " + "cleared."); } return; } for (Principal p : loginContext.getSubject().getPrincipals()) { if (p instanceof UserPrincipal && USER_NAME.equals(p.getName())) { //Proper principal was found, return. return; } } throw new RuntimeException("Test failed. UserPrincipal " + USER_NAME + " expected."); }
public static void main(String[] args) throws Exception { System.setProperty("java.security.auth.login.config", new File(System.getProperty("test.src"), "sl.conf").toString()); LoginContext lc = new LoginContext("me"); if (SecondLoginModule.isLoaded) { throw new Exception(); } lc.login(); // Although only FirstLoginModule is specified in the JAAS login // config file, LoginContext will first create all LoginModule // implementations that are registered as services, which include // SecondLoginModule. if (!SecondLoginModule.isLoaded) { throw new Exception(); } }
private Subject loginViaKerberos(Builder b) { Set<Principal> principals = new HashSet<Principal>(); principals.add(new KerberosPrincipal(b.kerberosPrincipal)); Subject subject = new Subject(false, principals, new HashSet<Object>(), new HashSet<Object>()); ServerKeytabJaasConf conf = new ServerKeytabJaasConf(b.kerberosPrincipal, b.keytab.toString()); String confName = "NotUsed"; try { LoginContext loginContext = new LoginContext(confName, subject, null, conf); loginContext.login(); return loginContext.getSubject(); } catch (LoginException e) { throw new RuntimeException(e); } }
/** * Performs a Kerberos login given the {@code principal} and {@code keytab}. * * @return The {@code Subject} and {@code LoginContext} from the successful login. * @throws RuntimeException if the login failed */ Entry<LoginContext, Subject> performKerberosLogin() { // Loosely based on Apache Kerby's JaasKrbUtil class // Synchronized by the caller // Create a KerberosPrincipal given the principal. final Set<Principal> principals = new HashSet<Principal>(); principals.add(new KerberosPrincipal(principal)); final Subject subject = new Subject(false, principals, new HashSet<Object>(), new HashSet<Object>()); try { return login(null, jaasConf, subject); } catch (Exception e) { throw new RuntimeException("Failed to perform Kerberos login"); } }
/** * Performs a kerberos login, possibly logging out first. * * @param prevContext The LoginContext from the previous login, or null * @param conf JAAS Configuration object * @param subject The JAAS Subject * @return The context and subject from the login * @throws LoginException If the login failed. */ Entry<LoginContext, Subject> login(LoginContext prevContext, Configuration conf, Subject subject) throws LoginException { // Is synchronized by the caller // If a context was provided, perform a logout first if (null != prevContext) { prevContext.logout(); } // Create a LoginContext given the Configuration and Subject LoginContext loginContext = createLoginContext(conf); // Invoke the login loginContext.login(); // Get the Subject from the context and verify it's non-null (null would imply failure) Subject loggedInSubject = loginContext.getSubject(); if (null == loggedInSubject) { throw new RuntimeException("Failed to perform Kerberos login"); } // Send it back to the caller to use with launchRenewalThread return new AbstractMap.SimpleEntry<>(loginContext, loggedInSubject); }
@Override protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential) throws GeneralSecurityException, PreventedException { if (this.kerberosKdcSystemProperty != null) { logger.debug("Setting kerberos system property {} to {}", SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); System.setProperty(SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); } if (this.kerberosRealmSystemProperty != null) { logger.debug("Setting kerberos system property {} to {}", SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); System.setProperty(SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); } final String username = credential.getUsername(); final String password = getPasswordEncoder().encode(credential.getPassword()); final LoginContext lc = new LoginContext( this.realm, new UsernamePasswordCallbackHandler(username, password)); try { logger.debug("Attempting authentication for: {}", username); lc.login(); } finally { lc.logout(); } Principal principal = null; final Set<java.security.Principal> principals = lc.getSubject().getPrincipals(); if (principals != null && !principals.isEmpty()) { final java.security.Principal secPrincipal = principals.iterator().next(); principal = this.principalFactory.createPrincipal(secPrincipal.getName()); } return createHandlerResult(credential, principal, null); }
/** * {@inheritDoc} */ @Override protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential) throws GeneralSecurityException, PreventedException { if (this.kerberosKdcSystemProperty != null) { logger.debug("Setting kerberos system property {} to {}", SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); System.setProperty(SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); } if (this.kerberosRealmSystemProperty != null) { logger.debug("Setting kerberos system property {} to {}", SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); System.setProperty(SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); } final String username = credential.getUsername(); final String password = getPasswordEncoder().encode(credential.getPassword()); final LoginContext lc = new LoginContext( this.realm, new UsernamePasswordCallbackHandler(username, password)); try { logger.debug("Attempting authentication for: {}", username); lc.login(); } finally { lc.logout(); } Principal principal = null; final Set<java.security.Principal> principals = lc.getSubject().getPrincipals(); if (principals != null && principals.size() > 0) { principal = this.principalFactory.createPrincipal(principals.iterator().next().getName()); } return createHandlerResult(credential, principal, null); }
@Override protected HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential, final String originalPassword) throws GeneralSecurityException, PreventedException { if (this.kerberosKdcSystemProperty != null) { LOGGER.debug("Configured kerberos system property [{}] to [{}]", SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); System.setProperty(SYS_PROP_KERB5_KDC, this.kerberosKdcSystemProperty); } if (this.kerberosRealmSystemProperty != null) { LOGGER.debug("Setting kerberos system property [{}] to [{}]", SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); System.setProperty(SYS_PROP_KRB5_REALM, this.kerberosRealmSystemProperty); } final String username = credential.getUsername(); final String password = credential.getPassword(); final LoginContext lc = new LoginContext(this.realm, new UsernamePasswordCallbackHandler(username, password)); try { LOGGER.debug("Attempting authentication for: [{}]", username); lc.login(); } finally { lc.logout(); } Principal principal = null; final Set<java.security.Principal> principals = lc.getSubject().getPrincipals(); if (principals != null && !principals.isEmpty()) { final java.security.Principal secPrincipal = principals.iterator().next(); principal = this.principalFactory.createPrincipal(secPrincipal.getName()); } return createHandlerResult(credential, principal, null); }
/** * Log a user in from a keytab file. Loads a user identity from a keytab * 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 */ @InterfaceAudience.Public @InterfaceStability.Evolving public synchronized static void loginUserFromKeytab(String user, String path ) throws IOException { if (!isSecurityEnabled()) return; keytabFile = path; keytabPrincipal = user; Subject subject = new Subject(); LoginContext login; long start = 0; try { login = newLoginContext(HadoopConfiguration.KEYTAB_KERBEROS_CONFIG_NAME, subject, new HadoopConfiguration()); start = Time.now(); login.login(); metrics.loginSuccess.add(Time.now() - start); loginUser = new UserGroupInformation(subject); loginUser.setLogin(login); loginUser.setAuthenticationMethod(AuthenticationMethod.KERBEROS); } catch (LoginException le) { if (start > 0) { metrics.loginFailure.add(Time.now() - start); } throw new IOException("Login failure for " + user + " from keytab " + path+ ": " + le, le); } LOG.info("Login successful for user " + keytabPrincipal + " using keytab file " + keytabFile); }
/** * Log the current user out who previously logged in using keytab. * 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. */ @InterfaceAudience.Public @InterfaceStability.Evolving public void logoutUserFromKeytab() throws IOException { if (!isSecurityEnabled() || user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS) { return; } LoginContext login = getLogin(); if (login == null || keytabFile == null) { throw new IOException("loginUserFromKeytab must be done first"); } try { if (LOG.isDebugEnabled()) { LOG.debug("Initiating logout for " + getUserName()); } synchronized (UserGroupInformation.class) { login.logout(); } } catch (LoginException le) { throw new IOException("Logout failure for " + user + " from keytab " + keytabFile + ": " + le, le); } LOG.info("Logout successful for user " + keytabPrincipal + " using keytab file " + keytabFile); }
public User(String name, AuthenticationMethod authMethod, LoginContext login) { try { shortName = new HadoopKerberosName(name).getShortName(); } catch (IOException ioe) { throw new IllegalArgumentException("Illegal principal name " + name +": " + ioe.toString(), ioe); } fullName = name; this.authMethod = authMethod; this.login = login; }
@Test (timeout = 30000) public void testLoginObjectInSubject() throws Exception { UserGroupInformation loginUgi = UserGroupInformation.getLoginUser(); UserGroupInformation anotherUgi = new UserGroupInformation(loginUgi .getSubject()); LoginContext login1 = loginUgi.getSubject().getPrincipals(User.class) .iterator().next().getLogin(); LoginContext login2 = anotherUgi.getSubject().getPrincipals(User.class) .iterator().next().getLogin(); //login1 and login2 must be same instances Assert.assertTrue(login1 == login2); }
@Test (timeout = 30000) public void testLoginModuleCommit() throws Exception { UserGroupInformation loginUgi = UserGroupInformation.getLoginUser(); User user1 = loginUgi.getSubject().getPrincipals(User.class).iterator() .next(); LoginContext login = user1.getLogin(); login.logout(); login.login(); User user2 = loginUgi.getSubject().getPrincipals(User.class).iterator() .next(); // user1 and user2 must be same instances. Assert.assertTrue(user1 == user2); }
private synchronized LoginContext login(final String loginContextName) throws LoginException { if (loginContextName == null) { throw new LoginException("loginContext name (JAAS file section header) was null. " + "Please check your java.security.login.auth.config (=" + System.getProperty("java.security.login.auth.config") + ") and your " + ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY + "(=" + System.getProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "Client") + ")"); } LoginContext loginContext = new LoginContext(loginContextName,callbackHandler); loginContext.login(); LOG.info("successfully logged in."); return loginContext; }
@Override public void afterPropertiesSet() throws Exception { Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified"); LoginConfig loginConfig = new LoginConfig(this.servicePrincipal, this.debug, isInitiator); Set<Principal> princ = new HashSet<>(1); princ.add(new KerberosPrincipal(this.servicePrincipal)); Subject sub = new Subject(false, princ, new HashSet<>(), new HashSet<>()); final CallbackHandler handler = getUsernamePasswordHandler(servicePrincipal, password); LoginContext lc = new LoginContext("", sub, handler, loginConfig); lc.login(); this.serviceSubject = lc.getSubject(); }
private synchronized LoginContext login(final String loginContextName) throws LoginException { if (loginContextName == null) { throw new LoginException("loginContext name (JAAS file section header) was null. " + "Please check your java.security.login.auth.config (=" + System.getProperty("java.security.login.auth.config") + ") and your " + getLoginContextMessage()); } LoginContext loginContext = new LoginContext(loginContextName,callbackHandler); loginContext.login(); LOG.info("successfully logged in."); return loginContext; }
/** * Logout and log back in with the Kerberos identity. */ void renew() { try { // Lock on the instance of KerberosUtil synchronized (utilInstance) { Entry<LoginContext, Subject> pair = utilInstance.login(context, conf, subject); context = pair.getKey(); subject = pair.getValue(); } } catch (Exception e) { throw new RuntimeException("Failed to perform kerberos login"); } }