Skip to content
This repository has been archived by the owner on May 25, 2022. It is now read-only.

Commit

Permalink
feat: create scanner cli to dispatch the context data to different an…
Browse files Browse the repository at this point in the history
…alyser
  • Loading branch information
Andong Liao committed Apr 20, 2022
1 parent 1aaef98 commit 30e46ff
Show file tree
Hide file tree
Showing 20 changed files with 242 additions and 176 deletions.
61 changes: 0 additions & 61 deletions scanner_cli/src/main/kotlin/org/archguard/scanner/Runner.kt

This file was deleted.

71 changes: 71 additions & 0 deletions scanner_cli/src/main/kotlin/org/archguard/scanner/ctl/Runner.kt
@@ -0,0 +1,71 @@
package org.archguard.scanner.ctl

import chapi.domain.core.CodeDataStruct
import org.archguard.scanner.core.AnalyserSpec
import org.archguard.scanner.core.context.Context
import org.archguard.scanner.core.sourcecode.ASTSourceCodeAnalyser
import org.archguard.scanner.core.sourcecode.FrontierSourceCodeAnalyser
import org.archguard.scanner.core.sourcecode.SourceCodeContext
import org.archguard.scanner.ctl.client.ArchGuardHttpClient
import org.archguard.scanner.ctl.impl.CliSourceCodeContext
import org.archguard.scanner.ctl.loader.AnalyserDispatcher

// cli main entry
fun main() {
val params = mapOf(
"type" to "source_code",
"language" to "java",
"features" to "db",
"path" to "kotlin/org/archguard/scanner/Runner.kt",
"systemId" to "1",
"withoutStorage" to "false",
"archguard_server_url" to "http://localhost:8080/api/v1/",
"specs" to listOf(
mapOf(
"name" to "customized_scanner",
"url" to "https://raw.githubusercontent.com/archguard/archguard-scanner/master/official_scanner_specs.json"
)
)
)

// create source code context when type is source_code
val context: Context = CliSourceCodeContext(
language = params.getValue("language").toString(),
features = params.getValue("features").toString().split(","),
path = params.getValue("path").toString(),
systemId = params.getValue("systemId").toString(),
withoutStorage = params.getValue("systemId").toString().toBoolean(),
client = ArchGuardHttpClient(params.getValue("archguard_server_url").toString()),
)
val customizedScannerSpecs = (params.getValue("specs") as List<Map<String, String>>).map {
AnalyserSpec(
identifier = "db",
host = "host",
version = "version",
jar = "jar",
className = "DBAnalyser",
)
}

// execute
AnalyserDispatcher(context, customizedScannerSpecs).dispatch()
}

// move to scan_xxx

class JavaAnalyser(override val context: SourceCodeContext) : FrontierSourceCodeAnalyser {
override fun analyse(): List<CodeDataStruct> {
println("im in java analyser")
println("language: ${context.language}")
println("features: ${context.features}")
return listOf(CodeDataStruct(NodeName = "java"))
}
}

class DBAnalyser(override val context: SourceCodeContext) : ASTSourceCodeAnalyser {
override fun analyse(input: List<CodeDataStruct>): Any? {
println("im in db analyser")
println("input: ${input.map { it.NodeName }}")
return null
}
}
@@ -0,0 +1,6 @@
package org.archguard.scanner.ctl.client

import org.archguard.scanner.core.context.ArchGuardClient

// maybe?? 通过grpc回写分析数据
interface ArchGuardGrpcClient : ArchGuardClient
@@ -1,9 +1,10 @@
package org.archguard.scanner.client
package org.archguard.scanner.ctl.client

import chapi.domain.core.CodeDataStruct
import org.archguard.scanner.core.context.ArchGuardClient
import org.archguard.scanner.core.context.ContainerService

// 通过http api回写分析数据
class ArchGuardHttpClient(baseUrl: String) : ArchGuardClient {
override fun saveDataStructure(dataStructure: List<CodeDataStruct>, systemId: String, language: String) {
TODO("Not yet implemented")
Expand Down
@@ -0,0 +1,15 @@
package org.archguard.scanner.ctl.impl

import org.archguard.scanner.core.context.ArchGuardClient
import org.archguard.scanner.core.sourcecode.SourceCodeContext

class CliSourceCodeContext(
override val language: String,
override val features: List<String>,
override val client: ArchGuardClient,
override val path: String,
override val systemId: String,
override val withoutStorage: Boolean,
) : SourceCodeContext {
// extend SourceCodeContext to accept cil specific parameters(infra related), like memory limit, queue size, etc.
}
@@ -0,0 +1,20 @@
package org.archguard.scanner.ctl.impl

import org.archguard.scanner.core.AnalyserSpec

enum class OfficialAnalyserSpecs(val spec: AnalyserSpec) {
JAVA(
AnalyserSpec(
identifier = "java",
host = "https://github.com/archguard/scanner/releases/download/v1.5.0",
version = "1.5.0",
jar = "scan_sourcecode-1.5.0-all.jar",
className = "JavaAnalyser",
)
)
;

companion object {
fun specs() = values().map(OfficialAnalyserSpecs::spec)
}
}
@@ -0,0 +1,40 @@
package org.archguard.scanner.ctl.loader

import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import org.archguard.scanner.core.Analyser
import org.archguard.scanner.core.AnalyserSpec
import org.archguard.scanner.core.context.Context
import org.archguard.scanner.core.sourcecode.SourceCodeAnalyser
import org.archguard.scanner.core.sourcecode.SourceCodeContext
import org.archguard.scanner.ctl.impl.OfficialAnalyserSpecs

class AnalyserDispatcher(
private val context: Context,
customized: List<AnalyserSpec>,
) {
private val specs = customized + OfficialAnalyserSpecs.specs()

private fun getOrInstall(identifier: String): Analyser<Context> {
// specs 会形成一个优先级队列, 对于相同的identifier, 会优先使用用户自定义的. e.g. 自定义java analyser用来覆盖官方的analyser
val theOne = specs.find { identifier == it.identifier }
?: throw IllegalArgumentException("No analyser found for identifier: $identifier")
return AnalyserLoader.load(context, theOne)
}

fun dispatch() = runBlocking {
when (context) {
is SourceCodeContext -> {
val languageAnalyser = getOrInstall(context.language) as SourceCodeAnalyser
val ast = languageAnalyser.analyse(null) ?: return@runBlocking
context.features.map {
async {
(getOrInstall(it) as SourceCodeAnalyser).analyse(ast)
}
}.awaitAll()
}
else -> throw IllegalArgumentException("Unsupported context type")
}
}
}
@@ -0,0 +1,21 @@
package org.archguard.scanner.ctl.loader

import org.archguard.scanner.core.Analyser
import org.archguard.scanner.core.AnalyserSpec
import org.archguard.scanner.core.context.Context

// TODO load the scanner via classloader
// 扫描指定包/路径/类
object AnalyserLoader {

fun load(context: Context, spec: AnalyserSpec): Analyser<Context> {
// isInstalled
// install
// get with class for name

// support full class name or short class name
return Class.forName("org.archguard.scanner.ctl." + spec.className)
.declaredConstructors[0]
.newInstance(context) as Analyser<Context>
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

@@ -0,0 +1,7 @@
package org.archguard.scanner.core

import org.archguard.scanner.core.context.Context

interface Analyser<C : Context> {
val context: C
}
@@ -0,0 +1,10 @@
package org.archguard.scanner.core

data class AnalyserSpec(
val identifier: String,
val host: String,
val version: String,
val jar: String,
val className: String, // calculate via identifier??
)

18 changes: 0 additions & 18 deletions scanner_core/src/main/kotlin/org/archguard/scanner/core/Scanner.kt

This file was deleted.

Expand Up @@ -2,6 +2,9 @@ package org.archguard.scanner.core.context

import chapi.domain.core.CodeDataStruct

// TODO need to declare the structure
interface ContainerService

// client of the archguard, scanner can communicate to server via this client with limited functions
interface ArchGuardClient {
fun saveDataStructure(dataStructure: List<CodeDataStruct>, systemId: String, language: String)
Expand Down

0 comments on commit 30e46ff

Please sign in to comment.