mirror of
https://codeberg.org/PGPainless/vks-java.git
synced 2024-11-27 01:42:07 +01:00
Add vks-java-cli Command Line Frontend
This commit is contained in:
parent
352f6d3c7f
commit
181af197b5
7 changed files with 313 additions and 1 deletions
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
rootProject.name = 'VKS-Java'
|
rootProject.name = 'VKS-Java'
|
||||||
|
|
||||||
include 'vks-java'
|
include 'vks-java',
|
||||||
|
'vks-java-cli'
|
32
vks-java-cli/build.gradle
Normal file
32
vks-java-cli/build.gradle
Normal 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()
|
||||||
|
}
|
74
vks-java-cli/src/main/java/pgp/vks/client/cli/GetCmd.java
Normal file
74
vks-java-cli/src/main/java/pgp/vks/client/cli/GetCmd.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
vks-java-cli/src/main/java/pgp/vks/client/cli/UploadCmd.java
Normal file
79
vks-java-cli/src/main/java/pgp/vks/client/cli/UploadCmd.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
vks-java-cli/src/main/java/pgp/vks/client/cli/VKSCLI.java
Normal file
60
vks-java-cli/src/main/java/pgp/vks/client/cli/VKSCLI.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
Loading…
Reference in a new issue