use of org.apache.druid.server.security.AuthenticationResult in project druid by druid-io.
the class DBCredentialsValidatorTest method validateMissingCredentials.
@Test
public void validateMissingCredentials() {
String authenticatorName = "basic";
String authorizerName = "basic";
String username = "userB";
String password = "helloworld";
AuthenticationResult result = validator.validateCredentials(authenticatorName, authorizerName, username, password.toCharArray());
Assert.assertNull(result);
}
use of org.apache.druid.server.security.AuthenticationResult in project druid by druid-io.
the class LDAPRoleProvider method getRoles.
@Override
public Set<String> getRoles(String authorizerPrefix, AuthenticationResult authenticationResult) {
Set<String> roleNames = new HashSet<>();
Map<String, BasicAuthorizerGroupMapping> groupMappingMap = cacheManager.getGroupMappingMap(authorizerPrefix);
if (groupMappingMap == null) {
throw new IAE("Could not load groupMappingMap for authorizer [%s]", authorizerPrefix);
}
Map<String, BasicAuthorizerUser> userMap = cacheManager.getUserMap(authorizerPrefix);
if (userMap == null) {
throw new IAE("Could not load userMap for authorizer [%s]", authorizerPrefix);
}
// Get the groups assigned to the LDAP user
SearchResult searchResult = Optional.ofNullable(authenticationResult.getContext()).map(contextMap -> contextMap.get(BasicAuthUtils.SEARCH_RESULT_CONTEXT_KEY)).map(p -> {
if (p instanceof SearchResult) {
return (SearchResult) p;
} else {
return null;
}
}).orElse(null);
if (searchResult != null) {
try {
Set<LdapName> groupNamesFromLdap = getGroupsFromLdap(searchResult);
if (groupNamesFromLdap.isEmpty()) {
LOG.debug("User %s is not mapped to any groups", authenticationResult.getIdentity());
} else {
// Get the roles mapped to LDAP groups from the metastore.
// This allows us to authorize groups LDAP user belongs
roleNames.addAll(getRoles(groupMappingMap, groupNamesFromLdap));
}
} catch (NamingException e) {
LOG.error(e, "Exception in looking up groups for user %s", authenticationResult.getIdentity());
}
}
// Get the roles assigned to LDAP user from the metastore.
// This allow us to authorize LDAP users regardless of whether they belong to any groups or not in LDAP.
BasicAuthorizerUser user = userMap.get(authenticationResult.getIdentity());
if (user != null) {
roleNames.addAll(user.getRoles());
}
return roleNames;
}
use of org.apache.druid.server.security.AuthenticationResult in project druid by druid-io.
the class KerberosAuthenticator method getFilter.
@Override
public Filter getFilter() {
return new AuthenticationFilter() {
private Signer mySigner;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ClassLoader prevLoader = Thread.currentThread().getContextClassLoader();
try {
// AuthenticationHandler is created during Authenticationfilter.init using reflection with thread context class loader.
// In case of druid since the class is actually loaded as an extension and filter init is done in main thread.
// We need to set the classloader explicitly to extension class loader.
Thread.currentThread().setContextClassLoader(AuthenticationFilter.class.getClassLoader());
super.init(filterConfig);
String configPrefix = filterConfig.getInitParameter(CONFIG_PREFIX);
configPrefix = (configPrefix != null) ? configPrefix + "." : "";
Properties config = getConfiguration(configPrefix, filterConfig);
String signatureSecret = config.getProperty(configPrefix + SIGNATURE_SECRET);
if (signatureSecret == null) {
signatureSecret = Long.toString(ThreadLocalRandom.current().nextLong());
log.warn("'signature.secret' configuration not set, using a random value as secret");
}
final byte[] secretBytes = StringUtils.toUtf8(signatureSecret);
SignerSecretProvider signerSecretProvider = new SignerSecretProvider() {
@Override
public void init(Properties config, ServletContext servletContext, long tokenValidity) {
}
@Override
public byte[] getCurrentSecret() {
return secretBytes;
}
@Override
public byte[][] getAllSecrets() {
return new byte[][] { secretBytes };
}
};
mySigner = new Signer(signerSecretProvider);
} finally {
Thread.currentThread().setContextClassLoader(prevLoader);
}
}
// Copied from hadoop-auth's AuthenticationFilter, to allow us to change error response handling in doFilterSuper
@Override
protected AuthenticationToken getToken(HttpServletRequest request) throws AuthenticationException {
AuthenticationToken token = null;
String tokenStr = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(AuthenticatedURL.AUTH_COOKIE)) {
tokenStr = cookie.getValue();
try {
tokenStr = mySigner.verifyAndExtract(tokenStr);
} catch (SignerException ex) {
throw new AuthenticationException(ex);
}
break;
}
}
}
if (tokenStr != null) {
token = AuthenticationToken.parse(tokenStr);
if (!token.getType().equals(getAuthenticationHandler().getType())) {
throw new AuthenticationException("Invalid AuthenticationToken type");
}
if (token.isExpired()) {
throw new AuthenticationException("AuthenticationToken expired");
}
}
return token;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
// If there's already an auth result, then we have authenticated already, skip this.
if (request.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT) != null) {
filterChain.doFilter(request, response);
return;
}
// some other Authenticator didn't already validate this request.
if (loginContext == null) {
initializeKerberosLogin();
}
// Run the original doFilter method, but with modifications to error handling
doFilterSuper(request, response, filterChain);
}
/**
* Copied from hadoop-auth 2.7.3 AuthenticationFilter, to allow us to change error response handling.
* Specifically, we want to defer the sending of 401 Unauthorized so that other Authenticators later in the chain
* can check the request.
*/
private void doFilterSuper(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
boolean unauthorizedResponse = true;
int errCode = HttpServletResponse.SC_UNAUTHORIZED;
AuthenticationException authenticationEx = null;
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
boolean isHttps = "https".equals(httpRequest.getScheme());
try {
boolean newToken = false;
AuthenticationToken token;
try {
token = getToken(httpRequest);
} catch (AuthenticationException ex) {
log.warn("AuthenticationToken ignored: " + ex.getMessage());
// will be sent back in a 401 unless filter authenticates
authenticationEx = ex;
token = null;
}
if (getAuthenticationHandler().managementOperation(token, httpRequest, httpResponse)) {
if (token == null) {
if (log.isDebugEnabled()) {
log.debug("Request [{%s}] triggering authentication", getRequestURL(httpRequest));
}
token = getAuthenticationHandler().authenticate(httpRequest, httpResponse);
if (token != null && token.getExpires() != 0 && token != AuthenticationToken.ANONYMOUS) {
token.setExpires(System.currentTimeMillis() + getValidity() * 1000);
}
newToken = true;
}
if (token != null) {
unauthorizedResponse = false;
if (log.isDebugEnabled()) {
log.debug("Request [{%s}] user [{%s}] authenticated", getRequestURL(httpRequest), token.getUserName());
}
final AuthenticationToken authToken = token;
httpRequest = new HttpServletRequestWrapper(httpRequest) {
@Override
public String getAuthType() {
return authToken.getType();
}
@Override
public String getRemoteUser() {
return authToken.getUserName();
}
@Override
public Principal getUserPrincipal() {
return (authToken != AuthenticationToken.ANONYMOUS) ? authToken : null;
}
};
if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) {
String signedToken = mySigner.sign(token.toString());
tokenToAuthCookie(httpResponse, signedToken, getCookieDomain(), getCookiePath(), token.getExpires(), !token.isExpired() && token.getExpires() > 0, isHttps);
request.setAttribute(SIGNED_TOKEN_ATTRIBUTE, tokenToCookieString(signedToken, getCookieDomain(), getCookiePath(), token.getExpires(), !token.isExpired() && token.getExpires() > 0, isHttps));
}
// Since this request is validated also set DRUID_AUTHENTICATION_RESULT
request.setAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT, new AuthenticationResult(token.getName(), authorizerName, name, null));
doFilter(filterChain, httpRequest, httpResponse);
}
} else {
unauthorizedResponse = false;
}
} catch (AuthenticationException ex) {
// exception from the filter itself is fatal
errCode = HttpServletResponse.SC_FORBIDDEN;
authenticationEx = ex;
if (log.isDebugEnabled()) {
log.debug(ex, "Authentication exception: " + ex.getMessage());
} else {
log.warn("Authentication exception: " + ex.getMessage());
}
}
if (unauthorizedResponse) {
if (!httpResponse.isCommitted()) {
tokenToAuthCookie(httpResponse, "", getCookieDomain(), getCookiePath(), 0, false, isHttps);
// present.. reset to 403 if not found..
if ((errCode == HttpServletResponse.SC_UNAUTHORIZED) && (!httpResponse.containsHeader(org.apache.hadoop.security.authentication.client.KerberosAuthenticator.WWW_AUTHENTICATE))) {
errCode = HttpServletResponse.SC_FORBIDDEN;
}
if (authenticationEx == null) {
// Don't send an error response here, unlike the base AuthenticationFilter implementation.
// This request did not use Kerberos auth.
// Instead, we will send an error response in PreResponseAuthorizationCheckFilter to allow
// other Authenticator implementations to check the request.
filterChain.doFilter(request, response);
} else {
// Do send an error response here, we attempted Kerberos authentication and failed.
httpResponse.sendError(errCode, authenticationEx.getMessage());
}
}
}
}
};
}
use of org.apache.druid.server.security.AuthenticationResult in project druid by druid-io.
the class OverlordTest method setUp.
@Before
public void setUp() throws Exception {
req = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_ALLOW_UNSECURED_PATH)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED)).andReturn(null).anyTimes();
EasyMock.expect(req.getAttribute(AuthConfig.DRUID_AUTHENTICATION_RESULT)).andReturn(new AuthenticationResult("druid", "druid", null, null)).anyTimes();
req.setAttribute(AuthConfig.DRUID_AUTHORIZATION_CHECKED, true);
EasyMock.expectLastCall().anyTimes();
supervisorManager = EasyMock.createMock(SupervisorManager.class);
taskLockbox = EasyMock.createStrictMock(TaskLockbox.class);
taskLockbox.syncFromStorage();
EasyMock.expectLastCall().atLeastOnce();
taskLockbox.add(EasyMock.anyObject());
EasyMock.expectLastCall().atLeastOnce();
taskLockbox.remove(EasyMock.anyObject());
EasyMock.expectLastCall().atLeastOnce();
// for second Noop Task directly added to deep storage.
taskLockbox.add(EasyMock.anyObject());
EasyMock.expectLastCall().atLeastOnce();
taskLockbox.remove(EasyMock.anyObject());
EasyMock.expectLastCall().atLeastOnce();
taskActionClientFactory = EasyMock.createStrictMock(TaskActionClientFactory.class);
EasyMock.expect(taskActionClientFactory.create(EasyMock.anyObject())).andReturn(null).anyTimes();
EasyMock.replay(taskLockbox, taskActionClientFactory, req);
taskStorage = new HeapMemoryTaskStorage(new TaskStorageConfig(null));
runTaskCountDownLatches = new CountDownLatch[2];
runTaskCountDownLatches[0] = new CountDownLatch(1);
runTaskCountDownLatches[1] = new CountDownLatch(1);
taskCompletionCountDownLatches = new CountDownLatch[2];
taskCompletionCountDownLatches[0] = new CountDownLatch(1);
taskCompletionCountDownLatches[1] = new CountDownLatch(1);
announcementLatch = new CountDownLatch(1);
setupServerAndCurator();
curator.start();
curator.blockUntilConnected();
druidNode = new DruidNode("hey", "what", false, 1234, null, true, false);
ServiceEmitter serviceEmitter = new NoopServiceEmitter();
taskMaster = new TaskMaster(new TaskLockConfig(), new TaskQueueConfig(null, new Period(1), null, new Period(10)), new DefaultTaskConfig(), taskLockbox, taskStorage, taskActionClientFactory, druidNode, new TaskRunnerFactory<MockTaskRunner>() {
@Override
public MockTaskRunner build() {
return new MockTaskRunner(runTaskCountDownLatches, taskCompletionCountDownLatches);
}
}, new NoopServiceAnnouncer() {
@Override
public void announce(DruidNode node) {
announcementLatch.countDown();
}
}, new CoordinatorOverlordServiceConfig(null, null), serviceEmitter, supervisorManager, EasyMock.createNiceMock(OverlordHelperManager.class), new TestDruidLeaderSelector());
EmittingLogger.registerEmitter(serviceEmitter);
}
use of org.apache.druid.server.security.AuthenticationResult in project druid by druid-io.
the class MetadataStoreCredentialsValidator method validateCredentials.
@Override
@Nullable
public AuthenticationResult validateCredentials(String authenticatorName, String authorizerName, String username, char[] password) {
Map<String, BasicAuthenticatorUser> userMap = cacheManager.get().getUserMap(authenticatorName);
if (userMap == null) {
throw new IAE("No userMap is available for authenticator with prefix: [%s]", authenticatorName);
}
BasicAuthenticatorUser user = userMap.get(username);
if (user == null) {
return null;
}
BasicAuthenticatorCredentials credentials = user.getCredentials();
if (credentials == null) {
return null;
}
byte[] recalculatedHash = BasicAuthUtils.hashPassword(password, credentials.getSalt(), credentials.getIterations());
if (Arrays.equals(recalculatedHash, credentials.getHash())) {
return new AuthenticationResult(username, authorizerName, authenticatorName, null);
} else {
LOG.debug("Password incorrect for metadata store user %s", username);
throw new BasicSecurityAuthenticationException("User metadata store authentication failed.");
}
}
Aggregations