comparison sat_frontends/jp/cmd_pubsub.py @ 3939:8ae3e870be94

cli (pubsub): new `secret` subcommands: commands are added to `share`, `revoke` and `rotate` secrets of an encrypted pubsub node. rel 380
author Goffi <goffi@goffi.org>
date Sat, 15 Oct 2022 20:38:30 +0200
parents 6939594ba77e
children 08c1d5485411
comparison
equal deleted inserted replaced
3938:6939594ba77e 3939:8ae3e870be94
2561 use_profile=False, 2561 use_profile=False,
2562 help=_("set or retrieve items attachments"), 2562 help=_("set or retrieve items attachments"),
2563 ) 2563 )
2564 2564
2565 2565
2566 class SecretShare(base.CommandBase):
2567 def __init__(self, host):
2568 super().__init__(
2569 host,
2570 "share",
2571 use_pubsub=True,
2572 pubsub_flags={C.NODE},
2573 help=_("share a secret to let other entity encrypt or decrypt items"),
2574 )
2575
2576 def add_parser_options(self):
2577 self.parser.add_argument(
2578 "-k", "--key", metavar="ID", dest="secret_ids", action="append", default=[],
2579 help=_(
2580 "only share secrets with those IDs (default: share all secrets of the "
2581 "node)"
2582 )
2583 )
2584 self.parser.add_argument(
2585 "recipient", metavar="JID", help=_("entity who must get the shared secret")
2586 )
2587
2588 async def start(self):
2589 try:
2590 await self.host.bridge.psSecretShare(
2591 self.args.recipient,
2592 self.args.service,
2593 self.args.node,
2594 self.args.secret_ids,
2595 self.profile,
2596 )
2597 except Exception as e:
2598 self.disp(f"can't share secret: {e}", error=True)
2599 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
2600 else:
2601 self.disp("secrets have been shared")
2602 self.host.quit(C.EXIT_OK)
2603
2604
2605 class SecretRevoke(base.CommandBase):
2606 def __init__(self, host):
2607 super().__init__(
2608 host,
2609 "revoke",
2610 use_pubsub=True,
2611 pubsub_flags={C.NODE},
2612 help=_("revoke an encrypted node secret"),
2613 )
2614
2615 def add_parser_options(self):
2616 self.parser.add_argument(
2617 "secret_id", help=_("ID of the secrets to revoke")
2618 )
2619 self.parser.add_argument(
2620 "-r", "--recipient", dest="recipients", metavar="JID", action="append",
2621 default=[], help=_(
2622 "entity who must get the revocation notification (default: send to all "
2623 "entities known to have the shared secret)"
2624 )
2625 )
2626
2627 async def start(self):
2628 try:
2629 await self.host.bridge.psSecretRevoke(
2630 self.args.service,
2631 self.args.node,
2632 self.args.secret_id,
2633 self.args.recipients,
2634 self.profile,
2635 )
2636 except Exception as e:
2637 self.disp(f"can't revoke secret: {e}", error=True)
2638 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
2639 else:
2640 self.disp("secret {self.args.secret_id} has been revoked.")
2641 self.host.quit(C.EXIT_OK)
2642
2643
2644 class SecretRotate(base.CommandBase):
2645 def __init__(self, host):
2646 super().__init__(
2647 host,
2648 "rotate",
2649 use_pubsub=True,
2650 pubsub_flags={C.NODE},
2651 help=_("revoke existing secrets, create a new one and send notifications"),
2652 )
2653
2654 def add_parser_options(self):
2655 self.parser.add_argument(
2656 "-r", "--recipient", dest="recipients", metavar="JID", action="append",
2657 default=[], help=_(
2658 "entity who must get the revocation and shared secret notifications "
2659 "(default: send to all entities known to have the shared secret)"
2660 )
2661 )
2662
2663 async def start(self):
2664 try:
2665 await self.host.bridge.psSecretRotate(
2666 self.args.service,
2667 self.args.node,
2668 self.args.recipients,
2669 self.profile,
2670 )
2671 except Exception as e:
2672 self.disp(f"can't rotate secret: {e}", error=True)
2673 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
2674 else:
2675 self.disp("secret has been rotated")
2676 self.host.quit(C.EXIT_OK)
2677
2678
2679 class SecretList(base.CommandBase):
2680 def __init__(self, host):
2681 super().__init__(
2682 host,
2683 "list",
2684 use_pubsub=True,
2685 use_verbose=True,
2686 pubsub_flags={C.NODE},
2687 help=_("list known secrets for a pubsub node"),
2688 use_output=C.OUTPUT_LIST_DICT
2689 )
2690
2691 def add_parser_options(self):
2692 pass
2693
2694 async def start(self):
2695 try:
2696 secrets = data_format.deserialise(await self.host.bridge.psSecretsList(
2697 self.args.service,
2698 self.args.node,
2699 self.profile,
2700 ), type_check=list)
2701 except Exception as e:
2702 self.disp(f"can't list node secrets: {e}", error=True)
2703 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
2704 else:
2705 if not self.verbosity:
2706 # we don't print key if verbosity is not a least one, to avoid showing it
2707 # on the screen accidentally
2708 for secret in secrets:
2709 del secret["key"]
2710 await self.output(secrets)
2711 self.host.quit(C.EXIT_OK)
2712
2713
2714 class Secret(base.CommandBase):
2715 subcommands = (SecretShare, SecretRevoke, SecretRotate, SecretList)
2716
2717 def __init__(self, host):
2718 super().__init__(
2719 host,
2720 "secret",
2721 use_profile=False,
2722 help=_("handle encrypted nodes secrets"),
2723 )
2724
2725
2566 class HookCreate(base.CommandBase): 2726 class HookCreate(base.CommandBase):
2567 def __init__(self, host): 2727 def __init__(self, host):
2568 base.CommandBase.__init__( 2728 base.CommandBase.__init__(
2569 self, 2729 self,
2570 host, 2730 host,
2723 Affiliations, 2883 Affiliations,
2724 Reference, 2884 Reference,
2725 Search, 2885 Search,
2726 Transform, 2886 Transform,
2727 Attachments, 2887 Attachments,
2888 Secret,
2728 Hook, 2889 Hook,
2729 Uri, 2890 Uri,
2730 Node, 2891 Node,
2731 Cache, 2892 Cache,
2732 ) 2893 )