/*
* 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.ambari.logsearch.web.security;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.ambari.logsearch.common.ExternalServerClient;
import org.apache.ambari.logsearch.common.PropertiesHelper;
import org.apache.ambari.logsearch.conf.AuthPropsConfig;
import org.apache.ambari.logsearch.util.JSONUtil;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
/**
*
* Authentication provider to authenticate user from external-server using REST
* call
*/
@Named
public class LogsearchExternalServerAuthenticationProvider extends LogsearchAbstractAuthenticationProvider {
private static Logger LOG = Logger.getLogger(LogsearchExternalServerAuthenticationProvider.class);
private static final String ALLOWED_ROLE_PROP = "logsearch.roles.allowed";
private static enum PrivilegeInfo {
PERMISSION_LABEL("permission_label"),
PERMISSION_NAME("permission_name"),
PRINCIPAL_NAME("principal_name"),
PRINCIPAL_TYPE("principal_type"),
PRIVILEGE_ID("privilege_id"),
TYPE("type"),
USER_NAME("user_name");
private String propertyKey;
private PrivilegeInfo(String name) {
this.propertyKey = name;
}
public String toString() {
return propertyKey;
}
}
@Inject
private ExternalServerClient externalServerClient;
@Inject
private AuthPropsConfig authPropsConfig;
/**
* Authenticating user from external-server using REST call
*
* @param authentication the authentication request object.
* @return a fully authenticated object including credentials.
* @throws AuthenticationException if authentication fails.
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!authPropsConfig.isAuthExternalEnabled()) {
LOG.debug("external server auth is disabled.");
return authentication;
}
String username = authentication.getName();
String password = (String) authentication.getCredentials();
if (StringUtils.isBlank(username)) {
throw new BadCredentialsException("Username can't be null or empty.");
}
if (StringUtils.isBlank(password)) {
throw new BadCredentialsException("Password can't be null or empty.");
}
password = StringEscapeUtils.unescapeHtml(password);
username = StringEscapeUtils.unescapeHtml(username);
try {
String finalLoginUrl = authPropsConfig.getExternalAuthLoginUrl().replace("$USERNAME", username);
String responseObj = (String) externalServerClient.sendGETRequest(finalLoginUrl, String.class, username, password);
if (!isAllowedRole(responseObj)) {
LOG.error(username + " doesn't have permission");
throw new BadCredentialsException("Invalid User");
}
} catch (Exception e) {
LOG.error("Login failed for username :" + username + " Error :" + e.getLocalizedMessage());
throw new BadCredentialsException("Bad credentials");
}
authentication = new UsernamePasswordAuthenticationToken(username, password, getAuthorities());
return authentication;
}
/**
* Return true/false based on PEMISSION NAME return boolean
*/
private boolean isAllowedRole(String responseJson) {
String allowedRoleList[] = PropertiesHelper.getPropertyStringList(ALLOWED_ROLE_PROP);
List<String> values = new ArrayList<>();
JSONUtil.getValuesOfKey(responseJson, PrivilegeInfo.PERMISSION_NAME.toString(), values);
if (values.isEmpty()) {
return false;
}
if (allowedRoleList.length > 0 && responseJson != null) {
for (String allowedRole : allowedRoleList) {
for (String role : values) {
if (role.equals(allowedRole)) {
return true;
}
}
}
}
return false;
}
}