Skip to content

Commit

Permalink
feat: support for trufflehog
Browse files Browse the repository at this point in the history
  • Loading branch information
janniclas committed Nov 25, 2024
1 parent 73b539c commit f67ae50
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2024 Fraunhofer IEM. All rights reserved.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/

package de.fraunhofer.iem.spha.adapter.tools.trufflehog

import de.fraunhofer.iem.spha.adapter.AdapterResult
import de.fraunhofer.iem.spha.model.adapter.trufflehog.TrufflehogDto
import de.fraunhofer.iem.spha.model.adapter.trufflehog.TrufflehogReportDto
import de.fraunhofer.iem.spha.model.kpi.KpiId
import de.fraunhofer.iem.spha.model.kpi.RawValueKpi
import io.github.oshai.kotlinlogging.KotlinLogging
import java.io.InputStream
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.decodeFromStream

object TrufflehogAdapter {
private val logger = KotlinLogging.logger {}
private val jsonParser = Json {
ignoreUnknownKeys = true
explicitNulls = false
}

@OptIn(ExperimentalSerializationApi::class)
fun dtoFromJson(jsonData: InputStream): List<TrufflehogReportDto> {
val rawResult = jsonParser.decodeFromStream<TrufflehogDto>(jsonData)
return rawResult.results.mapNotNull {
try {
jsonParser.decodeFromJsonElement<TrufflehogReportDto>(it)
} catch (e: Exception) {
logger.warn { "Decoding of trufflehog result failed for $it with ${e.message}" }
null
}
}
}

fun transformDataToKpi(data: TrufflehogReportDto): Collection<AdapterResult> {
return transformDataToKpi(listOf(data))
}

fun transformDataToKpi(data: Collection<TrufflehogReportDto>): Collection<AdapterResult> {
return data.map {
val score = if (it.verifiedSecrets > 0) 0 else 100
AdapterResult.Success.Kpi(RawValueKpi(score = score, kind = KpiId.SECRETS))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Fraunhofer IEM. All rights reserved.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/

package de.fraunhofer.iem.spha.adapter.tools.trufflehog

import de.fraunhofer.iem.spha.adapter.AdapterResult
import java.nio.file.Files
import kotlin.io.path.Path
import kotlin.test.Test
import kotlin.test.assertEquals
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource

class TrufflehogAdapterTest {
@ParameterizedTest
@ValueSource(
strings =
[
"{}", // No schema
"{\"SchemaVersion\": 3}", // Not supported schema
]
)
fun testInvalidJson(input: String) {
input.byteInputStream().use {
assertThrows<Exception> { TrufflehogAdapter.dtoFromJson(it) }
}
}

@ParameterizedTest
@ValueSource(strings = ["{\"results\": []}"])
fun testEmptyDto(input: String) {
input.byteInputStream().use {
val dto = TrufflehogAdapter.dtoFromJson(it)
assertEquals(0, dto.count())
}
}

@Test
fun testResultDto() {
Files.newInputStream(Path("src/test/resources/trufflehog-no-result.json")).use {
val dto = assertDoesNotThrow { TrufflehogAdapter.dtoFromJson(it) }

val kpis = assertDoesNotThrow { TrufflehogAdapter.transformDataToKpi(dto) }

assertEquals(1, kpis.size)

kpis.forEach { assert(it is AdapterResult.Success) }

assertEquals(100, (kpis.first() as AdapterResult.Success.Kpi).rawValueKpi.score)
}
}

@Test
fun testResultResultDto() {
Files.newInputStream(Path("src/test/resources/trufflehog.json")).use {
val dto = assertDoesNotThrow { TrufflehogAdapter.dtoFromJson(it) }

val kpis = assertDoesNotThrow { TrufflehogAdapter.transformDataToKpi(dto) }

assertEquals(1, kpis.size)

kpis.forEach { assert(it is AdapterResult.Success) }

assertEquals(0, (kpis.first() as AdapterResult.Success.Kpi).rawValueKpi.score)
}
}
}
95 changes: 95 additions & 0 deletions adapter/src/test/resources/trufflehog-no-result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"results": [
{
"level": "info-0",
"ts": "2024-11-19T13:14:04Z",
"logger": "trufflehog",
"msg": "running source",
"source_manager_worker_id": "JrTPL",
"with_units": true
},
{
"level": "info-0",
"ts": "2024-11-19T13:14:04Z",
"logger": "trufflehog",
"msg": "scanning repo",
"source_manager_worker_id": "JrTPL",
"unit_kind": "dir",
"unit": "/tmp/",
"repo": "https://github.com/fraunhofer-iem/spha-demo",
"head": "2f6d0a9ccb3211eff95126a7e36c68063c2432ce"
},
{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "4a88901aaf9889a0672013bd4edfe8a99e290ab6",
"file": "src/main/java/com/example/demo/VulnerableJavaAppApplication.java",
"email": "Jan-Niclas Struewer \u003c[email protected]\u003e",
"repository": "https://github.com/fraunhofer-iem/spha-demo",
"timestamp": "2024-11-19 11:54:10 +0000",
"line": 9
}
}
},
"SourceID": 1,
"SourceType": 16,
"SourceName": "trufflehog - git",
"DetectorType": 895,
"DetectorName": "MongoDB",
"DetectorDescription": "MongoDB is a NoSQL database that uses a document-oriented data model. MongoDB credentials can be used to access and manipulate the database.",
"DecoderName": "PLAIN",
"Verified": false,
"VerificationError": "context deadline exceeded",
"Raw": "***agenda-live.mongo.cosmos.azure.com:10255/?appName=%40agenda-live\u0026maxIdleTimeMS=120000\u0026replicaSet=globaldb\u0026retryWrites=false\u0026ssl=true",
"RawV2": "",
"Redacted": "",
"ExtraData": {
"rotation_guide": "https://howtorotate.com/docs/tutorials/mongo/"
},
"StructuredData": null
},
{
"level": "info-0",
"ts": "2024-11-19T13:14:06Z",
"logger": "trufflehog",
"msg": "finished scanning",
"chunks": 63,
"bytes": 31905,
"verified_secrets": 0,
"unverified_secrets": 2,
"scan_duration": "2.020861236s",
"trufflehog_version": "3.83.7"
},
{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "4a88901aaf9889a0672013bd4edfe8a99e290ab6",
"file": "src/main/resources/application.properties",
"email": "Jan-Niclas Struewer \u003c[email protected]\u003e",
"repository": "https://github.com/fraunhofer-iem/spha-demo",
"timestamp": "2024-11-19 11:54:10 +0000",
"line": 1
}
}
},
"SourceID": 1,
"SourceType": 16,
"SourceName": "trufflehog - git",
"DetectorType": 895,
"DetectorName": "MongoDB",
"DetectorDescription": "MongoDB is a NoSQL database that uses a document-oriented data model. MongoDB credentials can be used to access and manipulate the database.",
"DecoderName": "PLAIN",
"Verified": false,
"VerificationError": "context deadline exceeded",
"Raw": "***agenda-live.mongo.cosmos.azure.com:10255/?appName=%40agenda-live\u0026maxIdleTimeMS=120000\u0026replicaSet=globaldb\u0026retryWrites=false\u0026ssl=true",
"RawV2": "",
"Redacted": "",
"ExtraData": {
"rotation_guide": "https://howtorotate.com/docs/tutorials/mongo/"
},
"StructuredData": null
}
]
}
95 changes: 95 additions & 0 deletions adapter/src/test/resources/trufflehog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"results": [
{
"level": "info-0",
"ts": "2024-11-19T13:14:04Z",
"logger": "trufflehog",
"msg": "running source",
"source_manager_worker_id": "JrTPL",
"with_units": true
},
{
"level": "info-0",
"ts": "2024-11-19T13:14:04Z",
"logger": "trufflehog",
"msg": "scanning repo",
"source_manager_worker_id": "JrTPL",
"unit_kind": "dir",
"unit": "/tmp/",
"repo": "https://github.com/fraunhofer-iem/spha-demo",
"head": "2f6d0a9ccb3211eff95126a7e36c68063c2432ce"
},
{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "4a88901aaf9889a0672013bd4edfe8a99e290ab6",
"file": "src/main/java/com/example/demo/VulnerableJavaAppApplication.java",
"email": "Jan-Niclas Struewer \u003c[email protected]\u003e",
"repository": "https://github.com/fraunhofer-iem/spha-demo",
"timestamp": "2024-11-19 11:54:10 +0000",
"line": 9
}
}
},
"SourceID": 1,
"SourceType": 16,
"SourceName": "trufflehog - git",
"DetectorType": 895,
"DetectorName": "MongoDB",
"DetectorDescription": "MongoDB is a NoSQL database that uses a document-oriented data model. MongoDB credentials can be used to access and manipulate the database.",
"DecoderName": "PLAIN",
"Verified": false,
"VerificationError": "context deadline exceeded",
"Raw": "***agenda-live.mongo.cosmos.azure.com:10255/?appName=%40agenda-live\u0026maxIdleTimeMS=120000\u0026replicaSet=globaldb\u0026retryWrites=false\u0026ssl=true",
"RawV2": "",
"Redacted": "",
"ExtraData": {
"rotation_guide": "https://howtorotate.com/docs/tutorials/mongo/"
},
"StructuredData": null
},
{
"level": "info-0",
"ts": "2024-11-19T13:14:06Z",
"logger": "trufflehog",
"msg": "finished scanning",
"chunks": 63,
"bytes": 31905,
"verified_secrets": 1,
"unverified_secrets": 2,
"scan_duration": "2.020861236s",
"trufflehog_version": "3.83.7"
},
{
"SourceMetadata": {
"Data": {
"Git": {
"commit": "4a88901aaf9889a0672013bd4edfe8a99e290ab6",
"file": "src/main/resources/application.properties",
"email": "Jan-Niclas Struewer \u003c[email protected]\u003e",
"repository": "https://github.com/fraunhofer-iem/spha-demo",
"timestamp": "2024-11-19 11:54:10 +0000",
"line": 1
}
}
},
"SourceID": 1,
"SourceType": 16,
"SourceName": "trufflehog - git",
"DetectorType": 895,
"DetectorName": "MongoDB",
"DetectorDescription": "MongoDB is a NoSQL database that uses a document-oriented data model. MongoDB credentials can be used to access and manipulate the database.",
"DecoderName": "PLAIN",
"Verified": false,
"VerificationError": "context deadline exceeded",
"Raw": "***agenda-live.mongo.cosmos.azure.com:10255/?appName=%40agenda-live\u0026maxIdleTimeMS=120000\u0026replicaSet=globaldb\u0026retryWrites=false\u0026ssl=true",
"RawV2": "",
"Redacted": "",
"ExtraData": {
"rotation_guide": "https://howtorotate.com/docs/tutorials/mongo/"
},
"StructuredData": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Fraunhofer IEM. All rights reserved.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
*
* SPDX-License-Identifier: MIT
* License-Filename: LICENSE
*/

package de.fraunhofer.iem.spha.model.adapter.trufflehog

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject

@Serializable data class TrufflehogDto(val results: List<JsonObject>)

@Serializable
data class TrufflehogReportDto(
val level: String?,
val ts: String?,
val logger: String?,
val msg: String?,
val chunks: Int?,
val bytes: Int?,
@SerialName("verified_secrets") val verifiedSecrets: Int,
@SerialName("unverified_secrets") val unverifiedSecrets: Int,
@SerialName("scan_duration") val scanDuration: String?,
@SerialName("trufflehog_version") val trufflehogVersion: String?,
)

0 comments on commit f67ae50

Please sign in to comment.