mirror of
https://codeberg.org/PGPainless/cert-d-pgpainless.git
synced 2025-09-10 02:39:45 +02:00
Initial commit
This commit is contained in:
commit
d18dfb1ca5
21 changed files with 1303 additions and 0 deletions
10
pgpainless-cert-d-cli/README.md
Normal file
10
pgpainless-cert-d-cli/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
<!--
|
||||
SPDX-FileCopyrightText: 2022 Paul Schaub <info@pgpainless.org>
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
# Command Line Interface for pgpainless-cert-d
|
||||
|
||||
This module utilizes [picocli](https://picocli.info) to provide a CLI application for use with the
|
||||
[Shared PGP Certificate Directory](https://sequoia-pgp.gitlab.io/pgp-cert-d/).
|
51
pgpainless-cert-d-cli/build.gradle
Normal file
51
pgpainless-cert-d-cli/build.gradle
Normal file
|
@ -0,0 +1,51 @@
|
|||
// SPDX-FileCopyrightText: 2021 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"
|
||||
|
||||
// Logging
|
||||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
|
||||
implementation project(":pgpainless-cert-d")
|
||||
implementation project(":pgp-cert-d-java-jdbc-sqlite-lookup")
|
||||
|
||||
// picocli for cli
|
||||
implementation "info.picocli:picocli:4.6.2"
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
mainClassName = 'pgp.cert_d.cli.PGPCertDCli'
|
||||
|
||||
jar {
|
||||
dependsOn(":pgpainless-cert-d:assemble", ":pgp-certificate-store:assemble", ":pgp-cert-d-java:assemble", ":pgpainless-core:assemble")
|
||||
manifest {
|
||||
attributes 'Main-Class': "$mainClassName"
|
||||
}
|
||||
|
||||
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
|
||||
|
||||
from {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
} {
|
||||
exclude "META-INF/*.SF"
|
||||
exclude "META-INF/*.DSA"
|
||||
exclude "META-INF/*.RSA"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.cert_d.cli;
|
||||
|
||||
import org.pgpainless.certificate_store.CertificateReader;
|
||||
import org.pgpainless.certificate_store.SharedPGPCertificateDirectoryAdapter;
|
||||
import pgp.cert_d.BaseDirectoryProvider;
|
||||
import pgp.cert_d.SharedPGPCertificateDirectoryImpl;
|
||||
import pgp.cert_d.cli.commands.Get;
|
||||
import pgp.cert_d.cli.commands.Import;
|
||||
import pgp.cert_d.cli.commands.MultiImport;
|
||||
import pgp.cert_d.jdbc.sqlite.DatabaseSubkeyLookup;
|
||||
import pgp.cert_d.jdbc.sqlite.SqliteSubkeyLookupDaoImpl;
|
||||
import pgp.certificate_store.SubkeyLookup;
|
||||
import pgp.certificate_store.exception.NotAStoreException;
|
||||
import pgp.certificate_store.CertificateDirectory;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@CommandLine.Command(
|
||||
subcommands = {
|
||||
Import.class,
|
||||
MultiImport.class,
|
||||
Get.class,
|
||||
}
|
||||
)
|
||||
public class PGPCertDCli {
|
||||
|
||||
@CommandLine.Option(names = "--base-directory", paramLabel = "DIRECTORY", description = "Overwrite the default certificate directory")
|
||||
File baseDirectory;
|
||||
|
||||
private static CertificateDirectory certificateDirectory;
|
||||
|
||||
private int executionStrategy(CommandLine.ParseResult parseResult) {
|
||||
try {
|
||||
initStore();
|
||||
} catch (NotAStoreException | SQLException e) {
|
||||
return -1;
|
||||
}
|
||||
return new CommandLine.RunLast().execute(parseResult);
|
||||
}
|
||||
|
||||
private void initStore() throws NotAStoreException, SQLException {
|
||||
SharedPGPCertificateDirectoryImpl certificateDirectory;
|
||||
SubkeyLookup subkeyLookup;
|
||||
if (baseDirectory == null) {
|
||||
baseDirectory = BaseDirectoryProvider.getDefaultBaseDir();
|
||||
}
|
||||
|
||||
certificateDirectory = new SharedPGPCertificateDirectoryImpl(
|
||||
baseDirectory,
|
||||
new CertificateReader());
|
||||
subkeyLookup = new DatabaseSubkeyLookup(
|
||||
SqliteSubkeyLookupDaoImpl.forDatabaseFile(new File(baseDirectory, "_pgpainless_subkey_map.db")));
|
||||
|
||||
PGPCertDCli.certificateDirectory = new SharedPGPCertificateDirectoryAdapter(certificateDirectory, subkeyLookup);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PGPCertDCli cli = new PGPCertDCli();
|
||||
new CommandLine(cli)
|
||||
.setExecutionStrategy(parserResult -> cli.executionStrategy(parserResult))
|
||||
.execute(args);
|
||||
}
|
||||
|
||||
public static CertificateDirectory getCertificateDirectory() {
|
||||
return certificateDirectory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.cert_d.cli.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import pgp.cert_d.cli.PGPCertDCli;
|
||||
import pgp.certificate_store.Certificate;
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import pgp.certificate_store.exception.BadNameException;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "get",
|
||||
description = "Retrieve certificates from the store")
|
||||
public class Get implements Runnable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Get.class);
|
||||
|
||||
@CommandLine.Parameters(
|
||||
paramLabel = "IDENTIFIER",
|
||||
arity = "1",
|
||||
description = "Certificate identifier (fingerprint or special name)"
|
||||
)
|
||||
String identifer;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Certificate certificate = PGPCertDCli.getCertificateDirectory()
|
||||
.getCertificate(identifer);
|
||||
if (certificate == null) {
|
||||
return;
|
||||
}
|
||||
Streams.pipeAll(certificate.getInputStream(), System.out);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("IO Error", e);
|
||||
System.exit(-1);
|
||||
} catch (BadDataException e) {
|
||||
LOGGER.error("Certificate file contains bad data.", e);
|
||||
System.exit(-1);
|
||||
} catch (BadNameException e) {
|
||||
LOGGER.error("Certificate fingerprint mismatch.", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.cert_d.cli.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import pgp.cert_d.cli.PGPCertDCli;
|
||||
import pgp.certificate_store.Certificate;
|
||||
import pgp.certificate_store.MergeCallback;
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "import",
|
||||
description = "Import or update a certificate")
|
||||
public class Import implements Runnable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Import.class);
|
||||
|
||||
// TODO: Replace with proper merge callback
|
||||
private final MergeCallback dummyMerge = new MergeCallback() {
|
||||
@Override
|
||||
public Certificate merge(Certificate data, Certificate existing) throws IOException {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Certificate certificate = PGPCertDCli.getCertificateDirectory().insertCertificate(System.in, dummyMerge);
|
||||
// CHECKSTYLE:OFF
|
||||
System.out.println(certificate.getFingerprint());
|
||||
// CHECKSTYLE:ON
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("IO-Error.", e);
|
||||
System.exit(-1);
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("Thread interrupted.", e);
|
||||
System.exit(-1);
|
||||
} catch (BadDataException e) {
|
||||
LOGGER.error("Certificate contains bad data.", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.cert_d.cli.commands;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import pgp.cert_d.cli.PGPCertDCli;
|
||||
import pgp.certificate_store.Certificate;
|
||||
import pgp.certificate_store.MergeCallback;
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@CommandLine.Command(name = "multi-import",
|
||||
description = "Import or update multiple certificates")
|
||||
public class MultiImport implements Runnable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MultiImport.class);
|
||||
|
||||
// TODO: Replace with proper merge callback
|
||||
private final MergeCallback dummyMerge = new MergeCallback() {
|
||||
@Override
|
||||
public Certificate merge(Certificate data, Certificate existing) throws IOException {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PGPPublicKeyRingCollection certificates = PGPainless.readKeyRing().publicKeyRingCollection(System.in);
|
||||
for (PGPPublicKeyRing cert : certificates) {
|
||||
ByteArrayInputStream certIn = new ByteArrayInputStream(cert.getEncoded());
|
||||
Certificate certificate = PGPCertDCli.getCertificateDirectory()
|
||||
.insertCertificate(certIn, dummyMerge);
|
||||
// CHECKSTYLE:OFF
|
||||
System.out.println(certificate.getFingerprint());
|
||||
// CHECKSTYLE:ON
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("IO-Error.", e);
|
||||
System.exit(-1);
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.error("Thread interrupted.", e);
|
||||
System.exit(-1);
|
||||
} catch (BadDataException e) {
|
||||
LOGGER.error("Certificate contains bad data.", e);
|
||||
System.exit(-1);
|
||||
} catch (PGPException e) {
|
||||
LOGGER.error("PGP Exception.", e);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Subcommands.
|
||||
*/
|
||||
package pgp.cert_d.cli.commands;
|
|
@ -0,0 +1,8 @@
|
|||
// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Command Line Interface for the Shared PGP Certificate Directory.
|
||||
*/
|
||||
package pgp.cert_d.cli;
|
|
@ -0,0 +1,17 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.cert_d.cli;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class DummyTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue