From 214f898fe764905cdf0361912fb60e8dabec164c Mon Sep 17 00:00:00 2001 From: Krzysztof Zmij Date: Mon, 24 Jul 2023 14:50:16 +0200 Subject: [PATCH 1/3] allow NPA to get longer time expiration for session token --- .../ing/wbaa/rokku/sts/StsServiceItTest.scala | 2 +- src/main/resources/application.conf | 1 + src/main/resources/reference.conf | 1 + .../com/ing/wbaa/rokku/sts/api/STSApi.scala | 45 ++++++++---- .../wbaa/rokku/sts/config/StsSettings.scala | 1 + .../sts/data/AuthenticationUserInfo.scala | 3 +- .../sts/keycloak/KeycloakTokenVerifier.scala | 14 +++- .../rokku/sts/service/TokenGeneration.scala | 11 +-- .../sts/service/UserTokenDbService.scala | 8 +- .../ing/wbaa/rokku/sts/api/AdminApiTest.scala | 4 +- .../ing/wbaa/rokku/sts/api/NpaApiTest.scala | 6 +- .../ing/wbaa/rokku/sts/api/STSApiTest.scala | 73 ++++++++++++++----- .../rokku/sts/data/aws/AwsRoleArnTest.scala | 6 +- .../sts/service/TokenGenerationTest.scala | 22 +----- .../sts/service/UserTokenDbServiceTest.scala | 22 +++--- 15 files changed, 131 insertions(+), 88 deletions(-) diff --git a/src/it/scala/com/ing/wbaa/rokku/sts/StsServiceItTest.scala b/src/it/scala/com/ing/wbaa/rokku/sts/StsServiceItTest.scala index 66a07d5..4241210 100644 --- a/src/it/scala/com/ing/wbaa/rokku/sts/StsServiceItTest.scala +++ b/src/it/scala/com/ing/wbaa/rokku/sts/StsServiceItTest.scala @@ -82,7 +82,7 @@ class StsServiceItTest extends AsyncWordSpec with Diagrams override protected[this] def getToken(awsSessionToken: AwsSessionToken, username: Username): Future[Option[(Username, UserAssumeRole, AwsSessionTokenExpiration)]] = Future.successful(None) - override def generateAwsSession(duration: Option[Duration]): AwsSession = AwsSession( + override def generateAwsSession(duration: Duration): AwsSession = AwsSession( AwsSessionToken("sessiontoken" + Random.alphanumeric.take(32).mkString), AwsSessionTokenExpiration(Instant.now().plusSeconds(20)) ) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index fa88f1b..1120541 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -37,6 +37,7 @@ rokku { defaultTokenSessionHours = ${?STS_DEFAULT_TOKEN_SESSION_HOURS} maxTokenSessionHours = ${?STS_MAX_TOKEN_SESSION_HOURS} + maxTokenSessionForNPAHours = ${?STS_MAX_TOKEN_SESSION_FOR_NPA_HOURS} # at least 32 bytes long. Make sure you set your own random key masterKey = ${?STS_MASTER_KEY} encryptionAlgorithm = ${?STS_ENCRYPTION_ALGORITHM} diff --git a/src/main/resources/reference.conf b/src/main/resources/reference.conf index 8804d3b..9999337 100644 --- a/src/main/resources/reference.conf +++ b/src/main/resources/reference.conf @@ -24,6 +24,7 @@ rokku { defaultTokenSessionHours = 8 maxTokenSessionHours = 24 + maxTokenSessionForNPAHours = 8760 #one year masterKey = "MakeSureYouChangeMasterKeyToRandomString" encryptionAlgorithm = "AES" adminGroups = "" diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala b/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala index a33584d..8d80e14 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala @@ -1,15 +1,15 @@ package com.ing.wbaa.rokku.sts.api import java.util.concurrent.TimeUnit - import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Route import com.ing.wbaa.rokku.sts.api.xml.TokenXML +import com.ing.wbaa.rokku.sts.config.StsSettings import com.ing.wbaa.rokku.sts.data._ import com.ing.wbaa.rokku.sts.data.aws._ import com.typesafe.scalalogging.LazyLogging -import directive.STSDirectives.{ authorizeToken, assumeRole } +import directive.STSDirectives.{ assumeRole, authorizeToken } import scala.concurrent.Future import scala.concurrent.duration._ @@ -17,29 +17,44 @@ import scala.util.{ Failure, Success } trait STSApi extends LazyLogging with TokenXML { + protected[this] def stsSettings: StsSettings + private val getOrPost = get | post & pathSingleSlash private val actionDirective = parameter("Action") | formField("Action") - private val parseDurationSeconds: Option[Int] => Option[Duration] = - _.map(durationSeconds => Duration(durationSeconds, TimeUnit.SECONDS)) + private def parseDurationSeconds(aui: AuthenticationUserInfo, durationSeconds: Option[Int]): Duration = { + val maxTokenSession = if (aui.isNPA) stsSettings.maxTokenSessionForNPADuration else stsSettings.maxTokenSessionDuration + val durationRequested = durationSeconds.map(ds => Duration(ds, TimeUnit.SECONDS)) + val d = durationRequested match { + case None => stsSettings.defaultTokenSessionDuration + case Some(durationRequested) => + if (durationRequested > maxTokenSession) maxTokenSession + else durationRequested + } + logger.debug("stsSettings.maxTokenSessionForNPADuration {}", stsSettings.maxTokenSessionForNPADuration) + logger.debug("stsSettings.maxTokenSessionDuration {}", stsSettings.maxTokenSessionDuration) + logger.debug("durationRequested {}", durationRequested) + d + } - private val getSessionTokenInputs = { + private def getSessionTokenInputs(aui: AuthenticationUserInfo) = { val input = "DurationSeconds".as[Int].? (parameter(input) & formField(input)).tmap { case (param, field) => - if (param.isDefined) parseDurationSeconds(param) - else parseDurationSeconds(field) + if (param.isDefined) parseDurationSeconds(aui, param) + else parseDurationSeconds(aui, field) } } - private val assumeRoleInputs = { + private def assumeRoleInputs(aui: AuthenticationUserInfo) = { (parameters("RoleArn", "RoleSessionName", "DurationSeconds".as[Int].?) | formFields("RoleArn", "RoleSessionName", "DurationSeconds".as[Int].?)).tmap(t => - t.copy(_1 = AwsRoleArn(t._1), _3 = parseDurationSeconds(t._3)) + t.copy(_1 = AwsRoleArn(t._1), _3 = parseDurationSeconds(aui, t._3)) ) } - protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], duration: Option[Duration]): Future[AwsCredentialWithToken] - protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Option[Duration]): Future[AwsCredentialWithToken] + protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], duration: Duration): Future[AwsCredentialWithToken] + + protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Duration): Future[AwsCredentialWithToken] // Keycloak protected[this] def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] @@ -58,8 +73,8 @@ trait STSApi extends LazyLogging with TokenXML { } private def getSessionTokenHandler: Route = { - getSessionTokenInputs { durationSeconds => - authorizeToken(verifyAuthenticationToken) { keycloakUserInfo => + authorizeToken(verifyAuthenticationToken) { keycloakUserInfo => + getSessionTokenInputs(keycloakUserInfo) { durationSeconds => onComplete(getAwsCredentialWithToken(keycloakUserInfo.userName, keycloakUserInfo.userGroups, durationSeconds)) { case Success(awsCredentialWithToken) => complete(getSessionTokenResponseToXML(awsCredentialWithToken)) case Failure(ex) => @@ -72,8 +87,8 @@ trait STSApi extends LazyLogging with TokenXML { } private def assumeRoleHandler: Route = { - assumeRoleInputs { (roleArn, roleSessionName, durationSeconds) => - authorizeToken(verifyAuthenticationToken) { keycloakUserInfo => + authorizeToken(verifyAuthenticationToken) { keycloakUserInfo => + assumeRoleInputs(keycloakUserInfo) { (roleArn, roleSessionName, durationSeconds) => assumeRole(keycloakUserInfo, roleArn) { assumeRole => onComplete(getAwsCredentialWithToken(keycloakUserInfo.userName, keycloakUserInfo.userGroups, assumeRole, durationSeconds)) { case Success(awsCredentialWithToken) => diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/config/StsSettings.scala b/src/main/scala/com/ing/wbaa/rokku/sts/config/StsSettings.scala index 7876707..9be7a0f 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/config/StsSettings.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/config/StsSettings.scala @@ -11,6 +11,7 @@ class StsSettings(config: Config) extends Extension { private[this] val rokkuStsConfig = config.getConfig("rokku.sts") val defaultTokenSessionDuration: Duration = Duration(rokkuStsConfig.getInt("defaultTokenSessionHours"), TimeUnit.HOURS) val maxTokenSessionDuration: Duration = Duration(rokkuStsConfig.getInt("maxTokenSessionHours"), TimeUnit.HOURS) + val maxTokenSessionForNPADuration: Duration = Duration(rokkuStsConfig.getInt("maxTokenSessionForNPAHours"), TimeUnit.HOURS) val masterKey: String = rokkuStsConfig.getString("masterKey") val encryptionAlgorithm: String = rokkuStsConfig.getString("encryptionAlgorithm") val adminGroups = rokkuStsConfig.getString("adminGroups").split(",").map(_.trim).toList diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/data/AuthenticationUserInfo.scala b/src/main/scala/com/ing/wbaa/rokku/sts/data/AuthenticationUserInfo.scala index 8add21a..6f455ec 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/data/AuthenticationUserInfo.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/data/AuthenticationUserInfo.scala @@ -8,4 +8,5 @@ case class AuthenticationUserInfo( userName: Username, userGroups: Set[UserGroup], keycloakTokenId: AuthenticationTokenId, - userRoles: Set[UserAssumeRole]) + userRoles: Set[UserAssumeRole], + isNPA: Boolean) diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala b/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala index 3c90714..c240d45 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala @@ -22,6 +22,17 @@ trait KeycloakTokenVerifier extends LazyLogging { import scala.jdk.CollectionConverters._ + /** + * Temporary we define NPA be Name - later we will change it to some keycloak role + * @param keycloakToken + * @return true if NPA + */ + private def isNPA(keycloakToken: AccessToken): Boolean = { + logger.debug("user getName={}", keycloakToken.getName) + logger.debug("is NPA={}", keycloakToken.getName == "NPA NPA") + keycloakToken.getName == "NPA NPA" + } + protected[this] def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] = Try { val accessToken = TokenVerifier.create(token.value, classOf[AccessToken]) @@ -39,7 +50,8 @@ trait KeycloakTokenVerifier extends LazyLogging { .getOrDefault("user-groups", new util.ArrayList[String]()) .asInstanceOf[util.ArrayList[String]].asScala.toSet.map(UserGroup), AuthenticationTokenId(keycloakToken.getId), - keycloakToken.getRealmAccess.getRoles.asScala.toSet.map(UserAssumeRole) + keycloakToken.getRealmAccess.getRoles.asScala.toSet.map(UserAssumeRole), + isNPA(keycloakToken) )) case Failure(exc: VerificationException) => logger.warn("Token (value={}) verification failed ex={}", token.value, exc.getMessage) diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/service/TokenGeneration.scala b/src/main/scala/com/ing/wbaa/rokku/sts/service/TokenGeneration.scala index 93570b8..909cfdd 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/service/TokenGeneration.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/service/TokenGeneration.scala @@ -21,17 +21,10 @@ trait TokenGeneration { AwsSecretKey(rand.alphanumeric.take(32).mkString) ) - protected[this] def generateAwsSession(duration: Option[Duration]): AwsSession = { - val tokenDuration = duration match { - case None => stsSettings.defaultTokenSessionDuration - case Some(durationRequested) => - if (durationRequested > stsSettings.maxTokenSessionDuration) stsSettings.maxTokenSessionDuration - else durationRequested - } - + protected[this] def generateAwsSession(duration: Duration): AwsSession = { AwsSession( sessionToken = AwsSessionToken(rand.alphanumeric.take(32).mkString), - expiration = AwsSessionTokenExpiration(Instant.now().plusMillis(tokenDuration.toMillis)) + expiration = AwsSessionTokenExpiration(Instant.now().plusMillis(duration.toMillis)) ) } } diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbService.scala b/src/main/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbService.scala index 7ea9a73..72a0b45 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbService.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbService.scala @@ -43,7 +43,7 @@ trait UserTokenDbService extends LazyLogging with TokenGeneration { * @param duration optional: the duration of the session, if duration is not given then it defaults to the application application default * @return */ - def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], duration: Option[Duration]): Future[AwsCredentialWithToken] = + def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], duration: Duration): Future[AwsCredentialWithToken] = for { (awsCredential, AccountStatus(isEnabled)) <- getOrGenerateAwsCredentialWithStatus(userName) awsSession <- getNewAwsSession(userName, duration) @@ -63,7 +63,7 @@ trait UserTokenDbService extends LazyLogging with TokenGeneration { * @param duration optional: the duration of the session, if duration is not given then it defaults to the application application default * @return */ - def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Option[Duration]): Future[AwsCredentialWithToken] = + def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Duration): Future[AwsCredentialWithToken] = for { (awsCredential, AccountStatus(isEnabled)) <- getOrGenerateAwsCredentialWithStatus(userName) awsSession <- getNewAwsSessionWithToken(userName, role, duration) @@ -149,7 +149,7 @@ trait UserTokenDbService extends LazyLogging with TokenGeneration { * @param generationTriesLeft Number of times to retry token generation, in case it collides * @return */ - private[this] def getNewAwsSession(userName: Username, duration: Option[Duration], generationTriesLeft: Int = 3): Future[AwsSession] = { + private[this] def getNewAwsSession(userName: Username, duration: Duration, generationTriesLeft: Int = 3): Future[AwsSession] = { val newAwsSession = generateAwsSession(duration) insertToken(newAwsSession.sessionToken, userName, newAwsSession.expiration) .flatMap { @@ -172,7 +172,7 @@ trait UserTokenDbService extends LazyLogging with TokenGeneration { * @param generationTriesLeft Number of times to retry token generation, in case it collides * @return */ - private[this] def getNewAwsSessionWithToken(userName: Username, role: UserAssumeRole, duration: Option[Duration], generationTriesLeft: Int = 3): Future[AwsSession] = { + private[this] def getNewAwsSessionWithToken(userName: Username, role: UserAssumeRole, duration: Duration, generationTriesLeft: Int = 3): Future[AwsSession] = { val newAwsSession = generateAwsSession(duration) insertToken(newAwsSession.sessionToken, userName, role, newAwsSession.expiration) .flatMap { diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/api/AdminApiTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/api/AdminApiTest.scala index 7d09152..0dd97ed 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/api/AdminApiTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/api/AdminApiTest.scala @@ -32,8 +32,8 @@ class AdminApiTest extends AnyWordSpec protected[this] def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] = token.value match { - case "valid" => Some(AuthenticationUserInfo(Username("username"), Set(UserGroup("admins"), UserGroup("group2")), AuthenticationTokenId("tokenOk"), Set.empty)) - case "notAdmin" => Some(AuthenticationUserInfo(Username("username"), Set(UserGroup("group1"), UserGroup("group2")), AuthenticationTokenId("tokenOk"), Set.empty)) + case "valid" => Some(AuthenticationUserInfo(Username("username"), Set(UserGroup("admins"), UserGroup("group2")), AuthenticationTokenId("tokenOk"), Set.empty, isNPA = false)) + case "notAdmin" => Some(AuthenticationUserInfo(Username("username"), Set(UserGroup("group1"), UserGroup("group2")), AuthenticationTokenId("tokenOk"), Set.empty, isNPA = false)) case _ => None } diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/api/NpaApiTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/api/NpaApiTest.scala index 40f5022..972247c 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/api/NpaApiTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/api/NpaApiTest.scala @@ -63,9 +63,9 @@ class NpaApiTest extends AnyWordSpec protected[this] def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] = token.value match { - case "non-npa-user-token" => Some(AuthenticationUserInfo(Username(nonNpaUser), Set(), AuthenticationTokenId("nonNpaUser?"), Set())) - case "npa-user-token" => Some(AuthenticationUserInfo(Username(npaUser), Set(), AuthenticationTokenId("npaUser"), Set(UserAssumeRole(keycloakSettings.npaRole)))) - case "npa-user-disabled-token" => Some(AuthenticationUserInfo(Username(disabledNpaUser), Set(), AuthenticationTokenId("disabledNpaUser"), Set(UserAssumeRole(keycloakSettings.npaRole)))) + case "non-npa-user-token" => Some(AuthenticationUserInfo(Username(nonNpaUser), Set(), AuthenticationTokenId("nonNpaUser?"), Set(), isNPA = false)) + case "npa-user-token" => Some(AuthenticationUserInfo(Username(npaUser), Set(), AuthenticationTokenId("npaUser"), Set(UserAssumeRole(keycloakSettings.npaRole)), isNPA = false)) + case "npa-user-disabled-token" => Some(AuthenticationUserInfo(Username(disabledNpaUser), Set(), AuthenticationTokenId("disabledNpaUser"), Set(UserAssumeRole(keycloakSettings.npaRole)), isNPA = false)) case _ => None } diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/api/STSApiTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/api/STSApiTest.scala index c7c494d..6dfd9c5 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/api/STSApiTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/api/STSApiTest.scala @@ -1,17 +1,20 @@ package com.ing.wbaa.rokku.sts.api -import java.time.Instant +import akka.actor.ActorSystem +import java.time.Instant import akka.http.scaladsl.model.headers.Cookie import akka.http.scaladsl.model.{ FormData, StatusCodes } import akka.http.scaladsl.server.{ AuthorizationFailedRejection, MissingFormFieldRejection, MissingQueryParamRejection, Route } import akka.http.scaladsl.testkit.ScalatestRouteTest +import com.ing.wbaa.rokku.sts.config.StsSettings import com.ing.wbaa.rokku.sts.data import com.ing.wbaa.rokku.sts.data._ import com.ing.wbaa.rokku.sts.data.aws._ import org.scalatest.diagrams.Diagrams import org.scalatest.wordspec.AnyWordSpec +import java.util.concurrent.TimeUnit import scala.concurrent.Future import scala.concurrent.duration._ import scala.xml.NodeSeq @@ -32,11 +35,12 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { override def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] = token.value match { - case "valid" => Some(data.AuthenticationUserInfo(Username("name"), Set(UserGroup("testgroup")), AuthenticationTokenId("token"), Set(UserAssumeRole("testrole")))) - case _ => None + case "valid" => Some(data.AuthenticationUserInfo(Username("name"), Set(UserGroup("testgroup")), AuthenticationTokenId("token"), Set(UserAssumeRole("testrole")), isNPA = false)) + case "validNPA" => Some(data.AuthenticationUserInfo(Username("name"), Set(UserGroup("testgroup")), AuthenticationTokenId("token"), Set(UserAssumeRole("testrole")), isNPA = true)) + case _ => None } - override protected[this] def getAwsCredentialWithToken(userName: Username, groups: Set[UserGroup], duration: Option[Duration]): Future[AwsCredentialWithToken] = { + override protected[this] def getAwsCredentialWithToken(userName: Username, groups: Set[UserGroup], duration: Duration): Future[AwsCredentialWithToken] = { Future.successful(AwsCredentialWithToken( AwsCredential( AwsAccessKey("accesskey"), @@ -44,12 +48,12 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { ), AwsSession( AwsSessionToken("token"), - AwsSessionTokenExpiration(Instant.ofEpochMilli(duration.getOrElse(1.second).toMillis)) + AwsSessionTokenExpiration(Instant.ofEpochMilli(duration.toMillis)) ) )) } - override protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Option[Duration]): Future[AwsCredentialWithToken] = { + override protected[this] def getAwsCredentialWithToken(userName: Username, userGroups: Set[UserGroup], role: UserAssumeRole, duration: Duration): Future[AwsCredentialWithToken] = { Future.successful(AwsCredentialWithToken( AwsCredential( AwsAccessKey("accesskey"), @@ -57,10 +61,17 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { ), AwsSession( AwsSessionToken("token"), - AwsSessionTokenExpiration(Instant.ofEpochMilli(duration.getOrElse(1.second).toMillis)) + AwsSessionTokenExpiration(Instant.ofEpochMilli(duration.toMillis)) ) )) } + + val testSystem: ActorSystem = ActorSystem.create("test-system") + override protected[this] def stsSettings: StsSettings = new StsSettings(testSystem.settings.config) { + override val defaultTokenSessionDuration: Duration = Duration(8, TimeUnit.HOURS) + override val maxTokenSessionDuration: Duration = Duration(24, TimeUnit.HOURS) + override val maxTokenSessionForNPADuration: Duration = Duration(10, TimeUnit.DAYS) + } } private val s3Routes: Route = new MockStsApi().stsRoutes @@ -76,13 +87,16 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { }.stsRoutes val validOAuth2TokenHeader: RequestTransformer = addHeader("Authorization", "Bearer valid") + val validNPAOAuth2TokenHeader: RequestTransformer = addHeader("Authorization", "Bearer validNPA") val validOAuth2TokenCookie: RequestTransformer = addHeader(Cookie("X-Authorization-Token", "valid")) val invalidOAuth2TokenHeader: RequestTransformer = addHeader("Authorization", "Bearer invalid") val invalidOAuth2TokenCookie: RequestTransformer = addHeader(Cookie("X-Authorization-Token", "invalid")) val actionGetSessionToken = "?Action=GetSessionToken" val actionAssumeRole = "?Action=AssumeRole" - val durationQuery = "&DurationSeconds=3600" + val duration1hQuery = "&DurationSeconds=3600" + val duration48hQuery = "&DurationSeconds=172800" + val duration20dQuery = "&DurationSeconds=1728000" val roleNameSessionQuery = "&RoleSessionName=app1" val arnQuery = "&RoleArn=arn:aws:iam::123456789012:role/testrole" val webIdentityTokenQuery = "&WebIdentityToken=Atza%7CIQ" @@ -111,12 +125,33 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { } "return a session token with 1h expiration time because valid credentials" in { - Get(s"/$actionGetSessionToken$durationQuery") ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + Get(s"/$actionGetSessionToken$duration1hQuery") ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { assert(status == StatusCodes.OK) assert(responseAs[String] == "1970-01-01T01:00:00Z") } } + "return max session token with 24h expiration time because longer time is not allowed for users" in { + Get(s"/$actionGetSessionToken$duration48hQuery") ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + assert(status == StatusCodes.OK) + assert(responseAs[String] == "1970-01-02T00:00:00Z") + } + } + + "return a session token with 48h expiration time because NPA can have longer time" in { + Get(s"/$actionGetSessionToken$duration48hQuery") ~> validNPAOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + assert(status == StatusCodes.OK) + assert(responseAs[String] == "1970-01-03T00:00:00Z") + } + } + + "return max session token with 10 days expiration time because longer time is not allowed for NPA" in { + Get(s"/$actionGetSessionToken$duration20dQuery") ~> validNPAOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + assert(status == StatusCodes.OK) + assert(responseAs[String] == "1970-01-11T00:00:00Z") + } + } + "return rejection because invalid credentials" in { Get(s"/$actionGetSessionToken") ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(AuthorizationFailedRejection)) @@ -153,7 +188,7 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { } "return a session token with 1h expiration time because valid credentials" in { - Post("/", FormData(queryToFormData(actionGetSessionToken, durationQuery))) ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + Post("/", FormData(queryToFormData(actionGetSessionToken, duration1hQuery))) ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { assert(status == StatusCodes.OK) assert(responseAs[String] == "1970-01-01T01:00:00Z") } @@ -170,7 +205,7 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { } "return a session token with 1h expiration time because credentials are valid" in { - Get(s"/$actionAssumeRole$durationQuery$arnQuery$roleNameSessionQuery") ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + Get(s"/$actionAssumeRole$duration1hQuery$arnQuery$roleNameSessionQuery") ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { assert(status == StatusCodes.OK) assert(responseAs[String] == "1970-01-01T01:00:00Z") } @@ -183,13 +218,13 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { } "return rejection because no arn parameter" in { - Get(s"/$actionAssumeRole$roleNameSessionQuery") ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { + Get(s"/$actionAssumeRole$roleNameSessionQuery") ~> validOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(MissingQueryParamRejection("RoleArn"))) } } "return rejection because no roleSessionName parameter" in { - Get(s"/$actionAssumeRole$arnQuery") ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { + Get(s"/$actionAssumeRole$arnQuery") ~> validOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(MissingQueryParamRejection("RoleSessionName"))) } } @@ -204,38 +239,38 @@ class STSApiTest extends AnyWordSpec with Diagrams with ScalatestRouteTest { "STS api the POST method for assumeRole" should { "return a session token because credentials are valid" in { - Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, durationQuery))) ~> validOAuth2TokenHeader ~> s3Routes ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, duration1hQuery))) ~> validOAuth2TokenHeader ~> s3Routes ~> check { assert(status == StatusCodes.OK) assert(responseAs[String] == "") } } "return rejection because invalid credentials" in { - Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, durationQuery))) ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, duration1hQuery))) ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(AuthorizationFailedRejection)) } } "return rejection because no arn parameter" in { - Post("/", FormData(queryToFormData(actionAssumeRole, roleNameSessionQuery, durationQuery))) ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, roleNameSessionQuery, duration1hQuery))) ~> validOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(MissingFormFieldRejection("RoleArn"))) } } "return rejection because no roleSessionName parameter" in { - Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery))) ~> invalidOAuth2TokenHeader ~> s3Routes ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery))) ~> validOAuth2TokenHeader ~> s3Routes ~> check { assert(rejections.contains(MissingFormFieldRejection("RoleSessionName"))) } } "return rejection because no credentials" in { - Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, durationQuery))) ~> s3Routes ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, duration1hQuery))) ~> s3Routes ~> check { assert(rejections.contains(AuthorizationFailedRejection)) } } "return a session token with 1h expiration time because valid credentials" in { - Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, durationQuery))) ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { + Post("/", FormData(queryToFormData(actionAssumeRole, arnQuery, roleNameSessionQuery, duration1hQuery))) ~> validOAuth2TokenHeader ~> s3RoutesWithExpirationTime ~> check { assert(status == StatusCodes.OK) assert(responseAs[String] == "1970-01-01T01:00:00Z") } diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/data/aws/AwsRoleArnTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/data/aws/AwsRoleArnTest.scala index 400ace4..41172c2 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/data/aws/AwsRoleArnTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/data/aws/AwsRoleArnTest.scala @@ -13,7 +13,7 @@ class AwsRoleArnTest extends AnyWordSpec { val result = AwsRoleArn(s"arn:aws:iam::123456789012:role/$testRoleName") .getRoleUserCanAssume( - AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set(UserAssumeRole(testRoleName))) + AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set(UserAssumeRole(testRoleName)), isNPA = false) ) assert(result.contains(UserAssumeRole(testRoleName))) } @@ -23,7 +23,7 @@ class AwsRoleArnTest extends AnyWordSpec { val result = AwsRoleArn(s"arn:aws:iam:invalid:123456789012:role/$testRoleName") .getRoleUserCanAssume( - AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set(UserAssumeRole(testRoleName))) + AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set(UserAssumeRole(testRoleName)), isNPA = false) ) assert(result.isEmpty) } @@ -33,7 +33,7 @@ class AwsRoleArnTest extends AnyWordSpec { val result = AwsRoleArn(s"arn:aws:iam::123456789012:role/$testRoleName") .getRoleUserCanAssume( - AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set.empty) + AuthenticationUserInfo(Username(""), Set.empty, AuthenticationTokenId(""), Set.empty, isNPA = false) ) assert(result.isEmpty) } diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/service/TokenGenerationTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/service/TokenGenerationTest.scala index 6343746..33f27a1 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/service/TokenGenerationTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/service/TokenGenerationTest.scala @@ -14,10 +14,7 @@ import scala.concurrent.duration.Duration class TokenGenerationTest extends AnyWordSpec with Diagrams with TokenGeneration { val testSystem: ActorSystem = ActorSystem.create("test-system") - override protected[this] def stsSettings: StsSettings = new StsSettings(testSystem.settings.config) { - override val defaultTokenSessionDuration: Duration = Duration(8, TimeUnit.HOURS) - override val maxTokenSessionDuration: Duration = Duration(24, TimeUnit.HOURS) - } + override protected[this] def stsSettings: StsSettings = new StsSettings(testSystem.settings.config) "Token generation" should { val allowedCharacters = (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).toSet @@ -35,25 +32,12 @@ class TokenGenerationTest extends AnyWordSpec with Diagrams with TokenGeneration assert(diff >= 0 && diff < allowedOffsetMillis) } - "has no duration specified" in { - val generatedAwsSession = generateAwsSession(None) - assert(generatedAwsSession.sessionToken.value.forall(allowedCharacters.contains)) - assertExpirationValid(generatedAwsSession.expiration, stsSettings.defaultTokenSessionDuration) - } - - "has duration within range of max specified" in { + "has duration set to 2h" in { val customDuration = Duration(2, TimeUnit.HOURS) - val generatedAwsSession = generateAwsSession(Some(customDuration)) + val generatedAwsSession = generateAwsSession(customDuration) assert(generatedAwsSession.sessionToken.value.forall(allowedCharacters.contains)) assertExpirationValid(generatedAwsSession.expiration, customDuration) } - - "has duration larger than max specified" in { - val customDuration = Duration(25, TimeUnit.HOURS) - val generatedAwsSession = generateAwsSession(Some(customDuration)) - assert(generatedAwsSession.sessionToken.value.forall(allowedCharacters.contains)) - assertExpirationValid(generatedAwsSession.expiration, stsSettings.maxTokenSessionDuration) - } } } diff --git a/src/test/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbServiceTest.scala b/src/test/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbServiceTest.scala index b5d354e..5c10d98 100644 --- a/src/test/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbServiceTest.scala +++ b/src/test/scala/com/ing/wbaa/rokku/sts/service/UserTokenDbServiceTest.scala @@ -67,7 +67,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { "are new credentials and a new token with specified duration" in { val testObject = new TestObject - new UserTokenDbServiceTest {}.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], Some(testObject.duration)).map { c => + new UserTokenDbServiceTest {}.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], testObject.duration).map { c => assertExpirationValid(c.session.expiration, testObject.duration) } } @@ -77,7 +77,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { new UserTokenDbServiceTest { override protected[this] def getUserAccountByName(userName: Username): Future[Option[UserAccount]] = Future.successful(Some(UserAccount(userName, None, AccountStatus(false), NPA(false), Set()))) - }.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], Some(testObject.duration)).map { c => + }.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], testObject.duration).map { c => assertExpirationValid(c.session.expiration, testObject.duration) } } @@ -94,7 +94,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { } recoverToSucceededIf[Exception] { - utdst.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], Some(testObject.duration)).map { c => + utdst.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], testObject.duration).map { c => assertExpirationValid(c.session.expiration, testObject.duration) } } @@ -104,8 +104,8 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { "have existing credentials and a new token" in { val testObject = new TestObject val utds = new UserTokenDbServiceTest {} - utds.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], None).flatMap { firstReturn => - utds.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], None).map { secondReturn => + utds.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], testObject.duration).flatMap { firstReturn => + utds.getAwsCredentialWithToken(testObject.userName, Set.empty[UserGroup], testObject.duration).map { secondReturn => assert(firstReturn.awsCredential == secondReturn.awsCredential) assert(firstReturn.session != secondReturn.session) } @@ -117,7 +117,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { "has valid accesskey and sessiontoken is active" in { val t = new TestObject val utds = new UserTokenDbServiceTest {} - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(t.duration)).flatMap { awsCredWithToken => + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], t.duration).flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, Some(awsCredWithToken.session.sessionToken)).map { u => assert(u.map(_.userName).contains(Username("u"))) assert(u.map(_.awsAccessKey).contains(AwsAccessKey("a"))) @@ -134,7 +134,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { override protected[this] def getToken(awsSessionToken: AwsSessionToken, userName: Username): Future[Option[(Username, UserAssumeRole, AwsSessionTokenExpiration)]] = Future.successful(Some((Username("u"), UserAssumeRole("testGroup"), AwsSessionTokenExpiration(Instant.now().minusSeconds(20))))) } - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(Duration(-1, TimeUnit.HOURS))) + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Duration(-1, TimeUnit.HOURS)) .flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, Some(awsCredWithToken.session.sessionToken)) .map(b => assert(b.isEmpty)) @@ -147,7 +147,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { override protected[this] def getToken(awsSessionToken: AwsSessionToken, userName: Username): Future[Option[(Username, UserAssumeRole, AwsSessionTokenExpiration)]] = Future.successful(Some((Username("u"), UserAssumeRole("testRole"), AwsSessionTokenExpiration(Instant.now().plusSeconds(20))))) } - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(t.duration)) + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], t.duration) .flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, Some(awsCredWithToken.session.sessionToken)).map { u => assert(u.map(_.userName).contains(Username("u"))) @@ -167,7 +167,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { "has valid accesskey, no sessiontoken and is not an NPA" in { val t = new TestObject val utds = new UserTokenDbServiceTest {} - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(t.duration)).flatMap { awsCredWithToken => + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], t.duration).flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, None).map(a => assert(a.isEmpty)) } } @@ -178,7 +178,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { override protected[this] def getUserAccountByAccessKey(awsAccessKey: AwsAccessKey): Future[Option[UserAccount]] = Future.successful(Some(UserAccount(Username("u"), Some(AwsCredential(AwsAccessKey("a"), AwsSecretKey("s"))), AccountStatus(true), NPA(true), Set.empty[UserGroup]))) } - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(t.duration)).flatMap { awsCredWithToken => + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], t.duration).flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, None).map(a => assert(a.isDefined)) } } @@ -189,7 +189,7 @@ class UserTokenDbServiceTest extends AsyncWordSpec with Diagrams { override protected[this] def getUserAccountByAccessKey(awsAccessKey: AwsAccessKey): Future[Option[UserAccount]] = Future.successful(Some(UserAccount(Username("u"), Some(AwsCredential(AwsAccessKey("a"), AwsSecretKey("s"))), AccountStatus(false), NPA(false), Set.empty[UserGroup]))) } - utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], Some(t.duration)).flatMap { awsCredWithToken => + utds.getAwsCredentialWithToken(t.userName, Set.empty[UserGroup], t.duration).flatMap { awsCredWithToken => utds.isCredentialActive(awsCredWithToken.awsCredential.accessKey, Some(awsCredWithToken.session.sessionToken)).map(a => assert(!a.isDefined)) } } From 51c160969ef095d0e2fdb3fb182a7e9060a2c765 Mon Sep 17 00:00:00 2001 From: Krzysztof Zmij Date: Mon, 24 Jul 2023 14:50:38 +0200 Subject: [PATCH 2/3] update libs --- build.sbt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build.sbt b/build.sbt index a623d6c..f5ee2a2 100644 --- a/build.sbt +++ b/build.sbt @@ -35,25 +35,25 @@ libraryDependencies ++= Seq( "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion, "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2", - "ch.qos.logback" % "logback-classic" % "1.4.1", + "ch.qos.logback" % "logback-classic" % "1.4.7", "com.typesafe.akka" %% "akka-slf4j" % akkaVersion, "org.keycloak" % "keycloak-core" % keycloakVersion, "org.keycloak" % "keycloak-adapter-core" % keycloakVersion, "org.keycloak" % "keycloak-admin-client" % keycloakVersion, "org.jboss.logging" % "jboss-logging" % "3.5.0.Final", - "org.apache.httpcomponents" % "httpclient" % "4.5.13", + "org.apache.httpcomponents" % "httpclient" % "4.5.14", "ch.qos.logback.contrib" % "logback-json-classic" % logbackJson, "ch.qos.logback.contrib" % "logback-jackson" % logbackJson, - "com.auth0" % "java-jwt" % "4.0.0", + "com.auth0" % "java-jwt" % "4.3.0", "com.bettercloud" % "vault-java-driver" % "5.1.0", - "redis.clients" % "jedis" % "4.3.0-m1", - "org.scalatest" %% "scalatest" % "3.2.13" % "test, it", + "redis.clients" % "jedis" % "4.4.0", + "org.scalatest" %% "scalatest" % "3.2.15" % "test, it", "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test, "com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test, - "com.amazonaws" % "aws-java-sdk-sts" % "1.12.307" % IntegrationTest, + "com.amazonaws" % "aws-java-sdk-sts" % "1.12.471" % IntegrationTest, ) dependencyOverrides ++= Seq( - "com.fasterxml.jackson.core" % "jackson-databind" % "2.14.2", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.1", ) configs(IntegrationTest) From 2bc2bc083692d03593ee97c9c71c34f825fcef02 Mon Sep 17 00:00:00 2001 From: Krzysztof Zmij Date: Tue, 25 Jul 2023 13:21:59 +0200 Subject: [PATCH 3/3] ajust log debug --- .../scala/com/ing/wbaa/rokku/sts/api/STSApi.scala | 11 +++++------ .../rokku/sts/keycloak/KeycloakTokenVerifier.scala | 7 ++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala b/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala index 8d80e14..25fd66d 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/api/STSApi.scala @@ -24,17 +24,16 @@ trait STSApi extends LazyLogging with TokenXML { private def parseDurationSeconds(aui: AuthenticationUserInfo, durationSeconds: Option[Int]): Duration = { val maxTokenSession = if (aui.isNPA) stsSettings.maxTokenSessionForNPADuration else stsSettings.maxTokenSessionDuration + logger.debug("maxTokenSession {}", maxTokenSession) val durationRequested = durationSeconds.map(ds => Duration(ds, TimeUnit.SECONDS)) - val d = durationRequested match { + val durationResult = durationRequested match { case None => stsSettings.defaultTokenSessionDuration case Some(durationRequested) => if (durationRequested > maxTokenSession) maxTokenSession - else durationRequested + else durationRequested } - logger.debug("stsSettings.maxTokenSessionForNPADuration {}", stsSettings.maxTokenSessionForNPADuration) - logger.debug("stsSettings.maxTokenSessionDuration {}", stsSettings.maxTokenSessionDuration) - logger.debug("durationRequested {}", durationRequested) - d + logger.debug("durationResult {}", durationResult) + durationResult } private def getSessionTokenInputs(aui: AuthenticationUserInfo) = { diff --git a/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala b/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala index c240d45..26d9c84 100644 --- a/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala +++ b/src/main/scala/com/ing/wbaa/rokku/sts/keycloak/KeycloakTokenVerifier.scala @@ -23,14 +23,15 @@ trait KeycloakTokenVerifier extends LazyLogging { import scala.jdk.CollectionConverters._ /** - * Temporary we define NPA be Name - later we will change it to some keycloak role + * Temporary we define NPA by Name - later we will change it to some keycloak role * @param keycloakToken * @return true if NPA */ private def isNPA(keycloakToken: AccessToken): Boolean = { + val isNPA = keycloakToken.getName == "NPA NPA" logger.debug("user getName={}", keycloakToken.getName) - logger.debug("is NPA={}", keycloakToken.getName == "NPA NPA") - keycloakToken.getName == "NPA NPA" + logger.debug("is NPA={}", isNPA) + isNPA } protected[this] def verifyAuthenticationToken(token: BearerToken): Option[AuthenticationUserInfo] = Try {