Commit f7146ede by Shwetha GS

ATLAS-494 UI Authentication (nixonrodrigues via shwethags)

parent 2824f15a
/*
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.
*/
/* Generic */
body {
font-family: 'Raleway', sans-serif;
background-color: #f6f7fb;
color: #686868;
}
a {
color: #359f89;
}
header {
background-color: #fff;
border-bottom: 1px #e7e8ed solid;
}
textarea:focus, button:focus {
outline: none !important;
}
textarea {
resize: none;
}
/* Bootstrap Extended */
.form-control:focus {
box-shadow: none;
}
.breadcrumb {
padding: 8px 25px;
background-color: transparent;
margin-bottom: 0px;
font-weight: 600;
line-height: 44px;
}
.breadcrumb>li+li:before {
padding: 0 10px;
font-family: FontAwesome;
color: #686868;
content: "\f105";
}
.well {
background-color: #f6f7fa;
border: 1px solid #e8e9ef;
}
/* Header */
.main-search .form-control {
border: none;
border-left: 1px #e7e8ed solid;
border-radius: 0px;
box-shadow: none;
height: 60px;
font-size: 18px;
font-style: italic;
-webkit-font-smoothing: antialiased;
}
.main-search .input-group-addon {
font-size: 20px;
color: #b5b9bc;
background: none;
border: none;
}
.page-title {
background-color: #fff;
padding: 50px;
}
.page-title h1 {
margin-top: 0px;
margin-bottom: 20px;
font-weight: 600;
-webkit-font-smoothing: antialiased;
}
.page-title h1 small {
position: relative;
bottom: 5px;
margin-left: 15px;
padding-left: 15px;
border-left: 1px #e8e9ef solid;
color: #b4b7bc;
font-size: 40%;
font-weight: 600;
text-transform: uppercase;
}
.page-title .sub-title {
margin-bottom: 40px;
}
/* Atlas Specific */
.atlast-tabbable {
margin: 50px 0px;
}
.atlast-tabbable .nav-tabs {
border-bottom: 1px solid #e8e9ee;
}
.atlast-tabbable .nav-tabs>li>a {
padding: 15px 30px;
text-transform: uppercase;
letter-spacing: 1px;
border-radius: 2px 2px 0 0;
}
.atlast-tabbable .nav-tabs>li.active>a, .atlast-tabbable .nav-tabs>li.active>a:focus,
.atlast-tabbable .nav-tabs>li.active>a:hover {
border: 1px solid #e8e9ee;
border-bottom-color: transparent;
}
.atlast-tabbable .tab-content {
background-color: #fff;
padding: 35px;
border: 1px solid #e8e9ee;
border-top: none;
}
.btn-atlas {
padding: 10px 20px;
background-color: #fff;
color: #37bb9b;
border: 1px #37bb9b solid;
border-radius: 4px;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
transition: all .3s ease;
}
.btn-atlas:hover {
background-color: #37bb9b;
color: #fff;
}
.atlas-tag {
padding: 6px 12px;
background-color: #4a90e2;
color: #fff;
font-size: 12px;
text-transform: uppercase;
border-radius: 4px;
}
.atlas-tag i.fa {
position: relative;
right: -5px;
cursor: pointer;
}
.btn-tag {
color: #4a90e2;
border: 1px #4a90e2 solid;
background-color: #fff;
border-radius: 4px;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
transition: all .3s ease;
}
/* Login Page */
.login-pane {
margin-top: 50px;
background: #323544;
color: #eee;
padding: 15px;
border-radius: 5px;
}
.login-pane h2 {
margin-bottom: 40px;
}
.login-pane .input-group {
margin: 20px 0px;
}
.login-pane .form-control, .login-pane .input-group-addon {
background-color: transparent;
border-radius: 0px;
}
.login-pane .form-control {
border-left: none;
color: #eee;
}
.login-pane .form-control:focus {
border-color: #CCC;
}
.login-pane .input-group-addon {
border-right: none;
color: #ccc;
}
.login-pane .form-control:focus+.input-group-addon {
border-color: #66afe9;
}
.login-pane .btn-atlas {
background-color: #37bb9b;
color: #fff;
}
.btn-tag:hover {
color: #fff;
background-color: #4a90e2;
}
/* Login Page */
.login-pane {
margin-top: 35%;
background: #323544;
color: #eee;
padding: 15px;
border-radius: 5px;
}
.login-pane h2 {
margin-bottom: 40px;
}
.login-pane .input-group {
margin: 20px 0px;
}
.login-pane .form-control, .login-pane .input-group-addon {
background-color: transparent;
border-radius: 0px;
}
.login-pane .form-control {
border-left: none;
color: #eee;
}
.login-pane .form-control:focus {
border-color: #CCC;
}
.login-pane .input-group-addon {
border-right: none;
color: #ccc;
}
.login-pane .form-control:focus+.input-group-addon {
border-color: #66afe9;
}
.login-pane .btn-atlas {
background-color: #37bb9b;
color: #fff;
}
.errorBox {
position: absolute;
right: 36px;
display: none;
top: 26px;
width: 251px;
}
.errorBox .alert {
box-shadow: 4px 3px 8px -2px gray;
}
.close {
padding: 6px;
font-size: 15px;
}
\ No newline at end of file
......@@ -42,6 +42,9 @@
<li data-ui-sref-active="active">
<a ng-if="!username" class="menu-link" href="javascript:void(0)" ng-click="showAbout()">About</a>
</li>
<li data-ui-sref-active="active">
<a ng-if="!username" class="menu-link" href="/logout.html">Logout</a>
</li>
</ul>
</nav>
</div>
\ No newline at end of file
</div>
......@@ -114,3 +114,11 @@ atlas.server.ha.enabled=false
## if ACLs need to be set on the created nodes, uncomment these lines and set the values ##
#atlas.server.ha.zookeeper.acl=<scheme>:<id>
#atlas.server.ha.zookeeper.auth=<scheme>:<authinfo>
#### atlas.login.method {FILE,LDAP,AD} ####
atlas.login.method=FILE
### File path of users-credentials
atlas.login.credentials.file=${sys:atlas.home}/conf/users-credentials.properties
#username=password
admin=admin
user=user123
......@@ -356,7 +356,10 @@
<guava.version>14.0</guava.version>
<fastutil.version>6.5.16</fastutil.version>
<guice.version>4.0</guice.version>
<spring.version>3.1.3.RELEASE</spring.version>
<spring.security.version>3.1.3.RELEASE</spring.security.version>
<spring-ldap-core.version>1.3.1.RELEASE</spring-ldap-core.version>
<javax.servlet.version>3.1.0</javax.servlet.version>
<!-- Needed for hooks -->
<aopalliance.version>1.0</aopalliance.version>
<commons-conf.version>1.10</commons-conf.version>
......@@ -1626,6 +1629,7 @@
<exclude>*.json</exclude>
<exclude>**/overlays/**</exclude>
<exclude>dev-support/**</exclude>
<exclude>**/users-credentials.properties</exclude>
<exclude>**/public/css/animate.min.css</exclude>
<exclude>**/public/css/fonts/**</exclude>
<exclude>**/public/css/font-awesome.min.css</exclude>
......
......@@ -3,6 +3,7 @@ Apache Atlas Release Notes
--trunk - unreleased
INCOMPATIBLE CHANGES:
ATLAS-494 UI Authentication (nixonrodrigues via shwethags)
ATLAS-621 Introduce entity state in Id object (shwethags)
ATLAS-474 Server does not start if the type is updated with same super type class information (dkantor via shwethags)
ATLAS-479 Add description for different types during create time (guptaneeru via shwethags)
......
......@@ -231,6 +231,58 @@
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>${spring-ldap-core.version}</version>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-dashboard</artifactId>
<type>war</type>
......
/*
* 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.atlas.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class PropertiesUtil extends PropertyPlaceholderConfigurer {
private static Map<String, String> propertiesMap = new HashMap<String, String>();
private static Logger logger = Logger.getLogger(PropertiesUtil.class);
protected List<String> xmlPropertyConfigurer = new ArrayList<String>();
private PropertiesUtil() {
}
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
Properties sysProps = System.getProperties();
if (sysProps != null) {
for (String key : sysProps.stringPropertyNames()) {
String value = sysProps.getProperty(key);
if (value != null) {
value = value.trim();
}
propertiesMap.put(key, value);
}
}
Set<Object> keySet = props.keySet();
for (Object key : keySet) {
String keyStr = key.toString();
propertiesMap.put(keyStr, props.getProperty(keyStr).trim());
}
super.processProperties(beanFactory, props);
}
public static String getProperty(String key, String defaultValue) {
if (key == null) {
return null;
}
String rtrnVal = propertiesMap.get(key);
if (rtrnVal == null) {
rtrnVal = defaultValue;
}
return rtrnVal;
}
public static String getProperty(String key) {
if (key == null) {
return null;
}
return propertiesMap.get(key);
}
public static String[] getPropertyStringList(String key) {
if (key == null) {
return null;
}
String value = propertiesMap.get(key);
if (value != null) {
String[] splitValues = value.split(",");
String[] returnValues = new String[splitValues.length];
for (int i = 0; i < splitValues.length; i++) {
returnValues[i] = splitValues[i].trim();
}
return returnValues;
} else {
return new String[0];
}
}
public static Integer getIntProperty(String key, int defaultValue) {
if (key == null) {
return null;
}
String rtrnVal = propertiesMap.get(key);
if (rtrnVal == null) {
return defaultValue;
}
return Integer.valueOf(rtrnVal);
}
public static Integer getIntProperty(String key) {
if (key == null) {
return null;
}
String rtrnVal = propertiesMap.get(key);
if (rtrnVal == null) {
return null;
}
return Integer.valueOf(rtrnVal);
}
public static boolean getBooleanProperty(String key, boolean defaultValue) {
if (key == null) {
return defaultValue;
}
String value = getProperty(key);
if (value == null) {
return defaultValue;
}
return Boolean.parseBoolean(value);
}
}
\ No newline at end of file
/*
* 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.atlas.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.springframework.util.DefaultPropertiesPersister;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XMLPropertiesUtil extends DefaultPropertiesPersister {
private static Logger logger = Logger.getLogger(XMLPropertiesUtil.class);
public XMLPropertiesUtil() {
}
@Override
public void loadFromXml(Properties properties, InputStream inputStream)
throws IOException {
try {
DocumentBuilderFactory xmlDocumentBuilderFactory = DocumentBuilderFactory
.newInstance();
xmlDocumentBuilderFactory.setIgnoringComments(true);
xmlDocumentBuilderFactory.setNamespaceAware(true);
DocumentBuilder xmlDocumentBuilder = xmlDocumentBuilderFactory
.newDocumentBuilder();
Document xmlDocument = xmlDocumentBuilder.parse(inputStream);
xmlDocument.getDocumentElement().normalize();
NodeList nList = xmlDocument.getElementsByTagName("property");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
String propertyName = "";
String propertyValue = "";
if (eElement.getElementsByTagName("name").item(0) != null) {
propertyName = eElement.getElementsByTagName("name")
.item(0).getTextContent().trim();
}
if (eElement.getElementsByTagName("value").item(0) != null) {
propertyValue = eElement.getElementsByTagName("value")
.item(0).getTextContent().trim();
}
properties.put(propertyName, propertyValue);
}
}
} catch (Exception e) {
logger.error("Error loading : ", e);
}
}
}
\ No newline at end of file
/*
* 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.atlas.web.dao;
import com.google.common.annotations.VisibleForTesting;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.web.model.User;
import org.apache.commons.configuration.Configuration;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@Repository
public class UserDao {
private static final Logger LOG = LoggerFactory.getLogger(UserDao.class);
private Properties userLogins;
@PostConstruct
public void init() {
loadFileLoginsDetails();
}
void loadFileLoginsDetails() {
String PROPERTY_FILE_PATH = null;
try {
Configuration configuration = ApplicationProperties.get();
PROPERTY_FILE_PATH = configuration
.getString("atlas.login.credentials.file");
if (PROPERTY_FILE_PATH != null && !"".equals(PROPERTY_FILE_PATH)) {
userLogins = new Properties();
userLogins.load(new FileInputStream(PROPERTY_FILE_PATH));
}else {
LOG.error("Error while reading user.properties file, filepath="
+ PROPERTY_FILE_PATH);
}
} catch (IOException | AtlasException e) {
LOG.error("Error while reading user.properties file, filepath="
+ PROPERTY_FILE_PATH, e);
}
}
public User loadUserByUsername(final String username)
throws UsernameNotFoundException {
String password = userLogins.getProperty(username);
if (password == null || password.isEmpty()) {
throw new UsernameNotFoundException("Username not found."
+ username);
}
User user = new User();
user.setUsername(username);
user.setPassword(password);
return user;
}
@VisibleForTesting
public void setUserLogins(Properties userLogins) {
this.userLogins = userLogins;
}
}
/*
* 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.atlas.web.filters;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.atlas.Atlas;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
@SuppressWarnings("deprecation")
class AtlasAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
private static final Logger LOG = LoggerFactory.getLogger(Atlas.class);
private String loginPath = "/login.jsp";
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
LOG.debug("redirecting to login page loginPath" + loginPath);
response.sendRedirect(loginPath);
}
}
/*
* 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 compliRance 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.atlas.web.model;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class User implements UserDetails {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private List<GrantedAuthority> authorities;
private boolean accountNonExpired = true;
private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true;
private boolean enabled = true;
public User(String userName2, String userPassword,
List<GrantedAuthority> grantedAuths) {
this.username = userName2;
this.password = userPassword;
this.authorities = grantedAuths;
}
public User() {
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public boolean isAccountNonExpired() {
return this.accountNonExpired;
}
public void setAccountNonExpired(boolean accountNonExpired) {
this.accountNonExpired = accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return this.accountNonLocked;
}
public void setAccountNonLocked(boolean accountNonLocked) {
this.accountNonLocked = accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return this.credentialsNonExpired;
}
public void setCredentialsNonExpired(boolean credentialsNonExpired) {
this.credentialsNonExpired = credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("User [username=");
builder.append(username);
builder.append(", authorities=");
builder.append(authorities);
builder.append(", accountNonExpired=");
builder.append(accountNonExpired);
builder.append(", accountNonLocked=");
builder.append(accountNonLocked);
builder.append(", credentialsNonExpired=");
builder.append(credentialsNonExpired);
builder.append(", enabled=");
builder.append(enabled);
builder.append("]");
return builder.toString();
}
}
/**
* 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.atlas.web.security;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.atlas.util.PropertiesUtil;
import org.apache.atlas.web.model.User;
import org.apache.log4j.Logger;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.authentication.BindAuthenticator;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.stereotype.Component;
@Component
public class AtlasADAuthenticationProvider extends
AtlasAbstractAuthenticationProvider {
private static Logger LOG = Logger
.getLogger(AtlasADAuthenticationProvider.class);
private String adURL;
private String adBindDN;
private String adBindPassword;
private String adUserSearchFilter;
private String adBase;
private String adReferral;
private String adDefaultRole;
@PostConstruct
public void setup() {
setADProperties();
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
try {
return getADBindAuthentication(authentication);
} catch (Exception e) {
throw new AtlasAuthenticationException(e.getMessage(), e.getCause());
}
}
private Authentication getADBindAuthentication(Authentication authentication)
throws Exception {
try {
String userName = authentication.getName();
String userPassword = "";
if (authentication.getCredentials() != null) {
userPassword = authentication.getCredentials().toString();
}
LdapContextSource ldapContextSource = getLdapContextSource();
if (adUserSearchFilter == null
|| adUserSearchFilter.trim().isEmpty()) {
adUserSearchFilter = "(sAMAccountName={0})";
}
BindAuthenticator bindAuthenticator = getBindAuthenticator(ldapContextSource);
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(
bindAuthenticator);
if (userName != null && userPassword != null
&& !userName.trim().isEmpty()
&& !userPassword.trim().isEmpty()) {
final List<GrantedAuthority> grantedAuths = getAuthorities(userName);
final UserDetails principal = new User(userName, userPassword,
grantedAuths);
final Authentication finalAuthentication = new UsernamePasswordAuthenticationToken(
principal, userPassword, grantedAuths);
authentication = ldapAuthenticationProvider
.authenticate(finalAuthentication);
authentication = getAuthenticationWithGrantedAuthority(authentication);
return authentication;
} else {
throw new AtlasAuthenticationException(
"AD Authentication Failed userName or userPassword is null or empty");
}
} catch (Exception e) {
LOG.error("AD Authentication Failed:", e);
throw new AtlasAuthenticationException("AD Authentication Failed ",
e);
}
}
private void setADProperties() {
adURL = PropertiesUtil.getProperty("atlas.ad.url", adURL);
adBindDN = PropertiesUtil.getProperty("atlas.ad.bind.dn", adBindDN);
adBindPassword = PropertiesUtil.getProperty("atlas.ad.bind.password",
adBindPassword);
adUserSearchFilter = PropertiesUtil.getProperty(
"atlas.ad.user.searchfilter", adUserSearchFilter);
adBase = PropertiesUtil.getProperty("atlas.ad.base.dn", adBase);
adReferral = PropertiesUtil
.getProperty("atlas.ad.referral", adReferral);
adDefaultRole = PropertiesUtil.getProperty("atlas.ad.default.role",
adDefaultRole);
}
private LdapContextSource getLdapContextSource() throws Exception {
LdapContextSource ldapContextSource = new DefaultSpringSecurityContextSource(
adURL);
ldapContextSource.setUserDn(adBindDN);
ldapContextSource.setPassword(adBindPassword);
ldapContextSource.setReferral(adReferral);
ldapContextSource.setCacheEnvironmentProperties(true);
ldapContextSource.setAnonymousReadOnly(false);
ldapContextSource.setPooled(true);
ldapContextSource.afterPropertiesSet();
return ldapContextSource;
}
private BindAuthenticator getBindAuthenticator(
LdapContextSource ldapContextSource) throws Exception {
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
adBase, adUserSearchFilter, ldapContextSource);
userSearch.setSearchSubtree(true);
BindAuthenticator bindAuthenticator = new BindAuthenticator(
ldapContextSource);
bindAuthenticator.setUserSearch(userSearch);
bindAuthenticator.afterPropertiesSet();
return bindAuthenticator;
}
}
/*
* 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.atlas.web.security;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
public abstract class AtlasAbstractAuthenticationProvider implements
AuthenticationProvider {
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication);
}
/**
*
* @param authentication
* @return
*/
public Authentication getAuthenticationWithGrantedAuthority(
Authentication authentication) {
UsernamePasswordAuthenticationToken result = null;
if (authentication != null && authentication.isAuthenticated()) {
final List<GrantedAuthority> grantedAuths = getAuthorities(authentication
.getName().toString());
final UserDetails userDetails = new User(authentication.getName()
.toString(), authentication.getCredentials().toString(),
grantedAuths);
result = new UsernamePasswordAuthenticationToken(userDetails,
authentication.getCredentials(), grantedAuths);
result.setDetails(authentication.getDetails());
return result;
}
return authentication;
}
/**
* This method will be modified when actual roles are introduced.
*
*/
protected List<GrantedAuthority> getAuthorities(String username) {
final List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
return grantedAuths;
}
}
/*
* 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.atlas.web.security;
import org.springframework.security.core.AuthenticationException;
public class AtlasAuthenticationException extends AuthenticationException {
public AtlasAuthenticationException(String message) {
super(message);
}
public AtlasAuthenticationException(String message, Throwable cause) {
super(message, cause);
}
}
\ No newline at end of file
/**
* 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.atlas.web.security;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.apache.atlas.ApplicationProperties;
import org.apache.commons.configuration.Configuration;
@Component
public class AtlasAuthenticationProvider extends
AtlasAbstractAuthenticationProvider {
private static final Logger LOG = LoggerFactory
.getLogger(AtlasAuthenticationProvider.class);
private String atlasAuthenticationMethod = "UNKNOWN";
enum AUTH_METHOD {
FILE, LDAP, AD
};
@Autowired
AtlasLdapAuthenticationProvider ldapAuthenticationProvider;
@Autowired
AtlasFileAuthenticationProvider fileAuthenticationProvider;
@Autowired
AtlasADAuthenticationProvider adAuthenticationProvider;
@PostConstruct
void setAuthenticationMethod() {
try {
Configuration configuration = ApplicationProperties.get();
this.atlasAuthenticationMethod = configuration.getString(
"atlas.login.method", "UNKNOWN");
} catch (Exception e) {
LOG.error(
"Error while getting atlas.login.method application properties",
e);
}
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
if (atlasAuthenticationMethod.equalsIgnoreCase(AUTH_METHOD.FILE.name())) {
authentication = fileAuthenticationProvider
.authenticate(authentication);
} else if (atlasAuthenticationMethod.equalsIgnoreCase(AUTH_METHOD.LDAP
.name())) {
authentication = ldapAuthenticationProvider
.authenticate(authentication);
} else if (atlasAuthenticationMethod.equalsIgnoreCase(AUTH_METHOD.AD
.name())) {
authentication = adAuthenticationProvider
.authenticate(authentication);
} else {
LOG.error("Invalid authentication method :"
+ atlasAuthenticationMethod);
}
if (authentication != null && authentication.isAuthenticated()) {
return authentication;
} else {
LOG.error("Authentication failed.");
throw new AtlasAuthenticationException("Authentication failed.");
}
}
}
/*
* 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 compliRance 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.atlas.web.security;
import java.util.Collection;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
@Component
public class AtlasFileAuthenticationProvider extends AtlasAbstractAuthenticationProvider {
private static Logger logger = Logger.getLogger(AtlasFileAuthenticationProvider.class);
@Autowired
private UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
if (username == null || username.isEmpty()) {
logger.error("Username can't be null or empty.");
throw new BadCredentialsException(
"Username can't be null or empty.");
}
if (password == null || password.isEmpty()) {
logger.error("Password can't be null or empty.");
throw new BadCredentialsException(
"Password can't be null or empty.");
}
UserDetails user = userDetailsService.loadUserByUsername(username);
if (!password.equals(user.getPassword())) {
logger.error("Wrong password " + username);
throw new BadCredentialsException("Wrong password");
}
Collection<? extends GrantedAuthority> authorities = getAuthorities(username);
authentication = new UsernamePasswordAuthenticationToken(username, password, authorities);
authentication = getAuthenticationWithGrantedAuthority(authentication);
return authentication;
}
}
/**
* 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.atlas.web.security;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.atlas.util.PropertiesUtil;
import org.apache.atlas.web.model.User;
import org.apache.log4j.Logger;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
import org.springframework.security.ldap.authentication.BindAuthenticator;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.stereotype.Component;
@Component
public class AtlasLdapAuthenticationProvider extends
AtlasAbstractAuthenticationProvider {
private static Logger LOG = Logger
.getLogger(AtlasLdapAuthenticationProvider.class);
private String ldapURL;
private String ldapUserDNPattern;
private String ldapGroupSearchBase;
private String ldapGroupSearchFilter;
private String ldapGroupRoleAttribute;
private String ldapBindDN;
private String ldapBindPassword;
private String ldapDefaultRole;
private String ldapUserSearchFilter;
private String ldapReferral;
private String ldapBase;
@PostConstruct
public void setup() {
setLdapProperties();
}
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
try {
return getLdapBindAuthentication(authentication);
} catch (Exception e) {
throw new AtlasAuthenticationException(e.getMessage(), e.getCause());
}
}
private Authentication getLdapBindAuthentication(
Authentication authentication) throws Exception {
try {
String userName = authentication.getName();
String userPassword = "";
if (authentication.getCredentials() != null) {
userPassword = authentication.getCredentials().toString();
}
LdapContextSource ldapContextSource = getLdapContextSource();
DefaultLdapAuthoritiesPopulator defaultLdapAuthoritiesPopulator = getDefaultLdapAuthoritiesPopulator(ldapContextSource);
if (ldapUserSearchFilter == null
|| ldapUserSearchFilter.trim().isEmpty()) {
ldapUserSearchFilter = "(uid={0})";
}
FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
ldapBase, ldapUserSearchFilter, ldapContextSource);
userSearch.setSearchSubtree(true);
BindAuthenticator bindAuthenticator = getBindAuthenticator(
userSearch, ldapContextSource);
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(
bindAuthenticator, defaultLdapAuthoritiesPopulator);
if (userName != null && userPassword != null
&& !userName.trim().isEmpty()
&& !userPassword.trim().isEmpty()) {
final List<GrantedAuthority> grantedAuths = getAuthorities(userName);
final UserDetails principal = new User(userName, userPassword,
grantedAuths);
final Authentication finalAuthentication = new UsernamePasswordAuthenticationToken(
principal, userPassword, grantedAuths);
authentication = ldapAuthenticationProvider
.authenticate(finalAuthentication);
authentication = getAuthenticationWithGrantedAuthority(authentication);
return authentication;
} else {
throw new AtlasAuthenticationException(
"LDAP Authentication::userName or userPassword is null or empty for userName "
+ userName);
}
} catch (Exception e) {
LOG.error("LDAP Authentication Failed:", e);
throw new AtlasAuthenticationException(
"LDAP Authentication Failed", e);
}
}
private void setLdapProperties() {
ldapURL = PropertiesUtil.getProperty("atlas.ldap.url", ldapURL);
ldapUserDNPattern = PropertiesUtil.getProperty(
"atlas.ldap.user.dnpattern", ldapUserDNPattern);
ldapGroupSearchBase = PropertiesUtil.getProperty(
"atlas.ldap.group.searchbase", ldapGroupSearchBase);
ldapGroupSearchFilter = PropertiesUtil.getProperty(
"atlas.ldap.group.searchfilter", ldapGroupSearchFilter);
ldapGroupRoleAttribute = PropertiesUtil.getProperty(
"atlas.ldap.group.roleattribute", ldapGroupRoleAttribute);
ldapBindDN = PropertiesUtil.getProperty("atlas.ldap.bind.dn",
ldapBindDN);
ldapBindPassword = PropertiesUtil.getProperty(
"atlas.ldap.bind.password", ldapBindDN);
ldapDefaultRole = PropertiesUtil.getProperty("atlas.ldap.default.role",
ldapDefaultRole);
ldapUserSearchFilter = PropertiesUtil.getProperty(
"atlas.ldap.user.searchfilter", ldapUserSearchFilter);
ldapReferral = PropertiesUtil.getProperty("atlas.ldap.referral",
ldapReferral);
ldapBase = PropertiesUtil.getProperty("atlas.ldap.base.dn", ldapBase);
}
private LdapContextSource getLdapContextSource() throws Exception {
LdapContextSource ldapContextSource = new DefaultSpringSecurityContextSource(
ldapURL);
ldapContextSource.setUserDn(ldapBindDN);
ldapContextSource.setPassword(ldapBindPassword);
ldapContextSource.setReferral(ldapReferral);
ldapContextSource.setCacheEnvironmentProperties(false);
ldapContextSource.setAnonymousReadOnly(false);
ldapContextSource.setPooled(true);
ldapContextSource.afterPropertiesSet();
return ldapContextSource;
}
private DefaultLdapAuthoritiesPopulator getDefaultLdapAuthoritiesPopulator(
LdapContextSource ldapContextSource) {
DefaultLdapAuthoritiesPopulator defaultLdapAuthoritiesPopulator = new DefaultLdapAuthoritiesPopulator(
ldapContextSource, ldapGroupSearchBase);
defaultLdapAuthoritiesPopulator
.setGroupRoleAttribute(ldapGroupRoleAttribute);
defaultLdapAuthoritiesPopulator
.setGroupSearchFilter(ldapGroupSearchFilter);
defaultLdapAuthoritiesPopulator.setIgnorePartialResultException(true);
return defaultLdapAuthoritiesPopulator;
}
private BindAuthenticator getBindAuthenticator(
FilterBasedLdapUserSearch userSearch,
LdapContextSource ldapContextSource) throws Exception {
BindAuthenticator bindAuthenticator = new BindAuthenticator(
ldapContextSource);
bindAuthenticator.setUserSearch(userSearch);
String[] userDnPatterns = new String[] { ldapUserDNPattern };
bindAuthenticator.setUserDnPatterns(userDnPatterns);
bindAuthenticator.afterPropertiesSet();
return bindAuthenticator;
}
}
/*
* 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.atlas.web.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.apache.atlas.web.dao.UserDao;
import org.apache.atlas.web.service.UserService;
import org.apache.atlas.web.model.User;
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserDao userDao;
@Override
public User loadUserByUsername(final String username)
throws UsernameNotFoundException {
return userDao.loadUserByUsername(username);
}
}
<!-- Licensed 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.
See accompanying LICENSE file. -->
<configuration>
<!-- # Ldap info start -->
<property>
<name>atlas.ldap.url</name>
<display-name>LDAP URL</display-name>
<value>ldap://172.22.98.129:389</value>
<description>LDAP Server URL, only used if
Authentication method
is LDAP
</description>
</property>
<property>
<name>atlas.ldap.user.dnpattern</name>
<value>uid={0},ou=People,dc=example,dc=com</value>
<description></description>
</property>
<property>
<name>atlas.ldap.group.searchbase</name>
<display-name>Group Search Base</display-name>
<value>dc=example,dc=com</value>
<description></description>
</property>
<property>
<name>atlas.ldap.group.searchfilter</name>
<display-name>Group Search Filter</display-name>
<value>(member=uid={0},ou=People,dc=example,dc=com)
</value>
<description></description>
</property>
<property>
<name>atlas.ldap.group.roleattribute</name>
<value>cn</value>
<description></description>
</property>
<property>
<name>atlas.ldap.base.dn</name>
<value>dc=example,dc=com</value>
<description>LDAP base dn or search base</description>
</property>
<property>
<name>atlas.ldap.bind.dn</name>
<display-name>Bind User</display-name>
<value>cn=Manager,dc=example,dc=com</value>
<description>LDAP bind dn or manager dn</description>
</property>
<property>
<name>atlas.ldap.bind.password</name>
<display-name>​Bind User Password</display-name>
<value>p@ssword</value>
<property-type>PASSWORD</property-type>
<description>Password for the account that can search
for users
</description>
<value-attributes>
<type>password</type>
<overridable>false</overridable>
</value-attributes>
</property>
<property>
<name>atlas.ldap.user.searchfilter</name>
<display-name>User Search Filter</display-name>
<value>(uid={0})</value>
<description></description>
</property>
<property>
<name>atlas.ldap.default.role</name>
<value>ROLE_USER</value>
</property>
<property>
<name>atlas.ldap.referral</name>
<value>ignore</value>
<description>follow or ignore</description>
</property>
<!-- # Ldap Info end -->
<!-- #AD info start -->
<property>
<name>atlas.ad.url</name>
<value>ldap://172.25.16.111:389</value>
<description></description>
</property>
<property>
<name>atlas.ad.bind.dn</name>
<value>CN=team,CN=Users,DC=SME,DC=support,DC=com</value>
<description>AD bind dn or manager dn</description>
</property>
<property>
<name>atlas.ad.bind.password</name>
<value>Abcd1234!!</value>
<description>AD bind password</description>
</property>
<property>
<name>atlas.ad.user.searchfilter</name>
<display-name>User Search Filter</display-name>
<value>(sAMAccountName={0})</value>
<description></description>
</property>
<property>
<name>atlas.ad.base.dn</name>
<value>DC=SME,DC=support,DC=com</value>
<description>AD base dn or search base</description>
</property>
<property>
<name>atlas.ad.referral</name>
<value>ignore</value>
<description>follow or ignore</description>
</property>
<property>
<name>atlas.ad.default.role</name>
<value>ROLE_USER</value>
</property>
<!-- AD info end -->
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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. -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<security:http pattern="/login.jsp" security="none" />
<security:http pattern="/css/**" security="none" />
<security:http pattern="/lib/**" security="none" />
<security:http disable-url-rewriting="true"
use-expressions="true" create-session="always"
entry-point-ref="authenticationProcessingFilterEntryPoint">
<security:session-management
session-fixation-protection="newSession" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<security:custom-filter position="FORM_LOGIN_FILTER"
ref="atlasUsernamePasswordAuthenticationFilter" />
<security:logout delete-cookies="JSESSIONID"
logout-url="/logout.html" />
<http-basic entry-point-ref="authenticationProcessingFilterEntryPoint" />
</security:http>
<beans:bean id="atlasUsernamePasswordAuthenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager"
ref="authenticationManager" />
<beans:property name="authenticationSuccessHandler"
ref="ajaxAuthSuccessHandler" />
<beans:property name="authenticationFailureHandler"
ref="ajaxAuthFailureHandler" />
</beans:bean>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.apache.atlas.web.filters.AtlasAuthenticationEntryPoint">
<beans:property name="loginFormUrl"
value="/login.jsp" />
<beans:property name="forceHttps" value="false" />
</beans:bean>
<beans:bean id="ajaxAuthSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl"
value="/index.html" />
</beans:bean>
<beans:bean id="ajaxAuthFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl"
value="/login.jsp?login_error=true " />
</beans:bean>
<beans:bean id="atlasAuthenticationProvider"
class="org.apache.atlas.web.security.AtlasAuthenticationProvider">
</beans:bean>
<security:authentication-manager
alias="authenticationManager">
<security:authentication-provider
ref="atlasAuthenticationProvider" />
</security:authentication-manager>
<security:global-method-security
pre-post-annotations="enabled" />
<context:component-scan base-package="org.apache.atlas.web" />
</beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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. -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<import resource="classpath:/spring-security.xml" />
<bean id="xmlPropertyConfigurer" class="org.apache.atlas.util.XMLPropertiesUtil" />
<bean id="propertyConfigurer" class="org.apache.atlas.util.PropertiesUtil">
<property name="locations">
<list>
<value>classpath:atlas-admin-site.xml
</value>
</list>
</property>
<property name="propertiesPersister" ref="xmlPropertyConfigurer" />
</bean>
</beans>
\ No newline at end of file
......@@ -50,4 +50,27 @@
<listener>
<listener-class>org.apache.atlas.web.listeners.GuiceServletConfig</listener-class>
</listener>
</web-app>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
\ No newline at end of file
<!--
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.
-->
<%@ page import="org.apache.atlas.ApplicationProperties,org.apache.commons.configuration.Configuration" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Atlas Login</title>
<meta name="description" content="description">
<meta name="keyword" content="keywords">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css" rel="stylesheet">
<link href='http://fonts.googleapis.com/css?family=Righteous' rel='stylesheet' type='text/css'>
<link href="/css/login.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="http://getbootstrap.com/docs-assets/js/html5shiv.js"></script>
<script src="http://getbootstrap.com/docs-assets/js/respond.min.js"></script>
<![endif]-->
<script src="https://code.jquery.com/jquery-2.2.1.min.js" integrity="sha256-gvQgAFzTH6trSrAWoH1iPo9Xc96QxSZ3feW6kem+O00=" crossorigin="anonymous"></script>
</head>
<body>
<div class="errorBox">
<a href="javascript:void(0)" class="close" title="close"><i class="fa fa-times"></i></a>
<div class="alert alert-danger">
<strong>Error!</strong> Invalid User credentials.<br> Please try again.
</div>
</div>
<div id="wrapper">
<div class="container-fluid">
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<form name='f' action='/j_spring_security_check' method='POST'>
<div class="login-pane">
<h2 align="center">Apache <strong>Atlas</strong></h2>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type='text' class="form-control" name='j_username' placeholder="Username" required >
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type='password' name='j_password' class="form-control" placeholder="Password" required >
</div>
<input class="btn-atlas btn-block" name="submit" type="submit" value="Login"/>
</div>
</form>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$('body').ready(function(){
var query = window.location.search.substring(1);
var statusArr = query.split('=');
var status = -1;
if(statusArr.length > 0){
status = statusArr[1];
}
if(status=="true"){
$('.errorBox').show();
}
});
$('.close').click(function(){
$('.errorBox').hide();
})
</script>
</body>
</html>
/**
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.atlas.web.security;
import java.io.File;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.web.TestUtils;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.mockito.Mock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import static org.mockito.Mockito.when;
public class FileAuthenticationTest {
private static ApplicationContext applicationContext = null;
private static AtlasAuthenticationProvider authProvider = null;
private String originalConf;
private static final Logger LOG = LoggerFactory
.getLogger(FileAuthenticationTest.class);
@Mock
Authentication authentication;
@BeforeMethod
public void setup1() {
MockitoAnnotations.initMocks(this);
}
@BeforeClass
public void setup() throws Exception {
String persistDir = TestUtils.getTempDirectory();
setupUserCredential(persistDir);
setUpAltasApplicationProperties(persistDir);
originalConf = System.getProperty("atlas.conf");
System.setProperty("atlas.conf", persistDir);
applicationContext = new ClassPathXmlApplicationContext(
"spring-security.xml");
authProvider = applicationContext
.getBean(org.apache.atlas.web.security.AtlasAuthenticationProvider.class);
}
private void setUpAltasApplicationProperties(String persistDir) throws Exception{
final PropertiesConfiguration configuration = new PropertiesConfiguration();
configuration.setProperty("atlas.login.method", "FILE");
configuration.setProperty("atlas.login.credentials.file", persistDir
+ "/users-credentials");
TestUtils.writeConfiguration(configuration, persistDir + File.separator
+ ApplicationProperties.APPLICATION_PROPERTIES);
}
private void setupUserCredential(String tmpDir) throws Exception {
StringBuilder credentialFileStr = new StringBuilder(1024);
credentialFileStr.append("admin=admin123\n");
credentialFileStr.append("user=user123\n");
credentialFileStr.append("test=test123\n");
File credentialFile = new File(tmpDir, "users-credentials");
FileUtils.write(credentialFile, credentialFileStr.toString());
}
@Test
public void testValidUserLogin() {
when(authentication.getName()).thenReturn("admin");
when(authentication.getCredentials()).thenReturn("admin123");
Authentication auth = authProvider.authenticate(authentication);
LOG.debug(" " + auth);
Assert.assertTrue(auth.isAuthenticated());
}
@Test
public void testInValidPasswordLogin() {
when(authentication.getName()).thenReturn("admin");
when(authentication.getCredentials()).thenReturn("wrongpassword");
try {
Authentication auth = authProvider.authenticate(authentication);
LOG.debug(" " + auth);
} catch (BadCredentialsException bcExp) {
Assert.assertEquals("Wrong password", bcExp.getMessage());
}
}
@Test
public void testInValidUsernameLogin() {
when(authentication.getName()).thenReturn("wrongUserName");
when(authentication.getCredentials()).thenReturn("wrongpassword");
try {
Authentication auth = authProvider.authenticate(authentication);
LOG.debug(" " + auth);
} catch (UsernameNotFoundException uExp) {
Assert.assertTrue(uExp.getMessage().contains("Username not found."));
}
}
@AfterClass
public void tearDown() throws Exception {
if (originalConf != null) {
System.setProperty("atlas.conf", originalConf);
}
applicationContext = null;
authProvider = null;
}
}
/*
* 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 compliRance 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.atlas.web.security;
import java.util.Properties;
import org.apache.atlas.web.dao.UserDao;
import org.apache.atlas.web.model.User;
import org.junit.Assert;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.testng.annotations.Test;
public class UserDaoTest {
@Test
public void testUserDaowithValidUserLoginAndPassword() {
Properties userLogins = new Properties();
userLogins.put("admin", "admin123");
UserDao user = new UserDao();
user.setUserLogins(userLogins);
User userBean = user.loadUserByUsername("admin");
Assert.assertTrue(userBean.getPassword().equals("admin123"));
}
@Test
public void testUserDaowithInValidLogin() {
boolean hadException = false;
Properties userLogins = new Properties();
userLogins.put("admin", "admin123");
userLogins.put("test", "test123");
UserDao user = new UserDao();
user.setUserLogins(userLogins);
try {
User userBean = user.loadUserByUsername("xyz");
} catch (UsernameNotFoundException uex) {
hadException = true;
}
Assert.assertTrue(hadException);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment