Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

server/cli/src/repo_key_cli.rs

//! `holger repo-key` — the repository signing key of the deb and rpm views, on this box
//! (lane HOL-SIGNED-APT-DNF, `server_lib::repo_sign`).
//!
//! | verb | what |
//! |---|---|
//! | `create --config <ron>` | make this box's key in the data root's key store (once; 0600), print its public half |
//! | `show --config <ron>` | print the public key `/-/repo-key.asc` serves |
//!
//! The public key goes to stdout (an armored `PGP PUBLIC KEY BLOCK`, what apt's `signed-by=`
//! and dnf's `gpgkey=` take); the fingerprint and the file go to stderr. The secret key is
//! never printed.

use std::path::PathBuf;

use anyhow::Result;
use clap::{Args, Subcommand};

use server_lib::repo_sign;

#[derive(Args)]
pub struct RepoKeyArgs {
    #[command(subcommand)]
    pub verb: RepoKeyVerb,
}

#[derive(Subcommand)]
pub enum RepoKeyVerb {
    /// Make this box's repository signing key (an Ed25519 OpenPGP key, in
    /// `<data root>/repo-signing/secret.asc`, mode 0600), once, and print its public half.
    /// A key already there is never replaced: remove the file first to make a new one.
    Create {
        #[arg(short, long)]
        config: PathBuf,
        /// The key's user ID (what apt and gpg print beside the fingerprint).
        #[arg(long, default_value = repo_sign::DEFAULT_USER_ID)]
        user_id: String,
    },
    /// Print this box's public repository key (what `/-/repo-key.asc` serves).
    Show {
        #[arg(short, long)]
        config: PathBuf,
    },
}

/// `holger repo-key`.
pub fn run(a: RepoKeyArgs) -> Result<()> {
    match a.verb {
        RepoKeyVerb::Create { config, user_id } => {
            let root = server_lib::read_ron_config(&config)?.data_root();
            let key = repo_sign::create(&root, &user_id)?;
            eprintln!(
                "made the repository signing key {} ({}) in {}; the deb and rpm views sign with it \
                 from the next start, and {} serves the public key below",
                key.fingerprint_hex(),
                key.user_id(),
                repo_sign::secret_path(&root).display(),
                repo_sign::KEY_PATH
            );
            print!("{}", key.public_armor());
        }
        RepoKeyVerb::Show { config } => {
            let root = server_lib::read_ron_config(&config)?.data_root();
            let Some(key) = repo_sign::load(&root)? else {
                anyhow::bail!("{}", repo_sign::NO_KEY);
            };
            eprintln!("{} ({})", key.fingerprint_hex(), key.user_id());
            print!("{}", key.public_armor());
        }
    }
    Ok(())
}