]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: jwt: Add new "add/del/show ssl jwt" CLI commands
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 2 Oct 2025 13:32:47 +0000 (15:32 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Mon, 13 Oct 2025 08:38:52 +0000 (10:38 +0200)
The new "add/del ssl jwt <file>" commands allow to change the "jwt" flag
of an already loaded certificate. It allows to delete certificates used
for JWT validation, which was not yet possible.
The "show ssl jwt" command iterates over all the ckch_stores and dumps
the ones that have the option set.

doc/configuration.txt
doc/management.txt
src/ssl_ckch.c

index 021721e0a654a47cb819ab5617aae3b6aab7dc50..14b2e8812489bcc5412e4022fefed7ba4261211b 100644 (file)
@@ -30742,6 +30742,9 @@ jwt [ off | on ]
   not work. In order to be deleted, a certificate must not be used, either for
   SSL handshakes or JWT validation.
 
+  This option can be changed during runtime via the "add ssl jwt" and "del ssl
+  jwt" CLI commands. See also "show ssl jwt" CLI command.
+
 12.8. ACME
 ----------
 
index dc01a00b19c8936b7007ab7a2dc6af5f4dfbae81..e98a4a9611d8432586150fa7cf78a578f0255ccd 100644 (file)
@@ -1834,6 +1834,13 @@ add ssl crt-list <crtlist> <payload>
     $ echo -e 'add ssl crt-list certlist1 <<\nfoobar.pem [allow-0rtt] foo.bar.com
     !test1.com\n' | socat /tmp/sock1 -
 
+add ssl jwt <filename>
+  Add an already loaded certificate to the list of certificates that can be
+  used for JWT validation (see "jwt_verify_cert" converter). This command does
+  not work on ongoing transactions.
+  See also "del ssl jwt" and "show ssl jwt" commands.
+  See "jwt" certificate option for more information.
+
 clear counters
   Clear the max values of the statistics counters in each proxy (frontend &
   backend) and in each server. The accumulated counters are not affected. The
@@ -2103,6 +2110,13 @@ del ssl crt-list <filename> <certfile[:line]>
   you will need to provide which line you want to delete. To display the line
   numbers, use "show ssl crt-list -n <crtlist>".
 
+del ssl jwt <filename>
+  Remove an already loaded certificate to the list of certificates that can be
+  used for JWT validation (see "jwt_verify_cert" converter). This command does
+  not work on ongoing transactions.
+  See also "add ssl jwt" and "show ssl jwt" commands.
+  See "jwt" certificate option for more information.
+
 del server <backend>/<server>
   Delete a removable server attached to the backend <backend>. A removable
   server is the server which satisfies all of these conditions :
@@ -3779,6 +3793,16 @@ show ssl crt-list [-n] [<filename>]
     ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com
     ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3]
 
+show ssl jwt
+  Display the list of certificates that can be used for JWT validation.
+  See also "add ssl jwt" and "del ssl jwt" commands.
+  See "jwt" certificate option for more information.
+
+  Example:
+    echo "show ssl jwt"  | socat /tmp/sock1 -
+    #filename
+    jwt.pem
+
 show ssl ocsp-response [[text|base64] <id|path>]
   Display the IDs of the OCSP tree entries corresponding to all the OCSP
   responses used in HAProxy, as well as the corresponding frontend
index f720f3729a87bd4b5fc9dc64cddce4f96a27d10a..43a76ca74d6359aec48de2f69ae21489fe88c49a 100644 (file)
@@ -88,6 +88,11 @@ struct show_cert_ctx {
        int transaction;
 };
 
+/* CLI context used by "show ssl jwt" */
+struct show_jwt_ctx {
+       struct ckch_store *cur_ckchs;
+};
+
 #define SHOW_SNI_OPT_1FRONTEND  (1 << 0) /* show only the selected frontend */
 #define SHOW_SNI_OPT_NOTAFTER   (1 << 1) /* show certificates that are [A]fter the notAfter date */
 
@@ -2444,6 +2449,113 @@ error:
        return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
 }
 
+static inline int cli_set_ssl_jwt(char **args, struct appctx *appctx, int value)
+{
+       struct ckch_store *ckchs;
+       char *err = NULL;
+
+       if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
+               return cli_err(appctx, "Can't allocate memory!\n");
+
+       /* check if there is a certificate to lookup */
+       if (!*args[3])
+               return cli_dynerr(appctx, memprintf(&err, "'%s ssl cert' expects a filename\n", args[0]));
+
+       /* The operations on the CKCH architecture are locked so we can
+        * manipulate ckch_store and ckch_inst */
+       if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
+               return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
+
+       if ((ckchs = ckchs_lookup(args[3])) == NULL)
+               goto error;
+
+       ckchs->conf.jwt = value;
+
+       HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
+       return 0;
+
+error:
+       HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
+       return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
+}
+
+/* parsing function for 'add ssl jwt <certfile>' */
+static int cli_parse_add_jwt(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       return cli_set_ssl_jwt(args, appctx, 1);
+}
+
+/* parsing function for 'del ssl jwt <certfile>' */
+static int cli_parse_del_jwt(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       return cli_set_ssl_jwt(args, appctx, 0);
+}
+
+/* parsing function for 'show ssl jwt <certfile>' */
+static int cli_parse_show_jwt(char **args, char *payload, struct appctx *appctx, void *private)
+{
+       struct show_jwt_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+
+       if (!cli_has_level(appctx, ACCESS_LVL_OPER))
+               return cli_err(appctx, "Can't allocate memory!\n");
+
+       /* The operations on the CKCH architecture are locked so we can
+        * manipulate ckch_store and ckch_inst */
+       if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
+               return cli_err(appctx, "Can't show!\nOperations on certificates are currently locked!\n");
+
+       return 0;
+
+error:
+       HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
+       return cli_err(appctx, "Can't display the certificate: Not found or the certificate is a bundle!\n");
+}
+
+/* IO handler of "show ssl jwt".
+ * It makes use of a show_jwt_ctx context.
+ */
+static int cli_io_handler_show_jwt(struct appctx *appctx)
+{
+       struct show_jwt_ctx *ctx = appctx->svcctx;
+       struct buffer *trash = alloc_trash_chunk();
+       struct ebmb_node *node;
+       struct ckch_store *ckchs = NULL;
+
+       if (trash == NULL)
+               return 1;
+
+       if (!ctx->cur_ckchs) {
+               chunk_appendf(trash, "# filename\n");
+               node = ebmb_first(&ckchs_tree);
+       } else {
+               node = &ctx->cur_ckchs->node;
+       }
+       while (node) {
+               ckchs = ebmb_entry(node, struct ckch_store, node);
+               if (ckchs->conf.jwt)
+                       chunk_appendf(trash, "%s\n", ckchs->path);
+
+               node = ebmb_next(node);
+               if (applet_putchk(appctx, trash) == -1)
+                       goto yield;
+       }
+
+       ctx->cur_ckchs = NULL;
+       free_trash_chunk(trash);
+       return 1;
+yield:
+
+       free_trash_chunk(trash);
+       ctx->cur_ckchs = ckchs;
+       return 0; /* should come back */
+}
+
+/* release function of the 'show ssl jwt' command */
+static void cli_release_show_jwt(struct appctx *appctx)
+{
+       HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
+}
+
 
 /*
  * Dump a CKCH in PEM format over the CLI
@@ -4570,6 +4682,10 @@ static struct cli_kw_list cli_kws = {{ },{
        { { "show", "ssl", "cert", NULL },      "show ssl cert [<certfile>]              : display the SSL certificates used in memory, or the details of a file", cli_parse_show_cert, cli_io_handler_show_cert, cli_release_show_cert },
        { { "dump", "ssl", "cert", NULL },      "dump ssl cert <certfile>                : dump the SSL certificates in PEM format",                               cli_parse_dump_cert, cli_io_handler_dump_cert, cli_release_dump_cert },
 
+       { { "add", "ssl", "jwt", NULL },        "add ssl jwt <certfile>                  : add certificate to list of certificates used for JWT validation",       cli_parse_add_jwt, NULL, NULL },
+       { { "del", "ssl", "jwt", NULL },        "del ssl jwt <certfile>                  : remove certificate from list of certificates used for JWT validation",  cli_parse_del_jwt, NULL, NULL },
+       { { "show", "ssl", "jwt", NULL },       "show ssl jwt                            : show list of certificates used for JWT validation",                     cli_parse_show_jwt, cli_io_handler_show_jwt, cli_release_show_jwt },
+
 
        { { "new", "ssl", "ca-file", NULL },    "new ssl ca-file <cafile>                : create a new CA file to be used in a crt-list",                         cli_parse_new_cafile, NULL, NULL },
        { { "add", "ssl", "ca-file", NULL },    "add ssl ca-file <cafile> <payload>      : add a certificate into the CA file",                                    cli_parse_set_cafile, NULL, NULL },