summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko <heiko@schaefer.name>2021-05-06 17:22:39 +0200
committerHeiko <heiko@schaefer.name>2021-05-06 18:17:31 +0200
commit53adfe14c15f5bee30c74b318f3671a447086cfd (patch)
tree940e5bc456de81eee3d1054a6eaf7406f5f57a5d
parent1848cc60aa0c5b9ed79de5369e0d219b1fa86000 (diff)
downloadopenpgp-ca-53adfe14c15f5bee30c74b318f3671a447086cfd.tar.gz
Break the project into separate crates:
- openpgp-ca-lib - openpgp-ca-bin - openpgp-ca-restd
-rw-r--r--.reuse/dep52
-rw-r--r--Cargo.lock35
-rw-r--r--Cargo.toml76
-rw-r--r--openpgp-ca-bin/Cargo.toml26
-rw-r--r--openpgp-ca-bin/src/bin.rs (renamed from src/bin.rs)0
-rw-r--r--openpgp-ca-bin/src/cli.rs (renamed from src/cli.rs)0
-rw-r--r--openpgp-ca-lib/Cargo.toml44
-rw-r--r--openpgp-ca-lib/diesel.toml (renamed from diesel.toml)0
-rw-r--r--openpgp-ca-lib/migrations/.gitkeep (renamed from migrations/.gitkeep)0
-rw-r--r--openpgp-ca-lib/migrations/2020-08-17-130000_database/down.sql (renamed from migrations/2020-08-17-130000_database/down.sql)0
-rw-r--r--openpgp-ca-lib/migrations/2020-08-17-130000_database/up.sql (renamed from migrations/2020-08-17-130000_database/up.sql)0
-rw-r--r--openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/down.sql (renamed from migrations/2020-10-13-130000_extend_certs/down.sql)0
-rw-r--r--openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/up.sql (renamed from migrations/2020-10-13-130000_extend_certs/up.sql)0
-rw-r--r--openpgp-ca-lib/src/bridge.rs (renamed from src/bridge.rs)0
-rw-r--r--openpgp-ca-lib/src/ca.rs (renamed from src/ca.rs)0
-rw-r--r--openpgp-ca-lib/src/ca_secret.rs (renamed from src/ca_secret.rs)0
-rw-r--r--openpgp-ca-lib/src/cert.rs (renamed from src/cert.rs)0
-rw-r--r--openpgp-ca-lib/src/db/mod.rs (renamed from src/db/mod.rs)0
-rw-r--r--openpgp-ca-lib/src/db/models.rs (renamed from src/db/models.rs)0
-rw-r--r--openpgp-ca-lib/src/db/schema.rs (renamed from src/db/schema.rs)0
-rw-r--r--openpgp-ca-lib/src/export.rs (renamed from src/export.rs)0
-rw-r--r--openpgp-ca-lib/src/lib.rs (renamed from src/lib.rs)7
-rw-r--r--openpgp-ca-lib/src/pgp.rs (renamed from src/pgp.rs)0
-rw-r--r--openpgp-ca-lib/src/revocation.rs (renamed from src/revocation.rs)0
-rw-r--r--openpgp-ca-lib/src/update.rs (renamed from src/update.rs)0
-rw-r--r--openpgp-ca-lib/tests/gnupg/mod.rs (renamed from tests/gnupg/mod.rs)0
-rw-r--r--openpgp-ca-lib/tests/test_gpg.rs (renamed from tests/test_gpg.rs)0
-rw-r--r--openpgp-ca-lib/tests/test_oca.rs (renamed from tests/test_oca.rs)0
-rw-r--r--openpgp-ca-restd/Cargo.toml51
-rw-r--r--openpgp-ca-restd/src/README.md (renamed from src/restd/README.md)0
-rw-r--r--openpgp-ca-restd/src/bin.rs (renamed from src/restd/bin.rs)5
-rw-r--r--openpgp-ca-restd/src/cert_info.rs (renamed from src/restd/cert_info.rs)0
-rw-r--r--openpgp-ca-restd/src/cli.rs (renamed from src/restd/cli.rs)0
-rw-r--r--openpgp-ca-restd/src/client.rs (renamed from src/restd/client.rs)4
-rw-r--r--openpgp-ca-restd/src/json.rs (renamed from src/restd/json.rs)4
-rw-r--r--openpgp-ca-restd/src/lib.rs17
-rw-r--r--openpgp-ca-restd/src/process_certs.rs (renamed from src/restd/process_certs.rs)15
-rw-r--r--openpgp-ca-restd/src/restd.rs (renamed from src/restd/mod.rs)27
-rw-r--r--openpgp-ca-restd/src/util.rs (renamed from src/restd/util.rs)0
-rw-r--r--openpgp-ca-restd/tests/gnupg/mod.rs544
-rw-r--r--openpgp-ca-restd/tests/test_restd.rs (renamed from tests/test_restd.rs)9
41 files changed, 747 insertions, 119 deletions
diff --git a/.reuse/dep5 b/.reuse/dep5
index 1b09bfa..7209a51 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -8,7 +8,7 @@ Copyright: 2019-2020 Heiko Schaefer <heiko@schaefer.name>
License: GPL-3.0-or-later
-Files: src/db/schema.rs Cargo.lock
+Files: openpgp-ca-lib/src/db/schema.rs Cargo.lock
Copyright: 2019-2020 Heiko Schaefer <heiko@schaefer.name>
License: CC0-1.0
diff --git a/Cargo.lock b/Cargo.lock
index 2c0e1c2..3e29be3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1737,27 +1737,48 @@ name = "openpgp-ca"
version = "0.10.1"
dependencies = [
"anyhow",
+ "clap",
+ "openpgp-ca-lib",
+ "structopt",
+]
+
+[[package]]
+name = "openpgp-ca-lib"
+version = "0.10.1"
+dependencies = [
+ "anyhow",
"chbs",
"chrono",
- "clap",
"csv",
"diesel",
"diesel_migrations",
- "futures",
- "futures-util",
- "lazy_static",
- "once_cell",
"openpgp-keylist",
"publicsuffix",
+ "rexpect",
+ "sequoia-net",
+ "sequoia-openpgp",
+ "sha2",
+ "tempfile",
+ "tokio 0.2.25",
+]
+
+[[package]]
+name = "openpgp-ca-restd"
+version = "0.10.1"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "clap",
+ "csv",
+ "once_cell",
+ "openpgp-ca-lib",
"reqwest 0.10.10",
"rexpect",
"rocket",
"rocket_contrib",
- "sequoia-net",
"sequoia-openpgp",
"serde",
"serde_json",
- "sha2",
"structopt",
"tempfile",
"tokio 0.2.25",
diff --git a/Cargo.toml b/Cargo.toml
index e203265..c0a0636 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,73 +1,9 @@
# SPDX-FileCopyrightText: 2019-2021 Heiko Schaefer <heiko@schaefer.name>
# SPDX-License-Identifier: GPL-3.0-or-later
-[package]
-name = "openpgp-ca"
-version = "0.10.1"
-description = "OpenPGP CA is a tool for managing and certifying OpenPGP keys"
-authors = ["Heiko Schaefer <heiko@schaefer.name>"]
-license = "GPL-3.0-or-later"
-categories = ["cryptography", "email"]
-keywords = ["OpenPGP", "Sequoia", "PGP"]
-homepage = "https://openpgp-ca.org"
-repository = "https://gitlab.com/openpgp-ca/openpgp-ca"
-documentation = "https://openpgp-ca.org/doc/"
-edition = "2018"
-
-[lib]
-name = "openpgp_ca_lib"
-path = "src/lib.rs"
-
-[[bin]]
-name = "openpgp-ca"
-path = "src/bin.rs"
-
-[[bin]]
-name = "openpgp-ca-restd"
-path = "src/restd/bin.rs"
-
-[dependencies]
-structopt = "0.3"
-clap = "2.33"
-
-diesel = { version = "1.4", features = ["sqlite"] }
-diesel_migrations = "1.4"
-
-lazy_static = "1.4"
-once_cell = "1.4"
-anyhow = "1.0"
-chrono = { version = "0.4", features = ["serde"] }
-
-reqwest = { version = "0.10", features = ["blocking", "json"] }
-
-chbs = "0.0.8"
-publicsuffix = "1.5"
-
-sha2 = "0.9"
-
-futures = "0.3"
-futures-util = "0.3"
-
-openpgp-keylist = "0.2"
-
-sequoia-openpgp = "1.1"
-sequoia-net = "0.23"
-
-# restd
-# -> use unreleased rocket 0.5 for now (which works with rust stable)
-# (use fitting version of serde that go with that rocket 0.5 revision)
-rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "1f1f44f336e5a172361fc1860461bb03667b1ed2"}
-rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "1f1f44f336e5a172361fc1860461bb03667b1ed2", features = ["handlebars_templates"] }
-serde = { version = "=1.0.118", features = ["derive"] }
-serde_json = "=1.0.60"
-
-# for rocket 0.5
-[dependencies.tokio]
-version = "0.2.22"
-features = ["fs", "io-std", "io-util", "rt-threaded", "sync", "signal", "macros"]
-
-# for tests
-[dev-dependencies]
-tempfile = "3.1"
-csv = "1.1"
-rexpect = "0.4"
+[workspace]
+members = [
+ "openpgp-ca-lib",
+ "openpgp-ca-bin",
+ "openpgp-ca-restd",
+]
diff --git a/openpgp-ca-bin/Cargo.toml b/openpgp-ca-bin/Cargo.toml
new file mode 100644
index 0000000..167dc3d
--- /dev/null
+++ b/openpgp-ca-bin/Cargo.toml
@@ -0,0 +1,26 @@
+# SPDX-FileCopyrightText: 2019-2021 Heiko Schaefer <heiko@schaefer.name>
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[package]
+name = "openpgp-ca"
+version = "0.10.1"
+description = "OpenPGP CA is a tool for managing and certifying OpenPGP keys"
+authors = ["Heiko Schaefer <heiko@schaefer.name>"]
+license = "GPL-3.0-or-later"
+categories = ["cryptography", "email"]
+keywords = ["OpenPGP", "Sequoia", "PGP"]
+homepage = "https://openpgp-ca.org"
+repository = "https://gitlab.com/openpgp-ca/openpgp-ca"
+documentation = "https://openpgp-ca.org/doc/"
+edition = "2018"
+
+[[bin]]
+name = "openpgp-ca"
+path = "src/bin.rs"
+
+[dependencies]
+structopt = "0.3"
+clap = "2.33"
+anyhow = "1.0"
+
+openpgp-ca-lib = { path = "../openpgp-ca-lib" }
diff --git a/src/bin.rs b/openpgp-ca-bin/src/bin.rs
index 7205f43..7205f43 100644
--- a/src/bin.rs
+++ b/openpgp-ca-bin/src/bin.rs
diff --git a/src/cli.rs b/openpgp-ca-bin/src/cli.rs
index 41f02ec..41f02ec 100644
--- a/src/cli.rs
+++ b/openpgp-ca-bin/src/cli.rs
diff --git a/openpgp-ca-lib/Cargo.toml b/openpgp-ca-lib/Cargo.toml
new file mode 100644
index 0000000..8fabe52
--- /dev/null
+++ b/openpgp-ca-lib/Cargo.toml
@@ -0,0 +1,44 @@
+# SPDX-FileCopyrightText: 2019-2021 Heiko Schaefer <heiko@schaefer.name>
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[package]
+name = "openpgp-ca-lib"
+version = "0.10.1"
+description = "OpenPGP CA is a tool for managing and certifying OpenPGP keys"
+authors = ["Heiko Schaefer <heiko@schaefer.name>"]
+license = "GPL-3.0-or-later"
+categories = ["cryptography", "email"]
+keywords = ["OpenPGP", "Sequoia", "PGP"]
+homepage = "https://openpgp-ca.org"
+repository = "https://gitlab.com/openpgp-ca/openpgp-ca"
+documentation = "https://openpgp-ca.org/doc/"
+edition = "2018"
+
+[lib]
+name = "openpgp_ca_lib"
+path = "src/lib.rs"
+
+[dependencies]
+diesel = { version = "1.4", features = ["sqlite"] }
+diesel_migrations = "1.4"
+
+anyhow = "1.0"
+chrono = { version = "0.4", features = ["serde"] }
+
+tokio = { version = "0.2.22", features = ["fs", "io-std", "io-util", "rt-threaded", "sync", "signal", "macros"] }
+
+chbs = "0.0.8"
+publicsuffix = "1.5"
+
+sha2 = "0.9"
+
+openpgp-keylist = "0.2"
+
+sequoia-openpgp = "1.1"
+sequoia-net = "0.23"
+
+# for tests
+[dev-dependencies]
+tempfile = "3.1"
+csv = "1.1"
+rexpect = "0.4"
diff --git a/diesel.toml b/openpgp-ca-lib/diesel.toml
index aa52397..aa52397 100644
--- a/diesel.toml
+++ b/openpgp-ca-lib/diesel.toml
diff --git a/migrations/.gitkeep b/openpgp-ca-lib/migrations/.gitkeep
index e69de29..e69de29 100644
--- a/migrations/.gitkeep
+++ b/openpgp-ca-lib/migrations/.gitkeep
diff --git a/migrations/2020-08-17-130000_database/down.sql b/openpgp-ca-lib/migrations/2020-08-17-130000_database/down.sql
index d65762f..d65762f 100644
--- a/migrations/2020-08-17-130000_database/down.sql
+++ b/openpgp-ca-lib/migrations/2020-08-17-130000_database/down.sql
diff --git a/migrations/2020-08-17-130000_database/up.sql b/openpgp-ca-lib/migrations/2020-08-17-130000_database/up.sql
index 5b089e9..5b089e9 100644
--- a/migrations/2020-08-17-130000_database/up.sql
+++ b/openpgp-ca-lib/migrations/2020-08-17-130000_database/up.sql
diff --git a/migrations/2020-10-13-130000_extend_certs/down.sql b/openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/down.sql
index 84ae708..84ae708 100644
--- a/migrations/2020-10-13-130000_extend_certs/down.sql
+++ b/openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/down.sql
diff --git a/migrations/2020-10-13-130000_extend_certs/up.sql b/openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/up.sql
index a3d5c92..a3d5c92 100644
--- a/migrations/2020-10-13-130000_extend_certs/up.sql
+++ b/openpgp-ca-lib/migrations/2020-10-13-130000_extend_certs/up.sql
diff --git a/src/bridge.rs b/openpgp-ca-lib/src/bridge.rs
index ddf014a..ddf014a 100644
--- a/src/bridge.rs
+++ b/openpgp-ca-lib/src/bridge.rs
diff --git a/src/ca.rs b/openpgp-ca-lib/src/ca.rs
index 9ce8d7c..9ce8d7c 100644
--- a/src/ca.rs
+++ b/openpgp-ca-lib/src/ca.rs
diff --git a/src/ca_secret.rs b/openpgp-ca-lib/src/ca_secret.rs
index 03180be..03180be 100644
--- a/src/ca_secret.rs
+++ b/openpgp-ca-lib/src/ca_secret.rs
diff --git a/src/cert.rs b/openpgp-ca-lib/src/cert.rs
index 63c7891..63c7891 100644
--- a/src/cert.rs
+++ b/openpgp-ca-lib/src/cert.rs
diff --git a/src/db/mod.rs b/openpgp-ca-lib/src/db/mod.rs
index dee370f..dee370f 100644
--- a/src/db/mod.rs
+++ b/openpgp-ca-lib/src/db/mod.rs
diff --git a/src/db/models.rs b/openpgp-ca-lib/src/db/models.rs
index 9503bc5..9503bc5 100644
--- a/src/db/models.rs
+++ b/openpgp-ca-lib/src/db/models.rs
diff --git a/src/db/schema.rs b/openpgp-ca-lib/src/db/schema.rs
index 9c2a729..9c2a729 100644
--- a/src/db/schema.rs
+++ b/openpgp-ca-lib/src/db/schema.rs
diff --git a/src/export.rs b/openpgp-ca-lib/src/export.rs
index dc356b7..dc356b7 100644
--- a/src/export.rs
+++ b/openpgp-ca-lib/src/export.rs
diff --git a/src/lib.rs b/openpgp-ca-lib/src/lib.rs
index 76d58de..0977ecc 100644
--- a/src/lib.rs
+++ b/openpgp-ca-lib/src/lib.rs
@@ -15,17 +15,12 @@ extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
-#[macro_use]
-extern crate rocket;
-
mod bridge;
pub mod ca;
mod ca_secret;
mod cert;
-mod db;
+pub mod db;
mod export;
pub mod pgp;
mod revocation;
mod update;
-
-pub mod restd;
diff --git a/src/pgp.rs b/openpgp-ca-lib/src/pgp.rs
index a5b535c..a5b535c 100644
--- a/src/pgp.rs
+++ b/openpgp-ca-lib/src/pgp.rs
diff --git a/src/revocation.rs b/openpgp-ca-lib/src/revocation.rs
index 0fa2d97..0fa2d97 100644
--- a/src/revocation.rs
+++ b/openpgp-ca-lib/src/revocation.rs
diff --git a/src/update.rs b/openpgp-ca-lib/src/update.rs
index 0987004..0987004 100644
--- a/src/update.rs
+++ b/openpgp-ca-lib/src/update.rs
diff --git a/tests/gnupg/mod.rs b/openpgp-ca-lib/tests/gnupg/mod.rs
index 6eb9c5b..6eb9c5b 100644
--- a/tests/gnupg/mod.rs
+++ b/openpgp-ca-lib/tests/gnupg/mod.rs
diff --git a/tests/test_gpg.rs b/openpgp-ca-lib/tests/test_gpg.rs
index cb63488..cb63488 100644
--- a/tests/test_gpg.rs
+++ b/openpgp-ca-lib/tests/test_gpg.rs
diff --git a/tests/test_oca.rs b/openpgp-ca-lib/tests/test_oca.rs
index 8132e68..8132e68 100644
--- a/tests/test_oca.rs
+++ b/openpgp-ca-lib/tests/test_oca.rs
diff --git a/openpgp-ca-restd/Cargo.toml b/openpgp-ca-restd/Cargo.toml
new file mode 100644
index 0000000..b0c4d17
--- /dev/null
+++ b/openpgp-ca-restd/Cargo.toml
@@ -0,0 +1,51 @@
+# SPDX-FileCopyrightText: 2019-2021 Heiko Schaefer <heiko@schaefer.name>
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+[package]
+name = "openpgp-ca-restd"
+version = "0.10.1"
+description = "OpenPGP CA is a tool for managing and certifying OpenPGP keys"
+authors = ["Heiko Schaefer <heiko@schaefer.name>"]
+license = "GPL-3.0-or-later"
+categories = ["cryptography", "email"]
+keywords = ["OpenPGP", "Sequoia", "PGP"]
+homepage = "https://openpgp-ca.org"
+repository = "https://gitlab.com/openpgp-ca/openpgp-ca"
+documentation = "https://openpgp-ca.org/doc/"
+edition = "2018"
+
+[[bin]]
+name = "openpgp-ca-restd"
+path = "src/bin.rs"
+
+[dependencies]
+structopt = "0.3"
+clap = "2.33"
+
+once_cell = "1.4"
+anyhow = "1.0"
+chrono = { version = "0.4", features = ["serde"] }
+
+reqwest = { version = "0.10", features = ["blocking", "json"] }
+
+sequoia-openpgp = "1.1"
+
+openpgp-ca-lib = { path = "../openpgp-ca-lib" }
+
+# restd
+# -> use unreleased rocket 0.5 for now (which works with rust stable)
+# (use fitting version of serde that go with that rocket 0.5 revision)
+rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "1f1f44f336e5a172361fc1860461bb03667b1ed2" }
+rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "1f1f44f336e5a172361fc1860461bb03667b1ed2", features = ["handlebars_templates"] }
+serde = { version = "=1.0.118", features = ["derive"] }
+serde_json = "=1.0.60"
+
+[dependencies.tokio]
+version = "0.2.22"
+features = ["fs", "io-std", "io-util", "rt-threaded", "sync", "signal", "macros"]
+
+# for tests
+[dev-dependencies]
+tempfile = "3.1"
+csv = "1.1"
+rexpect = "0.4"
diff --git a/src/restd/README.md b/openpgp-ca-restd/src/README.md
index 4711a15..4711a15 100644
--- a/src/restd/README.md
+++ b/openpgp-ca-restd/src/README.md
diff --git a/src/restd/bin.rs b/openpgp-ca-restd/src/bin.rs
index b75f5fc..045091c 100644
--- a/src/restd/bin.rs
+++ b/openpgp-ca-restd/src/bin.rs
@@ -12,11 +12,14 @@
#[macro_use]
extern crate rocket;
+mod cert_info;
mod cli;
+pub mod json;
+mod process_certs;
+mod restd;
pub mod util;
use cli::RestdCli;
-use openpgp_ca_lib::restd;
use structopt::StructOpt;
#[launch]
diff --git a/src/restd/cert_info.rs b/openpgp-ca-restd/src/cert_info.rs
index 449d6ea..449d6ea 100644
--- a/src/restd/cert_info.rs
+++ b/openpgp-ca-restd/src/cert_info.rs
diff --git a/src/restd/cli.rs b/openpgp-ca-restd/src/cli.rs
index eb577d5..eb577d5 100644
--- a/src/restd/cli.rs
+++ b/openpgp-ca-restd/src/cli.rs
diff --git a/src/restd/client.rs b/openpgp-ca-restd/src/client.rs
index e660b41..a7cf230 100644
--- a/src/restd/client.rs
+++ b/openpgp-ca-restd/src/client.rs
@@ -11,9 +11,7 @@
use reqwest::{Response, StatusCode};
-use crate::restd::json::{
- CertResultJson, Certificate, ReturnError, ReturnGoodJson,
-};
+use crate::json::{CertResultJson, Certificate, ReturnError, ReturnGoodJson};
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
pub struct Client {
diff --git a/src/restd/json.rs b/openpgp-ca-restd/src/json.rs
index 7d677c1..0bcd970 100644
--- a/src/restd/json.rs
+++ b/openpgp-ca-restd/src/json.rs
@@ -10,8 +10,8 @@ use rocket::response::status::BadRequest;
use rocket_contrib::json::Json;
use serde::{Deserialize, Serialize};
-use crate::db::models;
-use crate::restd::cert_info::CertInfo;
+use crate::cert_info::CertInfo;
+use openpgp_ca_lib::db::models;
/// A container for return-data about one Cert.
///
diff --git a/openpgp-ca-restd/src/lib.rs b/openpgp-ca-restd/src/lib.rs
new file mode 100644
index 0000000..7e41456
--- /dev/null
+++ b/openpgp-ca-restd/src/lib.rs
@@ -0,0 +1,17 @@
+// Copyright 2019-2021 Heiko Schaefer <heiko@schaefer.name>
+//
+// This file is part of OpenPGP CA
+// https://gitlab.com/openpgp-ca/openpgp-ca
+//
+// SPDX-FileCopyrightText: 2019-2021 Heiko Schaefer <heiko@schaefer.name>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#[macro_use]
+extern crate rocket;
+
+pub mod cert_info;
+pub mod client;
+pub mod json;
+pub mod process_certs;
+pub mod restd;
+pub mod util;
diff --git a/src/restd/process_certs.rs b/openpgp-ca-restd/src/process_certs.rs
index a04b4ec..d411111 100644
--- a/src/restd/process_certs.rs
+++ b/openpgp-ca-restd/src/process_certs.rs
@@ -8,6 +8,7 @@
use core::time::Duration;
use std::collections::HashSet;
+use std::error::Error;
use std::ops::Deref;
use std::str::FromStr;
use std::time::SystemTime;
@@ -19,13 +20,13 @@ use sequoia_openpgp::types::{
};
use sequoia_openpgp::{Cert, Message, Packet};
-use crate::ca::OpenpgpCa;
-use crate::pgp::Pgp;
+use openpgp_ca_lib::ca::OpenpgpCa;
+use openpgp_ca_lib::pgp::Pgp;
+
+use crate::cert_info::CertInfo;
+use crate::json::*;
use crate::restd;
-use crate::restd::cert_info::CertInfo;
-use crate::restd::json::*;
-use crate::restd::util::{is_email_in_domain, split_emails, user_id_filter};
-use std::error::Error;
+use crate::util::{is_email_in_domain, split_emails, user_id_filter};
const STANDARD_POLICY: &StandardPolicy = &StandardPolicy::new();
@@ -604,7 +605,7 @@ pub fn process_certs(
#[cfg(test)]
mod tests {
- use crate::restd::process_certs::unpack_certring;
+ use crate::process_certs::unpack_certring;
#[test]
fn test_certring() {
diff --git a/src/restd/mod.rs b/openpgp-ca-restd/src/restd.rs
index abe99f2..7c16101 100644
--- a/src/restd/mod.rs
+++ b/openpgp-ca-restd/src/restd.rs
@@ -14,22 +14,13 @@ use rocket::http::Status;
use rocket::response::status::BadRequest;
use rocket_contrib::json::Json;
-use crate::ca::OpenpgpCa;
-use crate::db::models;
-use crate::pgp::Pgp;
-use crate::restd::cert_info::CertInfo;
-use crate::restd::json::*;
-use crate::restd::process_certs::{
- cert_to_cert_info, cert_to_warn, process_certs,
-};
-
-mod cli;
-mod process_certs;
-mod util;
-
-pub mod cert_info;
-pub mod client;
-pub mod json;
+use openpgp_ca_lib::ca::OpenpgpCa;
+use openpgp_ca_lib::db::models;
+use openpgp_ca_lib::pgp::Pgp;
+
+use crate::cert_info::CertInfo;
+use crate::json::*;
+use crate::process_certs::{cert_to_cert_info, cert_to_warn, process_certs};
static DB: OnceCell<Option<String>> = OnceCell::new();
@@ -39,10 +30,10 @@ thread_local! {
}
// CA certifications are good for 365 days
-const CERTIFICATION_DAYS: u64 = 365;
+pub const CERTIFICATION_DAYS: u64 = 365;
// armored cert size limit (1 MiB)
-const CERT_SIZE_LIMIT: usize = 1024 * 1024;
+pub const CERT_SIZE_LIMIT: usize = 1024 * 1024;
// FIXME: link for information about bad certificates
// - and what to do about them
diff --git a/src/restd/util.rs b/openpgp-ca-restd/src/util.rs
index d636e20..d636e20 100644
--- a/src/restd/util.rs
+++ b/openpgp-ca-restd/src/util.rs
diff --git a/openpgp-ca-restd/tests/gnupg/mod.rs b/openpgp-ca-restd/tests/gnupg/mod.rs
new file mode 100644
index 0000000..6eb9c5b
--- /dev/null
+++ b/openpgp-ca-restd/tests/gnupg/mod.rs
@@ -0,0 +1,544 @@
+// Copyright 2019-2020 Heiko Schaefer <heiko@schaefer.name>
+//
+// This file is part of OpenPGP CA
+// https://gitlab.com/openpgp-ca/openpgp-ca
+//
+// SPDX-FileCopyrightText: 2019-2020 Heiko Schaefer <heiko@schaefer.name>
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+use std::collections::BTreeMap;
+use std::collections::HashMap;
+
+use std::fmt;
+use std::io::Read;
+use std::io::Write;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+use std::process::Stdio;
+
+use anyhow::{Context, Result};
+use csv::StringRecord;
+
+// FIXME: `LC_ALL=C` to make calls locale-independent
+
+pub fn make_context() -> Result<Ctx> {
+ let ctx = Ctx::ephemeral().context(
+ "SKIP: Failed to create GnuPG context. Is GnuPG installed?",
+ )?;
+
+ ctx.start("gpg-agent").context(
+ "SKIP: Failed to to start gpg-agent. Is the GnuPG agent installed?",
+ )?;
+
+ Ok(ctx)
+}
+
+/// A GnuPG context.
+#[derive(Debug)]
+pub struct Ctx {
+ homedir: Option<PathBuf>,
+ components: BTreeMap<String, PathBuf>,
+ directories: BTreeMap<String, PathBuf>,
+ sockets: BTreeMap<String, PathBuf>,
+ #[allow(dead_code)] // We keep it around for the cleanup.
+ ephemeral: Option<tempfile::TempDir>,
+}
+
+impl Ctx {
+ /// Creates a new context for the default GnuPG home directory.
+ pub fn new() -> Result<Self> {
+ Self::make(None, None)
+ }
+
+ /// get the homedir Path
+ pub fn get_homedir(&self) -> &Path {
+ self.homedir.as_ref().unwrap().as_path()
+ }
+
+ /// Creates a new context for the given GnuPG home directory.
+ pub fn with_homedir<P>(homedir: P) -> Result<Self>
+ where
+ P: AsRef<Path>,
+ {
+ Self::make(Some(homedir.as_ref()), None)
+ }
+
+ /// Creates a new ephemeral context.
+ ///
+ /// The created home directory will be deleted once this object is
+ /// dropped.
+ pub fn ephemeral() -> Result<Self> {
+ Self::make(None, Some(tempfile::tempdir()?))
+ }
+
+ /// don't delete home directory.
+ /// this is intended for manually debugging data that was created in a
+ /// test-run.
+ pub fn leak_tempdir(&mut self) -> Option<PathBuf> {
+ if self.ephemeral.is_some() {
+ let _ = self.stop_all();
+ let _ = self.remove_socket_dir();
+ }
+ self.ephemeral.take().map(tempfile::TempDir::into_path)
+ }
+
+ fn make(
+ homedir: Option<&Path>,
+ ephemeral: Option<tempfile::TempDir>,
+ ) -> Result<Self> {
+ let mut components: BTreeMap<String, PathBuf> = Default::default();
+ let mut directories: BTreeMap<String, PathBuf> = Default::default();
+ let mut sockets: BTreeMap<String, PathBuf> = Default::default();
+
+ let homedir: Option<PathBuf> = ephemeral
+ .as_ref()
+ .map(|tmp| tmp.path())
+ .or(homedir)
+ .map(|p| p.into());
+
+ for fields in
+ Self::gpgconf(&homedir, &["--list-components"], 3)?.into_iter()
+ {
+ components.insert(
+ String::from_utf8(fields[0].clone())?,
+ String::from_utf8(fields[2].clone())?.into(),
+ );
+ }
+
+ for fields in Self::gpgconf(&homedir, &["--list-dirs"], 2)?.into_iter()
+ {
+ let (mut key, value) = (fields[0].clone(), fields[1].clone());
+ if key.ends_with(b"-socket") {
+ let l = key.len();
+ key.truncate(l - b"-socket".len());
+ sockets.insert(
+ String::from_utf8(key)?,
+ String::from_utf8(value)?.into(),
+ );
+ } else {
+ directories.insert(
+ String::from_utf8(key)?,
+ String::from_utf8(value)?.into(),
+ );
+ }
+ }
+
+ Ok(Ctx {
+ homedir,
+ components,
+ directories,
+ sockets,
+ ephemeral,
+ })
+ }
+
+ fn gpgconf(
+ homedir: &Option<PathBuf>,
+ arguments: &[&str],
+ nfields: usize,
+ ) -> Result<Vec<Vec<Vec<u8>>>> {
+ let nl = |&c: &u8| c as char == '\n';
+ let colon = |&c: &u8| c as char == ':';
+
+ let mut gpgconf = Command::new("gpgconf");
+ if let Some(homedir) = homedir {
+ gpgconf.arg("--homedir").arg(homedir);
+
+ // https://dev.gnupg.org/T4496
+ gpgconf.env("GNUPGHOME", homedir);
+ }
+
+ for argument in arguments {
+ gpgconf.arg(argument);
+ }
+ let output = gpgconf.output().map_err(|e| -> anyhow::Error {
+ GnupgError::GgpConf(e.to_string()).into()
+ })?;
+
+ if output.status.success() {
+ let mut result = Vec::new();
+ for line in output.stdout.split(nl) {
+ if line.is_empty() {
+ // EOF.
+ break;
+ }
+
+ let fields = line
+ .splitn(nfields, colon)
+ .map(|f| f.to_vec())
+ .collect::<Vec<_>>();
+
+ if fields.len() != nfields {
+ return Err(GnupgError::GgpConf(format!(
+ "Malformed response, expected {} fields, \
+ on line: {:?}",
+ nfields, line
+ ))
+ .into());
+ }
+
+ result.push(fields);
+ }
+ Ok(result)
+ } else {
+ Err(GnupgError::GgpConf(
+ String::from_utf8_lossy(&output.stderr).into_owned(),
+ )
+ .into())
+ }
+ }
+
+ /// Returns the path to a GnuPG component.
+ pub fn component<C>(&self, component: C) -> Result<&Path>
+ where
+ C: AsRef<str>,
+ {
+ self.components
+ .get(component.as_ref())
+ .map(|p| p.as_path())
+ .ok_or_else(|| {
+ GnupgError::GgpConf(format!(
+ "No such component {:?}",
+ component.as_ref()
+ ))
+ .into()
+ })
+ }
+
+ /// Returns the path to a GnuPG directory.
+ pub fn directory<C>(&self, directory: C) -> Result<&Path>
+ where
+ C: AsRef<str>,
+ {
+ self.directories
+ .get(directory.as_ref())
+ .map(|p| p.as_path())
+ .ok_or_else(|| {
+ GnupgError::GgpConf(format!(
+ "No such directory {:?}",
+ directory.as_ref()
+ ))
+ .into()
+ })
+ }
+
+ /// Returns the path to a GnuPG socket.
+ pub fn socket<C>(&self, socket: C) -> Result<&Path>
+ where
+ C: AsRef<str>,
+ {
+ self.sockets
+ .get(socket.as_ref())
+ .map(|p| p.as_path())
+ .ok_or_else(|| {
+ GnupgError::GgpConf(format!(
+ "No such socket {:?}",
+ socket.as_ref()
+ ))
+ .into()
+ })
+ }
+
+ /// Creates directories for RPC communication.
+ pub fn create_socket_dir(&self) -> Result<()> {
+ Self::gpgconf(&self.homedir, &["--create-socketdir"], 1)?;
+ Ok(())
+ }
+
+ /// Removes directories for RPC communication.
+ ///
+ /// Note: This will stop all servers once they note that their
+ /// socket is gone.
+ pub fn remove_socket_dir(&self) -> Result<()> {
+ Self::gpgconf(&self.homedir, &["--remove-socketdir"], 1)?;
+ Ok(())
+ }
+
+ /// Starts a GnuPG component.
+ pub fn start(&self, component: &str) -> Result<()> {
+ self.create_socket_dir()?;
+ Self::gpgconf(&self.homedir, &["--launch", component], 1)?;
+ Ok(())
+ }
+
+ /// Stops a GnuPG component.
+ pub fn stop(&self, component: &str) -> Result<()> {
+ Self::gpgconf(&self.homedir, &["--kill", component], 1)?;
+ Ok(())
+ }
+
+ /// Stops all GnuPG components.
+ pub fn stop_all(&self) -> Result<()> {
+ self.stop("all")
+ }
+}
+
+impl Drop for Ctx {
+ fn drop(&mut self) {
+ if self.ephemeral.is_some() {
+ let _ = self.stop_all();
+ let _ = self.remove_socket_dir();
+ }
+ }
+}
+
+impl std::error::Error for GnupgError {}
+
+impl fmt::Display for GnupgError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ GnupgError::GgpConf(s) => write!(f, "gpgconf: {}", s),
+ GnupgError::OperationFailed(s) => {
+ write!(f, "Operation failed: {}", s)
+ }
+ GnupgError::ProtocolError(s) => {
+ write!(f, "Protocol violation: {}", s)
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+/// Errors used in this module.
+pub enum GnupgError {
+ /// Errors related to `gpgconf`.
+ GgpConf(String),
+
+ /// The remote operation failed.
+ OperationFailed(String),
+
+ /// The remote party violated the protocol.
+ ProtocolError(String),
+}
+
+pub fn import(ctx: &Ctx, what: &[u8]) {
+ let mut gpg = Command::new("gpg")
+ .stdin(Stdio::piped())
+ .arg("--homedir")
+ .arg(ctx.directory("homedir").unwrap())
+ .arg("--import")
+ .spawn()
+ .expect("failed to start gpg");
+ gpg.stdin.as_mut().unwrap().write_all(what).unwrap();
+ let status = gpg.wait().unwrap();
+ assert!(status.success());
+}
+
+pub fn export(ctx: &Ctx, search: &str) -> String {
+ let mut out = String::new();
+
+ let mut gpg = Command::new("gpg")
+ .stdout(Stdio::piped())
+ .arg("--homedir")
+ .arg(ctx.directory("homedir").unwrap())
+ .arg("--armor")
+ .arg("--export")
+ .arg(search)
+ .spawn()
+ .expect("failed to start gpg");
+ let status = gpg.wait().unwrap();
+ gpg.stdout
+ .as_mut()
+ .unwrap()
+ .read_to_string(&mut out)
+ .unwrap();
+ assert!(status.success());
+
+ out
+}
+
+pub fn export_secret(ctx: &Ctx, search: &str) -> String {
+ let mut out = String::new();
+
+ let mut gpg = Command::new("gpg")
+ .stdout(Stdio::piped())
+ .arg("--homedir")
+ .arg(ctx.directory("homedir").unwrap())
+ .arg("--armor")
+ .arg("--export-secret-keys")
+ .arg(search)
+ .spawn()
+ .expect("failed to start gpg");
+ let status = gpg.wait().unwrap();
+ gpg.stdout
+ .as_mut()
+ .unwrap()
+ .read_to_string(&mut out)
+ .unwrap();
+ assert!(status.success());
+
+ out
+}
+
+pub fn list_keys(ctx: &Ctx) -> Result<HashMap<String, String>> {
+ let res = list_keys_raw(&ctx);
+
+ // filter: keep only the "uid" lines
+ let uids = res
+ .iter()
+ .filter(|&line| line.get(0) == Some("uid"))
+ .cloned()
+ .collect::<Vec<_>>();
+
+ // map: uid -> trust
+ Ok(uids
+ .iter()
+ .map(|u| (u.get(9).unwrap().to_owned(), u.get(1).unwrap().to_owned()))
+ .collect())
+}
+
+fn list_keys_raw(ctx: &Ctx) -> Vec<StringRecord> {
+ let gpg = Command::new("gpg")
+ .stdin(Stdio::piped())
+ .arg("--homedir")
+ .arg(ctx.directory("homedir").unwrap())
+ .arg("--list-keys")
+ .arg("--with-colons")
+ .output()
+ .expect("failed to start gpg");
+
+ let mut rdr = csv::ReaderBuilder::new()
+ .has_headers(false)
+ .delimiter(b':')
+ .flexible(true)
+ .from_reader(gpg.stdout.as_slice());
+
+ let status = gpg.status;
+ assert!(status.success());
+
+ rdr.records().map(|rec| rec.unwrap()).collect()
+}
+
+pub fn edit_trust(ctx: &Ctx, user_id: &str, trust: u8) -> Result<()> {
+ let homedir =
+ String::from(ctx.directory("homedir").unwrap().to_str().unwrap());
+
+ let cmd = format!("gpg --homedir {} --edit-key {}", homedir, user_id);
+
+ let mut p = rexpect::spawn(&cmd, Some(10_000)).unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("trust").unwrap();
+ p.exp_string("Your decision?").unwrap();
+ p.send_line(&format!("{}", trust)).unwrap();
+ p.exp_string(
+ "Do you really want to set this key to ultimate trust? (y/N)",
+ )
+ .unwrap();
+ p.send_line("y").unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("quit").unwrap();
+ p.exp_eof().unwrap();
+
+ Ok(())
+}
+
+pub fn make_revocation(
+ ctx: &Ctx,
+ user_id: &str,
+ filename: &str,
+ reason: u8,
+) -> Result<()> {
+ let homedir =
+ String::from(ctx.directory("homedir").unwrap().to_str().unwrap());
+
+ let cmd = format!(
+ "gpg --homedir {} --output {} --gen-revoke {}",
+ homedir, filename, user_id
+ );
+
+ let mut p = rexpect::spawn(&cmd, Some(10_000)).unwrap();
+ p.exp_string("Create a revocation certificate for this key? (y/N)")
+ .unwrap();
+ p.send_line("y").unwrap();
+ p.exp_string("Your decision?").unwrap();
+ p.send_line(&format!("{}", reason)).unwrap();
+ p.exp_string(">").unwrap();
+ p.send_line("").unwrap();
+ p.exp_string("Is this okay? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_eof().unwrap();
+
+ Ok(())
+}
+
+pub fn edit_expire(ctx: &Ctx, user_id: &str, expires: &str) -> Result<()> {
+ let homedir =
+ String::from(ctx.directory("homedir").unwrap().to_str().unwrap());
+
+ let cmd = format!("gpg --homedir {} --edit-key {}", homedir, user_id);
+
+ let mut p = rexpect::spawn(&cmd, Some(10_000)).unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("expire").unwrap();
+ p.exp_string("Key is valid for? (0)").unwrap();
+ p.send_line(expires).unwrap();
+ p.exp_string("Is this correct? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("quit").unwrap();
+ p.exp_string("Save changes? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_eof().unwrap();
+
+ Ok(())
+}
+
+pub fn create_user(ctx: &Ctx, user_id: &str) {
+ let mut gpg = Command::new("gpg")
+ .stdin(Stdio::piped())
+ .arg("--homedir")
+ .arg(ctx.directory("homedir").unwrap())
+ .arg("--quick-generate-key")
+ .arg("--batch")
+ .arg("--passphrase")
+ .arg("")
+ .arg(user_id.to_string())
+ .spawn()
+ .expect("failed to start gpg");
+ let status = gpg.wait().unwrap();
+ assert!(status.success());
+}
+
+pub fn sign(ctx: &Ctx, user_id: &str) -> Result<()> {
+ let homedir =
+ String::from(ctx.directory("homedir").unwrap().to_str().unwrap());
+
+ let cmd = format!("gpg --homedir {} --edit-key {}", homedir, user_id);
+
+ let mut p = rexpect::spawn(&cmd, Some(10_000)).unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("sign").unwrap();
+ p.exp_string("Really sign? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("save").unwrap();
+ p.exp_eof().unwrap();
+
+ Ok(())
+}
+
+pub fn tsign(ctx: &Ctx, user_id: &str, level: u8, trust: u8) -> Result<()> {
+ let homedir =
+ String::from(ctx.directory("homedir").unwrap().to_str().unwrap());
+
+ let cmd = format!("gpg --homedir {} --edit-key {}", homedir, user_id);
+
+ let mut p = rexpect::spawn(&cmd, Some(10_000)).unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("tsign").unwrap();
+ p.exp_string("Your selection?").unwrap();
+ p.send_line(&format!("{}", trust)).unwrap();
+ p.exp_string("Your selection?").unwrap();
+ p.send_line(&format!("{}", level)).unwrap();
+ p.exp_string("Your selection?").unwrap();
+ p.send_line("").unwrap(); // domain
+ p.exp_string("Really sign? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_string("gpg>").unwrap();
+ p.send_line("quit").unwrap();
+ p.exp_string("Save changes? (y/N)").unwrap();
+ p.send_line("y").unwrap();
+ p.exp_eof().unwrap();
+
+ Ok(())
+}
diff --git a/tests/test_restd.rs b/openpgp-ca-restd/tests/test_restd.rs
index d978df6..b2d456b 100644
--- a/tests/test_restd.rs
+++ b/openpgp-ca-restd/tests/test_restd.rs
@@ -6,12 +6,13 @@
// SPDX-FileCopyrightText: 2019-2020 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: GPL-3.0-or-later
-use openpgp_ca_lib::ca::OpenpgpCa;
-use openpgp_ca_lib::restd;
-use openpgp_ca_lib::restd::client::Client;
-use openpgp_ca_lib::restd::json::{
+use openpgp_ca_restd::client::Client;
+use openpgp_ca_restd::json::{
Action, CertResultJson, CertStatus, Certificate,
};
+use openpgp_ca_restd::restd;
+
+use openpgp_ca_lib::ca::OpenpgpCa;
use rocket::futures::prelude::future::{AbortHandle, Abortable};