Add module pgpainless-wot-cli

This commit is contained in:
Paul Schaub 2023-06-29 17:49:12 +02:00
parent 1c79952150
commit d024dacabb
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
15 changed files with 408 additions and 1 deletions

View File

@ -0,0 +1,70 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
plugins {
id 'application'
id 'org.jetbrains.kotlin.jvm' version "$kotlinVersion"
id "com.github.johnrengelman.shadow" version "6.1.0"
}
group 'org.pgpainless'
repositories {
mavenCentral()
}
dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
// JUnit
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlinVersion"
// CLI
implementation "info.picocli:picocli:4.6.3"
annotationProcessor "info.picocli:picocli-codegen:4.6.3"
// Logging
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
// Web of Trust
implementation(project(":pgpainless-wot"))
// Web Key Directory
implementation("org.pgpainless:wkd-java:0.1.1")
}
mainClassName = 'org.pgpainless.wot.cli.WotCLI'
application {
mainClass = mainClassName
}
jar {
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
manifest {
attributes 'Main-Class': "$mainClassName"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
}
test {
useJUnitPlatform()
}

View File

@ -0,0 +1,84 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli
import org.pgpainless.util.DateUtil
import org.pgpainless.wot.cli.subcommands.*
import org.pgpainless.wot.dijkstra.sq.ReferenceTime
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.HelpCommand
import picocli.CommandLine.Option
import java.io.File
import java.util.*
import java.util.concurrent.Callable
import kotlin.system.exitProcess
@Command(name = "pgpainless-wot",
subcommands = [
AuthenticateCmd::class,
IdentifyCmd::class,
ListCmd::class,
LookupCmd::class,
PathCmd::class,
HelpCommand::class
]
)
class WotCLI: Callable<Int> {
@Option(names = ["--trust-root", "-r"], required = true)
var trustRoot: Array<String> = arrayOf()
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true)
var keyring: File? = null
/*
@Option(names = ["--gpg"], description = ["Read trust roots and keyring from GnuPG."])
var gpg = false
@Option(names = ["--network"], description = ["Look for missing certificates on a key server or the WKD."])
var keyServer = "hkps://keyserver.ubuntu.com"
@Option(names = ["--certification-network"], description = ["Treat the web of trust as a certification network instead of an authentication network."])
var certificationNetwork = false
@Option(names = ["--gossip"], description = ["Find arbitrary paths by treating all certificates as trust-roots with zero trust."])
var gossip = false
*/
@Option(names = ["--trust-amount", "-a"], description = ["The required amount of trust."])
var amount = 1200
@Option(names = ["--time"], description = ["Reference time."])
var time: String? = null
fun getReferenceTime(): ReferenceTime {
return if (time == null) {
ReferenceTime.now()
} else {
val date = DateUtil.parseUTCDate(time)
ReferenceTime.timestamp(date)
}
}
/**
* Execute the command.
*
* @return exit code
*/
override fun call(): Int {
require(trustRoot.isNotEmpty()) {
"Expected at least one trust-root."
}
return 0
}
companion object {
@JvmStatic
fun main(args: Array<String>): Unit = exitProcess(CommandLine(WotCLI()).execute(*args))
}
}

View File

@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.AuthenticateAPI
import org.pgpainless.wot.cli.WotCLI
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import picocli.CommandLine.ParentCommand
import java.util.concurrent.Callable
@Command(name = "authenticate")
class AuthenticateCmd: Callable<Int> {
@ParentCommand
lateinit var parent: WotCLI
@Parameters(index = "0")
lateinit var fingerprint: String
@Parameters(index = "1")
lateinit var userId: String
@CommandLine.Option(names = ["--email"], description = ["Consider all user-IDs that contain the given email address."])
var email = false
/**
* Execute the command.
* @return exit code
*/
override fun call(): Int {
val api = AuthenticateAPI()
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
/**
* Enum listing possible output formats.
*/
enum class Format(private val displayName: String) {
humanReadable("human-readable"),
dot("dot")
;
override fun toString(): String = displayName
companion object {
@JvmStatic
fun fromString(displayName: String): Format {
for (format in Format.values()) {
if (format.displayName == displayName) {
return format
}
}
throw NoSuchElementException("Invalid displayName $displayName")
}
}
}

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.IdentifyAPI
import org.pgpainless.wot.cli.WotCLI
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import java.util.concurrent.Callable
@Command(name = "identify")
class IdentifyCmd: Callable<Int> {
@CommandLine.ParentCommand
lateinit var parent: WotCLI
@Parameters(index = "0", description = ["Certificate fingerprint."])
lateinit var fingerprint: String
/**
* Execute the command.
*
* @return exit code
*/
override fun call(): Int {
val api = IdentifyAPI()
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.ListAPI
import org.pgpainless.wot.cli.WotCLI
import picocli.CommandLine
import picocli.CommandLine.Command
import java.util.concurrent.Callable
@Command(name = "list", description = ["Find all bindings that can be authenticated for all certificates."])
class ListCmd: Callable<Int> {
@CommandLine.ParentCommand
lateinit var parent: WotCLI
/**
* Execute the command.
*
* @return exit code
*/
override fun call(): Int {
val api = ListAPI()
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.LookupAPI
import org.pgpainless.wot.cli.WotCLI
import picocli.CommandLine.*
import java.util.concurrent.Callable
@Command(name = "lookup")
class LookupCmd: Callable<Int> {
@ParentCommand
lateinit var parent: WotCLI
@Option(names = ["--email"], description = ["Consider all user-IDs that contain the given email address."])
var email = false
@Parameters(index = "0", description = ["User-ID"])
lateinit var userId: String
/**
* Execute the command.
*
* @return exit code
*/
override fun call(): Int {
val api = LookupAPI()
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.PathAPI
import org.pgpainless.wot.cli.WotCLI
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.Parameters
import java.util.concurrent.Callable
@Command(name = "path", description = ["Verify and lint a path."])
class PathCmd: Callable<Int> {
@CommandLine.ParentCommand
lateinit var parent: WotCLI
@Parameters(index = "*",
arity = "2..*",
description = ["List of fingerprints starting with the roots fingerprint or key ID and ending with the target certificates fingerprint or key ID and a user ID."],
)
lateinit var keyIdsOrFingerprints: Array<String>
/**
* Execute the command.
*
* @return exit code
*/
override fun call(): Int {
val api = PathAPI()
TODO("Not yet implemented")
}
}

View File

@ -2,9 +2,19 @@
//
// SPDX-License-Identifier: Apache-2.0
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
plugins {
id 'java-library'
id 'java-test-fixtures'
id 'org.jetbrains.kotlin.jvm' version "$kotlinVersion"
}
group 'org.pgpainless'
@ -14,6 +24,8 @@ repositories {
}
dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
// JUnit
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
@ -27,7 +39,7 @@ dependencies {
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation(project(":pgpainless-core"))
implementation(project(":wot-dijkstra"))
api(project(":wot-dijkstra"))
// Certificate store
api "org.pgpainless:pgp-certificate-store:$certDJavaVersion"

View File

@ -0,0 +1,13 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
/**
* Authenticate a binding.
* A binding is a pair consisting of a certificate and a User ID.
*/
class AuthenticateAPI() {
}

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
class IdentifyAPI {
}

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
class ListAPI {
}

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
class LookupAPI {
}

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
class PathAPI {
}

View File

@ -8,5 +8,6 @@ include 'pgpainless-core',
'pgpainless-sop',
'pgpainless-cli',
'pgpainless-wot',
'pgpainless-wot-cli',
'wot-dijkstra'