From 3043fe3e59a2ddfb80c69dd62e8749f015101787 Mon Sep 17 00:00:00 2001 From: Daniel Kavan Date: Thu, 28 May 2026 10:27:35 +0200 Subject: [PATCH 1/5] #171 KerberosSPNEGOAuthenticationProviderTest added --- ...erosSPNEGOAuthenticationProviderTest.scala | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala diff --git a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala new file mode 100644 index 0000000..d680652 --- /dev/null +++ b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala @@ -0,0 +1,119 @@ +/* + * 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.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import org.scalatest.BeforeAndAfterEach +import za.co.absa.loginsvc.rest.config.auth.{ActiveDirectoryLDAPConfig, KerberosConfig, LdapUserCredentialsConfig, ServiceAccountConfig} + +class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach { + + private val serviceAccount = ServiceAccountConfig( + "CN=%s,OU=Users,DC=example,DC=com", + Option(LdapUserCredentialsConfig("svc_user", "svc_pass")), + None, + None + ) + + private def createLdapConfig(kerberosConfig: KerberosConfig): ActiveDirectoryLDAPConfig = { + ActiveDirectoryLDAPConfig( + domain = "example.com", + url = "ldaps://localhost:636", + searchFilter = "(sAMAccountName={0})", + order = 1, + serviceAccount = serviceAccount, + enableKerberos = Some(kerberosConfig), + ldapRetry = None, + attributes = None + ) + } + + private def clearKerberosProperties(): Unit = { + System.clearProperty("javax.net.debug") + System.clearProperty("sun.security.krb5.debug") + System.clearProperty("sun.security.krb5.rcache") + System.clearProperty("java.security.krb5.conf") + } + + override def beforeEach(): Unit = { + clearKerberosProperties() + } + + override def afterEach(): Unit = { + clearKerberosProperties() + } + + // initialization tests + "KerberosSPNEGOAuthenticationProvider" should "set debug system properties to false when debug is None" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("javax.net.debug") shouldBe "false" + System.getProperty("sun.security.krb5.debug") shouldBe "false" + } + + it should "set debug system properties to false when debug is explicitly false" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(false)) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("javax.net.debug") shouldBe "false" + System.getProperty("sun.security.krb5.debug") shouldBe "false" + } + + it should "set debug system properties to true when debug is explicitly true" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("javax.net.debug") shouldBe "true" + System.getProperty("sun.security.krb5.debug") shouldBe "true" + } + + it should "always set sun.security.krb5.rcache to none" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("sun.security.krb5.rcache") shouldBe "none" + } + + it should "set java.security.krb5.conf when krbFileLocation is non-empty" in { + val kerberosConfig = KerberosConfig("/etc/krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("java.security.krb5.conf") shouldBe "/etc/krb5.conf" + } + + it should "not set java.security.krb5.conf when krbFileLocation is empty" in { + val kerberosConfig = KerberosConfig("", "test.keytab", "HTTP/host@REALM", debug = None) + val ldapConfig = createLdapConfig(kerberosConfig) + + new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + System.getProperty("java.security.krb5.conf") shouldBe null + } +} + From 6e7a10fa50598be574ac87f93191801fa951034c Mon Sep 17 00:00:00 2001 From: Daniel Kavan Date: Thu, 28 May 2026 11:17:11 +0200 Subject: [PATCH 2/5] #171 KerberosSPNEGOAuthenticationProviderTest added/adjusted --- ...erosSPNEGOAuthenticationProviderTest.scala | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala index d680652..58868b0 100644 --- a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala +++ b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala @@ -59,53 +59,51 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers } // initialization tests - "KerberosSPNEGOAuthenticationProvider" should "set debug system properties to false when debug is None" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) + "KerberosSPNEGOAuthenticationProvider" should + "set debug system properties to false when debug is None" + + " and set java.security.krb5.conf when krbFileLocation is non-empty" + + " and always set sun.security.krb5.rcache to none" in { + val kerberosConfig = KerberosConfig("/etc/krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) val ldapConfig = createLdapConfig(kerberosConfig) new KerberosSPNEGOAuthenticationProvider(ldapConfig) System.getProperty("javax.net.debug") shouldBe "false" System.getProperty("sun.security.krb5.debug") shouldBe "false" + System.getProperty("java.security.krb5.conf") shouldBe "/etc/krb5.conf" + System.getProperty("sun.security.krb5.rcache") shouldBe "none" } - it should "set debug system properties to false when debug is explicitly false" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(false)) + it should "set debug system properties to false when debug is explicitly false" + + " and set java.security.krb5.conf when krbFileLocation is non-empty" + + " and always set sun.security.krb5.rcache to none" in { + val kerberosConfig = KerberosConfig("/etc/krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(false)) val ldapConfig = createLdapConfig(kerberosConfig) new KerberosSPNEGOAuthenticationProvider(ldapConfig) System.getProperty("javax.net.debug") shouldBe "false" System.getProperty("sun.security.krb5.debug") shouldBe "false" + + System.getProperty("java.security.krb5.conf") shouldBe "/etc/krb5.conf" + System.getProperty("sun.security.krb5.rcache") shouldBe "none" } - it should "set debug system properties to true when debug is explicitly true" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) + it should "set debug system properties to true when debug is explicitly true" + + " and set java.security.krb5.conf when krbFileLocation is non-empty" + + " and always set sun.security.krb5.rcache to none" in { + val kerberosConfig = KerberosConfig("/etc/krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) val ldapConfig = createLdapConfig(kerberosConfig) new KerberosSPNEGOAuthenticationProvider(ldapConfig) System.getProperty("javax.net.debug") shouldBe "true" System.getProperty("sun.security.krb5.debug") shouldBe "true" - } - - it should "always set sun.security.krb5.rcache to none" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) - val ldapConfig = createLdapConfig(kerberosConfig) - - new KerberosSPNEGOAuthenticationProvider(ldapConfig) + System.getProperty("java.security.krb5.conf") shouldBe "/etc/krb5.conf" System.getProperty("sun.security.krb5.rcache") shouldBe "none" } - it should "set java.security.krb5.conf when krbFileLocation is non-empty" in { - val kerberosConfig = KerberosConfig("/etc/krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) - val ldapConfig = createLdapConfig(kerberosConfig) - - new KerberosSPNEGOAuthenticationProvider(ldapConfig) - - System.getProperty("java.security.krb5.conf") shouldBe "/etc/krb5.conf" - } it should "not set java.security.krb5.conf when krbFileLocation is empty" in { val kerberosConfig = KerberosConfig("", "test.keytab", "HTTP/host@REALM", debug = None) From f900806390b2c903ac3aa2203feb798dc478fc83 Mon Sep 17 00:00:00 2001 From: Daniel Kavan Date: Thu, 28 May 2026 11:32:24 +0200 Subject: [PATCH 3/5] #171 KerberosSPNEGOAuthenticationProviderTest added/adjusted - current implementation --- ...KerberosSPNEGOAuthenticationProvider.scala | 2 +- ...erosSPNEGOAuthenticationProviderTest.scala | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) 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 97b7156..49abcb3 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 @@ -59,7 +59,7 @@ class KerberosSPNEGOAuthenticationProvider(activeDirectoryLDAPConfig: ActiveDire provider } - private def sunJaasKerberosTicketValidator: SunJaasKerberosTicketValidator = + private[kerberos] def sunJaasKerberosTicketValidator: SunJaasKerberosTicketValidator = { val ticketValidator: SunJaasKerberosTicketValidator = new SunJaasKerberosTicketValidator() ticketValidator.setServicePrincipal(kerberos.spn) diff --git a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala index 58868b0..06bf18e 100644 --- a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala +++ b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala @@ -19,8 +19,10 @@ package za.co.absa.loginsvc.rest.provider.kerberos import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import org.scalatest.BeforeAndAfterEach +import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator import za.co.absa.loginsvc.rest.config.auth.{ActiveDirectoryLDAPConfig, KerberosConfig, LdapUserCredentialsConfig, ServiceAccountConfig} + class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach { private val serviceAccount = ServiceAccountConfig( @@ -113,5 +115,39 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers System.getProperty("java.security.krb5.conf") shouldBe null } + + // ticketValidator debug tests - currently hardcoded to true, insensitive to kerberosDebug + private def getTicketValidatorDebug(validator: SunJaasKerberosTicketValidator): Boolean = { + val debugField = classOf[SunJaasKerberosTicketValidator].getDeclaredField("debug") + debugField.setAccessible(true) + debugField.getBoolean(validator) + } + + it should "have ticketValidator debug set to true even when kerberosDebug is None (hardcoded)" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", None) + val ldapConfig = createLdapConfig(kerberosConfig) + val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + val validator = provider.sunJaasKerberosTicketValidator + getTicketValidatorDebug(validator) shouldBe true + } + + it should "have ticketValidator debug set to true even when kerberosDebug is explicitly false (hardcoded)" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(false)) + val ldapConfig = createLdapConfig(kerberosConfig) + val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + val validator = provider.sunJaasKerberosTicketValidator + getTicketValidatorDebug(validator) shouldBe true + } + + it should "have ticketValidator debug set to true when kerberosDebug is explicitly true (hardcoded)" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(true)) + val ldapConfig = createLdapConfig(kerberosConfig) + val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) + + val validator = provider.sunJaasKerberosTicketValidator + getTicketValidatorDebug(validator) shouldBe true + } } From 8e0d3409cc8cadf9229e93a779bdda93e26a3ec4 Mon Sep 17 00:00:00 2001 From: Daniel Kavan Date: Thu, 28 May 2026 11:35:23 +0200 Subject: [PATCH 4/5] #171 KerberosSPNEGOAuthenticationProvider.sunJaasKerberosTicketValidator now sets ticket validation's debug based on kerberosDebug. KerberosSPNEGOAuthenticationProviderTest adjusted. --- .../KerberosSPNEGOAuthenticationProvider.scala | 2 +- .../KerberosSPNEGOAuthenticationProviderTest.scala | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) 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 49abcb3..f25bd6e 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 @@ -64,7 +64,7 @@ class KerberosSPNEGOAuthenticationProvider(activeDirectoryLDAPConfig: ActiveDire val ticketValidator: SunJaasKerberosTicketValidator = new SunJaasKerberosTicketValidator() ticketValidator.setServicePrincipal(kerberos.spn) ticketValidator.setKeyTabLocation(new FileSystemResource(kerberos.keytabFileLocation)) - ticketValidator.setDebug(true) + ticketValidator.setDebug(kerberosDebug) ticketValidator.afterPropertiesSet() ticketValidator } diff --git a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala index 06bf18e..642b86a 100644 --- a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala +++ b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala @@ -116,32 +116,34 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers System.getProperty("java.security.krb5.conf") shouldBe null } - // ticketValidator debug tests - currently hardcoded to true, insensitive to kerberosDebug + /** + * Uses reflection to access the private `debug` field of the SunJaasKerberosTicketValidator instance + */ private def getTicketValidatorDebug(validator: SunJaasKerberosTicketValidator): Boolean = { val debugField = classOf[SunJaasKerberosTicketValidator].getDeclaredField("debug") debugField.setAccessible(true) debugField.getBoolean(validator) } - it should "have ticketValidator debug set to true even when kerberosDebug is None (hardcoded)" in { + it should "have ticketValidator debug set to false even when kerberosDebug is None (default)" in { val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", None) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) val validator = provider.sunJaasKerberosTicketValidator - getTicketValidatorDebug(validator) shouldBe true + getTicketValidatorDebug(validator) shouldBe false } - it should "have ticketValidator debug set to true even when kerberosDebug is explicitly false (hardcoded)" in { + it should "have ticketValidator debug set to false even when kerberosDebug is explicitly false" in { val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(false)) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) val validator = provider.sunJaasKerberosTicketValidator - getTicketValidatorDebug(validator) shouldBe true + getTicketValidatorDebug(validator) shouldBe false } - it should "have ticketValidator debug set to true when kerberosDebug is explicitly true (hardcoded)" in { + it should "have ticketValidator debug set to true when kerberosDebug is explicitly true" in { val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(true)) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) From f64449a907a4cc9eb2262ca7330a42305aac5649 Mon Sep 17 00:00:00 2001 From: Daniel Kavan Date: Thu, 28 May 2026 12:42:33 +0200 Subject: [PATCH 5/5] #171 wording changed --- .../KerberosSPNEGOAuthenticationProviderTest.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala index 642b86a..d97fe56 100644 --- a/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala +++ b/api/src/test/scala/za/co/absa/loginsvc/rest/provider/kerberos/KerberosSPNEGOAuthenticationProviderTest.scala @@ -125,8 +125,8 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers debugField.getBoolean(validator) } - it should "have ticketValidator debug set to false even when kerberosDebug is None (default)" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", None) + it should "have ticketValidator debug set to false even when ldapConfig.kerberos.debug is None (default)" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = None) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) @@ -134,8 +134,8 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers getTicketValidatorDebug(validator) shouldBe false } - it should "have ticketValidator debug set to false even when kerberosDebug is explicitly false" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(false)) + it should "have ticketValidator debug set to false even when ldapConfig.kerberos.debug is explicitly false" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(false)) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig) @@ -143,8 +143,8 @@ class KerberosSPNEGOAuthenticationProviderTest extends AnyFlatSpec with Matchers getTicketValidatorDebug(validator) shouldBe false } - it should "have ticketValidator debug set to true when kerberosDebug is explicitly true" in { - val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", Some(true)) + it should "have ticketValidator debug set to true when ldapConfig.kerberos.debug is explicitly true" in { + val kerberosConfig = KerberosConfig("krb5.conf", "test.keytab", "HTTP/host@REALM", debug = Some(true)) val ldapConfig = createLdapConfig(kerberosConfig) val provider = new KerberosSPNEGOAuthenticationProvider(ldapConfig)