You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by sh...@apache.org on 2015/12/11 10:33:16 UTC
kylin git commit: KYLIN-1219 support SSO with Spring SAML
Repository: kylin
Updated Branches:
refs/heads/2.x-staging 82258382d -> 9ba89b886
KYLIN-1219 support SSO with Spring SAML
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/9ba89b88
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/9ba89b88
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/9ba89b88
Branch: refs/heads/2.x-staging
Commit: 9ba89b88679ac9e543d1e85f955ad63e8192f9cc
Parents: 8225838
Author: shaofengshi <sh...@apache.org>
Authored: Fri Dec 11 17:32:18 2015 +0800
Committer: shaofengshi <sh...@apache.org>
Committed: Fri Dec 11 17:33:01 2015 +0800
----------------------------------------------------------------------
build/bin/kylin.sh | 9 +-
build/conf/kylin.properties | 37 +-
.../test_case_data/localmeta/kylin.properties | 4 +-
.../test_case_data/sandbox/kylin.properties | 4 +-
pom.xml | 2 +
server/pom.xml | 28 ++
.../security/KylinAuthenticationProvider.java | 101 +++++
.../kylin/rest/security/LdapProvider.java | 1 +
.../rest/security/SAMLUserDetailsService.java | 32 ++
.../src/main/resources/applicationContext.xml | 6 +-
.../resources/kylin-server-log4j.properties | 5 +
server/src/main/resources/kylinSecurity.xml | 452 ++++++++++++++++---
12 files changed, 586 insertions(+), 95 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/build/bin/kylin.sh
----------------------------------------------------------------------
diff --git a/build/bin/kylin.sh b/build/bin/kylin.sh
index 9e91131..50c5ce2 100644
--- a/build/bin/kylin.sh
+++ b/build/bin/kylin.sh
@@ -49,11 +49,7 @@ then
- useSandbox=`sh ${dir}/get-properties.sh kylin.sandbox`
- spring_profile="default"
- if [ "$useSandbox" = "true" ]
- then spring_profile="sandbox"
- fi
+ spring_profile=`sh ${dir}/get-properties.sh kylin.security.profile`
#retrive $hive_dependency and $hbase_dependency
source ${dir}/find-hive-dependency.sh
@@ -64,7 +60,8 @@ then
fi
export HBASE_CLASSPATH_PREFIX=${tomcat_root}/bin/bootstrap.jar:${tomcat_root}/bin/tomcat-juli.jar:${tomcat_root}/lib/*:$HBASE_CLASSPATH_PREFIX
- export HBASE_CLASSPATH=$hive_dependency:${HBASE_CLASSPATH}
+ mkdir -p ${KYLIN_HOME}/ext
+ export HBASE_CLASSPATH=$hive_dependency:${KYLIN_HOME}/lib/*:${KYLIN_HOME}/ext/*:${HBASE_CLASSPATH}
#debug if encounter NoClassDefError
#hbase classpath
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/build/conf/kylin.properties
----------------------------------------------------------------------
diff --git a/build/conf/kylin.properties b/build/conf/kylin.properties
index cc91824..36f34a7 100644
--- a/build/conf/kylin.properties
+++ b/build/conf/kylin.properties
@@ -60,19 +60,42 @@ kylin.hbase.region.cut.small=5
kylin.hbase.region.cut.medium=10
kylin.hbase.region.cut.large=50
-## Config for Restful APP ##
-# database connection settings:
-ldap.server=
+
+## kylin security configurations
+
+# spring security profile, options: testing, ldap, saml
+# with "testing" profile, user can use pre-defined name/pwd like KYLIN/ADMIN to login
+kylin.security.profile=testing
+
+# default roles and admin roles in LDAP, for ldap and saml
+acl.defaultRole=ROLE_ANALYST,ROLE_MODELER
+acl.adminRole=ROLE_ADMIN
+
+#LDAP authentication configuration
+ldap.server=ldap://ldap_server:389
ldap.username=
ldap.password=
+
+#LDAP user account directory;
ldap.user.searchBase=
ldap.user.searchPattern=
ldap.user.groupSearchBase=
-ldap.service.searchBase=OU=
+
+#LDAP service account directory
+ldap.service.searchBase=
ldap.service.searchPattern=
ldap.service.groupSearchBase=
-acl.adminRole=
-acl.defaultRole=
+
+#SAML configurations for SSO
+# SAML IDP metadata file location
+saml.metadata.file=classpath:sso_metadata.xml
+saml.metadata.entityBaseURL=https://hostname/kylin
+saml.context.scheme=https
+saml.context.serverName=hostname
+saml.context.serverPort=443
+saml.context.contextPath=/kylin
+
+
ganglia.group=
ganglia.port=8664
@@ -105,5 +128,5 @@ kylin.web.contact_mail=
#env DEV|QA|PROD
deploy.env=DEV
-###########################config info for sandbox#######################
+###########################deprecated configs#######################
kylin.sandbox=true
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/examples/test_case_data/localmeta/kylin.properties
----------------------------------------------------------------------
diff --git a/examples/test_case_data/localmeta/kylin.properties b/examples/test_case_data/localmeta/kylin.properties
index 48f01f5..a008494 100644
--- a/examples/test_case_data/localmeta/kylin.properties
+++ b/examples/test_case_data/localmeta/kylin.properties
@@ -40,7 +40,7 @@ kylin.job.yarn.app.rest.check.interval.seconds=10
kylin.hbase.default.compression.codec=gzip
-
+kylin.security.profile=testing
## Config for Restful APP ##
# database connection settings:
ldap.server=
@@ -57,7 +57,5 @@ acl.defaultRole=
ganglia.group=
ganglia.port=8664
-###########################config info for sandbox#######################
-kylin.sandbox=true
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/examples/test_case_data/sandbox/kylin.properties
----------------------------------------------------------------------
diff --git a/examples/test_case_data/sandbox/kylin.properties b/examples/test_case_data/sandbox/kylin.properties
index 35e2927..a12bc40 100644
--- a/examples/test_case_data/sandbox/kylin.properties
+++ b/examples/test_case_data/sandbox/kylin.properties
@@ -51,6 +51,8 @@ kylin.job.yarn.app.rest.check.interval.seconds=10
#default compression codec for htable,snappy,lzo,gzip,lz4
kylin.hbase.default.compression.codec=gzip
+kylin.security.profile=testing
+
## Config for Restful APP ##
# database connection settings:
ldap.server=
@@ -96,6 +98,4 @@ kylin.web.contact_mail=
#env DEV|QA|PROD
deploy.env=DEV
-###########################config info for sandbox#######################
-kylin.sandbox=true
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 82dc06b..28ab8d7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,8 @@
<!-- REST Service -->
<spring.framework.version>3.1.2.RELEASE</spring.framework.version>
+ <spring.framework.security.extensions.version>1.0.1.RELEASE</spring.framework.security.extensions.version>
+ <opensaml.version>2.6.1</opensaml.version>
<spring.boot.version>1.2.7.RELEASE</spring.boot.version>
<!-- Calcite Version -->
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 304bb73..eeb37f7 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -204,6 +204,34 @@
<version>${spring.framework.version}</version>
</dependency>
<dependency>
+ <groupId>org.springframework.security.extensions</groupId>
+ <artifactId>spring-security-saml2-core</artifactId>
+ <version>${spring.framework.security.extensions.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opensaml</groupId>
+ <artifactId>opensaml</artifactId>
+ <version>${opensaml.version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>xml-apis</artifactId>
+ <groupId>org.apache.xerces</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <groupId>org.slf4j</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>serializer</artifactId>
+ <groupId>org.apache.xerces</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <groupId>org.slf4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java b/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
new file mode 100644
index 0000000..be28bdd
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
@@ -0,0 +1,101 @@
+package org.apache.kylin.rest.security;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+import org.apache.kylin.rest.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.saml.SAMLAuthenticationProvider;
+import org.springframework.util.Assert;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+/**
+ * A wrapper class for the authentication provider; Will do something more for Kylin.
+ */
+public class KylinAuthenticationProvider implements AuthenticationProvider {
+
+ private static final Logger logger = LoggerFactory.getLogger(KylinAuthenticationProvider.class);
+
+ @Autowired
+ UserService userService;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ //Embedded authentication provider
+ private AuthenticationProvider authenticationProvider;
+
+ MessageDigest md = null;
+
+ public KylinAuthenticationProvider(AuthenticationProvider authenticationProvider) {
+ super();
+ Assert.notNull(authenticationProvider, "The embedded authenticationProvider should not be null.");
+ this.authenticationProvider = authenticationProvider;
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Failed to init Message Digest ", e);
+ }
+ }
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+ Authentication authed = null;
+ Cache userCache = cacheManager.getCache("UserCache");
+ md.reset();
+ byte[] hashKey = md.digest((authentication.getName() + authentication.getCredentials()).getBytes());
+ String userKey = Arrays.toString(hashKey);
+
+ Element authedUser = userCache.get(userKey);
+ if (null != authedUser) {
+ authed = (Authentication) authedUser.getObjectValue();
+ SecurityContextHolder.getContext().setAuthentication(authed);
+ } else {
+ try {
+ authed = authenticationProvider.authenticate(authentication);
+ userCache.put(new Element(userKey, authed));
+ } catch (AuthenticationException e) {
+ logger.error("Failed to auth user: " + authentication.getName(), e);
+ throw e;
+ }
+
+ logger.debug("Authenticated user " + authed.toString());
+
+ UserDetails user = (UserDetails)authed.getDetails();
+ Assert.notNull(user, "The UserDetail is null.");
+
+ logger.debug("User authorities :" + user.getAuthorities());
+ if (!userService.userExists(user.getUsername())) {
+ userService.createUser(user);
+ } else {
+ userService.updateUser(user);
+ }
+ }
+
+ return authed;
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return authenticationProvider.supports(authentication);
+ }
+
+ public AuthenticationProvider getAuthenticationProvider() {
+ return authenticationProvider;
+ }
+
+ public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
+ this.authenticationProvider = authenticationProvider;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java b/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
index b34a2bd..2dae90b 100644
--- a/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
+++ b/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
@@ -41,6 +41,7 @@ import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
/**
* @author xduo
+ * @deprecated replaced by KylinAuthenticationProvider
*
*/
public class LdapProvider extends LdapAuthenticationProvider {
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java b/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
new file mode 100644
index 0000000..8d13805
--- /dev/null
+++ b/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
@@ -0,0 +1,32 @@
+package org.apache.kylin.rest.security;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.ldap.userdetails.LdapUserDetailsService;
+import org.springframework.security.saml.SAMLCredential;
+
+/**
+ * An implementation of SAMLUserDetailsService by delegating the query to LdapUserDetailsService.
+ */
+public class SAMLUserDetailsService implements org.springframework.security.saml.userdetails.SAMLUserDetailsService {
+
+ private static final Logger logger = LoggerFactory.getLogger(SAMLUserDetailsService.class);
+ private LdapUserDetailsService ldapUserDetailsService;
+
+ public SAMLUserDetailsService(LdapUserDetailsService ldapUserDetailsService) {
+ this.ldapUserDetailsService = ldapUserDetailsService;
+ }
+
+ @Override
+ public Object loadUserBySAML(SAMLCredential samlCredential) throws UsernameNotFoundException {
+ final String userEmail = samlCredential.getAttributeAsString("email");
+ logger.debug("samlCredential.email:" + userEmail);
+ final String userName = userEmail.substring(0, userEmail.indexOf("@"));
+
+ UserDetails userDetails = ldapUserDetailsService.loadUserByUsername(userName);
+ logger.debug("userDeail by search ldap with '" + userName + "' is: " + userDetails);
+ return userDetails;
+ }
+}
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/resources/applicationContext.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/applicationContext.xml b/server/src/main/resources/applicationContext.xml
index a103b56..dd66070 100644
--- a/server/src/main/resources/applicationContext.xml
+++ b/server/src/main/resources/applicationContext.xml
@@ -85,19 +85,19 @@
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehcache"/>
- <beans profile="default">
+ <beans profile="ldap,saml">
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml" p:shared="true"/>
</beans>
- <beans profile="sandbox,testing">
+ <beans profile="testing">
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache-test.xml" p:shared="true"/>
</beans>
<!-- hbase storage/global lock Config -->
- <beans profile="default,sandbox">
+ <beans profile="ldap,saml">
<bean id="aclHBaseStorage" class="org.apache.kylin.rest.security.RealAclHBaseStorage"/>
<bean id="jobLock" class="org.apache.kylin.storage.hbase.util.ZookeeperJobLock"/>
</beans>
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/resources/kylin-server-log4j.properties
----------------------------------------------------------------------
diff --git a/server/src/main/resources/kylin-server-log4j.properties b/server/src/main/resources/kylin-server-log4j.properties
index a93627a..f4df80d 100644
--- a/server/src/main/resources/kylin-server-log4j.properties
+++ b/server/src/main/resources/kylin-server-log4j.properties
@@ -49,3 +49,8 @@ log4j.logger.org.apache.kylin.query=DEBUG, query
log4j.logger.org.apache.kylin.rest.controller.JobController=DEBUG, job
log4j.logger.org.apache.kylin.rest.service.JobService=DEBUG, job
log4j.logger.org.apache.kylin.job=DEBUG, job
+
+#spring security config
+log4j.logger.org.springframework.security=INFO,file
+log4j.logger.org.opensaml=INFO,file
+log4j.logger.PROTOCOL_MESSAGE=INFO,file
http://git-wip-us.apache.org/repos/asf/kylin/blob/9ba89b88/server/src/main/resources/kylinSecurity.xml
----------------------------------------------------------------------
diff --git a/server/src/main/resources/kylinSecurity.xml b/server/src/main/resources/kylinSecurity.xml
index ee3c891..3b2125a 100644
--- a/server/src/main/resources/kylinSecurity.xml
+++ b/server/src/main/resources/kylinSecurity.xml
@@ -1,39 +1,16 @@
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:scr="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:scr="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ 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/tx
- http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
+ http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<scr:global-method-security pre-post-annotations="enabled">
<scr:expression-handler ref="expressionHandler" />
</scr:global-method-security>
- <scr:http auto-config="true" use-expressions="true">
- <scr:http-basic entry-point-ref="unauthorisedEntryPoint" />
-
- <scr:intercept-url pattern="/api/user/authentication*/**" access="permitAll" />
- <scr:intercept-url pattern="/api/query*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/metadata*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/**/metrics" access="permitAll" />
- <scr:intercept-url pattern="/api/cache*/**" access="permitAll" />
- <scr:intercept-url pattern="/api/cubes/src/tables" access="hasAnyRole('ROLE_ANALYST')" />
- <scr:intercept-url pattern="/api/cubes*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/models*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/streaming*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/job*/**" access="isAuthenticated()" />
- <scr:intercept-url pattern="/api/admin/config" access="permitAll" />
- <scr:intercept-url pattern="/api/projects" access="permitAll" />
- <scr:intercept-url pattern="/api/admin*/**" access="hasRole('ROLE_ADMIN')" />
- <scr:intercept-url pattern="/api/**" access="isAuthenticated()" />
-
- <scr:logout invalidate-session="true" delete-cookies="JSESSIONID" />
- <scr:session-management session-fixation-protection="newSession" />
- </scr:http>
-
- <!-- user auth -->
- <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
-
<!-- acl config -->
<bean id="aclPermissionFactory" class="org.apache.kylin.rest.security.AclPermissionFactory" />
@@ -45,6 +22,12 @@
<constructor-arg ref="aclService" />
<property name="permissionFactory" ref="aclPermissionFactory" />
</bean>
+
+ <bean id="ldapSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
+ <constructor-arg value="${ldap.server}" />
+ <property name="userDn" value="${ldap.username}" />
+ <property name="password" value="${ldap.password}" />
+ </bean>
<bean id="aclAuthorizationStrategy"
class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
@@ -70,72 +53,76 @@
<constructor-arg ref="auditLogger" />
</bean>
- <beans profile="default">
- <bean id="ldapUserAuthProvider" class="org.apache.kylin.rest.security.LdapProvider">
+ <beans profile="ldap">
+ <bean id="kylinUserAuthProvider" class="org.apache.kylin.rest.security.KylinAuthenticationProvider">
<constructor-arg>
- <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
- <constructor-arg ref="ldapSource" />
- <property name="userSearch">
- <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
- <constructor-arg index="0" value="${ldap.user.searchBase}" />
- <constructor-arg index="1" value="${ldap.user.searchPattern}" />
- <constructor-arg index="2" ref="ldapSource" />
+ <bean id="ldapUserAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
+ <constructor-arg>
+ <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
+ <constructor-arg ref="ldapSource" />
+ <property name="userSearch">
+ <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
+ <constructor-arg index="0" value="${ldap.user.searchBase}" />
+ <constructor-arg index="1" value="${ldap.user.searchPattern}" />
+ <constructor-arg index="2" ref="ldapSource" />
+ </bean>
+ </property>
</bean>
- </property>
- </bean>
- </constructor-arg>
- <constructor-arg>
- <bean class="org.apache.kylin.rest.security.AuthoritiesPopulator">
- <constructor-arg index="0" ref="ldapSource" />
- <constructor-arg index="1" value="${ldap.user.groupSearchBase}" />
- <constructor-arg index="2" value="${acl.adminRole}" />
- <constructor-arg index="3" value="${acl.defaultRole}" />
+ </constructor-arg>
+ <constructor-arg>
+ <bean class="org.apache.kylin.rest.security.AuthoritiesPopulator">
+ <constructor-arg index="0" ref="ldapSource" />
+ <constructor-arg index="1" value="${ldap.user.groupSearchBase}" />
+ <constructor-arg index="2" value="${acl.adminRole}" />
+ <constructor-arg index="3" value="${acl.defaultRole}" />
+ </bean>
+ </constructor-arg>
</bean>
</constructor-arg>
</bean>
- <bean id="ldapServiceAccountAuthProvider" class="org.apache.kylin.rest.security.LdapProvider">
+ <bean id="kylinServiceAccountAuthProvider" class="org.apache.kylin.rest.security.KylinAuthenticationProvider">
<constructor-arg>
- <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
- <constructor-arg ref="ldapSource" />
- <property name="userSearch">
- <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
- <constructor-arg index="0" value="${ldap.service.searchBase}" />
- <constructor-arg index="1" value="${ldap.service.searchPattern}" />
- <constructor-arg index="2" ref="ldapSource" />
+ <bean id="ldapServiceAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
+ <constructor-arg>
+ <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
+ <constructor-arg ref="ldapSource" />
+ <property name="userSearch">
+ <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
+ <constructor-arg index="0" value="${ldap.service.searchBase}" />
+ <constructor-arg index="1" value="${ldap.service.searchPattern}" />
+ <constructor-arg index="2" ref="ldapSource" />
+ </bean>
+ </property>
</bean>
- </property>
- </bean>
- </constructor-arg>
- <constructor-arg>
- <bean class="org.apache.kylin.rest.security.AuthoritiesPopulator">
- <constructor-arg index="0" ref="ldapSource" />
- <constructor-arg index="1" value="${ldap.service.groupSearchBase}" />
- <constructor-arg index="2" value="${acl.adminRole}" />
- <constructor-arg index="3" value="${acl.defaultRole}" />
+ </constructor-arg>
+ <constructor-arg>
+ <bean class="org.apache.kylin.rest.security.AuthoritiesPopulator">
+ <constructor-arg index="0" ref="ldapSource" />
+ <constructor-arg index="1" value="${ldap.service.groupSearchBase}" />
+ <constructor-arg index="2" value="${acl.adminRole}" />
+ <constructor-arg index="3" value="${acl.defaultRole}" />
+ </bean>
+ </constructor-arg>
</bean>
</constructor-arg>
</bean>
- <scr:authentication-manager alias="authenticationManager">
+ <scr:authentication-manager alias="ldapAuthenticationManager">
<!-- do user ldap auth -->
- <scr:authentication-provider ref="ldapUserAuthProvider"></scr:authentication-provider>
+ <scr:authentication-provider ref="kylinUserAuthProvider"></scr:authentication-provider>
<!-- do service account ldap auth -->
- <scr:authentication-provider ref="ldapServiceAccountAuthProvider"></scr:authentication-provider>
-
- <!-- custom user provider <authentication-provider user-service-ref="userService"> <password-encoder ref="passwordEncoder" /> </authentication-provider> -->
+ <scr:authentication-provider ref="kylinServiceAccountAuthProvider"></scr:authentication-provider>
</scr:authentication-manager>
- <bean id="ldapSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
- <constructor-arg value="${ldap.server}" />
- <property name="userDn" value="${ldap.username}" />
- <property name="password" value="${ldap.password}" />
- </bean>
</beans>
- <beans profile="sandbox,testing">
- <scr:authentication-manager alias="authenticationManager">
+ <beans profile="testing">
+ <!-- user auth -->
+ <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
+
+ <scr:authentication-manager alias="testingAuthenticationManager">
<scr:authentication-provider>
<scr:user-service>
<scr:user name="MODELER" password="$2a$10$Le5ernTeGNIARwMJsY0WaOLioNQdb0QD11DwjeyNqqNRp5NaDo2FG" authorities="ROLE_MODELER" />
@@ -146,4 +133,321 @@
</scr:authentication-provider>
</scr:authentication-manager>
</beans>
+
+ <beans profile="testing,ldap">
+ <scr:http auto-config="true" use-expressions="true">
+ <scr:http-basic entry-point-ref="unauthorisedEntryPoint" />
+
+ <scr:intercept-url pattern="/api/user/authentication*/**" access="permitAll" />
+ <scr:intercept-url pattern="/api/query*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/metadata*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/**/metrics" access="permitAll" />
+ <scr:intercept-url pattern="/api/cache*/**" access="permitAll" />
+ <scr:intercept-url pattern="/api/cubes/src/tables" access="hasAnyRole('ROLE_ANALYST')" />
+ <scr:intercept-url pattern="/api/cubes*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/models*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/streaming*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/job*/**" access="isAuthenticated()" />
+ <scr:intercept-url pattern="/api/admin/config" access="permitAll" />
+ <scr:intercept-url pattern="/api/projects" access="permitAll" />
+ <scr:intercept-url pattern="/api/admin*/**" access="hasRole('ROLE_ADMIN')" />
+ <scr:intercept-url pattern="/api/**" access="isAuthenticated()" />
+
+ <scr:logout invalidate-session="true" delete-cookies="JSESSIONID" />
+ <scr:session-management session-fixation-protection="newSession" />
+ </scr:http>
+ </beans>
+
+ <beans profile="saml">
+ <!-- Enable auto-wiring -->
+ <context:annotation-config/>
+
+ <!-- Scan for auto-wiring classes in spring saml packages -->
+ <context:component-scan base-package="org.springframework.security.saml"/>
+
+ <!-- Unsecured pages -->
+ <scr:http security="none" pattern="/images/**"/>
+ <scr:http security="none" pattern="/css/**"/>
+ <scr:http security="none" pattern="/fonts/**"/>
+ <scr:http security="none" pattern="/js/**"/>
+ <scr:http security="none" pattern="/login/**"/>
+ <scr:http security="none" pattern="/api/projects" />
+
+ <!-- Secured pages with SAML as entry point -->
+ <scr:http entry-point-ref="samlEntryPoint" use-expressions="false">
+ <scr:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
+ <scr:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
+ <scr:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
+ </scr:http>
+
+ <!-- Central storage of cryptographic keys -->
+ <bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
+ <constructor-arg value="classpath:samlKeystore.jks"/>
+ <constructor-arg type="java.lang.String" value="changeit"/>
+ <constructor-arg>
+ <map>
+ <entry key="kylin" value="changeit"/>
+ </map>
+ </constructor-arg>
+ <constructor-arg type="java.lang.String" value="kylin"/>
+ </bean>
+
+ <!-- Filters for processing of SAML messages -->
+ <bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy">
+ <scr:filter-chain-map request-matcher="ant">
+ <scr:filter-chain pattern="/saml/login/**" filters="samlEntryPoint"/>
+ <scr:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter"/>
+ <scr:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter"/>
+ <scr:filter-chain pattern="/saml/SSO/**" filters="samlWebSSOProcessingFilter"/>
+ <scr:filter-chain pattern="/saml/SSOHoK/**" filters="samlWebSSOHoKProcessingFilter"/>
+ <scr:filter-chain pattern="/saml/SingleLogout/**" filters="samlLogoutProcessingFilter"/>
+ </scr:filter-chain-map>
+ </bean>
+
+ <!-- Handler deciding where to redirect user after successful login -->
+ <bean id="successRedirectHandler"
+ class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
+ <property name="defaultTargetUrl" value="/models"/>
+ </bean>
+
+ <!-- Handler deciding where to redirect user after failed login -->
+ <bean id="failureRedirectHandler"
+ class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
+ <property name="useForward" value="true"/>
+ <property name="defaultFailureUrl" value="/login"/>
+ </bean>
+
+ <!-- Handler for successful logout -->
+ <bean id="successLogoutHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler">
+ <property name="defaultTargetUrl" value="/login"/>
+ </bean>
+
+ <scr:authentication-manager alias="samlAuthenticationManager">
+ <!-- Register authentication manager for SAML provider -->
+ <scr:authentication-provider ref="kylinAuthenticationProvider"/>
+ </scr:authentication-manager>
+
+ <!-- Logger for SAML messages and events -->
+ <bean id="samlLogger" class="org.springframework.security.saml.log.SAMLDefaultLogger"/>
+
+ <!-- Filter automatically generates default SP metadata -->
+ <bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
+ <constructor-arg>
+ <bean class="org.springframework.security.saml.metadata.MetadataGenerator">
+ <property name="extendedMetadata">
+ <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
+ <property name="idpDiscoveryEnabled" value="false"/>
+ </bean>
+ </property>
+ <property name="entityBaseURL" value = "${saml.metadata.entityBaseURL}"/>
+ </bean>
+ </constructor-arg>
+ </bean>
+
+ <!-- Entry point to initialize authentication, default values taken from properties file -->
+ <bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
+ <property name="defaultProfileOptions">
+ <bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
+ <property name="includeScoping" value="false"/>
+ </bean>
+ </property>
+ </bean>
+
+ <!-- The filter is waiting for connections on URL suffixed with filterSuffix and presents SP metadata there -->
+ <bean id="metadataDisplayFilter" class="org.springframework.security.saml.metadata.MetadataDisplayFilter"/>
+
+ <!-- IDP Metadata configuration - paths to metadata of IDPs in circle of trust is here -->
+ <bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
+ <constructor-arg>
+ <list>
+ <!-- Example of classpath metadata with Extended Metadata -->
+ <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
+ <constructor-arg>
+ <bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
+ <constructor-arg>
+ <value type="java.io.File">classpath:sso_metadata.xml</value>
+ </constructor-arg>
+ <property name="parserPool" ref="parserPool"/>
+ </bean>
+ </constructor-arg>
+ <constructor-arg>
+ <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
+ </bean>
+ </constructor-arg>
+ <property name="metadataTrustCheck" value="false"/>
+ </bean>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="ldapUserAuthoritiesPopulator" class="org.apache.kylin.rest.security.AuthoritiesPopulator">
+ <constructor-arg index="0" ref="ldapSource" />
+ <constructor-arg index="1" value="${ldap.user.groupSearchBase}" />
+ <constructor-arg index="2" value="${acl.adminRole}" />
+ <constructor-arg index="3" value="${acl.defaultRole}" />
+ </bean>
+
+ <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
+ <constructor-arg index="0" value="${ldap.user.searchBase}" />
+ <constructor-arg index="1" value="${ldap.user.searchPattern}" />
+ <constructor-arg index="2" ref="ldapSource" />
+ </bean>
+
+
+ <bean id="samlUserDetailsService" class="org.apache.kylin.rest.security.SAMLUserDetailsService">
+ <constructor-arg>
+ <bean id="ldapUserDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
+ <constructor-arg ref="userSearch" />
+ <constructor-arg ref="ldapUserAuthoritiesPopulator" />
+ </bean>
+ </constructor-arg>
+ </bean>
+
+ <bean id="kylinAuthenticationProvider" class="org.apache.kylin.rest.security.KylinAuthenticationProvider">
+ <constructor-arg>
+ <!-- SAML Authentication Provider responsible for validating of received SAML messages -->
+ <bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
+ <!-- OPTIONAL property: can be used to store/load user data after login -->
+ <property name="userDetails" ref="samlUserDetailsService" />
+ </bean>
+ </constructor-arg>
+ </bean>
+
+
+ <!-- Provider of default SAML Context -->
+ <!--
+ <bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderImpl"/>
+ -->
+
+ <!-- Provider of a SAML Context behind a LoadBanlancer or reverse proxy -->
+ <bean id="contextProvider" class="org.springframework.security.saml.context.SAMLContextProviderLB">
+ <property name="scheme" value="${saml.context.scheme}"/>
+ <property name="serverName" value="${saml.context.serverName}"/>
+ <property name="serverPort" value="${saml.context.serverPort}"/>
+ <property name="includeServerPortInRequestURL" value="false"/>
+ <property name="contextPath" value="${saml.context.contextPath}"/>
+ </bean>
+
+
+ <!-- Processing filter for WebSSO profile messages -->
+ <bean id="samlWebSSOProcessingFilter" class="org.springframework.security.saml.SAMLProcessingFilter">
+ <property name="authenticationManager" ref="samlAuthenticationManager"/>
+ <property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
+ <property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
+ </bean>
+
+ <!-- Processing filter for WebSSO Holder-of-Key profile -->
+ <bean id="samlWebSSOHoKProcessingFilter" class="org.springframework.security.saml.SAMLWebSSOHoKProcessingFilter">
+ <property name="authenticationManager" ref="samlAuthenticationManager"/>
+ <property name="authenticationSuccessHandler" ref="successRedirectHandler"/>
+ <property name="authenticationFailureHandler" ref="failureRedirectHandler"/>
+ </bean>
+
+ <!-- Logout handler terminating local session -->
+ <bean id="logoutHandler"
+ class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
+ <property name="invalidateHttpSession" value="false"/>
+ </bean>
+
+ <!-- Override default logout processing filter with the one processing SAML messages -->
+ <bean id="samlLogoutFilter" class="org.springframework.security.saml.SAMLLogoutFilter">
+ <constructor-arg index="0" ref="successLogoutHandler"/>
+ <constructor-arg index="1" ref="logoutHandler"/>
+ <constructor-arg index="2" ref="logoutHandler"/>
+ </bean>
+
+ <!-- Filter processing incoming logout messages -->
+ <!-- First argument determines URL user will be redirected to after successful global logout -->
+ <bean id="samlLogoutProcessingFilter" class="org.springframework.security.saml.SAMLLogoutProcessingFilter">
+ <constructor-arg index="0" ref="successLogoutHandler"/>
+ <constructor-arg index="1" ref="logoutHandler"/>
+ </bean>
+
+ <!-- Class loading incoming SAML messages from httpRequest stream -->
+ <bean id="processor" class="org.springframework.security.saml.processor.SAMLProcessorImpl">
+ <constructor-arg>
+ <list>
+ <ref bean="redirectBinding"/>
+ <ref bean="postBinding"/>
+ <ref bean="artifactBinding"/>
+ <ref bean="soapBinding"/>
+ <ref bean="paosBinding"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <!-- SAML 2.0 WebSSO Assertion Consumer -->
+ <bean id="webSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerImpl"/>
+
+ <!-- SAML 2.0 Holder-of-Key WebSSO Assertion Consumer -->
+ <bean id="hokWebSSOprofileConsumer" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
+
+ <!-- SAML 2.0 Web SSO profile -->
+ <bean id="webSSOprofile" class="org.springframework.security.saml.websso.WebSSOProfileImpl"/>
+
+ <!-- SAML 2.0 Holder-of-Key Web SSO profile -->
+ <bean id="hokWebSSOProfile" class="org.springframework.security.saml.websso.WebSSOProfileConsumerHoKImpl"/>
+
+ <!-- SAML 2.0 ECP profile -->
+ <bean id="ecpprofile" class="org.springframework.security.saml.websso.WebSSOProfileECPImpl"/>
+
+ <!-- SAML 2.0 Logout Profile -->
+ <bean id="logoutprofile" class="org.springframework.security.saml.websso.SingleLogoutProfileImpl"/>
+
+ <!-- Bindings, encoders and decoders used for creating and parsing messages -->
+ <bean id="postBinding" class="org.springframework.security.saml.processor.HTTPPostBinding">
+ <constructor-arg ref="parserPool"/>
+ <constructor-arg ref="velocityEngine"/>
+ </bean>
+
+ <bean id="redirectBinding" class="org.springframework.security.saml.processor.HTTPRedirectDeflateBinding">
+ <constructor-arg ref="parserPool"/>
+ </bean>
+
+ <bean id="artifactBinding" class="org.springframework.security.saml.processor.HTTPArtifactBinding">
+ <constructor-arg ref="parserPool"/>
+ <constructor-arg ref="velocityEngine"/>
+ <constructor-arg>
+ <bean class="org.springframework.security.saml.websso.ArtifactResolutionProfileImpl">
+ <constructor-arg>
+ <bean class="org.apache.commons.httpclient.HttpClient">
+ <constructor-arg>
+ <bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
+ </constructor-arg>
+ </bean>
+ </constructor-arg>
+ <property name="processor">
+ <bean class="org.springframework.security.saml.processor.SAMLProcessorImpl">
+ <constructor-arg ref="soapBinding"/>
+ </bean>
+ </property>
+ </bean>
+ </constructor-arg>
+ </bean>
+
+ <bean id="soapBinding" class="org.springframework.security.saml.processor.HTTPSOAP11Binding">
+ <constructor-arg ref="parserPool"/>
+ </bean>
+
+ <bean id="paosBinding" class="org.springframework.security.saml.processor.HTTPPAOS11Binding">
+ <constructor-arg ref="parserPool"/>
+ </bean>
+
+ <!-- Initialization of OpenSAML library-->
+ <bean class="org.springframework.security.saml.SAMLBootstrap"/>
+
+ <!-- Initialization of the velocity engine -->
+ <bean id="velocityEngine" class="org.springframework.security.saml.util.VelocityFactory" factory-method="getEngine"/>
+
+ <!-- XML parser pool needed for OpenSAML parsing -->
+ <bean id="parserPool" class="org.opensaml.xml.parse.StaticBasicParserPool" init-method="initialize">
+ <property name="builderFeatures">
+ <map>
+ <entry key="http://apache.org/xml/features/dom/defer-node-expansion" value="false"/>
+ </map>
+ </property>
+ </bean>
+
+ <bean id="parserPoolHolder" class="org.springframework.security.saml.parser.ParserPoolHolder"/>
+ </beans>
</beans>
\ No newline at end of file