diff --git a/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/ActiveDirectoryLdapAuthoritiesPopulator.scala b/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/ActiveDirectoryLdapAuthoritiesPopulator.scala new file mode 100644 index 0000000..8fb3480 --- /dev/null +++ b/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/ActiveDirectoryLdapAuthoritiesPopulator.scala @@ -0,0 +1,45 @@ +/* + * Copyright 2023 ABSA Group Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package za.co.absa.loginsvc.rest.provider.kerberos + +import org.springframework.ldap.core.DirContextOperations +import org.springframework.security.core.GrantedAuthority +import org.springframework.security.core.authority.{AuthorityUtils, SimpleGrantedAuthority} +import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator + +import java.util +import javax.naming.ldap.LdapName + +class ActiveDirectoryLdapAuthoritiesPopulator extends LdapAuthoritiesPopulator { + + import scala.collection.JavaConverters._ + + override def getGrantedAuthorities(userData: DirContextOperations, username: String): util.Collection[_ <: GrantedAuthority] = { + val groups = userData.getStringAttributes("memberOf") + + if (groups == null) { + AuthorityUtils.NO_AUTHORITIES + } + else { + groups.map({group => + val ldapName = new LdapName(group) + val role = ldapName.getRdn(ldapName.size() - 1).getValue.toString + new SimpleGrantedAuthority(role) + }).toList.asJava + } + } +} diff --git a/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProvider.scala b/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProvider.scala index e646182..f452838 100644 --- a/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProvider.scala +++ b/api/src/main/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProvider.scala @@ -23,13 +23,18 @@ import org.springframework.security.core.authority.AuthorityUtils import org.springframework.security.core.userdetails.{User, UserDetails, UserDetailsService} import org.springframework.security.kerberos.authentication.{KerberosAuthenticationProvider, KerberosServiceAuthenticationProvider} import org.springframework.security.kerberos.authentication.sun.{SunJaasKerberosClient, SunJaasKerberosTicketValidator} +import org.springframework.security.kerberos.client.config.SunJaasKrb5LoginConfig +import org.springframework.security.kerberos.client.ldap.KerberosLdapContextSource import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter +import org.springframework.security.ldap.search.FilterBasedLdapUserSearch +import org.springframework.security.ldap.userdetails.{LdapUserDetailsMapper, LdapUserDetailsService} import za.co.absa.loginsvc.rest.config.auth.ActiveDirectoryLDAPConfig class KerberosSPNEGOAuthenticationProvider(activeDirectoryLDAPConfig: ActiveDirectoryLDAPConfig) { //TODO: Split into Multiple files for neater implementation - private val kerberos = activeDirectoryLDAPConfig.enableKerberos.get + private val ldapConfig = activeDirectoryLDAPConfig + private val kerberos = ldapConfig.enableKerberos.get private val kerberosDebug = kerberos.debug.getOrElse(false) private val logger = LoggerFactory.getLogger(classOf[KerberosSPNEGOAuthenticationProvider]) logger.debug(s"KerberosSPNEGOAuthenticationProvider init") @@ -39,7 +44,7 @@ class KerberosSPNEGOAuthenticationProvider(activeDirectoryLDAPConfig: ActiveDire if (kerberos.krbFileLocation.nonEmpty) { logger.info(s"Using KRB5 CONF from ${kerberos.krbFileLocation}") - System.setProperty("java.security.krb5.conf", kerberos.krbFileLocation) + System.setProperty("java.security.krb5.ini", kerberos.krbFileLocation) } def kerberosAuthenticationProvider(): KerberosAuthenticationProvider = @@ -77,6 +82,31 @@ class KerberosSPNEGOAuthenticationProvider(activeDirectoryLDAPConfig: ActiveDire ticketValidator } + private def loginConfig(): SunJaasKrb5LoginConfig = { + val loginConfig = new SunJaasKrb5LoginConfig() + loginConfig.setServicePrincipal(kerberos.spn) + loginConfig.setKeyTabLocation(new FileSystemResource(kerberos.keytabFileLocation)) + loginConfig.setDebug(kerberosDebug) + loginConfig.setIsInitiator(true) + loginConfig.setUseTicketCache(false) + loginConfig.afterPropertiesSet() + loginConfig + } + + private def kerberosLdapContextSource(): KerberosLdapContextSource = { + val contextSource = new KerberosLdapContextSource(ldapConfig.url) + contextSource.setLoginConfig(loginConfig()) + contextSource.afterPropertiesSet() + contextSource + } + + private def ldapUserDetailsService() = { + val userSearch = new FilterBasedLdapUserSearch(activeDirectoryLDAPConfig.domain, activeDirectoryLDAPConfig.searchFilter, kerberosLdapContextSource()) + val service = new LdapUserDetailsService(userSearch, new ActiveDirectoryLdapAuthoritiesPopulator()) + service.setUserDetailsMapper(new LdapUserDetailsMapper()) + service + } + private def dummyUserDetailsService = new DummyUserDetailsService }