Add vks-java-cli Command Line Frontend

This commit is contained in:
Paul Schaub 2022-04-06 16:17:57 +02:00
parent 352f6d3c7f
commit 181af197b5
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
7 changed files with 313 additions and 1 deletions

View File

@ -4,4 +4,5 @@
rootProject.name = 'VKS-Java'
include 'vks-java'
include 'vks-java',
'vks-java-cli'

32
vks-java-cli/build.gradle Normal file
View File

@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
plugins {
id 'application'
}
group 'org.pgpainless'
repositories {
mavenCentral()
}
dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
// VKS-Java
implementation project(":vks-java")
// CLI
implementation "info.picocli:picocli:4.6.3"
}
application {
mainClass = 'pgp.vks.client.cli.VKSCLI'
}
test {
useJUnitPlatform()
}

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.vks.client.cli;
import pgp.vks.client.Get;
import pgp.vks.client.VKS;
import picocli.CommandLine;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@CommandLine.Command(name = "get", description = "Retrieve an OpenPGP certificate from the key server")
public class GetCmd implements Runnable {
@CommandLine.Mixin
VKSCLI.KeyServerMixin keyServerMixin;
@CommandLine.ArgGroup(exclusive = true, multiplicity = "1")
Exclusive by;
static class Exclusive {
@CommandLine.Option(names = {"-f", "--by-fingerprint"}, description = "Retrieve a key by its fingerprint (NOT prefixed with '0x')")
String fingerprint;
@CommandLine.Option(names = {"-i", "--by-keyid"}, description = "Retrieve a key by its decimal key ID or that of one of its subkeys.")
Long keyId;
@CommandLine.Option(names = {"-e", "--by-email"}, description = "Retrieve a key by email address.")
String email;
}
public void run() {
VKS vks;
try {
vks = keyServerMixin.parent.getApi();
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
Get get = vks.get();
InputStream inputStream = null;
try {
if (by.fingerprint != null) {
inputStream = get.byFingerprint(by.fingerprint);
} else if (by.keyId != null) {
inputStream = get.byKeyId(by.keyId);
} else if (by.email != null) {
inputStream = get.byEmail(by.email);
} else {
throw new IllegalArgumentException("Missing --by-* option.");
}
int read;
byte[] buf = new byte[4096];
while ((read = inputStream.read(buf)) != -1) {
System.out.write(buf, 0, read);
}
} catch (IOException e) {
throw new AssertionError(e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new AssertionError(e);
}
}
}
}
}

View File

@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.vks.client.cli;
import pgp.vks.client.RequestVerify;
import pgp.vks.client.VKS;
import picocli.CommandLine;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.List;
@CommandLine.Command(name = "request-verification", description = "Request verification for unverified user-ids")
public class RequestVerificationCmd implements Runnable {
@CommandLine.Mixin
VKSCLI.KeyServerMixin keyServerMixin;
@CommandLine.Option(names = {"-t", "--token"}, description = "Access token. Can be retrieved by uploading the certificate.",
required = true, arity = "1", paramLabel = "TOKEN")
String token;
@CommandLine.Option(names = {"-l", "--locale"}, description = "Locale for the verification mail")
List<String> locale = Arrays.asList("en_US", "en_GB");
@CommandLine.Option(names = {"-e", "--email"}, description = "Email addresses to request a verification mail for", required = true, arity = "1..*")
String[] addresses = new String[0];
@Override
public void run() {
VKS vks;
try {
vks = keyServerMixin.parent.getApi();
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
RequestVerify requestVerify = vks.requestVerification();
try {
RequestVerify.Response response = requestVerify
.forEmailAddresses(addresses)
.execute(token, locale);
System.out.println("Verification E-Mails for key " + response.getKeyFingerprint() + " have been sent.");
System.out.println("Token: " + response.getToken());
System.out.println("Status:");
for (String address : response.getStatus().keySet()) {
System.out.println("\t" + address + "\t" + response.getStatus().get(address));
}
} catch (IOException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.vks.client.cli;
import pgp.vks.client.RequestVerify;
import pgp.vks.client.Status;
import pgp.vks.client.Upload;
import pgp.vks.client.VKS;
import pgp.vks.client.exception.CertCannotBePublishedException;
import picocli.CommandLine;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
@CommandLine.Command(name = "upload", description = "Upload an OpenPGP certificate to the key server")
public class UploadCmd implements Runnable {
@CommandLine.Mixin
VKSCLI.KeyServerMixin keyServerMixin;
@CommandLine.Option(names = {"-r", "--request-verification"},
description = "Request verification mails for unpublished email addresses")
boolean requestVerification;
public void run() {
VKS vks;
try {
vks = keyServerMixin.parent.getApi();
} catch (MalformedURLException e) {
throw new AssertionError(e);
}
Upload upload = vks.upload();
try {
Upload.Response response = upload.cert(System.in);
// Unpublished mail addresses
List<String> unpublished = new ArrayList<>();
int maxMailLen = 0;
for (String address : response.getStatus().keySet()) {
Status status = response.getStatus().get(address);
if (address.length() > maxMailLen) {
maxMailLen = address.length();
}
if (status != Status.published && status != Status.revoked) {
unpublished.add(address);
}
}
System.out.println("Uploaded key " + response.getKeyFingerprint());
System.out.println("Token: " + response.getToken());
if (!requestVerification || unpublished.isEmpty()) {
System.out.println("Status:");
for (String address : response.getStatus().keySet()) {
Status status = response.getStatus().get(address);
System.out.format("%-" + maxMailLen + "s %s\n", address, status);
}
return;
}
RequestVerify.Response verifyResponse = vks.requestVerification().forEmailAddresses(unpublished.toArray(new String[0]))
.execute(response.getToken());
System.out.println("Status:");
for (String address : verifyResponse.getStatus().keySet()) {
Status status = response.getStatus().get(address);
System.out.format("%-" + maxMailLen + "s %s\n", address, status);
}
} catch (CertCannotBePublishedException e) {
throw new AssertionError(e.getMessage());
} catch (IOException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.vks.client.cli;
import pgp.vks.client.VKS;
import pgp.vks.client.VKSImpl;
import picocli.CommandLine;
import java.net.MalformedURLException;
@CommandLine.Command(
subcommands = {
CommandLine.HelpCommand.class,
GetCmd.class,
UploadCmd.class,
RequestVerificationCmd.class
}
)
public class VKSCLI {
String keyServer;
public static void main(String[] args) {
int exitCode = execute(args);
if (exitCode != 0) {
System.exit(exitCode);
}
}
public static int execute(String[] args) {
return new CommandLine(VKSCLI.class)
.setExitCodeExceptionMapper(new CommandLine.IExitCodeExceptionMapper() {
@Override
public int getExitCode(Throwable exception) {
return 1;
}
})
.setCommandName("vkscli")
.execute(args);
}
public VKS getApi() throws MalformedURLException {
return new VKSImpl(keyServer);
}
public static class KeyServerMixin {
@CommandLine.ParentCommand
VKSCLI parent;
@CommandLine.Option(names = "--key-server",
description = "Address of the Verifying Key Server.\nDefaults to 'https://keys.openpgp.org'",
paramLabel = "KEYSERVER")
public void setKeyServer(String keyServer) {
parent.keyServer = keyServer;
}
}
}

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Command Line Interface for VKS-Java.
*/
package pgp.vks.client.cli;