@SuppressWarnings("unchecked") @Override public void configure(Map<String, ?> configs, String saslMechanism, List<AppConfigurationEntry> jaasConfigEntries) { if (!OAuthBearerLoginModule.OAUTHBEARER_MECHANISM.equals(saslMechanism)) throw new IllegalArgumentException(String.format("Unexpected SASL mechanism: %s", saslMechanism)); if (Objects.requireNonNull(jaasConfigEntries).size() != 1 || jaasConfigEntries.get(0) == null) throw new IllegalArgumentException( String.format("Must supply exactly 1 non-null JAAS mechanism configuration (size was %d)", jaasConfigEntries.size())); this.moduleOptions = Collections.unmodifiableMap((Map<String, String>) jaasConfigEntries.get(0).getOptions()); configured = true; }
@SuppressWarnings("unchecked") @Override public void configure(Map<String, ?> configs, String saslMechanism, List<AppConfigurationEntry> jaasConfigEntries) { if (!OAuthBearerLoginModule.OAUTHBEARER_MECHANISM.equals(saslMechanism)) throw new IllegalArgumentException(String.format("Unexpected SASL mechanism: %s", saslMechanism)); if (Objects.requireNonNull(jaasConfigEntries).size() != 1 || jaasConfigEntries.get(0) == null) throw new IllegalArgumentException( String.format("Must supply exactly 1 non-null JAAS mechanism configuration (size was %d)", jaasConfigEntries.size())); final Map<String, String> unmodifiableModuleOptions = Collections .unmodifiableMap((Map<String, String>) jaasConfigEntries.get(0).getOptions()); this.moduleOptions = unmodifiableModuleOptions; configured = true; }
/** * Returns the configuration option for <code>key</code> from this context. * If login module name is specified, return option value only from that module. */ public static String configEntryOption(List<AppConfigurationEntry> configurationEntries, String key, String loginModuleName) { for (AppConfigurationEntry entry : configurationEntries) { if (loginModuleName != null && !loginModuleName.equals(entry.getLoginModuleName())) continue; Object val = entry.getOptions().get(key); if (val != null) return (String) val; } return null; }
public static String get(Configuration configuration, String section, String key) throws IOException { AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(section); if (configurationEntries == null) { String errorMessage = "Could not find a '" + section + "' entry in this configuration."; throw new IOException(errorMessage); } for (AppConfigurationEntry entry : configurationEntries) { Object val = entry.getOptions().get(key); if (val != null) return (String) val; } return null; } }
/** * Constructor based on a JAAS configuration * * For digest, you should have a pair of user name and password defined. * * @param configuration * @throws IOException */ public ClientCallbackHandler(Configuration configuration) throws IOException { if (configuration == null) return; AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT); if (configurationEntries == null) { String errorMessage = "Could not find a '" + AuthUtils.LOGIN_CONTEXT_CLIENT + "' entry in this configuration: Client cannot start."; throw new IOException(errorMessage); } _password = ""; for (AppConfigurationEntry entry : configurationEntries) { if (entry.getOptions().get(USERNAME) != null) { _username = (String) entry.getOptions().get(USERNAME); } if (entry.getOptions().get(PASSWORD) != null) { _password = (String) entry.getOptions().get(PASSWORD); } } }
/** * Pull a set of keys out of a Configuration. * * @param configuration The config to pull the key/value pairs out of. * @param section The app configuration entry name to get stuff from. * @return Return a map of the configs in conf. */ public static SortedMap<String, ?> pullConfig(Configuration configuration, String section) throws IOException { AppConfigurationEntry[] configurationEntries = ClientAuthUtils.getEntries(configuration, section); if (configurationEntries == null) { return null; } TreeMap<String, Object> results = new TreeMap<>(); for (AppConfigurationEntry entry : configurationEntries) { Map<String, ?> options = entry.getOptions(); for (String key : options.keySet()) { results.put(key, options.get(key)); } } return results; }
/** * Pull a the value given section and key from Configuration * * @param configuration The config to pull the key/value pairs out of. * @param section The app configuration entry name to get stuff from. * @param key The key to look up inside of the section * @return Return a the String value of the configuration value */ public static String get(Configuration configuration, String section, String key) throws IOException { AppConfigurationEntry[] configurationEntries = ClientAuthUtils.getEntries(configuration, section); if (configurationEntries == null) { return null; } for (AppConfigurationEntry entry : configurationEntries) { Object val = entry.getOptions().get(key); if (val != null) { return (String) val; } } return null; }
public SaslServerCallbackHandler(Configuration configuration) throws IOException { String serverSection = System.getProperty( ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, ZooKeeperSaslServer.DEFAULT_LOGIN_CONTEXT_NAME); AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(serverSection); if (configurationEntries == null) { String errorMessage = "Could not find a '" + serverSection + "' entry in this configuration: Server cannot start."; LOG.error(errorMessage); throw new IOException(errorMessage); } credentials.clear(); for(AppConfigurationEntry entry: configurationEntries) { Map<String,?> options = entry.getOptions(); // Populate DIGEST-MD5 user -> password map with JAAS configuration entries from the "Server" section. // Usernames are distinguished from other options by prefixing the username with a "user_" prefix. for(Map.Entry<String, ?> pair : options.entrySet()) { String key = pair.getKey(); if (key.startsWith(USER_PREFIX)) { String userName = key.substring(USER_PREFIX.length()); credentials.put(userName,(String)pair.getValue()); } } } }
public SaslQuorumServerCallbackHandler(Configuration configuration, String serverSection, Set<String> authzHosts) throws IOException { AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(serverSection); if (configurationEntries == null) { String errorMessage = "Could not find a '" + serverSection + "' entry in this configuration: Server cannot start."; LOG.error(errorMessage); throw new IOException(errorMessage); } credentials.clear(); for(AppConfigurationEntry entry: configurationEntries) { Map<String,?> options = entry.getOptions(); // Populate DIGEST-MD5 user -> password map with JAAS configuration entries from the "QuorumServer" section. // Usernames are distinguished from other options by prefixing the username with a "user_" prefix. for(Map.Entry<String, ?> pair : options.entrySet()) { String key = pair.getKey(); if (key.startsWith(USER_PREFIX)) { String userName = key.substring(USER_PREFIX.length()); credentials.put(userName,(String)pair.getValue()); } } } // authorized host lists this.authzHosts = authzHosts; }
public ServerCallbackHandler(Configuration configuration) throws IOException { if (configuration == null) return; AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_SERVER); if (configurationEntries == null) { String errorMessage = "Could not find a '" + AuthUtils.LOGIN_CONTEXT_SERVER + "' entry in this configuration: Server cannot start."; throw new IOException(errorMessage); } credentials.clear(); for (AppConfigurationEntry entry : configurationEntries) { Map<String, ?> options = entry.getOptions(); // Populate DIGEST-MD5 user -> password map with JAAS configuration entries from the "Server" section. // Usernames are distinguished from other options by prefixing the username with a "user_" prefix. for (Map.Entry<String, ?> pair : options.entrySet()) { String key = pair.getKey(); if (key.startsWith(USER_PREFIX)) { String userName = key.substring(USER_PREFIX.length()); credentials.put(userName, (String) pair.getValue()); } } } }
Map<String, ?> options = entry.getOptions();
public SaslQuorumServerCallbackHandler(Configuration configuration, String serverSection, Set<String> authzHosts) throws IOException { AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(serverSection); if (configurationEntries == null) { String errorMessage = "Could not find a '" + serverSection + "' entry in this configuration: Server cannot start."; LOG.error(errorMessage); throw new IOException(errorMessage); } credentials.clear(); for(AppConfigurationEntry entry: configurationEntries) { Map<String,?> options = entry.getOptions(); // Populate DIGEST-MD5 user -> password map with JAAS configuration entries from the "QuorumServer" section. // Usernames are distinguished from other options by prefixing the username with a "user_" prefix. for(Map.Entry<String, ?> pair : options.entrySet()) { String key = pair.getKey(); if (key.startsWith(USER_PREFIX)) { String userName = key.substring(USER_PREFIX.length()); credentials.put(userName,(String)pair.getValue()); } } } // authorized host lists this.authzHosts = authzHosts; }
public SaslServerCallbackHandler(Configuration configuration) throws IOException { String serverSection = System.getProperty( ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, ZooKeeperSaslServer.DEFAULT_LOGIN_CONTEXT_NAME); AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(serverSection); if (configurationEntries == null) { String errorMessage = "Could not find a '" + serverSection + "' entry in this configuration: Server cannot start."; LOG.error(errorMessage); throw new IOException(errorMessage); } credentials.clear(); for(AppConfigurationEntry entry: configurationEntries) { Map<String,?> options = entry.getOptions(); // Populate DIGEST-MD5 user -> password map with JAAS configuration entries from the "Server" section. // Usernames are distinguished from other options by prefixing the username with a "user_" prefix. for(Map.Entry<String, ?> pair : options.entrySet()) { String key = pair.getKey(); if (key.startsWith(USER_PREFIX)) { String userName = key.substring(USER_PREFIX.length()); credentials.put(userName,(String)pair.getValue()); } } } }
if (entry.getOptions().get("useTicketCache") != null) { String val = (String) entry.getOptions().get("useTicketCache"); isUsingTicketCache = val.equals("true"); } else isUsingTicketCache = false; if (entry.getOptions().get("principal") != null) principal = (String) entry.getOptions().get("principal"); else principal = null;
@Test public void getNonExistentSectionTest() throws IOException { Map<String, String> optionMap = new HashMap<String, String>(); AppConfigurationEntry entry = Mockito.mock(AppConfigurationEntry.class); Mockito.<Map<String, ?>>when(entry.getOptions()).thenReturn(optionMap); String section = "bogus-section"; Configuration mockConfig = Mockito.mock(Configuration.class); Mockito.when(mockConfig.getAppConfigurationEntry(section)) .thenReturn(new AppConfigurationEntry[]{ entry }); Assert.assertNull( ClientAuthUtils.get(mockConfig, section, "nonexistent-key")); }
String password = ""; for (AppConfigurationEntry entry : configurationEntries) { Map options = entry.getOptions(); username = (String) options.getOrDefault("username", username); password = (String) options.getOrDefault("password", password);
@Test public void getFirstValueForValidKeyTest() throws IOException { String k = "the-key"; String expected = "good-value"; Map<String, String> optionMap = new HashMap<String, String>(); optionMap.put(k, expected); Map<String, String> badOptionMap = new HashMap<String, String>(); badOptionMap.put(k, "bad-value"); AppConfigurationEntry emptyEntry = Mockito.mock(AppConfigurationEntry.class); AppConfigurationEntry badEntry = Mockito.mock(AppConfigurationEntry.class); AppConfigurationEntry goodEntry = Mockito.mock(AppConfigurationEntry.class); Mockito.<Map<String, ?>>when(emptyEntry.getOptions()).thenReturn(new HashMap<String, String>()); Mockito.<Map<String, ?>>when(badEntry.getOptions()).thenReturn(badOptionMap); Mockito.<Map<String, ?>>when(goodEntry.getOptions()).thenReturn(optionMap); String section = "bogus-section"; Configuration mockConfig = Mockito.mock(Configuration.class); Mockito.when(mockConfig.getAppConfigurationEntry(section)) .thenReturn(new AppConfigurationEntry[]{ emptyEntry, goodEntry, badEntry }); Assert.assertEquals( ClientAuthUtils.get(mockConfig, section, k), expected); }
@Test public void makeDigestPayloadTest() throws NoSuchAlgorithmException { String section = "user-pass-section"; Map<String, String> optionMap = new HashMap<String, String>(); String user = "user"; String pass = "pass"; optionMap.put("username", user); optionMap.put("password", pass); AppConfigurationEntry entry = Mockito.mock(AppConfigurationEntry.class); Mockito.<Map<String, ?>>when(entry.getOptions()).thenReturn(optionMap); Configuration mockConfig = Mockito.mock(Configuration.class); Mockito.when(mockConfig.getAppConfigurationEntry(section)) .thenReturn(new AppConfigurationEntry[]{ entry }); MessageDigest digest = MessageDigest.getInstance("SHA-512"); byte[] output = digest.digest((user + ":" + pass).getBytes()); String sha = Hex.encodeHexString(output); // previous code used this method to generate the string, ensure the two match StringBuilder builder = new StringBuilder(); for (byte b : output) { builder.append(String.format("%02x", b)); } String stringFormatMethod = builder.toString(); Assert.assertEquals( ClientAuthUtils.makeDigestPayload(mockConfig, "user-pass-section"), sha); Assert.assertEquals(sha, stringFormatMethod); }
for (int i = 0; i < moduleCount; i++) { AppConfigurationEntry staticEntry = staticEntries[i]; checkEntry(staticEntry, dynamicEntries[i].getLoginModuleName(), LoginModuleControlFlag.REQUIRED, dynamicEntries[i].getOptions());
private void checkEntry(AppConfigurationEntry entry, String loginModule, LoginModuleControlFlag controlFlag, Map<String, ?> options) { assertEquals(loginModule, entry.getLoginModuleName()); assertEquals(controlFlag, entry.getControlFlag()); assertEquals(options, entry.getOptions()); }