Skip to content

Commit

Permalink
Støtte for opprettelse og redigering av SOPS config + default RoS-gen…
Browse files Browse the repository at this point in the history
…erering (#286)

* Add endpoint for initializing risc and sops config by calling init-risc-api

* WIP

* En bruker kan nå komme i gang med SOPS, og sette opp default RoS

* Fixing vulnerability in build-and-deploy-to-skip.yml

* Fix lint error

* Add clarifying comment

* Bumping packages

* Downgrading to kotlin 2.0.21 as ktlint does not support 2.1.0 yet
  • Loading branch information
larsore authored Dec 9, 2024
1 parent e3cebf0 commit 393a312
Show file tree
Hide file tree
Showing 42 changed files with 1,390 additions and 132 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ISSUER_URI="http://localhost:7007/api/auth"
RISC_FOLDER_PATH=".security/risc"
FILENAME_PREFIX="risc"
FILENAME_POSTFIX="risc"
FILENAME_POSTFIX="risc"
BACKEND_PUBLIC_KEY=${BACKEND_PUBLIC_KEY}
4 changes: 2 additions & 2 deletions .github/workflows/build-and-deploy-to-skip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ jobs:
echo "\"${{ needs.build.outputs.image_url }}\"" > "env/atgcp1-dev/ros-plugin-main/${{ env.ARGO_VERSION_FILE }}"
git config --global user.email "[email protected]"
git config --global user.name "Backstage Plugin Risk Scorecard Backend CI"
git commit -am "${{ github.event.head_commit.message }}"
git commit -am "Update Risk Scorecard Backend"
git push
prod-deploy-argo:
Expand Down Expand Up @@ -195,5 +195,5 @@ jobs:
echo "\"${{ needs.build.outputs.image_url }}\"" > "env/atgcp1-prod/ros-plugin-main/${{ env.ARGO_VERSION_FILE }}"
git config --global user.email "[email protected]"
git config --global user.name "Backstage Plugin Risk Scorecard Backend CI"
git commit -am "${{ github.event.head_commit.message }}"
git commit -am "Update Risk Scorecard Backend"
git push
7 changes: 4 additions & 3 deletions .run/✨Local Server.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
<option name="ACTIVE_PROFILES" value="local" />
<option name="ALTERNATIVE_JRE_PATH" value="temurin-21" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<envs>
<env name="BACKEND_PUBLIC_KEY" value="age18e0t6ve0vdxqzzjt7rxf0r6vzc37fhs5cad2qz40r02c3spzgvvq8uxz23" />
</envs>
<option name="envFilePaths">
<option value="$PROJECT_DIR$/.env" />
</option>
<module name="backstage-plugin-risk-scorecard-backend.main" />
<selectedOptions>
<option name="environmentVariables" />
</selectedOptions>
<option name="PASS_PARENT_ENVS" value="false" />
<option name="SPRING_BOOT_MAIN_CLASS" value="no.risc.RiScApplicationKt" />
<method v="2">
<option name="Make" enabled="true" />
Expand Down
90 changes: 52 additions & 38 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "3.3.2"
id("org.springframework.boot") version "3.4.0"
id("io.spring.dependency-management") version "1.1.6"
kotlin("jvm") version "2.0.20"
kotlin("plugin.spring") version "2.0.20"
id("org.jlleitschuh.gradle.ktlint") version "12.1.1"
kotlin("plugin.serialization") version "2.0.20"
kotlin("jvm") version "2.0.21"
kotlin("plugin.spring") version "2.0.21"
id("org.jlleitschuh.gradle.ktlint") version "12.1.2"
kotlin("plugin.serialization") version "2.0.21"
}

group = "no"
Expand All @@ -23,43 +23,61 @@ repositories {
}
}

val kotlinVersion = "2.0.21"
val springBootVersion = "3.4.0"
val springSecurityVersion = "6.4.1"
val kotlinxSerializationVersion = "1.7.3"
val kotlinxCoroutinesVersion = "1.9.0"
val nettyVersion = "4.1.115.Final"
val micrometerVersion = "1.14.1"
val fasterXmlJacksonVersion = "2.18.2"
val kotlinJsonSchemaVersion = "0.48"
val apacheCommonsVersion = "3.17.0"
val googleGsonVersion = "2.11.0"
val googleAuthVersion = "1.30.0"
val googleGuavaVersion = "33.3.1-jre"
val nimbusdsVersion = "9.47"
val bouncyCastleVersion = "1.79"
val jsonWebTokenVersion = "0.12.6"
val ninjaSquadVersion = "4.0.2"

dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.security:spring-security-oauth2-jose")
implementation("org.springframework.security:spring-security-oauth2-resource-server")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:1.8.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-security:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-actuator:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-webflux:$springBootVersion")
implementation("org.springframework.security:spring-security-oauth2-jose:$springSecurityVersion")
implementation("org.springframework.security:spring-security-oauth2-resource-server:$springSecurityVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinxCoroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")

implementation("io.netty:netty-all:4.1.112.Final")
implementation("io.netty:netty-all:$nettyVersion")

implementation("io.micrometer:micrometer-registry-prometheus")
implementation("io.micrometer:micrometer-registry-prometheus:$micrometerVersion")

implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml")
implementation("net.pwall.json:json-kotlin-schema:0.48")
implementation("org.apache.commons:commons-lang3:3.16.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$fasterXmlJacksonVersion")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$fasterXmlJacksonVersion")
implementation("net.pwall.json:json-kotlin-schema:$kotlinJsonSchemaVersion")
implementation("org.apache.commons:commons-lang3:$apacheCommonsVersion")

implementation("com.google.code.gson:gson:2.11.0")
implementation("com.google.auth:google-auth-library-credentials:1.24.1")
implementation("com.google.guava:guava:33.3.1-jre")
implementation("com.google.code.gson:gson:$googleGsonVersion")
implementation("com.google.auth:google-auth-library-credentials:$googleAuthVersion")
implementation("com.google.guava:guava:$googleGuavaVersion")

implementation("com.nimbusds:nimbus-jose-jwt:9.40")
implementation("org.bouncycastle:bcpkix-jdk18on:1.78.1")
implementation("com.nimbusds:nimbus-jose-jwt:$nimbusdsVersion")
implementation("org.bouncycastle:bcpkix-jdk18on:$bouncyCastleVersion")

implementation("io.jsonwebtoken:jjwt-api:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6")
implementation("io.jsonwebtoken:jjwt-api:$jsonWebTokenVersion")
runtimeOnly("io.jsonwebtoken:jjwt-impl:$jsonWebTokenVersion")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:$jsonWebTokenVersion")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("com.ninja-squad:springmockk:4.0.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.1")
testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion")
testImplementation("com.ninja-squad:springmockk:$ninjaSquadVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
}

tasks.withType<KotlinCompile> {
Expand All @@ -70,9 +88,5 @@ tasks.withType<KotlinCompile> {
}

tasks.withType<Test> {
environment["GITHUB_APP_ID"] = "828331"
environment["GITHUB_APP_INSTALLATION_ID"] = "47304902"
environment["PRIVATE_KEY_SECRET_NAME"] = "projects/spire-ros-5lmr/secrets/GITHUB_APP_PRIVATE_KEY/versions/1"
environment["RISC_PATH"] = ".sikkerhet/risc"
useJUnitPlatform()
}
10 changes: 10 additions & 0 deletions src/main/kotlin/no/risc/config/InitRiScServiceConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package no.risc.config

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component

@Component
@ConfigurationProperties(prefix = "init-risc")
class InitRiScServiceConfig {
lateinit var baseUrl: String
}
10 changes: 10 additions & 0 deletions src/main/kotlin/no/risc/config/SopsServiceConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package no.risc.config

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component

@Component
@ConfigurationProperties(prefix = "sops")
class SopsServiceConfig {
lateinit var backendPublicKey: String
}
68 changes: 68 additions & 0 deletions src/main/kotlin/no/risc/exception/GlobalExceptionHandler.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package no.risc.exception

import no.risc.exception.exceptions.AccessTokenValidationFailedException
import no.risc.exception.exceptions.CreateNewBranchException
import no.risc.exception.exceptions.CreatePullRequestException
import no.risc.exception.exceptions.CreatingRiScException
import no.risc.exception.exceptions.GcpProjectIdFetchException
import no.risc.exception.exceptions.GenerateInitialRiScException
import no.risc.exception.exceptions.GitHubFetchException
import no.risc.exception.exceptions.InvalidAccessTokensException
import no.risc.exception.exceptions.JSONSchemaFetchException
import no.risc.exception.exceptions.NoResourceIdFoundException
import no.risc.exception.exceptions.NoSopsConfigFoundException
import no.risc.exception.exceptions.PermissionDeniedOnGitHubException
import no.risc.exception.exceptions.RepositoryAccessException
import no.risc.exception.exceptions.RiScNotValidOnFetchException
Expand All @@ -13,12 +19,14 @@ import no.risc.exception.exceptions.SOPSDecryptionException
import no.risc.exception.exceptions.SopsConfigFetchException
import no.risc.exception.exceptions.SopsEncryptionException
import no.risc.exception.exceptions.UnableToParseResponseBodyException
import no.risc.exception.exceptions.UnableToWriteSopsConfigException
import no.risc.exception.exceptions.UpdatingRiScException
import no.risc.risc.ContentStatus
import no.risc.risc.DecryptionFailure
import no.risc.risc.ProcessRiScResultDTO
import no.risc.risc.ProcessingStatus
import no.risc.risc.RiScContentResultDTO
import no.risc.sops.model.GetSopsConfigResponseBody
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
Expand Down Expand Up @@ -156,6 +164,18 @@ internal class GlobalExceptionHandler {
)
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(GenerateInitialRiScException::class)
fun handleGenerateInitialRiScException(ex: GenerateInitialRiScException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ProcessRiScResultDTO(
ex.riScId,
ProcessingStatus.ErrorWhenGeneratingInitialRiSc,
ex.message,
)
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(UnableToParseResponseBodyException::class)
Expand Down Expand Up @@ -186,4 +206,52 @@ internal class GlobalExceptionHandler {
logger.error(ex.message, ex)
return ex.response
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(NoResourceIdFoundException::class)
fun handleNoResourceIdFoundException(ex: NoResourceIdFoundException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ex.response
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(GcpProjectIdFetchException::class)
fun handleGcpProjectIdFetchException(ex: GcpProjectIdFetchException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ex.response
}

@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
@ExceptionHandler(NoSopsConfigFoundException::class)
fun handleNoSopsConfigFoundException(ex: NoSopsConfigFoundException): GetSopsConfigResponseBody {
logger.info(ex.message)
return ex.response
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(CreateNewBranchException::class)
fun handleCreateNewBranchException(ex: CreateNewBranchException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ex.response
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(UnableToWriteSopsConfigException::class)
fun handleUnableToWriteSopsConfigException(ex: UnableToWriteSopsConfigException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ex.response
}

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
@ExceptionHandler(GitHubFetchException::class)
fun handleFetchRepositoryBranchesException(ex: GitHubFetchException): ProcessRiScResultDTO {
logger.error(ex.message, ex)
return ex.response
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO

data class CreateNewBranchException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO

data class GcpProjectIdFetchException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package no.risc.exception.exceptions

data class GenerateInitialRiScException(
override val message: String,
val riScId: String,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO

data class GitHubFetchException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO

data class NoResourceIdFoundException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.sops.model.GetSopsConfigResponseBody

data class NoSopsConfigFoundException(
override val message: String,
val response: GetSopsConfigResponseBody,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO
import java.lang.Exception

data class SopsConfigGenerateFetchException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package no.risc.exception.exceptions

import no.risc.risc.ProcessRiScResultDTO

data class UnableToWriteSopsConfigException(
override val message: String,
val response: ProcessRiScResultDTO,
) : Exception()
Loading

0 comments on commit 393a312

Please sign in to comment.