JWTEmitter now runs among tests when tests are running
continuous-integration/drone/push Build is passing Details

dev
Override-6 2 years ago
parent a20ba55248
commit fdfc3cbac1

@ -77,11 +77,11 @@ class Authenticator(url: URL, key: PublicKey, algorithm: JwtAsymmetricAlgorithm)
import ctx.v.*
findByMail(mail)
.someOrFail(UserNotFound)// await one second if password fails to reduce bruteforce
.someOrFail(UserNotFound)// await one second if password fails to reduce bruteforce //FIXME this wont actually reduce bruteforce
.filterOrElse(_.passwordHash == hashPassword(password))(ZIO.sleep(1.second) *> ZIO.fail(InvalidPassword))
}
private inline def insert(user: User) = quote {
private def insert(user: User) = quote {
query[User].insert(
_.id -> user.id,
_.name -> user.name,

@ -19,11 +19,11 @@
</Appenders>
<Loggers>
<Logger name="JWTEmitter" additivity="false" includeLocation="false">
<Logger level="ALL" name="JWTEmitter" additivity="false" includeLocation="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="LogFile"/>
</Logger>
<Root level="ALL" includeLocation="false">
<Root level="INFO" includeLocation="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="LogFile"/>
</Root>

@ -18,12 +18,13 @@ import scala.util.chaining.scalaUtilChainingOps
object Main extends ZIOAppDefault:
private val KeyFactory = java.security.KeyFactory.getInstance("RSA")
private val EmitterPresenceHook = Path.of("/tmp/emitter.presence")
private val app = Http.collectZIO[Request] {
case r@(Method.GET | Method.POST) -> _ / "jwt" =>
case r@(Method.GET | Method.POST) -> _ =>
ZIO.serviceWithZIO[JwtGenerator](_.generateTokenResponse(r))
case _ =>
ZIO.succeed(Response(status = Status.NotFound))
ZIO.succeed(Response(status = Status.MethodNotAllowed))
}
private def parsePort(port: Option[String]): Task[Int] =
@ -54,7 +55,10 @@ object Main extends ZIOAppDefault:
}
parsePort(port) <&> loadKey(keyFile)
private def onStart(port: Int) =
Console.printLine(s"JWT AppToken open on port $port") *> ZIO.attempt {
Files.createFile(EmitterPresenceHook)
}
private def startServer(port: Int, key: PrivateKey) =
val config = ServerConfig.default
@ -64,10 +68,12 @@ object Main extends ZIOAppDefault:
val generator =
new JwtGenerator(Duration.ofDays(15), key, JwtAlgorithm.RS256)
val configLayer = ServerConfig.live(config)
(Server.install(
app
) *> Console.printLine(s"JWT AppToken open on port $port") *> ZIO.never)
(Server.install(app) *> onStart(port) *> ZIO.never)
.provide(configLayer, Server.live, ZLayer.succeed(generator))
.catchAllCause(c => {
Files.writeString(EmitterPresenceHook, "A")
ZIO.failCause(c)
})
val run =
ZIO.serviceWithZIO[ZIOAppArgs](args => parseArgs(args.getArgs))

@ -3,39 +3,39 @@
{
"name" : "Test Task name not available here/\/login page handler/login situation tests/login with unknown account",
"status" : "Success",
"durationMillis" : "4103",
"durationMillis" : "3877",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "login situation tests", "login with unknown account"]
},
{
"name" : "Test Task name not available here/\/login page handler/login situation tests/login with known account",
"status" : "Failure",
"durationMillis" : "1",
"status" : "Success",
"durationMillis" : "4862",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "login situation tests", "login with known account"]
},
{
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with no password attribute",
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/empty packet",
"status" : "Success",
"durationMillis" : "2681",
"durationMillis" : "2683",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with no password attribute"]
"labels" : ["\/login page handler", "erroned request body tests", "empty packet"]
},
{
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/empty packet",
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with no password attribute",
"status" : "Success",
"durationMillis" : "2697",
"durationMillis" : "2698",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "empty packet"]
"labels" : ["\/login page handler", "erroned request body tests", "with no password attribute"]
},
{
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with no mail attribute",
"status" : "Success",
"durationMillis" : "2702",
"durationMillis" : "2697",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with no mail attribute"]
@ -43,7 +43,7 @@
{
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with invalid json",
"status" : "Success",
"durationMillis" : "2717",
"durationMillis" : "2679",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with invalid json"]

@ -5,23 +5,21 @@ echo GENERATING TEMPORARY KEY PAIRS FOR TESTS
rm -r /tmp/keys &> /dev/null
mkdir -p /tmp/keys
cd /tmp/keys
keytool -genkey -noprompt \
keytool -genkeypair \
-alias key \
-keyalg RSA \
-validity 2 \
-keystore test.keystore \
-keysize 4069 \
-sigalg SHA256withRSA \
-storetype PKCS12 \
-keystore store.p12 \
-dname "CN=x.y.com, OU=TB, O=TBA, L=dzqdz, S=dqzdzq, C=GB" \
-storepass 123456789 \
-keypass 123456789
keytool -noprompt -export \
-alias key \
-keystore test.keystore \
-rfc \
-file public.cert \
-keypass 123456789 \
-storepass 123456789
keytool -v -export -file public.cert -keystore store.p12 -alias key -storepass 123456789
openssl pkcs12 -in store.p12 -nodes -nocerts -out key.pem -passin pass:123456789
openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out key.pcqks -nocrypt
openssl pkcs12 -in test.keystore -nodes -nocerts -out private.pcks -passin pass:123456789
openssl pkcs12 -in test.keystore -nokeys -out public.cert -passin pass:123456789
#openssl pkcs8 -topk8 -inform PEM -outform DER -in test.keystore -out private.pcks -passin pass:123456789
#openssl pkcs8 -topk8 -inform PEM -outform DER -in test.keystore -out public.cert -passin pass:123456789

@ -1,8 +1,35 @@
package org.tbasket.test
import com.sun.nio.file.ExtendedOpenOption
import io.netty.buffer.ByteBuf
import java.nio.channels.Pipe
import java.nio.file.{Files, Path, StandardOpenOption}
object TestEmitter:
val PORT = 5455
val PORT = 5457
def start(): Unit = {
val emitterPresence = Path.of("/tmp/emitter.presence")
Files.deleteIfExists(emitterPresence)
val process = new ProcessBuilder(
"bash",
"./mill", "JWTEmitter.run",
"-k", "/tmp/keys/key.pcqks",
"-p", TestServerConfig.emitterURL.port.get.toString
)
.inheritIO()
.start()
Runtime.getRuntime.addShutdownHook(new Thread((() => process.destroy()): Runnable))
//the emitter will create the /tmp/emitter.presence file once it started, this is to inform us that the server is OP
while (Files.notExists(emitterPresence))
Thread.sleep(500)
if (Files.readString(emitterPresence) == "A") {
System.err.println("Emitter did not start successfully")
System.exit(1)
}
Files.delete(emitterPresence)
}

@ -15,6 +15,7 @@ object TestLayers {
val auth = {
TestEmitter.start()
val publicKey = TestServerConfig.emitterCertificate.getPublicKey
val auth = new Authenticator(TestServerConfig.emitterURL, publicKey, TestServerConfig.emitterKeyAlgorithm)
ZLayer.succeed(auth)
@ -42,7 +43,7 @@ object TestLayers {
val in = getClass.getClassLoader.getResourceAsStream(url)
val bytes = in.readAllBytes()
in.close()
val requests = new String(bytes).split(';')
requests.foreach(statement.execute)
}

@ -17,7 +17,7 @@ object TestServerConfig extends ServerConfig {
private final val CertFactory = CertificateFactory.getInstance("X509")
override def emitterURL: URL = URL.fromString(s"http://localhost/$PORT").getOrElse(null)
override def emitterURL: URL = URL.fromString(s"http://localhost:$PORT").getOrElse(null)
override def emitterCertificate: Certificate =
CertFactory.generateCertificate(Files.newInputStream(Path.of("/tmp/keys/public.cert")))

@ -14,7 +14,7 @@ import zio.*
import zio.http.netty.client.ConnectionPool
import zio.http.*
import zio.http.model.{HeaderNames, Headers}
import zio.http.model.Headers.Header
import zio.http.model.Headers.{Header, empty}
import zio.json.*
import zio.json.ast.{Json, JsonCursor}
import zio.test.*
@ -65,9 +65,8 @@ object LoginPageHandlerTests extends ZIOSpecDefault {
test("login with known account") {
for
response <- post(Request.post(Body.fromString("""{"password":"123456","email":"maximebatista18@gmail.com"}"""), URL.empty))
json <- getJsonBody(response)
//errorType <- parseAttribute(json, "error", JsonCursor.field("error").isString)
yield
assert(response)(hasField("body", _.body, equalTo(Body.empty))) //TODO assert that the cookie name is JWT
assert(response)(hasField("headers", _.headers, exists(hasField("key", _.key, equalTo(HeaderNames.setCookie)))))
}
)