Colin Watson has proposed merging ~cjwatson/lp-signing:charm-action-register-client into lp-signing:master.
Commit message: charm: Add a register-client action Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~cjwatson/lp-signing/+git/lp-signing/+merge/448278 Registering a new client with the signing service currently involves manually running a couple of undocumented commands. Package these up as an action. -- Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/lp-signing:charm-action-register-client into lp-signing:master.
diff --git a/charm/lp-signing/README.md b/charm/lp-signing/README.md index 03d5325..36ccca6 100644 --- a/charm/lp-signing/README.md +++ b/charm/lp-signing/README.md @@ -9,3 +9,10 @@ lp-signing/leader -- /srv/lp-signing/code/env/bin/lp-signing generate-key-pair` to do this; the private halves should be stored in each of `juju config lp-signing service_private_keys` and `juju config lp-signing key_storage_private_keys`, each of which is a JSON-encoded list of strings. + +To register a new client, run: + + juju run-action --wait lp-signing/leader register-client name=<client name> + +This will return the new private and public keys; you will need to configure +the client service with these. diff --git a/charm/lp-signing/actions.yaml b/charm/lp-signing/actions.yaml new file mode 100644 index 0000000..f841a39 --- /dev/null +++ b/charm/lp-signing/actions.yaml @@ -0,0 +1,14 @@ +register-client: + description: > + Generate a key pair and use it to register a new client with the signing + service. This returns the new private and public key, which should be + used to configure the client. + params: + name: + type: string + description: > + The name of the client. This should typically be an identifier for + the client's role, rather than something like a hostname which might + change when the client system is redeployed. + required: + - name diff --git a/charm/lp-signing/actions/actions.py b/charm/lp-signing/actions/actions.py new file mode 100755 index 0000000..7e76442 --- /dev/null +++ b/charm/lp-signing/actions/actions.py @@ -0,0 +1,86 @@ +#! /usr/bin/python3 +# Copyright 2023 Canonical Ltd. This software is licensed under the +# GNU Affero General Public License version 3 (see the file LICENSE). + +import subprocess +import sys +import traceback +from pathlib import Path +from tempfile import TemporaryDirectory + +sys.path.append("lib") + +from charms.layer import basic # noqa: E402 + +basic.bootstrap_charm_deps() +basic.init_config_states() + +from charmhelpers.core import hookenv # noqa: E402 +from ols import base # noqa: E402 + + +def register_client(): + params = hookenv.action_get() + hookenv.log("Generating key pair.") + script = Path(base.code_dir(), "env", "bin", "lp-signing") + with TemporaryDirectory() as tmp: + subprocess.run(["chown", f"{base.user()}:", tmp], check=True) + private_key_path = Path(tmp, "private") + public_key_path = Path(tmp, "public") + subprocess.run( + [ + "sudo", + "-H", + "-u", + base.user(), + script, + "generate-key-pair", + "--private-key-path", + private_key_path, + "--public-key-path", + public_key_path, + ], + check=True, + ) + with open(private_key_path) as private_key_file, open( + public_key_path + ) as public_key_file: + private_key = private_key_file.read().rstrip("\n") + public_key = public_key_file.read().rstrip("\n") + subprocess.run( + [ + "sudo", + "-H", + "-u", + base.user(), + f"SERVICE_CONFIG={base.service_config_path()}", + script, + "register-client", + params["name"], + public_key, + ], + check=True, + ) + # Yes, we include the private key in the output; the person running this + # action will need it to configure the calling service. + hookenv.action_set({"private": private_key, "public": public_key}) + + +def main(argv): + action = Path(argv[0]).name + try: + if action == "register-client": + register_client() + else: + hookenv.action_fail(f"Action {action} not implemented.") + except Exception: + hookenv.action_fail("Unhandled exception") + tb = traceback.format_exc() + hookenv.action_set(dict(traceback=tb)) + hookenv.log(f"Unhandled exception in action {action}:") + for line in tb.splitlines(): + hookenv.log(line) + + +if __name__ == "__main__": + main(sys.argv) diff --git a/charm/lp-signing/actions/register-client b/charm/lp-signing/actions/register-client new file mode 120000 index 0000000..405a394 --- /dev/null +++ b/charm/lp-signing/actions/register-client @@ -0,0 +1 @@ +actions.py \ No newline at end of file
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp