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
8 years ago
by
nixonrodrigues
Committed by
Madhan Neethiraj
8 years ago
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
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
680 additions
and
17 deletions
+680
-17
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
+35
-10
AtlasAuthenticationSuccessHandler.java
...atlas/web/security/AtlasAuthenticationSuccessHandler.java
+5
-0
spring-security.xml
webapp/src/main/resources/spring-security.xml
+6
-2
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
...
@@ -198,3 +198,12 @@ atlas.rest-csrf.custom-header=X-XSRF-HEADER
######### Enable Taxonomy #########
######### Enable Taxonomy #########
atlas.feature.taxonomy.enable
=
true
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=
This diff is collapsed.
Click to expand it.
release-log.txt
View file @
854b7928
...
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
...
@@ -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)
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES:
ALL CHANGES:
ATLAS-1244 added support for KnoxSSO Authentication
ATLAS-1295 Build failure due to patch for ATLAS-1081 (apoorvnaik via sumasai)
ATLAS-1295 Build failure due to patch for ATLAS-1081 (apoorvnaik via sumasai)
ATLAS-1081 Atlas jetty server configuration (shwethags)
ATLAS-1081 Atlas jetty server configuration (shwethags)
ATLAS-1257 Map Entity REST APIs to ATLAS v1 backend (sumasai)
ATLAS-1257 Map Entity REST APIs to ATLAS v1 backend (sumasai)
...
...
This diff is collapsed.
Click to expand it.
webapp/pom.xml
View file @
854b7928
...
@@ -355,6 +355,18 @@
...
@@ -355,6 +355,18 @@
<scope>
test
</scope>
<scope>
test
</scope>
</dependency>
</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>
</dependencies>
<build>
<build>
...
...
This diff is collapsed.
Click to expand it.
webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java
View file @
854b7928
...
@@ -435,7 +435,7 @@ public class AtlasAuthenticationFilter extends AuthenticationFilter {
...
@@ -435,7 +435,7 @@ public class AtlasAuthenticationFilter extends AuthenticationFilter {
Collection
<
String
>
headerNames
=
httpResponse
.
getHeaderNames
();
Collection
<
String
>
headerNames
=
httpResponse
.
getHeaderNames
();
for
(
String
headerName
:
headerNames
)
{
for
(
String
headerName
:
headerNames
)
{
String
value
=
httpResponse
.
getHeader
(
headerName
);
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
;
chk
=
false
;
break
;
break
;
}
}
...
...
This diff is collapsed.
Click to expand it.
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
;
}
}
This diff is collapsed.
Click to expand it.
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
;
}
}
This diff is collapsed.
Click to expand it.
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
;
}
}
This diff is collapsed.
Click to expand it.
webapp/src/main/java/org/apache/atlas/web/security/AtlasAbstractAuthenticationProvider.java
View file @
854b7928
...
@@ -22,7 +22,11 @@ package org.apache.atlas.web.security;
...
@@ -22,7 +22,11 @@ package org.apache.atlas.web.security;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
org.apache.hadoop.conf.Configuration
;
import
org.apache.hadoop.security.UserGroupInformation
;
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.AuthenticationProvider
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.Authentication
;
...
@@ -33,6 +37,7 @@ import org.springframework.security.core.userdetails.UserDetails;
...
@@ -33,6 +37,7 @@ import org.springframework.security.core.userdetails.UserDetails;
public
abstract
class
AtlasAbstractAuthenticationProvider
implements
public
abstract
class
AtlasAbstractAuthenticationProvider
implements
AuthenticationProvider
{
AuthenticationProvider
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
AtlasAbstractAuthenticationProvider
.
class
);
@Override
@Override
public
boolean
supports
(
Class
<?>
authentication
)
{
public
boolean
supports
(
Class
<?>
authentication
)
{
...
@@ -92,16 +97,20 @@ public abstract class AtlasAbstractAuthenticationProvider implements
...
@@ -92,16 +97,20 @@ public abstract class AtlasAbstractAuthenticationProvider implements
return
authentication
;
return
authentication
;
}
}
public
List
<
GrantedAuthority
>
getAuthoritiesFromUGI
(
String
userName
)
{
public
static
List
<
GrantedAuthority
>
getAuthoritiesFromUGI
(
String
userName
)
{
List
<
GrantedAuthority
>
grantedAuths
=
new
ArrayList
<
GrantedAuthority
>();
List
<
GrantedAuthority
>
grantedAuths
=
new
ArrayList
<
GrantedAuthority
>();
UserGroupInformation
ugi
=
UserGroupInformation
.
createRemoteUser
(
userName
);
Configuration
config
=
new
Configuration
();
if
(
ugi
!=
null
)
{
String
[]
userGroups
=
ugi
.
getGroupNames
();
try
{
Groups
gp
=
new
Groups
(
config
);
List
<
String
>
userGroups
=
gp
.
getGroups
(
userName
);
if
(
userGroups
!=
null
)
{
if
(
userGroups
!=
null
)
{
for
(
String
group
:
userGroups
)
{
for
(
String
group
:
userGroups
)
{
grantedAuths
.
add
(
new
SimpleGrantedAuthority
(
group
));
grantedAuths
.
add
(
new
SimpleGrantedAuthority
(
group
));
}
}
}
}
}
catch
(
java
.
io
.
IOException
e
)
{
LOG
.
error
(
"Exception while fetching groups "
,
e
);
}
}
return
grantedAuths
;
return
grantedAuths
;
}
}
...
...
This diff is collapsed.
Click to expand it.
webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java
View file @
854b7928
...
@@ -39,6 +39,10 @@ public class AtlasAuthenticationProvider extends
...
@@ -39,6 +39,10 @@ public class AtlasAuthenticationProvider extends
public
static
final
String
FILE_AUTH_METHOD
=
"atlas.authentication.method.file"
;
public
static
final
String
FILE_AUTH_METHOD
=
"atlas.authentication.method.file"
;
public
static
final
String
LDAP_TYPE
=
"atlas.authentication.method.ldap.type"
;
public
static
final
String
LDAP_TYPE
=
"atlas.authentication.method.ldap.type"
;
private
boolean
ssoEnabled
=
false
;
@Autowired
@Autowired
AtlasLdapAuthenticationProvider
ldapAuthenticationProvider
;
AtlasLdapAuthenticationProvider
ldapAuthenticationProvider
;
...
@@ -67,17 +71,27 @@ public class AtlasAuthenticationProvider extends
...
@@ -67,17 +71,27 @@ public class AtlasAuthenticationProvider extends
public
Authentication
authenticate
(
Authentication
authentication
)
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
throws
AuthenticationException
{
if
(
ldapType
.
equalsIgnoreCase
(
"LDAP"
))
{
if
(
ssoEnabled
){
try
{
if
(
authentication
!=
null
){
authentication
=
ldapAuthenticationProvider
.
authenticate
(
authentication
);
authentication
=
getSSOAuthentication
(
authentication
);
}
catch
(
Exception
ex
)
{
if
(
authentication
!=
null
&&
authentication
.
isAuthenticated
()){
LOG
.
error
(
"Error while LDAP authentication"
,
ex
);
return
authentication
;
}
}
}
}
else
if
(
ldapType
.
equalsIgnoreCase
(
"AD"
))
{
}
else
{
try
{
authentication
=
adAuthenticationProvider
.
authenticate
(
authentication
);
if
(
ldapType
.
equalsIgnoreCase
(
"LDAP"
))
{
}
catch
(
Exception
ex
)
{
try
{
LOG
.
error
(
"Error while AD authentication"
,
ex
);
authentication
=
ldapAuthenticationProvider
.
authenticate
(
authentication
);
}
catch
(
Exception
ex
)
{
LOG
.
error
(
"Error while LDAP authentication"
,
ex
);
}
}
else
if
(
ldapType
.
equalsIgnoreCase
(
"AD"
))
{
try
{
authentication
=
adAuthenticationProvider
.
authenticate
(
authentication
);
}
catch
(
Exception
ex
)
{
LOG
.
error
(
"Error while AD authentication"
,
ex
);
}
}
}
}
}
...
@@ -97,4 +111,15 @@ public class AtlasAuthenticationProvider extends
...
@@ -97,4 +111,15 @@ public class AtlasAuthenticationProvider extends
throw
new
AtlasAuthenticationException
(
"Authentication failed."
);
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
;
}
}
}
This diff is collapsed.
Click to expand it.
webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationSuccessHandler.java
View file @
854b7928
...
@@ -43,6 +43,11 @@ public class AtlasAuthenticationSuccessHandler implements AuthenticationSuccessH
...
@@ -43,6 +43,11 @@ public class AtlasAuthenticationSuccessHandler implements AuthenticationSuccessH
ObjectMapper
mapper
=
new
ObjectMapper
();
ObjectMapper
mapper
=
new
ObjectMapper
();
json
.
put
(
"msgDesc"
,
"Success"
);
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
);
String
jsonAsStr
=
mapper
.
writeValueAsString
(
json
);
response
.
setContentType
(
"application/json"
);
response
.
setContentType
(
"application/json"
);
response
.
setStatus
(
HttpServletResponse
.
SC_OK
);
response
.
setStatus
(
HttpServletResponse
.
SC_OK
);
...
...
This diff is collapsed.
Click to expand it.
webapp/src/main/resources/spring-security.xml
View file @
854b7928
...
@@ -42,6 +42,7 @@
...
@@ -42,6 +42,7 @@
<security:session-management
<security:session-management
session-fixation-protection=
"newSession"
/>
session-fixation-protection=
"newSession"
/>
<intercept-url
pattern=
"/**"
access=
"isAuthenticated()"
/>
<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=
"krbAuthenticationFilter"
after=
"SERVLET_API_SUPPORT_FILTER"
/>
<security:custom-filter
ref=
"CSRFPreventionFilter"
after=
"REMEMBER_ME_FILTER"
/>
<security:custom-filter
ref=
"CSRFPreventionFilter"
after=
"REMEMBER_ME_FILTER"
/>
...
@@ -53,7 +54,7 @@
...
@@ -53,7 +54,7 @@
username-parameter=
"j_username"
username-parameter=
"j_username"
password-parameter=
"j_password"
/>
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"
/>
logout-url=
"/logout.html"
/>
<http-basic
/>
<http-basic
/>
<security:custom-filter
position=
"LAST"
ref=
"atlasAuthorizationFilter"
/>
<security:custom-filter
position=
"LAST"
ref=
"atlasAuthorizationFilter"
/>
...
@@ -61,7 +62,10 @@
...
@@ -61,7 +62,10 @@
<beans:bean
id=
"krbAuthenticationFilter"
class=
"org.apache.atlas.web.filters.AtlasAuthenticationFilter"
>
<beans:bean
id=
"krbAuthenticationFilter"
class=
"org.apache.atlas.web.filters.AtlasAuthenticationFilter"
>
</beans:bean>
</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
id=
"CSRFPreventionFilter"
class=
"org.apache.atlas.web.filters.AtlasCSRFPreventionFilter"
>
</beans:bean>
</beans:bean>
...
...
This diff is collapsed.
Click to expand it.
webapp/src/main/webapp/WEB-INF/web.xml
View file @
854b7928
...
@@ -79,5 +79,14 @@
...
@@ -79,5 +79,14 @@
</listener>
</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>
</web-app>
This diff is collapsed.
Click to expand it.
webapp/src/test/webapp/WEB-INF/web.xml
View file @
854b7928
...
@@ -73,4 +73,13 @@
...
@@ -73,4 +73,13 @@
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</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>
</web-app>
This diff is collapsed.
Click to expand it.
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