Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add tests on keycloak authenticator logic [do not merge] #761

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
397aa95
feat: Keycloak container with AdminClient
yshyn-iohk Oct 12, 2023
355359f
feat: migrate docker image of the Agent to Java 21
yshyn-iohk Oct 13, 2023
9c5773e
feat: migrate docker image of the Agent to Java 21
yshyn-iohk Oct 13, 2023
da86e6f
Merge branch 'main' into ATL-5916-java21
yshyn-iohk Oct 14, 2023
e753147
feat: add real and client creation to the tests
yshyn-iohk Oct 16, 2023
f09d557
chore: add @deprecation to the test containers in the shared module
yshyn-iohk Oct 16, 2023
e8c9b82
Merge remote-tracking branch 'origin/ATL-5916-java21' into test/keycl…
Oct 17, 2023
25a9a6c
chore: use sharedTest module for test containers
Oct 17, 2023
784d739
chore: remove deprecated modules
Oct 17, 2023
532b085
chore: make things compile
Oct 17, 2023
ec79f58
chore: truncate time to microseconds precision
Oct 17, 2023
b9cbe27
chore: truncate time to microseconds for all tests
Oct 18, 2023
885c88e
chore: remove test skip check on macos
Oct 18, 2023
be81c11
Merge branch 'main' into test/keycloak-authz-test
Oct 18, 2023
92f9c19
test: working keycloak container tests sample
Oct 18, 2023
e5f87a3
test: working keycloak test with resources setup
Oct 18, 2023
ee455be
test: complete flow for bootstraping and assertion
Oct 18, 2023
7a5207f
test: add actual tests for keycloak authenticator
Oct 19, 2023
d0cb97b
test: add tests when auto rpt upgrade is disabled
Oct 19, 2023
2d5bad6
test: add auth security logic test
Oct 19, 2023
7f02810
chore: remove duplicated tests
Oct 20, 2023
a0f6648
Merge branch 'main' into test/keycloak-authz-test
Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ lazy val V = new {
val typesafeConfig = "1.4.2"
val protobuf = "3.1.9"
val testContainersScala = "0.41.0"
val testContainersJavaKeycloak = "3.0.0"

val doobie = "1.0.0-RC2"
val quill = "4.7.3"
Expand Down Expand Up @@ -127,6 +128,7 @@ lazy val D = new {
// TODO we are adding test stuff to the main dependencies
val testcontainersPostgres: ModuleID = "com.dimafeng" %% "testcontainers-scala-postgresql" % V.testContainersScala
val testcontainersVault: ModuleID = "com.dimafeng" %% "testcontainers-scala-vault" % V.testContainersScala
val testcontainersKeycloak: ModuleID = "com.github.dasniko" % "testcontainers-keycloak" % V.testContainersJavaKeycloak

val doobiePostgres: ModuleID = "org.tpolecat" %% "doobie-postgres" % V.doobie
val doobieHikari: ModuleID = "org.tpolecat" %% "doobie-hikari" % V.doobie
Expand Down Expand Up @@ -155,6 +157,7 @@ lazy val D_Shared = new {
D.scalaPbGrpc,
D.testcontainersPostgres,
D.testcontainersVault,
D.testcontainersKeycloak,
D.zio,
// FIXME: split shared DB stuff as subproject?
D.doobieHikari,
Expand All @@ -163,6 +166,26 @@ lazy val D_Shared = new {
)
}

lazy val D_SharedTest = new {
lazy val dependencies: Seq[ModuleID] =
Seq(
D.typesafeConfig,
D.testcontainersPostgres,
D.testcontainersVault,
D.testcontainersKeycloak,
D.zio,
D.doobieHikari,
D.doobiePostgres,
D.zioCatsInterop,
D.zioJson,
D.zioHttp,
D.zioTest,
D.zioTestSbt,
D.zioTestMagnolia,
D.zioMock
)
}

lazy val D_Connect = new {

private lazy val logback = "ch.qos.logback" % "logback-classic" % V.logback % Test
Expand Down Expand Up @@ -403,6 +426,19 @@ lazy val shared = (project in file("shared"))
)
.enablePlugins(BuildInfoPlugin)

lazy val sharedTest = (project in file("shared-test"))
// .configure(publishConfigure)
.settings(
organization := "io.iohk.atala",
organizationName := "Input Output Global",
buildInfoPackage := "io.iohk.atala.sharedtest",
name := "sharedtest",
crossPaths := false,
libraryDependencies ++= D_SharedTest.dependencies
)
.dependsOn(shared)
.enablePlugins(BuildInfoPlugin)

// #########################
// ### Models & Services ###
// #########################
Expand Down Expand Up @@ -691,6 +727,7 @@ lazy val polluxDoobie = project
)
.dependsOn(polluxCore % "compile->compile;test->test")
.dependsOn(shared)
.dependsOn(sharedTest % Test)

// ########################
// ### Pollux Anoncreds ###
Expand Down Expand Up @@ -740,6 +777,7 @@ lazy val connectDoobie = project
libraryDependencies ++= D_Connect.sqlDoobieDependencies
)
.dependsOn(shared)
.dependsOn(sharedTest % Test)
.dependsOn(connectCore % "compile->compile;test->test")

// ############################
Expand Down Expand Up @@ -775,6 +813,7 @@ lazy val prismAgentWalletAPI = project
castorCore,
eventNotification
)
.dependsOn(sharedTest % Test)

lazy val prismAgentServer = project
.in(file("prism-agent/service/server"))
Expand All @@ -794,7 +833,7 @@ lazy val prismAgentServer = project
buildInfoPackage := "io.iohk.atala.agent.server.buildinfo",
Compile / packageDoc / publishArtifact := false
)
.enablePlugins(JavaAppPackaging, DockerPlugin)
.enablePlugins(JavaAppPackaging, DockerPlugin, AshScriptPlugin)
.enablePlugins(BuildInfoPlugin)
.dependsOn(prismAgentWalletAPI % "compile->compile;test->test")
.dependsOn(
Expand All @@ -807,6 +846,7 @@ lazy val prismAgentServer = project
castorCore,
eventNotification
)
.dependsOn(sharedTest % Test)

// ############################
// #### Release process #####
Expand All @@ -824,6 +864,7 @@ releaseProcess := Seq[ReleaseStep](

lazy val aggregatedProjects: Seq[ProjectReference] = Seq(
shared,
sharedTest,
models,
protocolConnection,
protocolCoordinateMediation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.iohk.atala.connect.sql.repository
import com.dimafeng.testcontainers.PostgreSQLContainer
import io.iohk.atala.connect.core.repository.{ConnectionRepository, ConnectionRepositorySpecSuite}
import io.iohk.atala.shared.db.DbConfig
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import zio.*
import zio.test.*

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.iohk.atala.test.container

import com.dimafeng.testcontainers.PostgreSQLContainer
import io.iohk.atala.sharedtest.containers.PostgresTestContainer.postgresContainer
import zio.*
import zio.ZIO.*
import io.iohk.atala.shared.test.containers.PostgresTestContainer.postgresContainer

object PostgresLayer {

Expand Down
12 changes: 10 additions & 2 deletions infrastructure/shared/docker-compose-demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
version: "3.8"

services:

db:
image: postgres:13
environment:
Expand Down Expand Up @@ -56,7 +55,16 @@ services:
prism-node:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://prism-agent:8085/_system/health"]
test:
[
"CMD",
"wget",
"--timeout=5",
"--tries=3",
"-O",
"/dev/null",
"http://prism-agent:8085/_system/health",
]
interval: 30s
timeout: 10s
retries: 5
Expand Down
11 changes: 10 additions & 1 deletion infrastructure/shared/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,16 @@ services:
vault-server:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://prism-agent:8085/_system/health"]
test:
[
"CMD",
"wget",
"--timeout=5",
"--tries=3",
"-O",
"/dev/null",
"http://prism-agent:8085/_system/health",
]
interval: 30s
timeout: 10s
retries: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import io.iohk.atala.pollux.sql.model.db.{CredentialDefinition, CredentialDefini
import io.iohk.atala.shared.db.ContextAwareTask
import io.iohk.atala.shared.db.Implicits.*
import io.iohk.atala.shared.models.{WalletAccessContext, WalletId}
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import io.iohk.atala.test.container.MigrationAspects.*
import zio.*
import zio.json.ast.Json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.iohk.atala.shared.db.ContextAwareTask
import io.iohk.atala.shared.db.Implicits.*
import io.iohk.atala.shared.models.WalletAccessContext
import io.iohk.atala.shared.models.WalletId
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import io.iohk.atala.test.container.MigrationAspects.*
import zio.*
import zio.json.ast.Json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import io.iohk.atala.shared.db.ContextAwareTask
import io.iohk.atala.shared.db.Implicits.*
import io.iohk.atala.shared.models.WalletAccessContext
import io.iohk.atala.shared.models.WalletId
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import io.iohk.atala.test.container.MigrationAspects.*
import zio.*
import zio.test.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.iohk.atala.pollux.sql.repository
import com.dimafeng.testcontainers.PostgreSQLContainer
import io.iohk.atala.pollux.core.repository._
import io.iohk.atala.shared.db.DbConfig
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import zio._
import zio.test._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.iohk.atala.pollux.sql.repository
import com.dimafeng.testcontainers.PostgreSQLContainer
import io.iohk.atala.pollux.core.repository._
import io.iohk.atala.shared.db.DbConfig
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import zio._
import zio.test._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,6 @@ object JWTVerificationTest extends ZIOSpecDefault {
validation <- JwtCredential.validateEncodedJWT(jwtCredential)(resolver)
} yield assert(validation.fold(_ => false, _ => true))(equalTo(false))
}
).when(!sys.props.get("os.name").contains("Mac OS X")) // Mac OS X throws `Curve not supported: secp256k1`
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@ object TokenIntrospection {
given JsonDecoder[TokenIntrospection] = JsonDecoder.derived
}

final case class TokenResponse(access_token: String, refresh_token: String)

object TokenResponse {
given JsonEncoder[TokenResponse] = JsonEncoder.derived
given JsonDecoder[TokenResponse] = JsonDecoder.derived
}

trait KeycloakClient {

def getRpt(accessToken: String): IO[AuthenticationError, String]

def getAccessToken(username: String, password: String): IO[AuthenticationError, TokenResponse]

def introspectToken(token: String): IO[AuthenticationError, TokenIntrospection]

/** Return list of permitted resources */
Expand All @@ -32,6 +41,7 @@ class KeycloakClientImpl(client: AuthzClient, httpClient: Client, keycloakConfig
extends KeycloakClient {

private val introspectionUrl = client.getServerConfiguration().getIntrospectionEndpoint()
private val tokenUrl = client.getServerConfiguration().getTokenEndpoint()

private val baseFormHeaders = Headers(Header.ContentType(MediaType.application.`x-www-form-urlencoded`))

Expand Down Expand Up @@ -72,6 +82,42 @@ class KeycloakClientImpl(client: AuthzClient, httpClient: Client, keycloakConfig
} yield result
}

override def getAccessToken(username: String, password: String): IO[AuthenticationError, TokenResponse] = {
for {
response <- Client
.request(
url = tokenUrl,
method = Method.POST,
headers = baseFormHeaders,
content = Body.fromURLEncodedForm(
Form(
FormField.simpleField("grant_type", "password"),
FormField.simpleField("client_id", keycloakConfig.clientId),
FormField.simpleField("client_secret", keycloakConfig.clientSecret),
FormField.simpleField("username", username),
FormField.simpleField("password", password),
)
)
)
.logError("Fail to get the accessToken on keyclaok.")
.mapError(e => AuthenticationError.UnexpectedError("Fail to get the accessToken on keyclaok."))
.provide(ZLayer.succeed(httpClient))
body <- response.body.asString
.logError("Fail parse keycloak token response.")
.mapError(e => AuthenticationError.UnexpectedError("Fail parse keycloak token response."))
result <-
if (response.status.code == 200) {
ZIO
.fromEither(body.fromJson[TokenResponse])
.logError("Fail to decode keycloak token response")
.mapError(e => AuthenticationError.UnexpectedError(e))
} else {
ZIO.logError(s"Keycloak token introspection was unsucessful. Status: ${response.status}. Response: $body") *>
ZIO.fail(AuthenticationError.UnexpectedError("Token introspection was unsuccessful."))
}
} yield result
}

override def getRpt(accessToken: String): IO[AuthenticationError, String] =
ZIO
.attemptBlocking {
Expand All @@ -97,9 +143,11 @@ class KeycloakClientImpl(client: AuthzClient, httpClient: Client, keycloakConfig
}

object KeycloakClientImpl {
val layer: RLayer[KeycloakConfig & Client, KeycloakClient] = ZLayer.fromZIO {
val layer: RLayer[KeycloakConfig & Client, KeycloakClient] =
authzClientLayer >>> ZLayer.fromFunction(KeycloakClientImpl(_, _, _))

def authzClientLayer: RLayer[KeycloakConfig, AuthzClient] = ZLayer.fromZIO {
for {
httpClient <- ZIO.service[Client]
keycloakConfig <- ZIO.service[KeycloakConfig]
config = KeycloakAuthzConfig(
keycloakConfig.keycloakUrl.toString(),
Expand All @@ -109,7 +157,6 @@ object KeycloakClientImpl {
null
)
client <- ZIO.attempt(AuthzClient.create(config))
} yield KeycloakClientImpl(client, httpClient, keycloakConfig)
} yield client
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import io.iohk.atala.iam.authentication.apikey.ApiKeyAuthenticatorImpl
import io.iohk.atala.iam.authentication.apikey.JdbcAuthenticationRepository
import io.iohk.atala.shared.models.WalletAccessContext
import io.iohk.atala.shared.models.WalletId
import io.iohk.atala.shared.test.containers.PostgresTestContainerSupport
import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport
import io.iohk.atala.test.container.DBTestUtils
import zio.*
import zio.test.*
Expand Down
Loading
Loading