mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
config: add the ability for plugins to specify that config values should be concealed.
And use it for `exposesecret-passphrase`. This is probably overly cautious, but it makes me feel a little better that we won't leak it to someone with read-only access. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
101aeea52c
commit
8293352425
@ -62,6 +62,8 @@ struct configvar {
|
|||||||
#define OPT_DYNAMIC (1 << (OPT_USER_START+6))
|
#define OPT_DYNAMIC (1 << (OPT_USER_START+6))
|
||||||
/* Keep whitespace at the end of the option argument */
|
/* Keep whitespace at the end of the option argument */
|
||||||
#define OPT_KEEP_WHITESPACE (1 << (OPT_USER_START+7))
|
#define OPT_KEEP_WHITESPACE (1 << (OPT_USER_START+7))
|
||||||
|
/* Don't show value in listconfigs */
|
||||||
|
#define OPT_CONCEAL (1 << (OPT_USER_START+8))
|
||||||
|
|
||||||
/* Use this instead of opt_register_*_arg if you want OPT_* from above */
|
/* Use this instead of opt_register_*_arg if you want OPT_* from above */
|
||||||
#define clnopt_witharg(names, type, cb, show, arg, desc) \
|
#define clnopt_witharg(names, type, cb, show, arg, desc) \
|
||||||
|
@ -124,10 +124,11 @@ Plugins are free to register any `name` for their `rpcmethod` as long as the nam
|
|||||||
|
|
||||||
There are currently four supported option 'types':
|
There are currently four supported option 'types':
|
||||||
|
|
||||||
- string: a string
|
- `string`: a string
|
||||||
- bool: a boolean
|
- `string-conceal`: a string which will appear as "..." in `listconfigs`.
|
||||||
- int: parsed as a signed integer (64-bit)
|
- `bool`: a boolean
|
||||||
- flag: no-arg flag option. Presented as `true` if config specifies it.
|
- `int`: parsed as a signed integer (64-bit)
|
||||||
|
- `flag`: no-arg flag option. Presented as `true` if config specifies it.
|
||||||
|
|
||||||
In addition, string and int types can specify `"multi": true` to indicate they can be specified multiple times. These will always be represented in `init` as a (possibly empty) JSON array. "multi" flag types do not make
|
In addition, string and int types can specify `"multi": true` to indicate they can be specified multiple times. These will always be represented in `init` as a (possibly empty) JSON array. "multi" flag types do not make
|
||||||
sense.
|
sense.
|
||||||
|
@ -65,6 +65,9 @@ static const char *get_opt_val(const struct opt_table *ot,
|
|||||||
char buf[],
|
char buf[],
|
||||||
const struct configvar *cv)
|
const struct configvar *cv)
|
||||||
{
|
{
|
||||||
|
if (ot->type & OPT_CONCEAL)
|
||||||
|
return "...";
|
||||||
|
|
||||||
if (ot->show == (void *)opt_show_charp) {
|
if (ot->show == (void *)opt_show_charp) {
|
||||||
/* Don't truncate or quote! */
|
/* Don't truncate or quote! */
|
||||||
return *(char **)ot->u.carg;
|
return *(char **)ot->u.carg;
|
||||||
|
@ -2095,8 +2095,10 @@ void add_config_deprecated(struct lightningd *ld,
|
|||||||
if (!opt->show(buf, sizeof(buf) - sizeof("..."), opt->u.carg))
|
if (!opt->show(buf, sizeof(buf) - sizeof("..."), opt->u.carg))
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|
||||||
if ((opt->type & OPT_SHOWINT)
|
if (opt->type & OPT_CONCEAL) {
|
||||||
|| (opt->type & OPT_SHOWMSATS)) {
|
strcpy(buf, "...");
|
||||||
|
} else if ((opt->type & OPT_SHOWINT)
|
||||||
|
|| (opt->type & OPT_SHOWMSATS)) {
|
||||||
if (streq(buf, "")
|
if (streq(buf, "")
|
||||||
|| strspn(buf, "-0123456789.") != strlen(buf))
|
|| strspn(buf, "-0123456789.") != strlen(buf))
|
||||||
errx(1, "Bad literal for %s: %s", name0, buf);
|
errx(1, "Bad literal for %s: %s", name0, buf);
|
||||||
|
@ -1168,7 +1168,10 @@ static const char *plugin_opt_add(struct plugin *plugin, const char *buffer,
|
|||||||
/* These all take an arg. */
|
/* These all take an arg. */
|
||||||
char *(*cb_arg)(const char *optarg, void *arg);
|
char *(*cb_arg)(const char *optarg, void *arg);
|
||||||
|
|
||||||
if (json_tok_streq(buffer, typetok, "string")) {
|
if (json_tok_streq(buffer, typetok, "string-conceal")) {
|
||||||
|
optflags |= OPT_CONCEAL;
|
||||||
|
cb_arg = (void *)plugin_opt_string_check;
|
||||||
|
} else if (json_tok_streq(buffer, typetok, "string")) {
|
||||||
cb_arg = (void *)plugin_opt_string_check;
|
cb_arg = (void *)plugin_opt_string_check;
|
||||||
} else if (json_tok_streq(buffer, typetok, "int")) {
|
} else if (json_tok_streq(buffer, typetok, "int")) {
|
||||||
cb_arg = (void *)plugin_opt_long_check;
|
cb_arg = (void *)plugin_opt_long_check;
|
||||||
|
1
plugins/.gitignore
vendored
1
plugins/.gitignore
vendored
@ -18,3 +18,4 @@ cln-renepay
|
|||||||
recover
|
recover
|
||||||
cln-askrene
|
cln-askrene
|
||||||
recklessrpc
|
recklessrpc
|
||||||
|
exposesecret
|
||||||
|
@ -156,7 +156,7 @@ int main(int argc, char *argv[])
|
|||||||
plugin_main(argv, init, take(exposesecret),
|
plugin_main(argv, init, take(exposesecret),
|
||||||
PLUGIN_RESTARTABLE, true, NULL, commands, ARRAY_SIZE(commands),
|
PLUGIN_RESTARTABLE, true, NULL, commands, ARRAY_SIZE(commands),
|
||||||
NULL, 0, NULL, 0, NULL, 0,
|
NULL, 0, NULL, 0, NULL, 0,
|
||||||
plugin_option("exposesecret-passphrase", "string",
|
plugin_option("exposesecret-passphrase", "string-conceal",
|
||||||
"Enable exposesecret command to allow HSM Secret backup, with this passphrase",
|
"Enable exposesecret command to allow HSM Secret backup, with this passphrase",
|
||||||
charp_option, NULL, &exposesecret->exposure_passphrase),
|
charp_option, NULL, &exposesecret->exposure_passphrase),
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -4453,6 +4453,10 @@ def test_listchannels_broken_message(node_factory):
|
|||||||
def test_exposesecret(node_factory):
|
def test_exposesecret(node_factory):
|
||||||
l1, l2 = node_factory.get_nodes(2, opts=[{'exposesecret-passphrase': "test_exposesecret"}, {}])
|
l1, l2 = node_factory.get_nodes(2, opts=[{'exposesecret-passphrase': "test_exposesecret"}, {}])
|
||||||
|
|
||||||
|
# listconfigs will conceal the value for us, even if we ask directly.
|
||||||
|
l1.rpc.listconfigs()['configs']['exposesecret-passphrase']['value_str'] == '...'
|
||||||
|
l1.rpc.listconfigs('exposesecret-passphrase')['configs']['exposesecret-passphrase']['value_str'] == '...'
|
||||||
|
|
||||||
# l2 won't expose the secret!
|
# l2 won't expose the secret!
|
||||||
with pytest.raises(RpcError, match="exposesecrets-passphrase is not set"):
|
with pytest.raises(RpcError, match="exposesecrets-passphrase is not set"):
|
||||||
l2.rpc.exposesecret(passphrase='test_exposesecret')
|
l2.rpc.exposesecret(passphrase='test_exposesecret')
|
||||||
|
Loading…
Reference in New Issue
Block a user