From a0409ba566e2df0a1198cc25405e4df110d3c0b8 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 25 Nov 2025 18:37:14 +0100 Subject: [PATCH 1/8] added Docker image build with jib, changed to Kotlin --- README.md | 5 + build.gradle | 152 ------------------------ build.gradle.kts | 121 +++++++++++++++++++ fireblocks-application/build.gradle | 24 ---- fireblocks-application/build.gradle.kts | 76 ++++++++++++ fireblocks-datamodel/build.gradle | 21 ---- fireblocks-datamodel/build.gradle.kts | 24 ++++ fireblocks-docker/Dockerfile | 20 ---- fireblocks-docker/build.gradle | 101 ---------------- fireblocks-service/build.gradle | 46 ------- fireblocks-service/build.gradle.kts | 49 ++++++++ gradle.properties | 4 + settings.gradle | 13 -- settings.gradle.kts | 25 ++++ 14 files changed, 304 insertions(+), 377 deletions(-) delete mode 100644 build.gradle create mode 100644 build.gradle.kts delete mode 100755 fireblocks-application/build.gradle create mode 100755 fireblocks-application/build.gradle.kts delete mode 100755 fireblocks-datamodel/build.gradle create mode 100755 fireblocks-datamodel/build.gradle.kts delete mode 100644 fireblocks-docker/Dockerfile delete mode 100644 fireblocks-docker/build.gradle delete mode 100755 fireblocks-service/build.gradle create mode 100755 fireblocks-service/build.gradle.kts delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/README.md b/README.md index 9c6bd86..3e24c1c 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,13 @@ For a full installation and configuration guide, please see the # Build and run the executable JAR in separate steps ./gradlew bootJar java -jar fireblocks-application/build/libs/fireblocks-application-${VERSION}.jar + +# Build the Docker image +./gradlew :fireblocks-application:jibDockerBuild ``` +Use the `fromDockerRegistry` and `toDockerRegistry` properties to override the base image and the target registry, for example by adding the `-PfromDockerRegistry=artifactory.company.com/example-docker-registry` and `-PtoDockerRegistry=artifactory.company.com/example-docker-registry` arguments. + ## Configuration The configuration options for the Securosys Custom Server are defined in the `application.yml`. diff --git a/build.gradle b/build.gradle deleted file mode 100644 index fc65cf7..0000000 --- a/build.gradle +++ /dev/null @@ -1,152 +0,0 @@ -import org.springframework.boot.gradle.plugin.SpringBootPlugin - -plugins { - id 'base' - id 'java' - id 'org.springframework.boot' version '3.5.6' apply false - id "io.freefair.lombok" version "9.0.0" apply false - id 'org.unbroken-dome.test-sets' version '4.1.0' apply false - id 'com.palantir.docker' version "0.36.0" apply false - id 'org.flywaydb.flyway' version '11.14.0' apply false -} - - -gradle.beforeProject { Project project -> - project.with { - apply plugin: 'project-report' - tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' - options.compilerArgs += ["-parameters"] - } - // BOM based dependency management - apply plugin: 'io.spring.dependency-management' - dependencyManagement { - dependencies { - dependency 'org.mariadb.jdbc:mariadb-java-client:3.5.6' - dependency group: 'org.postgresql', name: 'postgresql', version: '42.7.8' - dependency "org.hibernate.validator:hibernate-validator:9.0.1.Final" - dependency 'com.h2database:h2:2.4.240' - dependency "org.flywaydb:flyway-core:11.14.0" - dependency "org.flywaydb:flyway-mysql:11.14.0" - dependency 'commons-codec:commons-codec:1.19.0' - dependency group: 'org.flywaydb', name: 'flyway-database-postgresql', version: '11.14.0' - dependency 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13' - dependency "org.bouncycastle:bcprov-jdk18on:1.82" - dependency 'org.bouncycastle:bcpkix-jdk18on:1.82' - dependency 'org.bouncycastle:bcmail-jdk18on:1.82' - dependency 'jakarta.validation:jakarta.validation-api:3.1.1' - dependency 'jakarta.persistence:jakarta.persistence-api:3.1.0' - dependency 'com.nimbusds:oauth2-oidc-sdk:11.29.2' - //dependency 'com.nimbusds:nimbus-jose-jwt:10.5' - dependency 'com.splunk.logging:splunk-library-javalogging:1.11.8' - dependency 'org.apache.commons:commons-lang3:3.19.0' - dependency 'org.apache.httpcomponents.client5:httpclient5:5.5' - } - } - } -} - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -wrapper { - gradleVersion = '8.6' - distributionUrl = "https://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip" -} - -allprojects { - version = VERSION - group = 'com.securosys.fireblocks' - task dumpBuildProperties() { - description 'bump build properties relevant for our build pipeline' - group 'help' - doFirst { - def props = new Properties() - def file = file("$buildDir/build.properties") - new File(buildDir.absolutePath).mkdir() - file.createNewFile() - file.withWriter { - props.put("version", project.version) - props.store(it, null) - } - } - } - tasks.withType(Test) { - reports { - junitXml.mergeReruns = true - junitXml.outputLocation.set(file("${rootProject.buildDir}/reports/test-results")) - } - } - -} - -subprojects { - repositories { - mavenCentral() - maven { - url 'https://splunk.jfrog.io/splunk/ext-releases-local' - } - maven { - url "https://securosys.jfrog.io/artifactory/jce-maven" - credentials { - username = project.findProperty("artifactory_user") ?: System.getenv("ARTIFACTORY_USER") - password = project.findProperty("artifactory_password") ?: System.getenv("ARTIFACTORY_PASSWORD") - } - } - } - - pluginManager.withPlugin('java') { - apply plugin: 'org.unbroken-dome.test-sets' - apply plugin: 'io.spring.dependency-management' - - - tasks.withType(Jar).configureEach { - manifest.attributes( - 'Implementation-Title': project.name, - 'Implementation-Version': project.version, - 'Implementation-Vendor': 'Securosys SA' - ) - } - - tasks.withType(Test).configureEach { Test task -> - task.useJUnitPlatform() - task.doFirst { - // fetching the profile, the default is set so gradle tasks can be executed - def activeProfile = System.getProperty("activeTestProfile") == null ? "test" : System.getProperty("activeTestProfile") - - // setting the profile - systemProperty "spring.profiles.active",activeProfile - systemProperty "jdk.sunec.disableNative", "false" - environment "jdk.sunec.disableNative", "false" - environment "SPRING_PROFILES_ACTIVE", activeProfile - jvmArgs '--add-opens=java.base/sun.security.pkcs10=ALL-UNNAMED', '--add-opens=java.base/sun.security.x509=ALL-UNNAMED', '--add-opens=java.base/sun.security.pkcs=ALL-UNNAMED', '--add-opens=java.base/sun.security.util=ALL-UNNAMED' - println "Running ${project} tests with profile: ${activeProfile}" - } - //finalizedBy rootProject.tasks.named('aggregateTestReports') - - } - dependencies { - implementation enforcedPlatform(SpringBootPlugin.BOM_COORDINATES) - testImplementation 'org.junit.jupiter:junit-jupiter-api' - testImplementation 'org.mockito:mockito-junit-jupiter' - testImplementation 'org.assertj:assertj-core' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - } - tasks.named('test') { - useJUnitPlatform() - } - // Set JUnit 5 as default testing platform for all Java modules - tasks.withType(Test).configureEach { Test task -> - useJUnitPlatform() - - reports { - junitXml.outputLocation.set(file("${rootProject.buildDir}/reports/tests/${project.name}/xml")) - html.outputLocation.set(file("${rootProject.buildDir}/reports/tests/${project.name}/html")) - } - } - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..d6f4795 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,121 @@ +import org.springframework.boot.gradle.plugin.SpringBootPlugin + +plugins { + id("java") + id("io.spring.dependency-management") + id("org.springframework.boot") apply false + id("io.freefair.lombok") apply false + id("org.unbroken-dome.test-sets") apply false + id("com.google.cloud.tools.jib") apply false + id("org.flywaydb.flyway") apply false +} + +group = "com.securosys.fireblocks" +version = findProperty("VERSION") ?: "unspecified" + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +allprojects { + apply(plugin = "java") + apply(plugin = "io.spring.dependency-management") + + configurations { + compileOnly { + extendsFrom(configurations.annotationProcessor.get()) + } + } + + repositories { + mavenCentral() + maven { + url = uri("https://splunk.jfrog.io/splunk/ext-releases-local") + } + maven { + url = uri("https://securosys.jfrog.io/artifactory/jce-maven") + credentials { + username = findProperty("artifactory_user") as String? ?: System.getenv("ARTIFACTORY_USER") + password = findProperty("artifactory_password") as String? ?: System.getenv("ARTIFACTORY_PASSWORD") + } + } + } + + dependencies { + implementation(enforcedPlatform(SpringBootPlugin.BOM_COORDINATES)) + + implementation("org.springframework.boot:spring-boot-starter") + testImplementation("org.springframework.boot:spring-boot-starter-test") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + } + + dependencyManagement { + val bouncyCastleVersion = project.properties["bouncyCastleVersion"] as String + val flywayVersion = project.properties["flywayVersion"] as String + val springBootVersion = project.properties["springBootVersion"] as String + + imports { + mavenBom("org.springframework.boot:spring-boot-dependencies:$springBootVersion") + } + + dependencies { + dependency("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.14") + dependency("org.mariadb.jdbc:mariadb-java-client:3.5.6") + dependency("org.postgresql:postgresql:42.7.8") + dependency("org.hibernate.validator:hibernate-validator:9.0.1.Final") + dependency("com.h2database:h2:2.4.240") + dependency("org.flywaydb:flyway-core:$flywayVersion") + dependency("org.flywaydb:flyway-mysql:$flywayVersion") + dependency("commons-codec:commons-codec:1.19.0") + dependency("org.flywaydb:flyway-database-postgresql:$flywayVersion") + dependency("org.bouncycastle:bcprov-jdk18on:$bouncyCastleVersion") + dependency("org.bouncycastle:bcpkix-jdk18on:$bouncyCastleVersion") + dependency("org.bouncycastle:bcmail-jdk18on:$bouncyCastleVersion") + dependency("jakarta.validation:jakarta.validation-api:3.1.1") + dependency("jakarta.persistence:jakarta.persistence-api:3.1.0") + dependency("com.nimbusds:oauth2-oidc-sdk:11.29.2") + //dependency("com.nimbusds:nimbus-jose-jwt:10.5") + dependency("com.splunk.logging:splunk-library-javalogging:1.11.8") + dependency("org.apache.commons:commons-lang3:3.19.0") + dependency("org.apache.httpcomponents.client5:httpclient5:5.5") + } + } +} + +tasks.withType { + useJUnitPlatform() + doFirst { + val activeProfile = System.getProperty("activeTestProfile") ?: "test" + systemProperty("spring.profiles.active", activeProfile) + systemProperty("jdk.sunec.disableNative", "false") + environment("jdk.sunec.disableNative", "false") + environment("SPRING_PROFILES_ACTIVE", activeProfile) + jvmArgs = listOf( + "--add-opens=java.base/sun.security.pkcs10=ALL-UNNAMED", + "--add-opens=java.base/sun.security.x509=ALL-UNNAMED", + "--add-opens=java.base/sun.security.pkcs=ALL-UNNAMED", + "--add-opens=java.base/sun.security.util=ALL-UNNAMED" + ) + println("Running $project tests with profile: $activeProfile") + finalizedBy(rootProject.tasks.named("aggregateTestReports")) + } + reports { + junitXml.required.set(true) + junitXml.outputLocation.set(file("${rootProject.buildDir}/reports/tests/${project.name}/xml")) + html.outputLocation.set(file("${rootProject.buildDir}/reports/tests/${project.name}/html")) + } +} + +tasks.withType().configureEach { + manifest { + attributes( + mapOf( + "Implementation-Title" to project.name, + "Implementation-Version" to project.version, + "Implementation-Vendor" to "Securosys SA" + ) + ) + } +} diff --git a/fireblocks-application/build.gradle b/fireblocks-application/build.gradle deleted file mode 100755 index 30359bc..0000000 --- a/fireblocks-application/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Securosys SA -// SPDX-License-Identifier: Apache-2.0 - -apply plugin: 'java' -apply plugin: 'org.springframework.boot' - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation project(path: ':fireblocks-service') - - runtimeOnly 'com.h2database:h2' - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' -} - -tasks.assemble.doLast { - println 'Copying resources' - copy { - from "${project(':fireblocks-service').buildDir}/resources/main/" - into "build/resources/main" - include 'logback.xml' - } -} diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts new file mode 100755 index 0000000..1aed646 --- /dev/null +++ b/fireblocks-application/build.gradle.kts @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: Copyright 2025 Securosys SA +// SPDX-License-Identifier: Apache-2.0 + + +plugins { + id("java") + id("org.springframework.boot") + id("com.google.cloud.tools.jib") +} + +configurations { + create("deployment") +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation(project(":fireblocks-service")) + + runtimeOnly("com.h2database:h2") + runtimeOnly("org.mariadb.jdbc:mariadb-java-client") +} + +tasks.named("jar") { + // Custom jar configuration if needed +} + +tasks.named("assemble") { + doLast { + println("Copying resources") + copy { + from(project(":fireblocks-service").buildDir.resolve("resources/main/")) + into("build/resources/main") + include("logback.xml") + } + } +} + +jib { + val fromDockerRegistry = project.properties["fromDockerRegistry"] as String? ?: "registry-1.docker.io" + val toDockerRegistry = project.properties["toDockerRegistry"] as String? ?: "securosys.jfrog.io/external-key-store" + from { + image = "${fromDockerRegistry}/eclipse-temurin:21-jdk" + platforms { + platform { + architecture = "amd64" + os = "linux" + } + platform { + architecture = "arm64" + os = "linux" + } + } + } + to { + image = "${toDockerRegistry}/fireblocks-external-key-store:${project.version}" + } + container { + // current timestamp is not reproduible, but keeps track of build time in the image metadata + creationTime = "USE_CURRENT_TIMESTAMP" + jvmFlags = listOf( + "-Djava.security.egd=file:/dev/./urandom", + "--add-opens=java.base/sun.security.pkcs10=ALL-UNNAMED", + "--add-opens=java.base/sun.security.x509=ALL-UNNAMED", + "--add-opens=java.base/sun.security.pkcs=ALL-UNNAMED", + "--add-opens=java.base/sun.security.util=ALL-UNNAMED", + "-Dcom.securosys.primus.jce.logoutCloseReaderGracetimeMillis=0", + "-Dcom.securosys.primus.jce.cutLmsSignaturePrefix=false", + "-Dcom.securosys.primus.jce.fallBackToSignatureLessLogFetching=true", + "-XX:MinRAMPercentage=70", + "-XX:InitialRAMPercentage=70", + "-XX:MaxRAMPercentage=70" + ) + } +} diff --git a/fireblocks-datamodel/build.gradle b/fireblocks-datamodel/build.gradle deleted file mode 100755 index 2c3ea22..0000000 --- a/fireblocks-datamodel/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Securosys SA -// SPDX-License-Identifier: Apache-2.0 - -apply plugin: 'java' -apply plugin: 'io.freefair.lombok' - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'commons-codec:commons-codec' - implementation 'org.flywaydb:flyway-core' - implementation 'org.flywaydb:flyway-mysql' - implementation group: 'org.flywaydb', name: 'flyway-database-postgresql' - - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' - runtimeOnly 'com.h2database:h2' - runtimeOnly 'org.postgresql:postgresql' - - compileOnly 'com.fasterxml.jackson.core:jackson-annotations' -} - diff --git a/fireblocks-datamodel/build.gradle.kts b/fireblocks-datamodel/build.gradle.kts new file mode 100755 index 0000000..c801388 --- /dev/null +++ b/fireblocks-datamodel/build.gradle.kts @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2025 Securosys SA +// SPDX-License-Identifier: Apache-2.0 + + +plugins { + id("java") + id("io.freefair.lombok") +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-validation") + implementation("commons-codec:commons-codec") + implementation("org.flywaydb:flyway-core") + implementation("org.flywaydb:flyway-mysql") + implementation("org.flywaydb:flyway-database-postgresql") + + runtimeOnly("org.mariadb.jdbc:mariadb-java-client") + runtimeOnly("com.h2database:h2") + runtimeOnly("org.postgresql:postgresql") + + compileOnly("com.fasterxml.jackson.core:jackson-annotations") +} + diff --git a/fireblocks-docker/Dockerfile b/fireblocks-docker/Dockerfile deleted file mode 100644 index f79c6f8..0000000 --- a/fireblocks-docker/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM eclipse-temurin:17.0.17_10-jre-ubi10-minimal - -ENV spring.config.additional-location "/etc/app/config/" -ENV logging.config "/etc/app/config/logback.xml" -ENV JAVA_OPTS="-Dcom.securosys.primus.jce.logoutCloseReaderGracetimeMillis=0" - -# Embedded tomcat working directory -# External app configuration -VOLUME ["/tmp", "/etc/app/config" ] - -# Multi-layer setup according to Spring recommendations -ARG DEPENDENCY=install - -COPY ${DEPENDENCY}/BOOT-INF/lib /opt/app/lib -COPY ${DEPENDENCY}/META-INF /opt/app/META-INF -COPY ${DEPENDENCY}/BOOT-INF/classes /opt/app - -EXPOSE 8080 - -ENTRYPOINT ["java","-cp","/opt/app:/opt/app/lib/*","-Djava.security.egd=file:/dev/./urandom", "--add-opens", "java.base/sun.security.pkcs10=ALL-UNNAMED", "--add-opens", "java.base/sun.security.x509=ALL-UNNAMED", "--add-opens", "java.base/sun.security.pkcs=ALL-UNNAMED", "--add-opens", "java.base/sun.security.util=ALL-UNNAMED", "-Dcom.securosys.primus.jce.logoutCloseReaderGracetimeMillis=0", "-Dcom.securosys.primus.jce.cutLmsSignaturePrefix=false", "-Dcom.securosys.primus.jce.fallBackToSignatureLessLogFetching=true","com.securosys.fireblocks.FireblocksApplication"] \ No newline at end of file diff --git a/fireblocks-docker/build.gradle b/fireblocks-docker/build.gradle deleted file mode 100644 index 352dcc5..0000000 --- a/fireblocks-docker/build.gradle +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Securosys SA -// SPDX-License-Identifier: Apache-2.0 - -apply plugin: 'base' -apply plugin: 'com.palantir.docker' - -configurations { - deployment -} - -def dockerImageName = System.getenv("DOCKER_IMAGE_NAME"); -def artifactoryUrl= System.getenv("JFROG_ARTIFACTORY_URL"); -def internalPrefix = System.getenv("INTERNAL_PREFIX"); - -if(internalPrefix==null){ - internalPrefix="" -} -def artifactoryRealName= internalPrefix+System.getenv("JFROG_REPOSITORY_REAL_NAME"); - -dependencies { - deployment project(path: ':fireblocks-application', configuration: 'bootArchives') -} - -task unpackBootJar (type: Copy) { - dependsOn configurations.deployment - from(zipTree(configurations.deployment.files[0])) - into("build/dependency") - doLast { - println "Unzipping " + configurations.deployment.files[0] - } -} - -task prepareDockerContext(type: Copy) { - dependsOn unpackBootJar - into("build/docker") - from("Dockerfile") { into(".")} - from("build/dependency/BOOT-INF/lib") { into("install/BOOT-INF/lib") } - from("build/dependency/META-INF") { into("install/META-INF") } - from("build/dependency/BOOT-INF/classes") { into("install/BOOT-INF/classes") } - doLast { - println "Prepared Docker build context in 'build/docker/'" - } -} - -def imageName = "${dockerImageName}:${project.version}"; -def artifactoryName = "${artifactoryUrl}/${artifactoryRealName}/"; - -docker { - name "${artifactoryName}${imageName}" - dockerfile file("Dockerfile") - buildArgs(['PLATFORM': 'linux/amd64']) - copySpec.from(unpackBootJar.outputs).into("install") -} - -task dockerBuildAmd64(type: Exec) { - dependsOn prepareDockerContext - workingDir "build/docker" - def dockerImageNameAmd64 = System.getenv("DOCKER_IMAGE_NAME"); - def artifactoryUrlAmd64= System.getenv("JFROG_ARTIFACTORY_URL"); - def imageNameAmd64 = "${dockerImageNameAmd64}:${project.version}"; - def artifactoryRealNameAmd64= internalPrefix+System.getenv("JFROG_REPOSITORY_REAL_NAME"); - def artifactoryNameAmd64 = "${artifactoryUrlAmd64}/${artifactoryRealNameAmd64}/"; - - def tagAmd64 = "${artifactoryNameAmd64}${imageNameAmd64}" - println "Building Docker image: ${tagAmd64}" - - commandLine "docker", "build", "--no-cache", "--platform=linux/amd64", ".", - "-t", tagAmd64 -} - -task dockerBuildArm64(type: Exec) { - dependsOn prepareDockerContext - workingDir "build/docker" - def dockerImageNameArm64 = System.getenv("DOCKER_IMAGE_NAME"); - def artifactoryUrlArm64= System.getenv("JFROG_ARTIFACTORY_URL"); - def imageNameArm64 = "${dockerImageNameArm64}:${project.version}"; - def artifactoryRealNameArm64= internalPrefix+System.getenv("JFROG_REPOSITORY_REAL_NAME"); - def artifactoryNameArm64 = "${artifactoryUrlArm64}/${artifactoryRealNameArm64}/"; - - def tagArm64 = "${artifactoryNameArm64}${imageNameArm64}" - println "Building Docker image: ${tagArm64}" - - commandLine "docker", "build", "--no-cache", '--platform=linux/arm64', ".", - "-t", tagArm64 -} - -buildscript { - ext { - repoUser = findProperty('repoUser') ?: System.env.BINREPO_USER - repoPass = findProperty('repoPass') ?: System.env.BINREPO_TOKEN - } - repositories { - maven { - url 'https://binrepo.adnovum.ch/artifactory/adn-public-maven-vi' - credentials { - username = repoUser - password = repoPass - } - } - } -} \ No newline at end of file diff --git a/fireblocks-service/build.gradle b/fireblocks-service/build.gradle deleted file mode 100755 index 8548a98..0000000 --- a/fireblocks-service/build.gradle +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Securosys SA -// SPDX-License-Identifier: Apache-2.0 - -apply plugin: 'java' -apply plugin: 'idea' -apply plugin: 'io.freefair.lombok' - -repositories { - mavenCentral() -} - -dependencies { - implementation project(':fireblocks-datamodel') - - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.session:spring-session-core' - - implementation 'org.apache.commons:commons-lang3' - implementation 'commons-codec:commons-codec' - implementation 'org.apache.httpcomponents.client5:httpclient5' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui' - implementation 'com.splunk.logging:splunk-library-javalogging' - implementation 'com.nimbusds:nimbus-jose-jwt' - implementation 'com.nimbusds:oauth2-oidc-sdk' - implementation 'org.bouncycastle:bcprov-jdk18on:1.79' - implementation 'org.bouncycastle:bcpkix-jdk18on:1.79' - implementation 'org.bouncycastle:bcmail-jdk18on:1.79' - - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' - - testImplementation 'org.mariadb.jdbc:mariadb-java-client' - testImplementation 'org.postgresql:postgresql' - testImplementation 'com.h2database:h2' - - testImplementation 'io.rest-assured:rest-assured' - testImplementation 'io.rest-assured:spring-mock-mvc' - testImplementation 'org.apache.httpcomponents.client5:httpclient5:5.5' -} - -tasks.test { - useJUnitPlatform() -} diff --git a/fireblocks-service/build.gradle.kts b/fireblocks-service/build.gradle.kts new file mode 100755 index 0000000..7a413a4 --- /dev/null +++ b/fireblocks-service/build.gradle.kts @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2025 Securosys SA +// SPDX-License-Identifier: Apache-2.0 + + +plugins { + id("java") + id("idea") + id("io.freefair.lombok") +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(project(":fireblocks-datamodel")) + + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-validation") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springframework.session:spring-session-core") + + implementation("org.apache.commons:commons-lang3") + implementation("commons-codec:commons-codec") + implementation("org.apache.httpcomponents.client5:httpclient5") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui") + implementation("com.splunk.logging:splunk-library-javalogging") + implementation("com.nimbusds:nimbus-jose-jwt") + implementation("com.nimbusds:oauth2-oidc-sdk") + implementation("org.bouncycastle:bcprov-jdk18on") + implementation("org.bouncycastle:bcpkix-jdk18on") + implementation("org.bouncycastle:bcmail-jdk18on") + + testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.security:spring-security-test") + + testImplementation("org.mariadb.jdbc:mariadb-java-client") + testImplementation("org.postgresql:postgresql") + testImplementation("com.h2database:h2") + + testImplementation("io.rest-assured:rest-assured") + testImplementation("io.rest-assured:spring-mock-mvc") + testImplementation("org.apache.httpcomponents.client5:httpclient5:5.5") +} + +tasks.test { + useJUnitPlatform() +} diff --git a/gradle.properties b/gradle.properties index 3b9c413..db60d02 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,8 @@ org.gradle.daemon=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx1024m +bouncyCastleVersion=1.82 +flywayVersion=11.14.0 +springBootVersion=3.5.7 + VERSION=1.0.0 \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 60f76f0..0000000 --- a/settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -pluginManagement { - repositories { - mavenCentral() - gradlePluginPortal() - } -} - -rootProject.name = 'fireblocks-external-key-store' - -include 'fireblocks-application' -include 'fireblocks-service' -include 'fireblocks-datamodel' -include 'fireblocks-docker' \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..1d71927 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,25 @@ +pluginManagement { + val springBootVersion: String by settings + val flywayVersion: String by settings + + plugins { + id("java") + id("io.spring.dependency-management") version "1.1.7" + id("org.springframework.boot") version springBootVersion + id("io.freefair.lombok") version "9.0.0" + id("org.unbroken-dome.test-sets") version "4.1.0" + id("com.google.cloud.tools.jib") version "3.5.1" + id("org.flywaydb.flyway") version flywayVersion + } + + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = "fireblocks-external-key-store" + +include("fireblocks-application") +include("fireblocks-service") +include("fireblocks-datamodel") From 71563ee3f44b78b85717339326a72eb95f8c91e6 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 25 Nov 2025 18:46:51 +0100 Subject: [PATCH 2/8] add files to iamge --- fireblocks-application/build.gradle.kts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts index 1aed646..34b79b7 100755 --- a/fireblocks-application/build.gradle.kts +++ b/fireblocks-application/build.gradle.kts @@ -68,9 +68,21 @@ jib { "-Dcom.securosys.primus.jce.logoutCloseReaderGracetimeMillis=0", "-Dcom.securosys.primus.jce.cutLmsSignaturePrefix=false", "-Dcom.securosys.primus.jce.fallBackToSignatureLessLogFetching=true", + "-Dspring.config.additional-location=/etc/app/config/", + "-Dlogging.config=/etc/app/config/logback.xml", "-XX:MinRAMPercentage=70", "-XX:InitialRAMPercentage=70", "-XX:MaxRAMPercentage=70" ) } + extraDirectories { + paths { + path { + setFrom("src/main/resources") + includes.add("logback.xml") + includes.add("application.yml") + into = "/etc/app/config" + } + } + } } From dc459bb4772d4505826ba2020dd5912d8fb6f0eb Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Tue, 25 Nov 2025 19:19:48 +0100 Subject: [PATCH 3/8] add Docker labels --- fireblocks-application/build.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts index 34b79b7..f545557 100755 --- a/fireblocks-application/build.gradle.kts +++ b/fireblocks-application/build.gradle.kts @@ -74,6 +74,13 @@ jib { "-XX:InitialRAMPercentage=70", "-XX:MaxRAMPercentage=70" ) + // https://specs.opencontainers.org/image-spec/annotations/ + labels = mapOf( + "org.opencontainers.image.source" to "https://github.com/securosys-com/fireblocks-external-key-store", + "org.opencontainers.image.version" to "${project.version}", + "org.opencontainers.image.description" to "Fireblocks External Key Store Application", + "org.opencontainers.image.vendor" to "Securosys SA" + ) } extraDirectories { paths { From 3eb43c359c3bbf7c208013f12e5e57d914d538e7 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Wed, 26 Nov 2025 15:48:09 +0100 Subject: [PATCH 4/8] set LOGGING_CONFIG default from environment --- fireblocks-application/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts index f545557..bddacc0 100755 --- a/fireblocks-application/build.gradle.kts +++ b/fireblocks-application/build.gradle.kts @@ -59,6 +59,9 @@ jib { container { // current timestamp is not reproduible, but keeps track of build time in the image metadata creationTime = "USE_CURRENT_TIMESTAMP" + environment = mapOf( + "LOGGING_CONFIG" to "/etc/app/config/logback.xml" + ) jvmFlags = listOf( "-Djava.security.egd=file:/dev/./urandom", "--add-opens=java.base/sun.security.pkcs10=ALL-UNNAMED", @@ -69,7 +72,6 @@ jib { "-Dcom.securosys.primus.jce.cutLmsSignaturePrefix=false", "-Dcom.securosys.primus.jce.fallBackToSignatureLessLogFetching=true", "-Dspring.config.additional-location=/etc/app/config/", - "-Dlogging.config=/etc/app/config/logback.xml", "-XX:MinRAMPercentage=70", "-XX:InitialRAMPercentage=70", "-XX:MaxRAMPercentage=70" From e5112d670f982f49ec6fdd1585693c9b71c1bcab Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Wed, 26 Nov 2025 16:34:08 +0100 Subject: [PATCH 5/8] remove exec bit --- .gitlab-ci.yml | 0 fireblocks-application/build.gradle.kts | 0 fireblocks-datamodel/build.gradle.kts | 0 fireblocks-service/build.gradle.kts | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 .gitlab-ci.yml mode change 100755 => 100644 fireblocks-application/build.gradle.kts mode change 100755 => 100644 fireblocks-datamodel/build.gradle.kts mode change 100755 => 100644 fireblocks-service/build.gradle.kts diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml old mode 100755 new mode 100644 diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts old mode 100755 new mode 100644 diff --git a/fireblocks-datamodel/build.gradle.kts b/fireblocks-datamodel/build.gradle.kts old mode 100755 new mode 100644 diff --git a/fireblocks-service/build.gradle.kts b/fireblocks-service/build.gradle.kts old mode 100755 new mode 100644 From d093bc1ff709b5adbdce5bd3934da38d618388e5 Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Wed, 26 Nov 2025 16:42:31 +0100 Subject: [PATCH 6/8] remove /etc/app/config as resources are already copied to /app/resources --- fireblocks-application/build.gradle.kts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts index bddacc0..f82e133 100644 --- a/fireblocks-application/build.gradle.kts +++ b/fireblocks-application/build.gradle.kts @@ -60,7 +60,7 @@ jib { // current timestamp is not reproduible, but keeps track of build time in the image metadata creationTime = "USE_CURRENT_TIMESTAMP" environment = mapOf( - "LOGGING_CONFIG" to "/etc/app/config/logback.xml" + "LOGGING_CONFIG" to "/app/resources/logback.xml" ) jvmFlags = listOf( "-Djava.security.egd=file:/dev/./urandom", @@ -71,7 +71,6 @@ jib { "-Dcom.securosys.primus.jce.logoutCloseReaderGracetimeMillis=0", "-Dcom.securosys.primus.jce.cutLmsSignaturePrefix=false", "-Dcom.securosys.primus.jce.fallBackToSignatureLessLogFetching=true", - "-Dspring.config.additional-location=/etc/app/config/", "-XX:MinRAMPercentage=70", "-XX:InitialRAMPercentage=70", "-XX:MaxRAMPercentage=70" @@ -84,14 +83,4 @@ jib { "org.opencontainers.image.vendor" to "Securosys SA" ) } - extraDirectories { - paths { - path { - setFrom("src/main/resources") - includes.add("logback.xml") - includes.add("application.yml") - into = "/etc/app/config" - } - } - } } From 75989765bf42b64471d13ce4394efb3d24b23b2d Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Wed, 26 Nov 2025 17:20:45 +0100 Subject: [PATCH 7/8] remove execute bit --- .../src/main/resources/application-template.yml | 0 fireblocks-application/src/main/resources/application.yml | 0 fireblocks-application/src/main/resources/logback.xml | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 fireblocks-application/src/main/resources/application-template.yml mode change 100755 => 100644 fireblocks-application/src/main/resources/application.yml mode change 100755 => 100644 fireblocks-application/src/main/resources/logback.xml diff --git a/fireblocks-application/src/main/resources/application-template.yml b/fireblocks-application/src/main/resources/application-template.yml old mode 100755 new mode 100644 diff --git a/fireblocks-application/src/main/resources/application.yml b/fireblocks-application/src/main/resources/application.yml old mode 100755 new mode 100644 diff --git a/fireblocks-application/src/main/resources/logback.xml b/fireblocks-application/src/main/resources/logback.xml old mode 100755 new mode 100644 From 9460d5db8eac15bf6bd17e53ea40c9aecd3b821b Mon Sep 17 00:00:00 2001 From: Janne Kataja Date: Wed, 26 Nov 2025 19:21:42 +0100 Subject: [PATCH 8/8] set file.encoding UTF-8 --- fireblocks-application/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/fireblocks-application/build.gradle.kts b/fireblocks-application/build.gradle.kts index f82e133..109c2c6 100644 --- a/fireblocks-application/build.gradle.kts +++ b/fireblocks-application/build.gradle.kts @@ -63,6 +63,7 @@ jib { "LOGGING_CONFIG" to "/app/resources/logback.xml" ) jvmFlags = listOf( + "-Dfile.encoding=UTF-8", "-Djava.security.egd=file:/dev/./urandom", "--add-opens=java.base/sun.security.pkcs10=ALL-UNNAMED", "--add-opens=java.base/sun.security.x509=ALL-UNNAMED",