Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
atlas
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dataplatform
atlas
Commits
854b7928
Commit
854b7928
authored
Nov 02, 2016
by
nixonrodrigues
Committed by
Madhan Neethiraj
Nov 15, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ATLAS-1244: added support for KnoxSSO Authentication
Signed-off-by:
Madhan Neethiraj
<
madhan@apache.org
>
parent
ae92406d
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
669 additions
and
6 deletions
+669
-6
atlas-application.properties
distro/src/conf/atlas-application.properties
+9
-0
release-log.txt
release-log.txt
+1
-0
pom.xml
webapp/pom.xml
+12
-0
AtlasAuthenticationFilter.java
...g/apache/atlas/web/filters/AtlasAuthenticationFilter.java
+1
-1
AtlasKnoxSSOAuthenticationFilter.java
...e/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java
+428
-0
SSOAuthentication.java
.../java/org/apache/atlas/web/filters/SSOAuthentication.java
+74
-0
SSOAuthenticationProperties.java
...apache/atlas/web/filters/SSOAuthenticationProperties.java
+78
-0
AtlasAbstractAuthenticationProvider.java
...las/web/security/AtlasAbstractAuthenticationProvider.java
+13
-4
AtlasAuthenticationProvider.java
...pache/atlas/web/security/AtlasAuthenticationProvider.java
+25
-0
AtlasAuthenticationSuccessHandler.java
...atlas/web/security/AtlasAuthenticationSuccessHandler.java
+5
-0
spring-security.xml
webapp/src/main/resources/spring-security.xml
+5
-1
web.xml
webapp/src/main/webapp/WEB-INF/web.xml
+9
-0
web.xml
webapp/src/test/webapp/WEB-INF/web.xml
+9
-0
No files found.
distro/src/conf/atlas-application.properties
View file @
854b7928
...
...
@@ -198,3 +198,12 @@ atlas.rest-csrf.custom-header=X-XSRF-HEADER
######### Enable Taxonomy #########
atlas.feature.taxonomy.enable
=
true
############ KNOX Configs ################
#atlas.sso.knox.browser.useragent=Mozilla,Chrome,Opera
#atlas.sso.knox.enabled=true
#atlas.sso.knox.providerurl=https://<knox gateway ip>:8443/gateway/knoxsso/api/v1/websso
#atlas.sso.knox.publicKey=
release-log.txt
View file @
854b7928
...
...
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES:
ATLAS-1244 added support for KnoxSSO Authentication
ATLAS-1295 Build failure due to patch for ATLAS-1081 (apoorvnaik via sumasai)
ATLAS-1081 Atlas jetty server configuration (shwethags)
ATLAS-1257 Map Entity REST APIs to ATLAS v1 backend (sumasai)
...
...
webapp/pom.xml
View file @
854b7928
...
...
@@ -355,6 +355,18 @@
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
com.nimbusds
</groupId>
<artifactId>
nimbus-jose-jwt
</artifactId>
<version>
3.9
</version>
<scope>
compile
</scope>
<exclusions>
<exclusion>
<groupId>
org.bouncycastle
</groupId>
<artifactId>
bcprov-jdk15on
</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
...
...
webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java
View file @
854b7928
...
...
@@ -435,7 +435,7 @@ public class AtlasAuthenticationFilter extends AuthenticationFilter {
Collection
<
String
>
headerNames
=
httpResponse
.
getHeaderNames
();
for
(
String
headerName
:
headerNames
)
{
String
value
=
httpResponse
.
getHeader
(
headerName
);
if
(
headerName
.
equalsIgnoreCase
(
"Set-Cookie"
)
&&
value
.
startsWith
(
"
J
SESSIONID"
))
{
if
(
headerName
.
equalsIgnoreCase
(
"Set-Cookie"
)
&&
value
.
startsWith
(
"
ATLAS
SESSIONID"
))
{
chk
=
false
;
break
;
}
...
...
webapp/src/main/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java
0 → 100644
View file @
854b7928
/*
* 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
com.google.inject.Inject
;
import
com.nimbusds.jose.JOSEException
;
import
com.nimbusds.jose.JWSObject
;
import
com.nimbusds.jose.JWSVerifier
;
import
com.nimbusds.jose.crypto.RSASSAVerifier
;
import
com.nimbusds.jwt.SignedJWT
;
import
org.apache.atlas.ApplicationProperties
;
import
org.apache.atlas.web.security.AtlasAuthenticationProvider
;
import
org.apache.commons.configuration.Configuration
;
import
org.apache.commons.lang.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.security.authentication.AbstractAuthenticationToken
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.User
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.web.authentication.WebAuthenticationDetails
;
import
javax.servlet.*
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.security.PublicKey
;
import
java.security.cert.CertificateException
;
import
java.security.cert.CertificateFactory
;
import
java.security.cert.X509Certificate
;
import
java.security.interfaces.RSAPublicKey
;
import
java.text.ParseException
;
import
java.util.Date
;
import
java.util.List
;
public
class
AtlasKnoxSSOAuthenticationFilter
implements
Filter
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AtlasKnoxSSOAuthenticationFilter
.
class
);
public
static
final
String
BROWSER_USERAGENT
=
"atlas.sso.knox.browser.useragent"
;
public
static
final
String
JWT_AUTH_PROVIDER_URL
=
"atlas.sso.knox.providerurl"
;
public
static
final
String
JWT_PUBLIC_KEY
=
"atlas.sso.knox.publicKey"
;
public
static
final
String
JWT_COOKIE_NAME
=
"atlas.sso.knox.cookiename"
;
public
static
final
String
JWT_ORIGINAL_URL_QUERY_PARAM
=
"atlas.sso.knox.query.param.originalurl"
;
public
static
final
String
JWT_COOKIE_NAME_DEFAULT
=
"hadoop-jwt"
;
public
static
final
String
JWT_ORIGINAL_URL_QUERY_PARAM_DEFAULT
=
"originalUrl"
;
private
SSOAuthenticationProperties
jwtProperties
;
private
String
originalUrlQueryParam
=
"originalUrl"
;
private
String
authenticationProviderUrl
=
null
;
private
RSAPublicKey
publicKey
=
null
;
private
String
cookieName
=
"hadoop-jwt"
;
private
Configuration
configuration
=
null
;
private
boolean
ssoEnabled
=
false
;
private
JWSVerifier
verifier
=
null
;
@Inject
public
AtlasKnoxSSOAuthenticationFilter
()
{
try
{
configuration
=
ApplicationProperties
.
get
();
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Error while getting application properties"
,
e
);
}
ssoEnabled
=
configuration
.
getBoolean
(
"atlas.sso.knox.enabled"
,
false
);
jwtProperties
=
loadJwtProperties
();
setJwtProperties
();
}
public
AtlasKnoxSSOAuthenticationFilter
(
SSOAuthenticationProperties
jwtProperties
)
{
this
.
jwtProperties
=
jwtProperties
;
setJwtProperties
();
}
@Override
public
void
init
(
FilterConfig
filterConfig
)
throws
ServletException
{
}
/*
* doFilter of AtlasKnoxSSOAuthenticationFilter is the first in the filter list so in this it check for the request
* if the request is from browser and sso is enabled then it process the request against knox sso
* else if it's ssoenable and the request is with local login string then it show's the appropriate msg
* else if ssoenable is false then it contiunes with further filters as it was before sso
*/
@Override
public
void
doFilter
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
if
(!
ssoEnabled
)
{
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
return
;
}
HttpServletRequest
httpRequest
=
(
HttpServletRequest
)
servletRequest
;
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Knox doFilter {}"
,
httpRequest
.
getRequestURI
());
}
if
(
httpRequest
.
getSession
()
!=
null
&&
httpRequest
.
getSession
().
getAttribute
(
"locallogin"
)
!=
null
)
{
servletRequest
.
setAttribute
(
"ssoEnabled"
,
false
);
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
return
;
}
if
(!
isWebUserAgent
(
httpRequest
.
getHeader
(
"User-Agent"
))
||
jwtProperties
==
null
||
isAuthenticated
())
{
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
return
;
}
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Knox ssoEnabled {} {}"
,
ssoEnabled
,
httpRequest
.
getRequestURI
());
}
//if jwt properties are loaded and is current not authenticated then it will go for sso authentication
//Note : Need to remove !isAuthenticated() after knoxsso solve the bug from cross-origin script
HttpServletResponse
httpServletResponse
=
(
HttpServletResponse
)
servletResponse
;
String
serializedJWT
=
getJWTFromCookie
(
httpRequest
);
// if we get the hadoop-jwt token from the cookies then will process it further
if
(
serializedJWT
!=
null
)
{
SignedJWT
jwtToken
=
null
;
try
{
jwtToken
=
SignedJWT
.
parse
(
serializedJWT
);
boolean
valid
=
validateToken
(
jwtToken
);
//if the public key provide is correct and also token is not expired the process token
if
(
valid
)
{
String
userName
=
jwtToken
.
getJWTClaimsSet
().
getSubject
();
LOG
.
info
(
"SSO login user : {} "
,
userName
);
//if we get the userName from the token then log into atlas using the same user
if
(
userName
!=
null
&&
!
userName
.
trim
().
isEmpty
())
{
List
<
GrantedAuthority
>
grantedAuths
=
AtlasAuthenticationProvider
.
getAuthoritiesFromUGI
(
userName
);
final
UserDetails
principal
=
new
User
(
userName
,
""
,
grantedAuths
);
final
Authentication
finalAuthentication
=
new
UsernamePasswordAuthenticationToken
(
principal
,
""
,
grantedAuths
);
WebAuthenticationDetails
webDetails
=
new
WebAuthenticationDetails
(
httpRequest
);
((
AbstractAuthenticationToken
)
finalAuthentication
).
setDetails
(
webDetails
);
AtlasAuthenticationProvider
authenticationProvider
=
new
AtlasAuthenticationProvider
();
authenticationProvider
.
setSsoEnabled
(
ssoEnabled
);
Authentication
authentication
=
authenticationProvider
.
authenticate
(
finalAuthentication
);
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
}
filterChain
.
doFilter
(
servletRequest
,
httpServletResponse
);
}
else
{
// if the token is not valid then redirect to knox sso
String
ssourl
=
constructLoginURL
(
httpRequest
);
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO URL ={} invalid"
,
ssourl
);
}
httpServletResponse
.
sendRedirect
(
ssourl
);
}
}
catch
(
ParseException
e
)
{
LOG
.
warn
(
"Unable to parse the JWT token"
,
e
);
}
}
else
{
String
ssourl
=
constructLoginURL
(
httpRequest
);
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO URL = {} serializedJWT null"
,
ssourl
);
}
httpServletResponse
.
sendRedirect
(
ssourl
);
}
}
private
boolean
isWebUserAgent
(
String
userAgent
)
{
boolean
isWeb
=
false
;
if
(
jwtProperties
!=
null
)
{
String
userAgentList
[]
=
jwtProperties
.
getUserAgentList
();
if
(
userAgentList
!=
null
&&
userAgentList
.
length
>
0
)
{
for
(
String
ua
:
userAgentList
)
{
if
(
StringUtils
.
startsWithIgnoreCase
(
userAgent
,
ua
))
{
isWeb
=
true
;
break
;
}
}
}
}
return
isWeb
;
}
private
void
setJwtProperties
()
{
if
(
jwtProperties
!=
null
)
{
authenticationProviderUrl
=
jwtProperties
.
getAuthenticationProviderUrl
();
publicKey
=
jwtProperties
.
getPublicKey
();
cookieName
=
jwtProperties
.
getCookieName
();
originalUrlQueryParam
=
jwtProperties
.
getOriginalUrlQueryParam
();
if
(
publicKey
!=
null
)
{
verifier
=
new
RSASSAVerifier
(
publicKey
);
}
}
}
/**
* Do not try to validate JWT if user already authenticated via other
* provider
*
* @return true, if JWT validation required
*/
private
boolean
isAuthenticated
()
{
Authentication
existingAuth
=
SecurityContextHolder
.
getContext
().
getAuthentication
();
return
!(!(
existingAuth
!=
null
&&
existingAuth
.
isAuthenticated
())
||
existingAuth
instanceof
SSOAuthentication
);
}
/**
* Encapsulate the acquisition of the JWT token from HTTP cookies within the
* request.
*
* @param req servlet request to get the JWT token from
* @return serialized JWT token
*/
protected
String
getJWTFromCookie
(
HttpServletRequest
req
)
{
String
serializedJWT
=
null
;
Cookie
[]
cookies
=
req
.
getCookies
();
if
(
cookieName
!=
null
&&
cookies
!=
null
)
{
for
(
Cookie
cookie
:
cookies
)
{
if
(
cookieName
.
equals
(
cookie
.
getName
()))
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
cookieName
+
" cookie has been found and is being processed"
);
}
serializedJWT
=
cookie
.
getValue
();
break
;
}
}
}
return
serializedJWT
;
}
/**
* Create the URL to be used for authentication of the user in the absence
* of a JWT token within the incoming request.
*
* @param request for getting the original request URL
* @return url to use as login url for redirect
*/
protected
String
constructLoginURL
(
HttpServletRequest
request
)
{
String
delimiter
=
"?"
;
if
(
authenticationProviderUrl
.
contains
(
"?"
))
{
delimiter
=
"&"
;
}
StringBuilder
loginURL
=
new
StringBuilder
();
loginURL
.
append
(
authenticationProviderUrl
).
append
(
delimiter
).
append
(
originalUrlQueryParam
).
append
(
"="
).
append
(
request
.
getRequestURL
().
append
(
getOriginalQueryString
(
request
)));
return
loginURL
.
toString
();
}
private
String
getOriginalQueryString
(
HttpServletRequest
request
)
{
String
originalQueryString
=
request
.
getQueryString
();
return
(
originalQueryString
==
null
)
?
""
:
"?"
+
originalQueryString
;
}
/**
* This method provides a single method for validating the JWT for use in
* request processing. It provides for the override of specific aspects of
* this implementation through submethods used within but also allows for
* the override of the entire token validation algorithm.
*
* @param jwtToken the token to validate
* @return true if valid
*/
protected
boolean
validateToken
(
SignedJWT
jwtToken
)
{
boolean
isValid
=
validateSignature
(
jwtToken
);
if
(
isValid
)
{
isValid
=
validateExpiration
(
jwtToken
);
if
(!
isValid
)
{
LOG
.
warn
(
"Expiration time validation of JWT token failed."
);
}
}
else
{
LOG
.
warn
(
"Signature of JWT token could not be verified. Please check the public key"
);
}
return
isValid
;
}
/**
* Verify the signature of the JWT token in this method. This method depends
* on the public key that was established during init based upon the
* provisioned public key. Override this method in subclasses in order to
* customize the signature verification behavior.
*
* @param jwtToken the token that contains the signature to be validated
* @return valid true if signature verifies successfully; false otherwise
*/
protected
boolean
validateSignature
(
SignedJWT
jwtToken
)
{
boolean
valid
=
false
;
if
(
JWSObject
.
State
.
SIGNED
==
jwtToken
.
getState
())
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO token is in a SIGNED state"
);
}
if
(
jwtToken
.
getSignature
()
!=
null
)
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO token signature is not null"
);
}
try
{
if
(
verifier
!=
null
&&
jwtToken
.
verify
(
verifier
))
{
valid
=
true
;
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO token has been successfully verified"
);
}
}
else
{
LOG
.
warn
(
"SSO signature verification failed.Please check the public key"
);
}
}
catch
(
JOSEException
je
)
{
LOG
.
warn
(
"Error while validating signature"
,
je
);
}
catch
(
Exception
e
)
{
LOG
.
warn
(
"Error while validating signature"
,
e
);
}
}
}
return
valid
;
}
/**
* Validate that the expiration time of the JWT token has not been violated.
* If it has then throw an AuthenticationException. Override this method in
* subclasses in order to customize the expiration validation behavior.
*
* @param jwtToken the token that contains the expiration date to validate
* @return valid true if the token has not expired; false otherwise
*/
protected
boolean
validateExpiration
(
SignedJWT
jwtToken
)
{
boolean
valid
=
false
;
try
{
Date
expires
=
jwtToken
.
getJWTClaimsSet
().
getExpirationTime
();
if
(
expires
==
null
||
new
Date
().
before
(
expires
))
{
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"SSO token expiration date has been successfully validated"
);
}
valid
=
true
;
}
else
{
LOG
.
warn
(
"SSO expiration date validation failed."
);
}
}
catch
(
ParseException
pe
)
{
LOG
.
warn
(
"SSO expiration date validation failed."
,
pe
);
}
return
valid
;
}
@Override
public
void
destroy
()
{
}
public
SSOAuthenticationProperties
loadJwtProperties
()
{
String
providerUrl
=
configuration
.
getString
(
JWT_AUTH_PROVIDER_URL
);
if
(
providerUrl
!=
null
&&
configuration
.
getBoolean
(
"atlas.sso.knox.enabled"
,
false
))
{
SSOAuthenticationProperties
jwtProperties
=
new
SSOAuthenticationProperties
();
String
publicKeyPathStr
=
configuration
.
getString
(
JWT_PUBLIC_KEY
);
if
(
publicKeyPathStr
==
null
)
{
LOG
.
error
(
"Public key pem not specified for SSO auth provider {}. SSO auth will be disabled"
);
return
null
;
}
jwtProperties
.
setAuthenticationProviderUrl
(
providerUrl
);
jwtProperties
.
setCookieName
(
configuration
.
getString
(
JWT_COOKIE_NAME
,
JWT_COOKIE_NAME_DEFAULT
));
jwtProperties
.
setOriginalUrlQueryParam
(
configuration
.
getString
(
JWT_ORIGINAL_URL_QUERY_PARAM
,
JWT_ORIGINAL_URL_QUERY_PARAM_DEFAULT
));
String
userAgent
=
configuration
.
getString
(
BROWSER_USERAGENT
);
if
(
userAgent
!=
null
&&
!
userAgent
.
isEmpty
())
{
jwtProperties
.
setUserAgentList
(
userAgent
.
split
(
","
));
}
try
{
RSAPublicKey
publicKey
=
parseRSAPublicKey
(
publicKeyPathStr
);
jwtProperties
.
setPublicKey
(
publicKey
);
}
catch
(
IOException
e
)
{
LOG
.
error
(
"Unable to read public certificate file. JWT auth will be disabled."
,
e
);
}
catch
(
CertificateException
e
)
{
LOG
.
error
(
"Unable to parse public certificate file. JWT auth will be disabled."
,
e
);
}
catch
(
ServletException
e
)
{
LOG
.
error
(
"ServletException while processing the properties"
,
e
);
}
return
jwtProperties
;
}
else
{
return
null
;
}
}
/*
* public static RSAPublicKey getPublicKeyFromFile(String filePath) throws
* IOException, CertificateException {
* FileUtils.readFileToString(new File(filePath));
* getPublicKeyFromString(pemString); }
*/
public
static
RSAPublicKey
parseRSAPublicKey
(
String
pem
)
throws
CertificateException
,
UnsupportedEncodingException
,
ServletException
{
String
PEM_HEADER
=
"-----BEGIN CERTIFICATE-----\n"
;
String
PEM_FOOTER
=
"\n-----END CERTIFICATE-----"
;
String
fullPem
=
PEM_HEADER
+
pem
+
PEM_FOOTER
;
PublicKey
key
=
null
;
try
{
CertificateFactory
fact
=
CertificateFactory
.
getInstance
(
"X.509"
);
ByteArrayInputStream
is
=
new
ByteArrayInputStream
(
fullPem
.
getBytes
(
"UTF8"
));
X509Certificate
cer
=
(
X509Certificate
)
fact
.
generateCertificate
(
is
);
key
=
cer
.
getPublicKey
();
}
catch
(
CertificateException
ce
)
{
String
message
=
null
;
if
(
pem
.
startsWith
(
PEM_HEADER
))
{
message
=
"CertificateException - be sure not to include PEM header "
+
"and footer in the PEM configuration element."
;
}
else
{
message
=
"CertificateException - PEM may be corrupt"
;
}
throw
new
ServletException
(
message
,
ce
);
}
catch
(
UnsupportedEncodingException
uee
)
{
throw
new
ServletException
(
uee
);
}
return
(
RSAPublicKey
)
key
;
}
}
webapp/src/main/java/org/apache/atlas/web/filters/SSOAuthentication.java
0 → 100644
View file @
854b7928
/*
* 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
com.nimbusds.jwt.SignedJWT
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
java.util.Collection
;
/**
* Internal token which describes JWT authentication
*/
public
class
SSOAuthentication
implements
Authentication
{
private
final
SignedJWT
token
;
private
boolean
authenticated
=
false
;
public
SSOAuthentication
(
SignedJWT
token
)
{
this
.
token
=
token
;
}
@Override
public
SignedJWT
getCredentials
()
{
return
token
;
}
@Override
public
Object
getDetails
()
{
return
null
;
}
@Override
public
boolean
isAuthenticated
()
{
return
authenticated
;
}
@Override
public
void
setAuthenticated
(
boolean
authenticated
)
throws
IllegalArgumentException
{
this
.
authenticated
=
authenticated
;
}
@Override
public
String
getName
()
{
return
null
;
}
@Override
public
Collection
<?
extends
GrantedAuthority
>
getAuthorities
()
{
return
null
;
}
@Override
public
Object
getPrincipal
()
{
return
null
;
}
}
webapp/src/main/java/org/apache/atlas/web/filters/SSOAuthenticationProperties.java
0 → 100644
View file @
854b7928
/*
* 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.security.interfaces.RSAPublicKey
;
public
class
SSOAuthenticationProperties
{
private
String
authenticationProviderUrl
=
null
;
private
RSAPublicKey
publicKey
=
null
;
private
String
cookieName
=
"hadoop-jwt"
;
private
String
originalUrlQueryParam
=
null
;
private
String
[]
userAgentList
=
null
;
public
String
getAuthenticationProviderUrl
()
{
return
authenticationProviderUrl
;
}
public
void
setAuthenticationProviderUrl
(
String
authenticationProviderUrl
)
{
this
.
authenticationProviderUrl
=
authenticationProviderUrl
;
}
public
RSAPublicKey
getPublicKey
()
{
return
publicKey
;
}
public
void
setPublicKey
(
RSAPublicKey
publicKey
)
{
this
.
publicKey
=
publicKey
;
}
public
String
getCookieName
()
{
return
cookieName
;
}
public
void
setCookieName
(
String
cookieName
)
{
this
.
cookieName
=
cookieName
;
}
public
String
getOriginalUrlQueryParam
()
{
return
originalUrlQueryParam
;
}
public
void
setOriginalUrlQueryParam
(
String
originalUrlQueryParam
)
{
this
.
originalUrlQueryParam
=
originalUrlQueryParam
;
}
/**
* @return the userAgentList
*/
public
String
[]
getUserAgentList
()
{
return
userAgentList
;
}
/**
* @param userAgentList the userAgentList to set
*/
public
void
setUserAgentList
(
String
[]
userAgentList
)
{
this
.
userAgentList
=
userAgentList
;
}
}
webapp/src/main/java/org/apache/atlas/web/security/AtlasAbstractAuthenticationProvider.java
View file @
854b7928
...
...
@@ -22,7 +22,11 @@ package org.apache.atlas.web.security;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.apache.hadoop.conf.Configuration
;
import
org.apache.hadoop.security.UserGroupInformation
;
import
org.apache.hadoop.security.*
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.security.authentication.AuthenticationProvider
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
...
...
@@ -33,6 +37,7 @@ import org.springframework.security.core.userdetails.UserDetails;
public
abstract
class
AtlasAbstractAuthenticationProvider
implements
AuthenticationProvider
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AtlasAbstractAuthenticationProvider
.
class
);
@Override
public
boolean
supports
(
Class
<?>
authentication
)
{
...
...
@@ -92,16 +97,20 @@ public abstract class AtlasAbstractAuthenticationProvider implements
return
authentication
;
}
public
List
<
GrantedAuthority
>
getAuthoritiesFromUGI
(
String
userName
)
{
public
static
List
<
GrantedAuthority
>
getAuthoritiesFromUGI
(
String
userName
)
{
List
<
GrantedAuthority
>
grantedAuths
=
new
ArrayList
<
GrantedAuthority
>();
UserGroupInformation
ugi
=
UserGroupInformation
.
createRemoteUser
(
userName
);
if
(
ugi
!=
null
)
{
String
[]
userGroups
=
ugi
.
getGroupNames
();
Configuration
config
=
new
Configuration
();
try
{
Groups
gp
=
new
Groups
(
config
);
List
<
String
>
userGroups
=
gp
.
getGroups
(
userName
);
if
(
userGroups
!=
null
)
{
for
(
String
group
:
userGroups
)
{
grantedAuths
.
add
(
new
SimpleGrantedAuthority
(
group
));
}
}
}
catch
(
java
.
io
.
IOException
e
)
{
LOG
.
error
(
"Exception while fetching groups "
,
e
);
}
return
grantedAuths
;
}
...
...
webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java
View file @
854b7928
...
...
@@ -39,6 +39,10 @@ public class AtlasAuthenticationProvider extends
public
static
final
String
FILE_AUTH_METHOD
=
"atlas.authentication.method.file"
;
public
static
final
String
LDAP_TYPE
=
"atlas.authentication.method.ldap.type"
;
private
boolean
ssoEnabled
=
false
;
@Autowired
AtlasLdapAuthenticationProvider
ldapAuthenticationProvider
;
...
...
@@ -67,6 +71,15 @@ public class AtlasAuthenticationProvider extends
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
if
(
ssoEnabled
){
if
(
authentication
!=
null
){
authentication
=
getSSOAuthentication
(
authentication
);
if
(
authentication
!=
null
&&
authentication
.
isAuthenticated
()){
return
authentication
;
}
}
}
else
{
if
(
ldapType
.
equalsIgnoreCase
(
"LDAP"
))
{
try
{
authentication
=
ldapAuthenticationProvider
.
authenticate
(
authentication
);
...
...
@@ -80,6 +93,7 @@ public class AtlasAuthenticationProvider extends
LOG
.
error
(
"Error while AD authentication"
,
ex
);
}
}
}
if
(
authentication
!=
null
)
{
if
(
authentication
.
isAuthenticated
())
{
...
...
@@ -97,4 +111,15 @@ public class AtlasAuthenticationProvider extends
throw
new
AtlasAuthenticationException
(
"Authentication failed."
);
}
public
boolean
isSsoEnabled
()
{
return
ssoEnabled
;
}
public
void
setSsoEnabled
(
boolean
ssoEnabled
)
{
this
.
ssoEnabled
=
ssoEnabled
;
}
private
Authentication
getSSOAuthentication
(
Authentication
authentication
)
throws
AuthenticationException
{
return
authentication
;
}
}
webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationSuccessHandler.java
View file @
854b7928
...
...
@@ -43,6 +43,11 @@ public class AtlasAuthenticationSuccessHandler implements AuthenticationSuccessH
ObjectMapper
mapper
=
new
ObjectMapper
();
json
.
put
(
"msgDesc"
,
"Success"
);
if
(
request
.
getSession
()
!=
null
)
{
// incase of form based login mark it as local login in session
request
.
getSession
().
setAttribute
(
"locallogin"
,
"true"
);
request
.
getServletContext
().
setAttribute
(
request
.
getSession
().
getId
(),
"locallogin"
);
}
String
jsonAsStr
=
mapper
.
writeValueAsString
(
json
);
response
.
setContentType
(
"application/json"
);
response
.
setStatus
(
HttpServletResponse
.
SC_OK
);
...
...
webapp/src/main/resources/spring-security.xml
View file @
854b7928
...
...
@@ -42,6 +42,7 @@
<security:session-management
session-fixation-protection=
"newSession"
/>
<intercept-url
pattern=
"/**"
access=
"isAuthenticated()"
/>
<custom-filter
ref=
"ssoAuthenticationFilter"
after=
"BASIC_AUTH_FILTER"
/>
<security:custom-filter
ref=
"krbAuthenticationFilter"
after=
"SERVLET_API_SUPPORT_FILTER"
/>
<security:custom-filter
ref=
"CSRFPreventionFilter"
after=
"REMEMBER_ME_FILTER"
/>
...
...
@@ -53,7 +54,7 @@
username-parameter=
"j_username"
password-parameter=
"j_password"
/>
<security:logout
logout-success-url=
"/login.jsp"
delete-cookies=
"
J
SESSIONID"
<security:logout
logout-success-url=
"/login.jsp"
delete-cookies=
"
ATLAS
SESSIONID"
logout-url=
"/logout.html"
/>
<http-basic
/>
<security:custom-filter
position=
"LAST"
ref=
"atlasAuthorizationFilter"
/>
...
...
@@ -62,6 +63,9 @@
<beans:bean
id=
"krbAuthenticationFilter"
class=
"org.apache.atlas.web.filters.AtlasAuthenticationFilter"
>
</beans:bean>
<beans:bean
id=
"ssoAuthenticationFilter"
class=
"org.apache.atlas.web.filters.AtlasKnoxSSOAuthenticationFilter"
>
</beans:bean>
<beans:bean
id=
"CSRFPreventionFilter"
class=
"org.apache.atlas.web.filters.AtlasCSRFPreventionFilter"
>
</beans:bean>
...
...
webapp/src/main/webapp/WEB-INF/web.xml
View file @
854b7928
...
...
@@ -79,5 +79,14 @@
</listener>
<session-config>
<session-timeout>
60
</session-timeout>
<tracking-mode>
COOKIE
</tracking-mode>
<cookie-config>
<name>
ATLASSESSIONID
</name>
<http-only>
true
</http-only>
</cookie-config>
</session-config>
</web-app>
webapp/src/test/webapp/WEB-INF/web.xml
View file @
854b7928
...
...
@@ -73,4 +73,13 @@
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<session-config>
<session-timeout>
60
</session-timeout>
<tracking-mode>
COOKIE
</tracking-mode>
<cookie-config>
<name>
ATLASSESSIONID
</name>
<http-only>
true
</http-only>
</cookie-config>
</session-config>
</web-app>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment