cli (pubsub): new secret subcommands:
commands are added to `share`, `revoke` and `rotate` secrets of an encrypted pubsub node. rel 380
This commit is contained in:
parent
f99544e881
commit
b9f5c6b844
1 changed files with 161 additions and 0 deletions
|
|
@ -2563,6 +2563,166 @@ class Attachments(base.CommandBase):
|
|||
)
|
||||
|
||||
|
||||
class SecretShare(base.CommandBase):
|
||||
def __init__(self, host):
|
||||
super().__init__(
|
||||
host,
|
||||
"share",
|
||||
use_pubsub=True,
|
||||
pubsub_flags={C.NODE},
|
||||
help=_("share a secret to let other entity encrypt or decrypt items"),
|
||||
)
|
||||
|
||||
def add_parser_options(self):
|
||||
self.parser.add_argument(
|
||||
"-k", "--key", metavar="ID", dest="secret_ids", action="append", default=[],
|
||||
help=_(
|
||||
"only share secrets with those IDs (default: share all secrets of the "
|
||||
"node)"
|
||||
)
|
||||
)
|
||||
self.parser.add_argument(
|
||||
"recipient", metavar="JID", help=_("entity who must get the shared secret")
|
||||
)
|
||||
|
||||
async def start(self):
|
||||
try:
|
||||
await self.host.bridge.psSecretShare(
|
||||
self.args.recipient,
|
||||
self.args.service,
|
||||
self.args.node,
|
||||
self.args.secret_ids,
|
||||
self.profile,
|
||||
)
|
||||
except Exception as e:
|
||||
self.disp(f"can't share secret: {e}", error=True)
|
||||
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
|
||||
else:
|
||||
self.disp("secrets have been shared")
|
||||
self.host.quit(C.EXIT_OK)
|
||||
|
||||
|
||||
class SecretRevoke(base.CommandBase):
|
||||
def __init__(self, host):
|
||||
super().__init__(
|
||||
host,
|
||||
"revoke",
|
||||
use_pubsub=True,
|
||||
pubsub_flags={C.NODE},
|
||||
help=_("revoke an encrypted node secret"),
|
||||
)
|
||||
|
||||
def add_parser_options(self):
|
||||
self.parser.add_argument(
|
||||
"secret_id", help=_("ID of the secrets to revoke")
|
||||
)
|
||||
self.parser.add_argument(
|
||||
"-r", "--recipient", dest="recipients", metavar="JID", action="append",
|
||||
default=[], help=_(
|
||||
"entity who must get the revocation notification (default: send to all "
|
||||
"entities known to have the shared secret)"
|
||||
)
|
||||
)
|
||||
|
||||
async def start(self):
|
||||
try:
|
||||
await self.host.bridge.psSecretRevoke(
|
||||
self.args.service,
|
||||
self.args.node,
|
||||
self.args.secret_id,
|
||||
self.args.recipients,
|
||||
self.profile,
|
||||
)
|
||||
except Exception as e:
|
||||
self.disp(f"can't revoke secret: {e}", error=True)
|
||||
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
|
||||
else:
|
||||
self.disp("secret {self.args.secret_id} has been revoked.")
|
||||
self.host.quit(C.EXIT_OK)
|
||||
|
||||
|
||||
class SecretRotate(base.CommandBase):
|
||||
def __init__(self, host):
|
||||
super().__init__(
|
||||
host,
|
||||
"rotate",
|
||||
use_pubsub=True,
|
||||
pubsub_flags={C.NODE},
|
||||
help=_("revoke existing secrets, create a new one and send notifications"),
|
||||
)
|
||||
|
||||
def add_parser_options(self):
|
||||
self.parser.add_argument(
|
||||
"-r", "--recipient", dest="recipients", metavar="JID", action="append",
|
||||
default=[], help=_(
|
||||
"entity who must get the revocation and shared secret notifications "
|
||||
"(default: send to all entities known to have the shared secret)"
|
||||
)
|
||||
)
|
||||
|
||||
async def start(self):
|
||||
try:
|
||||
await self.host.bridge.psSecretRotate(
|
||||
self.args.service,
|
||||
self.args.node,
|
||||
self.args.recipients,
|
||||
self.profile,
|
||||
)
|
||||
except Exception as e:
|
||||
self.disp(f"can't rotate secret: {e}", error=True)
|
||||
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
|
||||
else:
|
||||
self.disp("secret has been rotated")
|
||||
self.host.quit(C.EXIT_OK)
|
||||
|
||||
|
||||
class SecretList(base.CommandBase):
|
||||
def __init__(self, host):
|
||||
super().__init__(
|
||||
host,
|
||||
"list",
|
||||
use_pubsub=True,
|
||||
use_verbose=True,
|
||||
pubsub_flags={C.NODE},
|
||||
help=_("list known secrets for a pubsub node"),
|
||||
use_output=C.OUTPUT_LIST_DICT
|
||||
)
|
||||
|
||||
def add_parser_options(self):
|
||||
pass
|
||||
|
||||
async def start(self):
|
||||
try:
|
||||
secrets = data_format.deserialise(await self.host.bridge.psSecretsList(
|
||||
self.args.service,
|
||||
self.args.node,
|
||||
self.profile,
|
||||
), type_check=list)
|
||||
except Exception as e:
|
||||
self.disp(f"can't list node secrets: {e}", error=True)
|
||||
self.host.quit(C.EXIT_BRIDGE_ERRBACK)
|
||||
else:
|
||||
if not self.verbosity:
|
||||
# we don't print key if verbosity is not a least one, to avoid showing it
|
||||
# on the screen accidentally
|
||||
for secret in secrets:
|
||||
del secret["key"]
|
||||
await self.output(secrets)
|
||||
self.host.quit(C.EXIT_OK)
|
||||
|
||||
|
||||
class Secret(base.CommandBase):
|
||||
subcommands = (SecretShare, SecretRevoke, SecretRotate, SecretList)
|
||||
|
||||
def __init__(self, host):
|
||||
super().__init__(
|
||||
host,
|
||||
"secret",
|
||||
use_profile=False,
|
||||
help=_("handle encrypted nodes secrets"),
|
||||
)
|
||||
|
||||
|
||||
class HookCreate(base.CommandBase):
|
||||
def __init__(self, host):
|
||||
base.CommandBase.__init__(
|
||||
|
|
@ -2725,6 +2885,7 @@ class Pubsub(base.CommandBase):
|
|||
Search,
|
||||
Transform,
|
||||
Attachments,
|
||||
Secret,
|
||||
Hook,
|
||||
Uri,
|
||||
Node,
|
||||
|
|
|
|||
Loading…
Reference in a new issue