MEDIUM: ssl: support a named crt-store section

This patch introduces named crt-store section. A named crt-store allows
to add a scope to the crt name.

For example, a crt named "foo.crt" in a crt-store named "web" will
result in a certificate called "@web/foo.crt".
This commit is contained in:
William Lallemand 2024-04-18 15:54:16 +02:00
parent 81a8a2cae1
commit ffea2e1a13
2 changed files with 58 additions and 9 deletions

View File

@ -4734,6 +4734,10 @@ section. It allows to configure certificate definitions and which files should
be loaded in it. A certificate definition must be written before it is used be loaded in it. A certificate definition must be written before it is used
elsewhere in the configuration. elsewhere in the configuration.
The "crt-store" takes an optional name in argument. If a name is specified,
every certificate of this store must be referenced using "@<name>/<crt>" or
"@<name>/<alias>".
Files in the certificate storage can also be updated dynamically with the CLI. Files in the certificate storage can also be updated dynamically with the CLI.
See "set ssl cert" in the section 9.3 of the management guide. See "set ssl cert" in the section 9.3 of the management guide.
@ -4780,9 +4784,16 @@ Example:
load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1" load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1"
load crt "site2.crt" key "site2.key" load crt "site2.crt" key "site2.key"
frontend in frontend in2
bind *:443 ssl crt "@/site1" crt "site2.crt" bind *:443 ssl crt "@/site1" crt "site2.crt"
crt-store web
load crt "site3.crt" alias "site3"
load crt "site4.crt" key "site4.key"
frontend in2
bind *:443 ssl crt "@web/site1" crt "site2.crt" crt "@web/site3" crt "@web/site4.crt"
4. Proxies 4. Proxies
---------- ----------

View File

@ -4065,6 +4065,8 @@ int ckch_store_load_files(struct ckch_conf *f, struct ckch_store *c, char **err)
return err_code; return err_code;
} }
static char current_crtstore_name[PATH_MAX] = {};
static int crtstore_parse_load(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx, static int crtstore_parse_load(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx,
const char *file, int linenum, char **err) const char *file, int linenum, char **err)
{ {
@ -4098,7 +4100,7 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
goto out; goto out;
} }
rv = snprintf(alias_name, sizeof(alias_name), "@%s/%s", "", args[cur_arg + 1]); rv = snprintf(alias_name, sizeof(alias_name), "@%s/%s", current_crtstore_name, args[cur_arg + 1]);
if (rv >= sizeof(alias_name)) { if (rv >= sizeof(alias_name)) {
memprintf(err, "parsing [%s:%d] : cannot parse '%s' value '%s', too long, max len is %ld.\n", memprintf(err, "parsing [%s:%d] : cannot parse '%s' value '%s', too long, max len is %ld.\n",
file, linenum, args[cur_arg], args[cur_arg + 1], sizeof(alias_name)); file, linenum, args[cur_arg], args[cur_arg + 1], sizeof(alias_name));
@ -4160,9 +4162,28 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
if (!final_name) { if (!final_name) {
final_name = f.crt; final_name = f.crt;
/* complete the name in the ckch_tree with 'crt-base' */ /* if no alias was used:
if (global_ssl.crt_base && *f.crt != '/') { * - when a crt-store exists, use @store/crt
int rv = snprintf(store_path, sizeof(store_path), "%s/%s", global_ssl.crt_base, f.crt); * - or use the absolute file (crt_base + crt)
* - or the relative file when no crt_base exists
*/
if (current_crtstore_name[0] != '\0') {
int rv;
/* add the crt-store name, avoid a double / if the crt starts by it */
rv = snprintf(alias_name, sizeof(alias_name), "@%s%s%s", current_crtstore_name, f.crt[0] != '/' ? "/" : "", f.crt);
if (rv >= sizeof(alias_name)) {
memprintf(err, "parsing [%s:%d] : cannot parse '%s' value '%s', too long, max len is %ld.\n",
file, linenum, args[cur_arg], args[cur_arg + 1], sizeof(alias_name));
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
final_name = alias_name;
} else if (global_ssl.crt_base && *f.crt != '/') {
int rv;
/* When no crt_store name, complete the name in the ckch_tree with 'crt-base' */
rv = snprintf(store_path, sizeof(store_path), "%s/%s", global_ssl.crt_base, f.crt);
if (rv >= sizeof(store_path)) { if (rv >= sizeof(store_path)) {
memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt); memprintf(err, "'%s/%s' : path too long", global_ssl.crt_base, f.crt);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
@ -4171,7 +4192,6 @@ static int crtstore_parse_load(char **args, int section_type, struct proxy *curp
final_name = store_path; final_name = store_path;
} }
} }
/* process and insert the ckch_store */ /* process and insert the ckch_store */
c = ckch_store_new(final_name); c = ckch_store_new(final_name);
if (!c) if (!c)
@ -4218,8 +4238,20 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw
char *errmsg = NULL; char *errmsg = NULL;
if (strcmp(args[0], "crt-store") == 0) { /* new crt-store section */ if (strcmp(args[0], "crt-store") == 0) { /* new crt-store section */
if (*args[1]) { if (!*args[1]) {
ha_alert("parsing [%s:%d] : 'crt-store' section does not support an argument.\n", file, linenum); current_crtstore_name[0] = '\0';
} else {
rc = snprintf(current_crtstore_name, sizeof(current_crtstore_name), "%s", args[1]);
if (rc >= sizeof(current_crtstore_name)) {
ha_alert("parsing [%s:%d] : 'crt-store' <name> argument is too long.\n", file, linenum);
current_crtstore_name[0] = '\0';
err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT;
goto out;
}
}
if (*args[2]) {
ha_alert("parsing [%s:%d] : 'crt-store' section only supports a <name> argument.\n", file, linenum);
err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT; err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT;
goto out; goto out;
} }
@ -4269,7 +4301,13 @@ static int cfg_parse_crtstore(const char *file, int linenum, char **args, int kw
return err_code; return err_code;
} }
REGISTER_CONFIG_SECTION("crt-store", cfg_parse_crtstore, NULL); static int cfg_post_parse_crtstore()
{
current_crtstore_name[0] = '\0';
return ERR_NONE;
}
REGISTER_CONFIG_SECTION("crt-store", cfg_parse_crtstore, cfg_post_parse_crtstore);
static struct cfg_kw_list cfg_kws = {ILH, { static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_CRTSTORE, "load", crtstore_parse_load }, { CFG_CRTSTORE, "load", crtstore_parse_load },