MINOR: ssl/cli: implement "add ssl ca-file"
In ticket #1805 an user is impacted by the limitation of size of the CLI buffer when updating a ca-file. This patch allows a user to append new certificates to a ca-file instead of trying to put them all with "set ssl ca-file" The implementation use a new function ssl_store_dup_cafile_entry() which duplicates a cafile_entry and its X509_STORE. ssl_store_load_ca_from_buf() was modified to take an apped parameter so we could share the function for "set" and "add".
This commit is contained in:
parent
d4774d3cfa
commit
62c0b99e3b
@ -1679,6 +1679,21 @@ add server <backend>/<server> [args]*
|
|||||||
Their syntax is similar to the server line from the configuration file,
|
Their syntax is similar to the server line from the configuration file,
|
||||||
please refer to their individual documentation for details.
|
please refer to their individual documentation for details.
|
||||||
|
|
||||||
|
add ssl ca-file <cafile> <payload>
|
||||||
|
Add a new certificate to a ca-file. This command is useful when you reached
|
||||||
|
the buffer size limit on the CLI and want to add multiple certicates.
|
||||||
|
Instead of doing a "set" with all the certificates you are able to add each
|
||||||
|
certificate individually. A "set ssl ca-file" will reset the ca-file.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
|
||||||
|
socat /var/run/haproxy.stat -
|
||||||
|
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate1.crt)\n" | \
|
||||||
|
socat /var/run/haproxy.stat -
|
||||||
|
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate2.crt)\n" | \
|
||||||
|
socat /var/run/haproxy.stat -
|
||||||
|
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -
|
||||||
|
|
||||||
add ssl crt-list <crtlist> <certificate>
|
add ssl crt-list <crtlist> <certificate>
|
||||||
add ssl crt-list <crtlist> <payload>
|
add ssl crt-list <crtlist> <payload>
|
||||||
Add an certificate in a crt-list. It can also be used for directories since
|
Add an certificate in a crt-list. It can also be used for directories since
|
||||||
@ -1821,8 +1836,8 @@ commit ssl ca-file <cafile>
|
|||||||
contexts that use it, you will need to add it to a crt-list with "add ssl
|
contexts that use it, you will need to add it to a crt-list with "add ssl
|
||||||
crt-list".
|
crt-list".
|
||||||
|
|
||||||
See also "new ssl ca-file", "set ssl ca-file", "abort ssl ca-file" and
|
See also "new ssl ca-file", "set ssl ca-file", "add ssl ca-file",
|
||||||
"add ssl crt-list".
|
"abort ssl ca-file" and "add ssl crt-list".
|
||||||
|
|
||||||
commit ssl cert <filename>
|
commit ssl cert <filename>
|
||||||
Commit a temporary SSL certificate update transaction.
|
Commit a temporary SSL certificate update transaction.
|
||||||
@ -2127,7 +2142,7 @@ httpclient <method> <URI>
|
|||||||
new ssl ca-file <cafile>
|
new ssl ca-file <cafile>
|
||||||
Create a new empty CA file tree entry to be filled with a set of CA
|
Create a new empty CA file tree entry to be filled with a set of CA
|
||||||
certificates and added to a crt-list. This command should be used in
|
certificates and added to a crt-list. This command should be used in
|
||||||
combination with "set ssl ca-file" and "add ssl crt-list".
|
combination with "set ssl ca-file", "add ssl ca-file" and "add ssl crt-list".
|
||||||
|
|
||||||
new ssl cert <filename>
|
new ssl cert <filename>
|
||||||
Create a new empty SSL certificate store to be filled with a certificate and
|
Create a new empty SSL certificate store to be filled with a certificate and
|
||||||
@ -2309,15 +2324,16 @@ set severity-output [ none | number | string ]
|
|||||||
duration of the current session.
|
duration of the current session.
|
||||||
|
|
||||||
set ssl ca-file <cafile> <payload>
|
set ssl ca-file <cafile> <payload>
|
||||||
This command is part of a transaction system, the "commit ssl ca-file" and
|
this command is part of a transaction system, the "commit ssl ca-file" and
|
||||||
"abort ssl ca-file" commands could be required.
|
"abort ssl ca-file" commands could be required.
|
||||||
If there is no on-going transaction, it will create a CA file tree entry into
|
if there is no on-going transaction, it will create a ca file tree entry into
|
||||||
which the certificates contained in the payload will be stored. The CA file
|
which the certificates contained in the payload will be stored. the ca file
|
||||||
entry will not be stored in the CA file tree and will only be kept in a
|
entry will not be stored in the ca file tree and will only be kept in a
|
||||||
temporary transaction. If a transaction with the same filename already exists,
|
temporary transaction. if a transaction with the same filename already exists,
|
||||||
the previous CA file entry will be deleted and replaced by the new one.
|
the previous ca file entry will be deleted and replaced by the new one.
|
||||||
Once the modifications are done, you have to commit the transaction through
|
once the modifications are done, you have to commit the transaction through
|
||||||
a "commit ssl ca-file" call.
|
a "commit ssl ca-file" call. If you want to add multiple certificates
|
||||||
|
separately, you can use the "add ssl ca-file" command
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
|
echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
|
||||||
|
@ -63,6 +63,7 @@ struct cafile_entry *ssl_store_get_cafile_entry(char *path, int oldest_entry);
|
|||||||
X509_STORE* ssl_store_get0_locations_file(char *path);
|
X509_STORE* ssl_store_get0_locations_file(char *path);
|
||||||
int ssl_store_add_uncommitted_cafile_entry(struct cafile_entry *entry);
|
int ssl_store_add_uncommitted_cafile_entry(struct cafile_entry *entry);
|
||||||
struct cafile_entry *ssl_store_create_cafile_entry(char *path, X509_STORE *store, enum cafile_type type);
|
struct cafile_entry *ssl_store_create_cafile_entry(char *path, X509_STORE *store, enum cafile_type type);
|
||||||
|
struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src);
|
||||||
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
|
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
|
||||||
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
||||||
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
||||||
|
@ -81,6 +81,26 @@ shell {
|
|||||||
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Remove the unliked CA file and create a new one with the "add ssl ca-file method"
|
||||||
|
|
||||||
|
haproxy h1 -cli {
|
||||||
|
send "del ssl ca-file new_cafile.crt"
|
||||||
|
expect ~ "CA file 'new_cafile.crt' deleted!"
|
||||||
|
|
||||||
|
send "new ssl ca-file new_cafile.crt"
|
||||||
|
expect ~ "New CA file created 'new_cafile.crt'!"
|
||||||
|
}
|
||||||
|
|
||||||
|
shell {
|
||||||
|
printf "add ssl ca-file new_cafile.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||||
|
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||||
|
}
|
||||||
|
|
||||||
|
shell {
|
||||||
|
printf "set ssl ca-file new_cafile.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||||
|
echo "commit ssl ca-file new_cafile.crt" | socat "${tmpdir}/h1/stats" -
|
||||||
|
}
|
||||||
|
|
||||||
haproxy h1 -cli {
|
haproxy h1 -cli {
|
||||||
send "show ssl ca-file"
|
send "show ssl ca-file"
|
||||||
expect ~ ".*new_cafile.crt - 1 certificate.*"
|
expect ~ ".*new_cafile.crt - 1 certificate.*"
|
||||||
|
@ -138,7 +138,9 @@ client c1 -connect ${h1_clearverifiedlst_sock} {
|
|||||||
# Update the server line's ca-file. The server certificate should now be accepted by
|
# Update the server line's ca-file. The server certificate should now be accepted by
|
||||||
# the frontend. We replace the single CA by a list of CAs that includes the correct one.
|
# the frontend. We replace the single CA by a list of CAs that includes the correct one.
|
||||||
shell {
|
shell {
|
||||||
printf "set ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n$(cat ${testdir}/set_cafile_interCA2.crt)\n$(cat ${testdir}/set_cafile_rootCA.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
printf "set ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA1.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||||
|
printf "add ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_interCA2.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||||
|
printf "add ssl ca-file ${testdir}/set_cafile_interCA1.crt <<\n$(cat ${testdir}/set_cafile_rootCA.crt)\n\n" | socat "${tmpdir}/h1/stats" -
|
||||||
echo "commit ssl ca-file ${testdir}/set_cafile_interCA1.crt" | socat "${tmpdir}/h1/stats" -
|
echo "commit ssl ca-file ${testdir}/set_cafile_interCA1.crt" | socat "${tmpdir}/h1/stats" -
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,6 +1076,67 @@ struct cafile_entry *ssl_store_create_cafile_entry(char *path, X509_STORE *store
|
|||||||
return ca_e;
|
return ca_e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Duplicate a cafile_entry
|
||||||
|
* Allocate the X509_STORE and copy the X509 and CRL inside.
|
||||||
|
*
|
||||||
|
* Return the newly allocated cafile_entry or NULL.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
|
||||||
|
{
|
||||||
|
struct cafile_entry *dst = NULL;
|
||||||
|
X509_STORE *store = NULL;
|
||||||
|
STACK_OF(X509_OBJECT) *objs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (src->ca_store) {
|
||||||
|
/* if there was a store in the src, copy it */
|
||||||
|
store = X509_STORE_new();
|
||||||
|
if (!store)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
objs = X509_STORE_get0_objects(src->ca_store);
|
||||||
|
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
|
||||||
|
X509 *cert;
|
||||||
|
X509_CRL *crl;
|
||||||
|
|
||||||
|
cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
|
||||||
|
if (cert) {
|
||||||
|
if (X509_STORE_add_cert(store, cert) == 0) {
|
||||||
|
/* only exits on error if the error is not about duplicate certificates */
|
||||||
|
if (!(ERR_GET_REASON(ERR_get_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
crl = X509_OBJECT_get0_X509_CRL(sk_X509_OBJECT_value(objs, i));
|
||||||
|
if (crl) {
|
||||||
|
if (X509_STORE_add_crl(store, crl) == 0) {
|
||||||
|
/* only exits on error if the error is not about duplicate certificates */
|
||||||
|
if (!(ERR_GET_REASON(ERR_get_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst = ssl_store_create_cafile_entry(src->path, store, src->type);
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
|
||||||
|
err:
|
||||||
|
X509_STORE_free(store);
|
||||||
|
ha_free(&dst);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete a cafile_entry. The caller is responsible from removing this entry
|
/* Delete a cafile_entry. The caller is responsible from removing this entry
|
||||||
* from the cafile_tree first if is was previously added into it. */
|
* from the cafile_tree first if is was previously added into it. */
|
||||||
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e)
|
void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e)
|
||||||
@ -2584,10 +2645,15 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
int errcode = 0;
|
int errcode = 0;
|
||||||
struct buffer *buf;
|
struct buffer *buf;
|
||||||
|
int add_cmd = 0;
|
||||||
|
|
||||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/* this is "add ssl ca-file" */
|
||||||
|
if (*args[0] == 'a')
|
||||||
|
add_cmd = 1;
|
||||||
|
|
||||||
if (!*args[3] || !payload)
|
if (!*args[3] || !payload)
|
||||||
return cli_err(appctx, "'set ssl ca-file expects a filename and CAs as a payload\n");
|
return cli_err(appctx, "'set ssl ca-file expects a filename and CAs as a payload\n");
|
||||||
|
|
||||||
@ -2620,8 +2686,7 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
old_cafile_entry = cafile_transaction.old_cafile_entry;
|
old_cafile_entry = cafile_transaction.old_cafile_entry;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* lookup for the certificate in the tree */
|
/* lookup for the certificate in the tree */
|
||||||
old_cafile_entry = ssl_store_get_cafile_entry(buf->area, 0);
|
old_cafile_entry = ssl_store_get_cafile_entry(buf->area, 0);
|
||||||
}
|
}
|
||||||
@ -2633,17 +2698,21 @@ static int cli_parse_set_cafile(char **args, char *payload, struct appctx *appct
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new cafile_entry without adding it to the cafile tree. */
|
/* if the transaction is new, duplicate the old_ca_file_entry, otherwise duplicate the cafile in the current transaction */
|
||||||
new_cafile_entry = ssl_store_create_cafile_entry(old_cafile_entry->path, NULL, CAFILE_CERT);
|
if (cafile_transaction.new_cafile_entry)
|
||||||
|
new_cafile_entry = ssl_store_dup_cafile_entry(cafile_transaction.new_cafile_entry);
|
||||||
|
else
|
||||||
|
new_cafile_entry = ssl_store_dup_cafile_entry(old_cafile_entry);
|
||||||
|
|
||||||
if (!new_cafile_entry) {
|
if (!new_cafile_entry) {
|
||||||
memprintf(&err, "%sCannot allocate memory!\n",
|
memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
|
||||||
err ? err : "");
|
|
||||||
errcode |= ERR_ALERT | ERR_FATAL;
|
errcode |= ERR_ALERT | ERR_FATAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill the new entry with the new CAs. */
|
/* Fill the new entry with the new CAs. The add_cmd variable determine
|
||||||
if (ssl_store_load_ca_from_buf(new_cafile_entry, payload, 0)) {
|
if we flush the X509_STORE or not */
|
||||||
|
if (ssl_store_load_ca_from_buf(new_cafile_entry, payload, add_cmd)) {
|
||||||
memprintf(&err, "%sInvalid payload\n", err ? err : "");
|
memprintf(&err, "%sInvalid payload\n", err ? err : "");
|
||||||
errcode |= ERR_ALERT | ERR_FATAL;
|
errcode |= ERR_ALERT | ERR_FATAL;
|
||||||
goto end;
|
goto end;
|
||||||
@ -3853,6 +3922,7 @@ 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 },
|
{ { "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 },
|
||||||
|
|
||||||
{ { "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 },
|
{ { "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 },
|
||||||
{ { "set", "ssl", "ca-file", NULL }, "set ssl ca-file <cafile> <payload> : replace a CA file", cli_parse_set_cafile, NULL, NULL },
|
{ { "set", "ssl", "ca-file", NULL }, "set ssl ca-file <cafile> <payload> : replace a CA file", cli_parse_set_cafile, NULL, NULL },
|
||||||
{ { "commit", "ssl", "ca-file", NULL }, "commit ssl ca-file <cafile> : commit a CA file", cli_parse_commit_cafile, cli_io_handler_commit_cafile_crlfile, cli_release_commit_cafile },
|
{ { "commit", "ssl", "ca-file", NULL }, "commit ssl ca-file <cafile> : commit a CA file", cli_parse_commit_cafile, cli_io_handler_commit_cafile_crlfile, cli_release_commit_cafile },
|
||||||
{ { "abort", "ssl", "ca-file", NULL }, "abort ssl ca-file <cafile> : abort a transaction for a CA file", cli_parse_abort_cafile, NULL, NULL },
|
{ { "abort", "ssl", "ca-file", NULL }, "abort ssl ca-file <cafile> : abort a transaction for a CA file", cli_parse_abort_cafile, NULL, NULL },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user