mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
cli: add 'show keystore' command to admin-exec
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -659,6 +659,25 @@ def nacm(args: List[str]) -> None:
|
||||
print(f"Unknown NACM subcommand: {subcommand}")
|
||||
|
||||
|
||||
def keystore(args: List[str]) -> None:
|
||||
data = get_json("/ietf-keystore:keystore", "running", quiet=True)
|
||||
if not data:
|
||||
user = os.environ.get('USER', 'unknown')
|
||||
print(f'No keystore data available (check NACM permissions for "{user}").')
|
||||
return
|
||||
|
||||
if RAW_OUTPUT:
|
||||
print(json.dumps(data, indent=2))
|
||||
return
|
||||
|
||||
if len(args) == 0 or not args[0]:
|
||||
cli_pretty(data, "show-keystore")
|
||||
elif len(args) >= 2 and args[0] in ("symmetric", "asymmetric"):
|
||||
cli_pretty(data, "show-keystore", "-t", args[0], "-n", args[1])
|
||||
else:
|
||||
print("Usage: show keystore [symmetric <name> | asymmetric <name>]")
|
||||
|
||||
|
||||
def execute_command(command: str, args: List[str]):
|
||||
command_mapping = {
|
||||
'bfd': bfd,
|
||||
@@ -667,6 +686,7 @@ def execute_command(command: str, args: List[str]):
|
||||
'dhcp': dhcp,
|
||||
'hardware': hardware,
|
||||
'interface': interface,
|
||||
'keystore': keystore,
|
||||
'lldp': lldp,
|
||||
'nacm': nacm,
|
||||
'ntp': ntp,
|
||||
|
||||
@@ -413,6 +413,20 @@ int infix_groups(kcontext_t *ctx)
|
||||
"| jq -r '.\"ietf-netconf-acm:nacm\".groups.group[].name'");
|
||||
}
|
||||
|
||||
int infix_sym_keys(kcontext_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return shellf("copy running -x /ietf-keystore:keystore/symmetric-keys "
|
||||
"| jq -r '.\"ietf-keystore:keystore\".\"symmetric-keys\".\"symmetric-key\"[].name'");
|
||||
}
|
||||
|
||||
int infix_asym_keys(kcontext_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return shellf("copy running -x /ietf-keystore:keystore/asymmetric-keys "
|
||||
"| jq -r '.\"ietf-keystore:keystore\".\"asymmetric-keys\".\"asymmetric-key\"[].name'");
|
||||
}
|
||||
|
||||
int kplugin_infix_fini(kcontext_t *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
@@ -432,6 +446,8 @@ int kplugin_infix_init(kcontext_t *ctx)
|
||||
kplugin_add_syms(plugin, ksym_new("ifaces", infix_ifaces));
|
||||
kplugin_add_syms(plugin, ksym_new("users", infix_users));
|
||||
kplugin_add_syms(plugin, ksym_new("groups", infix_groups));
|
||||
kplugin_add_syms(plugin, ksym_new("sym_keys", infix_sym_keys));
|
||||
kplugin_add_syms(plugin, ksym_new("asym_keys", infix_asym_keys));
|
||||
kplugin_add_syms(plugin, ksym_new("firewall_zones", infix_firewall_zones));
|
||||
kplugin_add_syms(plugin, ksym_new("firewall_policies", infix_firewall_policies));
|
||||
kplugin_add_syms(plugin, ksym_new("firewall_services", infix_firewall_services));
|
||||
|
||||
@@ -155,6 +155,20 @@
|
||||
<ACTION sym="STRING"/>
|
||||
</PTYPE>
|
||||
|
||||
<PTYPE name="SYM_KEYS">
|
||||
<COMPL>
|
||||
<ACTION sym="sym_keys@infix"/>
|
||||
</COMPL>
|
||||
<ACTION sym="STRING"/>
|
||||
</PTYPE>
|
||||
|
||||
<PTYPE name="ASYM_KEYS">
|
||||
<COMPL>
|
||||
<ACTION sym="asym_keys@infix"/>
|
||||
</COMPL>
|
||||
<ACTION sym="STRING"/>
|
||||
</PTYPE>
|
||||
|
||||
<VIEW name="main">
|
||||
<HOTKEY key="^D" cmd="exit"/>
|
||||
|
||||
@@ -353,6 +367,20 @@ echo "Public: $pub"
|
||||
</ACTION>
|
||||
</COMMAND>
|
||||
|
||||
<COMMAND name="keystore" help="Show keystore keys">
|
||||
<SWITCH name="subcommands" min="0">
|
||||
<COMMAND name="symmetric" help="Show details for a symmetric key">
|
||||
<PARAM name="name" ptype="/SYM_KEYS" help="Key name"/>
|
||||
<ACTION sym="script" in="tty" out="tty" interrupt="true">show keystore symmetric $KLISH_PARAM_name</ACTION>
|
||||
</COMMAND>
|
||||
<COMMAND name="asymmetric" help="Show details for an asymmetric key">
|
||||
<PARAM name="name" ptype="/ASYM_KEYS" help="Key name"/>
|
||||
<ACTION sym="script" in="tty" out="tty" interrupt="true">show keystore asymmetric $KLISH_PARAM_name</ACTION>
|
||||
</COMMAND>
|
||||
</SWITCH>
|
||||
<ACTION sym="script" in="tty" out="tty" interrupt="true">show keystore</ACTION>
|
||||
</COMMAND>
|
||||
|
||||
<COMMAND name="nacm" help="Show users and NACM status and groups">
|
||||
<SWITCH name="subcommands" min="0">
|
||||
<COMMAND name="group" help="Show details for a specific NACM group">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import base64
|
||||
import json
|
||||
import argparse
|
||||
import sys
|
||||
@@ -1030,6 +1031,7 @@ class DhcpServer:
|
||||
class Iface:
|
||||
# Class variable to hold routing-enabled interfaces for the current display session
|
||||
_routing_ifaces = set()
|
||||
_keystore = {}
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
@@ -3381,6 +3383,131 @@ def show_nacm_user(json):
|
||||
print("For detailed rules, use: show nacm group <name>")
|
||||
|
||||
|
||||
def _keystore_format_name(key_format):
|
||||
"""Simplify key-format to a short display name."""
|
||||
fmt = key_format.split(':')[-1] if ':' in key_format else key_format
|
||||
return fmt.replace('-key-format', '')
|
||||
|
||||
|
||||
def _keystore_decode_symmetric(key):
|
||||
"""Decode a symmetric key value for display."""
|
||||
key_format = key.get('key-format', '')
|
||||
fmt = _keystore_format_name(key_format)
|
||||
b64val = key.get('cleartext-symmetric-key', '')
|
||||
|
||||
if fmt == 'passphrase' and b64val:
|
||||
try:
|
||||
return base64.b64decode(b64val).decode('utf-8')
|
||||
except Exception:
|
||||
return b64val
|
||||
return b64val if b64val else '-'
|
||||
|
||||
|
||||
def _keystore_find_key(keystore, kind, name):
|
||||
"""Find a key by type and name in the keystore."""
|
||||
if kind == 'symmetric':
|
||||
keys = keystore.get('symmetric-keys', {}).get('symmetric-key', [])
|
||||
else:
|
||||
keys = keystore.get('asymmetric-keys', {}).get('asymmetric-key', [])
|
||||
for key in keys:
|
||||
if key.get('name') == name:
|
||||
return key
|
||||
return None
|
||||
|
||||
|
||||
def _keystore_asym_type(key):
|
||||
"""Derive asymmetric key algorithm from key format fields."""
|
||||
for field in ('private-key-format', 'public-key-format'):
|
||||
fmt = key.get(field, '')
|
||||
name = fmt.split(':')[-1] if ':' in fmt else fmt
|
||||
name = name.replace('-private-key-format', '').replace('-public-key-format', '')
|
||||
if name:
|
||||
return name
|
||||
return ''
|
||||
|
||||
|
||||
def show_keystore_detail(keystore, kind, name):
|
||||
"""Display detailed information about a specific key."""
|
||||
key = _keystore_find_key(keystore, kind, name)
|
||||
if not key:
|
||||
print(f'{kind.capitalize()} key "{name}" not found.')
|
||||
return
|
||||
|
||||
print(f"{'name':<{20}}: {name}")
|
||||
if kind == 'symmetric':
|
||||
fmt = _keystore_format_name(key.get('key-format', ''))
|
||||
value = _keystore_decode_symmetric(key)
|
||||
print(f"{'format':<{20}}: {fmt}")
|
||||
print(f"{'value':<{20}}: {value}")
|
||||
else:
|
||||
ktype = _keystore_asym_type(key)
|
||||
if ktype:
|
||||
print(f"{'algorithm':<{20}}: {ktype}")
|
||||
pub_fmt = _keystore_format_name(key.get('public-key-format', ''))
|
||||
if pub_fmt:
|
||||
print(f"{'public key format':<{20}}: {pub_fmt}")
|
||||
pub_key = key.get('public-key', '')
|
||||
if pub_key:
|
||||
print(f"{'public key':<{20}}: {pub_key}")
|
||||
|
||||
|
||||
def show_keystore(json, kind=None, name=None):
|
||||
"""Display keystore keys overview or detail for a specific key."""
|
||||
keystore = json.get("ietf-keystore:keystore", {})
|
||||
if not keystore:
|
||||
print("Keystore is empty.")
|
||||
return
|
||||
|
||||
if kind and name:
|
||||
show_keystore_detail(keystore, kind, name)
|
||||
return
|
||||
|
||||
TABLE_WIDTH = 72
|
||||
|
||||
# Symmetric keys
|
||||
sym_keys_data = keystore.get('symmetric-keys', {}).get('symmetric-key', [])
|
||||
if sym_keys_data:
|
||||
Decore.title("Symmetric Keys", TABLE_WIDTH)
|
||||
table = SimpleTable([
|
||||
Column('NAME', flexible=True),
|
||||
Column('FORMAT'),
|
||||
Column('VALUE', flexible=True)
|
||||
], min_width=TABLE_WIDTH)
|
||||
|
||||
for key in sym_keys_data:
|
||||
name = key.get('name', '')
|
||||
fmt = _keystore_format_name(key.get('key-format', ''))
|
||||
value = _keystore_decode_symmetric(key)
|
||||
table.row(name, fmt, value)
|
||||
|
||||
table.print()
|
||||
|
||||
# Asymmetric keys
|
||||
asym_keys_data = keystore.get('asymmetric-keys', {}).get('asymmetric-key', [])
|
||||
if asym_keys_data:
|
||||
Decore.title("Asymmetric Keys", TABLE_WIDTH)
|
||||
table = SimpleTable([
|
||||
Column('NAME', flexible=True),
|
||||
Column('TYPE'),
|
||||
Column('PUBLIC KEY', flexible=True)
|
||||
], min_width=TABLE_WIDTH)
|
||||
|
||||
for key in asym_keys_data:
|
||||
name = key.get('name', '')
|
||||
ktype = _keystore_asym_type(key)
|
||||
|
||||
pub_key = key.get('public-key', '')
|
||||
if len(pub_key) > 40:
|
||||
pub_key = pub_key[:37] + '...'
|
||||
|
||||
table.row(name, ktype, pub_key)
|
||||
|
||||
table.print()
|
||||
|
||||
if not sym_keys_data and not asym_keys_data:
|
||||
print("Keystore is empty.")
|
||||
|
||||
|
||||
def show_system(json):
|
||||
"""System information overivew"""
|
||||
if not json.get("ietf-system:system-state"):
|
||||
@@ -5369,6 +5496,10 @@ def main():
|
||||
subparsers.add_parser('show-nacm-group', help='Show NACM group details')
|
||||
subparsers.add_parser('show-nacm-user', help='Show NACM user details')
|
||||
|
||||
ks_parser = subparsers.add_parser('show-keystore', help='Show keystore keys')
|
||||
ks_parser.add_argument('-t', '--type', help='Key type (symmetric or asymmetric)')
|
||||
ks_parser.add_argument('-n', '--name', help='Key name')
|
||||
|
||||
subparsers.add_parser('show-ntp', help='Show NTP status') \
|
||||
.add_argument('-a', '--address', help='Show details for specific address')
|
||||
subparsers.add_parser('show-ntp-tracking', help='Show NTP tracking status')
|
||||
@@ -5438,6 +5569,8 @@ def main():
|
||||
show_nacm_group(json_data)
|
||||
elif args.command == "show-nacm-user":
|
||||
show_nacm_user(json_data)
|
||||
elif args.command == "show-keystore":
|
||||
show_keystore(json_data, getattr(args, 'type', None), args.name)
|
||||
elif args.command == "show-ntp":
|
||||
show_ntp(json_data, args.address)
|
||||
elif args.command == "show-ntp-tracking":
|
||||
|
||||
Reference in New Issue
Block a user