Skip to content

Commit

Permalink
Merge 955c89c into 3296030
Browse files Browse the repository at this point in the history
  • Loading branch information
gregorbg committed Aug 16, 2022
2 parents 3296030 + 955c89c commit 411f5f2
Show file tree
Hide file tree
Showing 325 changed files with 1,281 additions and 1,575 deletions.
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/tnoodle-ui"
directory: "/ui"
schedule:
interval: "monthly"
- package-ecosystem: "github-actions"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ jobs:
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: 'tnoodle-ui/coverage/lcov.info'
base-path: 'tnoodle-ui'
path-to-lcov: 'ui/coverage/lcov.info'
base-path: 'ui'
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<img src="./tnoodle-server/src/main/resources/icons/tnoodle_logo_1024.png" alt="TNoodle Logo" height="128px"/>
<img src="./core/src/main/resources/icons/tnoodle_logo_1024.png" alt="TNoodle Logo" height="128px"/>

# TNoodle

Expand Down Expand Up @@ -42,11 +42,11 @@ Gradle automagically handles all dependencies for you. You just need an Internet

When you're ready to develop, run the following and then visit <http://localhost:2014/scramble/>

./gradlew :webscrambles:runShadow
./gradlew :server:runShadow

To build a distributable/executable `.jar` file, run:

./gradlew :webscrambles:shadowJar
./gradlew :server:shadowJar

You can run the `.jar` from the commandline using: (replace the `$VERSION` tag accordingly)

Expand Down
11 changes: 11 additions & 0 deletions build-tools/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
kotlin("jvm")
}

repositories {
mavenCentral()
}

dependencies {
implementation(libs.bouncycastle)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.worldcubeassociation.tnoodle.core.crypto

import org.bouncycastle.util.io.pem.PemReader
import java.io.File
import java.io.Reader
import java.security.*
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec

object AsymmetricCipher {
const val ENCRYPTION_ALGORITHM = "RSA"
const val PUBLIC_KEY_PEM = "/rsa/tnoodle_public.pem"

private val PUBLIC_KEY_BYTES = loadRSAKeyBytesFromResource(PUBLIC_KEY_PEM)
val RSA_PUBLIC_KEY by lazy { generatePublicKey(PUBLIC_KEY_BYTES) }

private val CIPHER_KEY_FACTORY = KeyFactory.getInstance(ENCRYPTION_ALGORITHM)

fun loadRSAKeyBytesFromResource(resourcePath: String): ByteArray {
val keyStream = this::class.java.getResourceAsStream(resourcePath)
?: error("RSA key resource not found: $resourcePath")

return loadRSAKeyBytes(keyStream.reader())
}

fun loadRSAKeyBytesFromFile(keyFile: File): ByteArray {
return loadRSAKeyBytes(keyFile.reader())
}

private fun loadRSAKeyBytes(keyFileReader: Reader): ByteArray {
return keyFileReader.use { PemReader(it).readPemObject().content }
}

fun generatePublicKey(keyBytes: ByteArray): PublicKey {
val spec = X509EncodedKeySpec(keyBytes)
return CIPHER_KEY_FACTORY.generatePublic(spec)
}

fun generatePrivateKey(keyBytes: ByteArray): PrivateKey {
val spec = PKCS8EncodedKeySpec(keyBytes)
return CIPHER_KEY_FACTORY.generatePrivate(spec)
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
package org.worldcubeassociation.tnoodle.server.crypto
package org.worldcubeassociation.tnoodle.core.crypto

import java.security.*
import java.util.*

object BuildVerification {
const val SIGNATURE_PACKAGE = "signature"
const val SIGNATURE_SUFFIX = "sign"

const val SIGNATURE_ALGORITHM = "SHA256with${AsymmetricCipher.ENCRYPTION_ALGORITHM}"

private val SIGNATURE_INSTANCE by lazy { Signature.getInstance(SIGNATURE_ALGORITHM) }
val SIGNATURE_INSTANCE by lazy { Signature.getInstance(SIGNATURE_ALGORITHM) }
private val BASE64_ENCODER by lazy { Base64.getEncoder() }

private val VERIFICATION_KEY = AsymmetricCipher.RSA_PUBLIC_KEY

val BUILD_VERIFIED by lazy { checkBuildSignature(AsymmetricCipher.PUBLIC_KEY_PEM) }
val VERIFICATION_KEY_BYTES_BASE64 by lazy { VERIFICATION_KEY?.encoded?.let(BASE64_ENCODER::encodeToString) }
val VERIFICATION_KEY_BYTES_BASE64 by lazy { VERIFICATION_KEY.encoded?.let(BASE64_ENCODER::encodeToString) }

fun checkBuildSignature(resourcePath: String): Boolean {
val publicKey = VERIFICATION_KEY ?: return false

val fileBytes = this::class.java.getResourceAsStream(resourcePath)?.readBytes()
?: return false

val preparedCheck = SIGNATURE_INSTANCE.apply {
initVerify(publicKey)
initVerify(VERIFICATION_KEY)
update(fileBytes)
}

val signaturePath = "/signature$resourcePath.sign"
val signaturePath = "/$SIGNATURE_PACKAGE$resourcePath.$SIGNATURE_SUFFIX"
val signatureBytes = this::class.java.getResourceAsStream(signaturePath)?.readBytes()
?: return false

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.worldcubeassociation.tnoodle.core.util

object FrontendUtil {
const val FRONTEND_BINDING_PACKAGE = "wca/tnoodle-ui"
}
20 changes: 10 additions & 10 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import configurations.Languages.attachLocalRepositories
import configurations.ProjectVersions.TNOODLE_SYMLINK
import configurations.ProjectVersions.setTNoodleRelease
import crypto.BuildVerification.SIGNATURE_PACKAGE
import crypto.BuildVerification.SIGNATURE_SUFFIX
import org.worldcubeassociation.tnoodle.build.Languages.attachLocalRepositories
import org.worldcubeassociation.tnoodle.build.ProjectVersions.TNOODLE_SYMLINK
import org.worldcubeassociation.tnoodle.build.ProjectVersions.setTNoodleRelease
import org.worldcubeassociation.tnoodle.build.BuildSignature.SIGNATURE_PACKAGE
import org.worldcubeassociation.tnoodle.build.BuildSignature.SIGNATURE_SUFFIX

import crypto.BuildVerification.createBuildSignature
import org.worldcubeassociation.tnoodle.build.BuildSignature.createBuildSignature

import proguard.gradle.ProGuardTask

Expand Down Expand Up @@ -33,10 +33,10 @@ plugins {
}

val releasePrefix = "TNoodle-WCA"
val releaseProject = "webscrambles"
val releaseProject = "server"

tasks.create("registerReleaseTag") {
val signatureProject = project(":tnoodle-server")
val signatureProject = project(":core")
val filenameToSign = "rsa/tnoodle_public.pem"

val signatureStorage = signatureProject.file("src/main/resources/$SIGNATURE_PACKAGE/$filenameToSign.$SIGNATURE_SUFFIX")
Expand Down Expand Up @@ -125,9 +125,9 @@ tasks.create("runBackend") {
}

tasks.create("installCloud") {
dependsOn("registerCloudReleaseTag", ":cloudscrambles:appengineDeploy")
dependsOn("registerCloudReleaseTag", ":cloud:appengineDeploy")
}

tasks.create("installEmulateCloud") {
dependsOn("registerCloudReleaseTag", ":cloudscrambles:appengineRun")
dependsOn("registerCloudReleaseTag", ":cloud:appengineRun")
}
1 change: 1 addition & 0 deletions buildSrc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!src/main/kotlin/org/worldcubeassociation/tnoodle/build
2 changes: 2 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ dependencies {
implementation(libs.bouncycastle)
implementation(libs.eclipse.jgit)

implementation(project(":tools"))

// https://github.com/gradle/gradle/issues/15383#issuecomment-779893192
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}
2 changes: 2 additions & 0 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ dependencyResolutionManagement {
}
}
}

include("tools")
26 changes: 0 additions & 26 deletions buildSrc/src/main/kotlin/crypto/AsymmetricCipher.kt

This file was deleted.

27 changes: 0 additions & 27 deletions buildSrc/src/main/kotlin/crypto/BuildVerification.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.worldcubeassociation.tnoodle.build

import org.gradle.api.Project
import java.io.File
import org.worldcubeassociation.tnoodle.core.crypto.AsymmetricCipher
import org.worldcubeassociation.tnoodle.core.crypto.BuildVerification

object BuildSignature {
const val SIGNATURE_PACKAGE = BuildVerification.SIGNATURE_PACKAGE
const val SIGNATURE_SUFFIX = BuildVerification.SIGNATURE_SUFFIX

fun Project.createBuildSignature(signingKeyPath: String, fileToSign: File): ByteArray {
val privateKeyBytes = AsymmetricCipher.loadRSAKeyBytesFromFile(file(signingKeyPath))
val privateKey = AsymmetricCipher.generatePrivateKey(privateKeyBytes)

val fileBytes = fileToSign.readBytes()

val preparedCheck = BuildVerification.SIGNATURE_INSTANCE.apply {
initSign(privateKey)
update(fileBytes)
}

return preparedCheck.sign()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configurations
package org.worldcubeassociation.tnoodle.build

object CompilerSettings {
const val KOTLIN_JVM_TARGET = "1.8"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configurations
package org.worldcubeassociation.tnoodle.build

import org.gradle.api.Task
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configurations
package org.worldcubeassociation.tnoodle.build

import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Project
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.worldcubeassociation.tnoodle.build

import org.worldcubeassociation.tnoodle.core.util.FrontendUtil

object FrontendBindings {
const val PACKAGE_ROOT = FrontendUtil.FRONTEND_BINDING_PACKAGE
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configurations
package org.worldcubeassociation.tnoodle.build

import org.gradle.api.Project
import org.gradle.kotlin.dsl.maven
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package configurations
package org.worldcubeassociation.tnoodle.build

import org.gradle.api.Project
import org.gradle.api.Task
Expand Down
1 change: 1 addition & 0 deletions buildSrc/tools
10 changes: 5 additions & 5 deletions cloudscrambles/build.gradle.kts → cloud/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import configurations.CompilerSettings.KOTLIN_JVM_TARGET
import configurations.Languages.attachRemoteRepositories
import configurations.ProjectVersions.tNoodleImplOrDefault
import configurations.ProjectVersions.tNoodleVersionOrDefault
import org.worldcubeassociation.tnoodle.build.CompilerSettings.KOTLIN_JVM_TARGET
import org.worldcubeassociation.tnoodle.build.Languages.attachRemoteRepositories
import org.worldcubeassociation.tnoodle.build.ProjectVersions.tNoodleImplOrDefault
import org.worldcubeassociation.tnoodle.build.ProjectVersions.tNoodleVersionOrDefault
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

description = "An extension over the core server to expose scrambles in a Google Cloud environment"
Expand All @@ -17,7 +17,7 @@ plugins {
}

dependencies {
implementation(project(":tnoodle-server"))
implementation(project(":core"))

//implementation(libs.kotless.ktor)
implementation(libs.google.cloud.storage)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.worldcubeassociation.tnoodle.cloud

import io.ktor.server.application.*
import io.ktor.server.routing.*
import org.worldcubeassociation.tnoodle.core.ApplicationHandler
import org.worldcubeassociation.tnoodle.core.TNoodleServer
import org.worldcubeassociation.tnoodle.cloud.routing.HomepageHandler
import org.worldcubeassociation.tnoodle.cloud.routing.PuzzleListHandler
import org.worldcubeassociation.tnoodle.cloud.routing.ScrambleHandler
import org.worldcubeassociation.tnoodle.cloud.routing.ScrambleViewHandler
import org.worldcubeassociation.tnoodle.core.ServerEnvironmentConfig

object CloudscramblesServer : ApplicationHandler {
override fun spinUp(app: Application) {
val cloudscramblesWrapper = TNoodleServer(GoogleServerEnvironmentConfig)

app.routing {
HomepageHandler.install(this)

route("api") {
route("v0") {
ScrambleHandler.install(this)
ScrambleViewHandler.install(this)
PuzzleListHandler.install(this)
}
}
}

GoogleServerEnvironmentConfig.overrideFontConfig()

cloudscramblesWrapper.spinUp(app)
}
}

Loading

0 comments on commit 411f5f2

Please sign in to comment.