From ab46e3c1e27543fb19a8aa480531c41f0075a6fa Mon Sep 17 00:00:00 2001 From: Louis Opter Date: Tue, 1 Oct 2024 19:53:22 -0700 Subject: [PATCH] Improvements for `clan secrets key generate`. I am not sure to understand what `extract_public_key` was for. It seems like `age-keygen -y` will just work fine for a file like `extract_public_key` is looking for. Unless someone intentionally made a file with a comment like that without the private key in it. Messages are moved to stdout rather being logged. It feels like the output is meaningful in the first step users are going to take. Also makes testing easier, as log messages are captured differently than stdout. The call to add an user is changed to be easier to copy paste and work whether PGP or age is in use. A description for the command is added instead of help which does not seem to be displayed. --- pkgs/clan-cli/clan_cli/secrets/key.py | 61 ++++++++++--------------- pkgs/clan-cli/clan_cli/secrets/users.py | 1 + 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/secrets/key.py b/pkgs/clan-cli/clan_cli/secrets/key.py index f41091d0e..ea5cbb3e8 100644 --- a/pkgs/clan-cli/clan_cli/secrets/key.py +++ b/pkgs/clan-cli/clan_cli/secrets/key.py @@ -2,57 +2,40 @@ import argparse import json import logging import sys -from pathlib import Path from clan_cli.errors import ClanError from clan_cli.git import commit_files from . import sops from .secrets import update_secrets -from .sops import default_admin_key_path, generate_private_key +from .sops import ( + default_admin_key_path, + generate_private_key, + maybe_get_admin_public_key, +) log = logging.getLogger(__name__) -def extract_public_key(filepath: Path) -> str: - """ - Extracts the public key from a given text file. - """ - try: - with filepath.open() as file: - for line in file: - # Check if the line contains the public key - if line.startswith("# public key:"): - # Extract and return the public key part after the prefix - return line.strip().split(": ")[1] - except FileNotFoundError as e: - msg = f"The file at {filepath} was not found." - raise ClanError(msg) from e - except OSError as e: - msg = f"An error occurred while extracting the public key: {e}" - raise ClanError(msg) from e +def generate_key() -> sops.SopsKey: + key = maybe_get_admin_public_key() + if key is not None: + print(f"{key.key_type.name} key {key.pubkey} is already set") + return key - msg = f"Could not find the public key in the file at {filepath}." - raise ClanError(msg) - - -def generate_key() -> str: path = default_admin_key_path() - if path.exists(): - log.info(f"Key already exists at {path}") - return extract_public_key(path) - priv_key, pub_key = generate_private_key(out_file=path) - log.info( - f"Generated age private key at '{default_admin_key_path()}' for your user. Please back it up on a secure location or you will lose access to your secrets." + _, pub_key = generate_private_key(out_file=path) + print( + f"Generated age private key at '{path}' for your user. Please back it up on a secure location or you will lose access to your secrets." ) - return pub_key + return sops.SopsKey(pub_key, username="", key_type=sops.KeyType.AGE) def generate_command(args: argparse.Namespace) -> None: - pub_key = generate_key() - log.info( - f"Also add your age public key to the repository with: \nclan secrets users add {pub_key}" - ) + key = generate_key() + print("Also add your age public key to the repository with:") + key_type = key.key_type.name.lower() + print(f"clan secrets users add --{key_type}-key ") def show_command(args: argparse.Namespace) -> None: @@ -76,7 +59,13 @@ def register_key_parser(parser: argparse.ArgumentParser) -> None: required=True, ) - parser_generate = subparser.add_parser("generate", help="generate age key") + parser_generate = subparser.add_parser( + "generate", + description=( + "Generate an age key for the Clan, " + "to use PGP set `SOPS_PGP_FP` in your environment." + ), + ) parser_generate.set_defaults(func=generate_command) parser_show = subparser.add_parser("show", help="show public key") diff --git a/pkgs/clan-cli/clan_cli/secrets/users.py b/pkgs/clan-cli/clan_cli/secrets/users.py index 0a5c8809b..5348d1405 100644 --- a/pkgs/clan-cli/clan_cli/secrets/users.py +++ b/pkgs/clan-cli/clan_cli/secrets/users.py @@ -180,6 +180,7 @@ def register_users_parser(parser: argparse.ArgumentParser) -> None: "--pgp-key", help=( "public PGP encryption key of the user. " + # Use --fingerprint --fingerprint to get fingerprints for subkeys: "Execute `gpg -k --fingerprint --fingerprint` and remove spaces to get it." ), )