Skip to content

Commit

Permalink
Many fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandru committed Oct 17, 2022
1 parent 213f3ee commit 18a19d7
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 241 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ Or the native version:
make build-native
```

### Issues with native-image

- [Kotlinx Serialization with GraalVM Native Images](https://github.com/Kotlin/kotlinx.serialization/issues/1125)

## License

Copyright © 2018-2022 Alexandru Nedelcu, some rights reserved.
Expand Down
22 changes: 10 additions & 12 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,22 @@ repositories {
}

dependencies {
implementation(libs.kotlin.stdlib.jdk8)
implementation(libs.logback.classic)
implementation(libs.kaml)
implementation(libs.commons.codec)
implementation(libs.arrow.core)
implementation(libs.arrow.fx.coroutines)
implementation(libs.arrow.fx.stm)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktor.server.content.negotiation)
implementation(libs.ktor.server.core)
// implementation(libs.ktor.server.netty)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.tests.jvm)
implementation(libs.ktor.client.cio.jvm)
implementation(libs.commons.codec)
implementation(libs.commons.text)
implementation(libs.kaml)
implementation(libs.kotlin.stdlib.jdk8)
implementation(libs.kotlin.test.junit)
implementation(libs.kotlinx.cli)
implementation(libs.kotlinx.serialization.hocon)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktor.server.cio)
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.html.builder)
implementation(libs.ktor.server.tests.jvm)
implementation(libs.logback.classic)
}

tasks {
Expand All @@ -86,3 +83,4 @@ ktor {
archiveFileName.set("github-webhook-listener-fat.jar")
}
}

16 changes: 16 additions & 0 deletions config/application-dummy.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
http {
host: "0.0.0.0"
port: 8080
path: "/"
}

projects {
myproject {
action: "push"
ref: "refs/heads/gh-pages"
directory: "/tmp"
command: "touch ./i-was-here.txt"
timeout: "PT5S"
secret: "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,5 @@ ktor-server-cio = { group = "io.ktor", name = "ktor-server-cio", version.ref = "
kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" }

ktor-client-cio-jvm = { group = "io.ktor", name = "ktor-client-cio-jvm", version.ref = "ktor" }

ktor-server-html-builder = { group = "io.ktor", name = "ktor-server-html-builder", version.ref = "ktor" }
2 changes: 1 addition & 1 deletion src/main/docker/Dockerfile.jvm
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ COPY --from=build --chown=appuser:root /home/gradle/src/scripts/java-exec /opt/a
EXPOSE 8080
USER appuser

CMD ["/opt/app/java-exec","-jar","/opt/app/github-webhook-listener-fat.jar","start-server","-c","/opt/app/config/config.yaml"]
CMD ["/opt/app/java-exec","-jar","/opt/app/github-webhook-listener-fat.jar","/opt/app/config/config.yaml"]
5 changes: 2 additions & 3 deletions src/main/docker/Dockerfile.native
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
FROM --platform=linux/amd64 ghcr.io/graalvm/native-image:22.2.0 AS build
COPY --chown=root:root . /app/source
WORKDIR /app/source
RUN ./gradlew run -PnativeAgent --args="run-test-scenario -c ./config/application-dummy.yaml"
RUN ./gradlew nativeCompile
RUN ./gradlew nativeCompile --no-daemon

FROM --platform=linux/amd64 alpine:latest
RUN mkdir -p /opt/app/config
Expand All @@ -27,4 +26,4 @@ COPY --from=build --chown=appuser:root /app/source/config/application-dummy.yaml
EXPOSE 8080
USER appuser

CMD ["/opt/app/github-webhook-listener","start-server","-c","/opt/app/config/config.yaml"]
CMD ["/opt/app/github-webhook-listener","/opt/app/config/config.yaml"]
27 changes: 0 additions & 27 deletions src/main/docker/Dockerfile.native.old

This file was deleted.

18 changes: 2 additions & 16 deletions src/main/kotlin/org/alexn/hook/AppConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package org.alexn.hook

import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlConfiguration
import com.typesafe.config.ConfigFactory
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.hocon.Hocon
import java.io.File
import kotlin.time.Duration

Expand Down Expand Up @@ -39,26 +36,15 @@ data class AppConfig(
)

companion object {
@OptIn(ExperimentalSerializationApi::class)
fun parseHocon(string: String): AppConfig =
Hocon.decodeFromConfig(
serializer(),
ConfigFactory.parseString(string).resolve()
)

fun parseYaml(string: String): AppConfig =
yamlParser.decodeFromString(
serializer(),
string
)

fun loadFromFile(file: File): AppConfig {
fun parseYaml(file: File): AppConfig {
val txt = file.readText()
return if (file.extension.matches("(?i)yaml|yml".toRegex())) {
parseYaml(txt)
} else {
parseHocon(txt)
}
return parseYaml(txt)
}

private val yamlParser = Yaml(
Expand Down
25 changes: 14 additions & 11 deletions src/main/kotlin/org/alexn/hook/EventPayload.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import io.ktor.http.ContentType
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.apache.commons.codec.digest.HmacAlgorithms
import org.apache.commons.codec.digest.HmacUtils
Expand All @@ -20,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8
@Serializable
data class EventPayload(
val action: String?,
val ref: String?,
val ref: String?
) {
fun shouldProcess(prj: AppConfig.Project): Boolean =
(action ?: "push") == (prj.action ?: "push") && ref == prj.ref
Expand All @@ -36,40 +35,44 @@ data class EventPayload(
fun authenticateRequest(
body: String,
signatureKey: String,
signatureHeader: String?,
signatureHeader: String?
): Either<RequestError.Forbidden, Unit> {
if (signatureHeader == null)
if (signatureHeader == null) {
return RequestError.Forbidden("No signature header was provided").left()
}

val sha1Prefix = "sha1="
val sha256Prefix = "sha256="

if (signatureHeader.startsWith(sha256Prefix)) {
val hmacHex = HmacUtils(HmacAlgorithms.HMAC_SHA_256, signatureKey).hmacHex(body)
if (!signatureHeader.substring(sha256Prefix.length).equals(hmacHex, ignoreCase = true))
if (!signatureHeader.substring(sha256Prefix.length).equals(hmacHex, ignoreCase = true)) {
return RequestError.Forbidden("Invalid checksum (sha256)").left()
}
return Unit.right()
}
if (signatureHeader.startsWith(sha1Prefix)) {
val hmacHex = HmacUtils(HmacAlgorithms.HMAC_SHA_1, signatureKey).hmacHex(body)
if (!signatureHeader.substring(sha1Prefix.length).equals(hmacHex, ignoreCase = true))
if (!signatureHeader.substring(sha1Prefix.length).equals(hmacHex, ignoreCase = true)) {
return RequestError.Forbidden("Invalid checksum (sha1)").left()
}
return Unit.right()
}
return RequestError.Forbidden("Unsupported algorithm").left()
}

fun parse(contentType: ContentType, body: String): Either<RequestError, EventPayload> =
if (contentType.match(ContentType("application", "json")))
if (contentType.match(ContentType("application", "json"))) {
parseJson(body)
else if (contentType.match(ContentType("application", "x-www-form-urlencoded")))
} else if (contentType.match(ContentType("application", "x-www-form-urlencoded"))) {
parseFormData(body)
else
} else {
RequestError.UnsupportedMediaType("Cannot process `$contentType` media type").left()
}

fun parseJson(json: String): Either<RequestError.BadInput, EventPayload> {
try {
val payload = jsonParser.decodeFromString<EventPayload>(json)
val payload = jsonParser.decodeFromString(serializer(), json)
return payload.right()
} catch (e: SerializationException) {
return RequestError.BadInput("Invalid JSON", e).left()
Expand All @@ -88,7 +91,7 @@ data class EventPayload(
}
EventPayload(
action = map["action"],
ref = map["ref"],
ref = map["ref"]
).right()
} catch (e: AssertionError) {
RequestError.BadInput("Invalid form-urlencoded data", null).left()
Expand Down
Loading

0 comments on commit 18a19d7

Please sign in to comment.