You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2022/08/25 14:00:13 UTC
svn commit: r1903677 - in /httpd/httpd/trunk: changes-entries/ docs/manual/mod/ modules/md/ test/modules/md/
Author: icing
Date: Thu Aug 25 14:00:13 2022
New Revision: 1903677
URL: http://svn.apache.org/viewvc?rev=1903677&view=rev
Log:
mod_md v2.4.19 from github sync
*) mod_md: a new directive `MDStoreLocks` can be used on cluster
setups with a shared file system for `MDStoreDir` to order
activation of renewed certificates when several cluster nodes are
restarted at the same time. Store locks are not enabled by default.
Restored curl_easy cleanup behaviour from v2.4.14 and refactored
the use of curl_multi for OCSP requests to work with that.
Fixes <https://github.com/icing/mod_md/issues/293>.
Added:
httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
httpd/httpd/trunk/test/modules/md/test_820_locks.py
Modified:
httpd/httpd/trunk/docs/manual/mod/mod_md.xml
httpd/httpd/trunk/modules/md/md_curl.c
httpd/httpd/trunk/modules/md/md_http.c
httpd/httpd/trunk/modules/md/md_http.h
httpd/httpd/trunk/modules/md/md_log.h
httpd/httpd/trunk/modules/md/md_reg.c
httpd/httpd/trunk/modules/md/md_reg.h
httpd/httpd/trunk/modules/md/md_store.c
httpd/httpd/trunk/modules/md/md_store.h
httpd/httpd/trunk/modules/md/md_store_fs.c
httpd/httpd/trunk/modules/md/md_version.h
httpd/httpd/trunk/modules/md/mod_md.c
httpd/httpd/trunk/modules/md/mod_md_config.c
httpd/httpd/trunk/modules/md/mod_md_config.h
httpd/httpd/trunk/test/modules/md/conftest.py
Added: httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt?rev=1903677&view=auto
==============================================================================
--- httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt (added)
+++ httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt Thu Aug 25 14:00:13 2022
@@ -0,0 +1,8 @@
+ *) mod_md: a new directive `MDStoreLocks` can be used on cluster
+ setups with a shared file system for `MDStoreDir` to order
+ activation of renewed certificates when several cluster nodes are
+ restarted at the same time. Store locks are not enabled by default.
+
+ Restored curl_easy cleanup behaviour from v2.4.14 and refactored
+ the use of curl_multi for OCSP requests to work with that.
+ Fixes <https://github.com/icing/mod_md/issues/293>.
Modified: httpd/httpd/trunk/docs/manual/mod/mod_md.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_md.xml?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_md.xml (original)
+++ httpd/httpd/trunk/docs/manual/mod/mod_md.xml Thu Aug 25 14:00:13 2022
@@ -1405,7 +1405,7 @@ MDMessageCmd /etc/apache/md-message
</usage>
</directivesynopsis>
- <directivesynopsis>
+ <directivesynopsis>
<name>MDRetryFailover</name>
<description></description>
<syntax>MDRetryFailover <var>number</var></syntax>
@@ -1423,5 +1423,39 @@ MDMessageCmd /etc/apache/md-message
</p>
</usage>
</directivesynopsis>
+
+ <directivesynopsis>
+ <name>MDStoreLocks</name>
+ <description></description>
+ <syntax>MDStoreLocks on|off|<var>duration</var></syntax>
+ <default>MDStoreLocks off</default>
+ <contextlist>
+ <context>server config</context>
+ </contextlist>
+ <compatibility>Available in version 2.4.55 and later</compatibility>
+ <usage>
+ <p>
+ Enable this to use a lock file on server startup when
+ <directive>MDStoreDir</directive> is synchronized with the server
+ configuration and renewed certificates are activated.
+ </p><p>
+ Locking is intended for setups in a cluster that have a shared
+ file system for MDStoreDir. It will protect the activation of
+ renewed certificates when cluster nodes are restarted/reloaded
+ at the same time. Under the condition that the shared file
+ system does support file locking.
+ </p><p>
+ The default duration to obtain the lock is 5 seconds. If the log
+ cannot be obtained, an error is logged and the server startup will
+ continue. This may result in a cluster node to still use the
+ previous certificate afterwards.
+ </p><p>
+ A higher timeout will reduce that likelihood, but may delay server
+ startups/reloads in case the locks are not properly handled in
+ the underlying file system. A lock should only be held by a
+ httpd instance for a short duration.
+ </p>
+ </usage>
+ </directivesynopsis>
</modulesynopsis>
Modified: httpd/httpd/trunk/modules/md/md_curl.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_curl.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_curl.c (original)
+++ httpd/httpd/trunk/modules/md/md_curl.c Thu Aug 25 14:00:13 2022
@@ -253,18 +253,17 @@ static apr_status_t internals_setup(md_h
rv = APR_EGENERAL;
goto leave;
}
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
+ curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
}
else {
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, req->pool, "reusing curl instance from http");
}
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
- curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
-
internals = apr_pcalloc(req->pool, sizeof(*internals));
internals->curl = curl;
@@ -442,33 +441,41 @@ static void add_to_curlm(md_http_request
{
md_curl_internals_t *internals = req->internals;
- if (curlm && internals && internals->curlm == NULL) {
- curl_multi_add_handle(curlm, internals->curl);
+ assert(curlm);
+ assert(internals);
+ if (internals->curlm == NULL) {
internals->curlm = curlm;
}
+ assert(internals->curlm == curlm);
+ curl_multi_add_handle(curlm, internals->curl);
}
-static void remove_from_curlm(md_http_request_t *req, CURLM *curlm)
+static void remove_from_curlm_and_destroy(md_http_request_t *req, CURLM *curlm)
{
md_curl_internals_t *internals = req->internals;
- if (curlm && internals && internals->curlm == curlm) {
- curl_multi_remove_handle(curlm, internals->curl);
- internals->curlm = NULL;
- }
+ assert(curlm);
+ assert(internals);
+ assert(internals->curlm == curlm);
+ curl_multi_remove_handle(curlm, internals->curl);
+ internals->curlm = NULL;
+ md_http_req_destroy(req);
}
static apr_status_t md_curl_multi_perform(md_http_t *http, apr_pool_t *p,
md_http_next_req *nextreq, void *baton)
{
+ md_http_t *sub_http;
md_http_request_t *req;
CURLM *curlm = NULL;
CURLMcode mc;
struct CURLMsg *curlmsg;
+ apr_array_header_t *http_spares;
apr_array_header_t *requests;
int i, running, numfds, slowdown, msgcount;
apr_status_t rv;
+ http_spares = apr_array_make(p, 10, sizeof(md_http_t*));
requests = apr_array_make(p, 10, sizeof(md_http_request_t*));
curlm = curl_multi_init();
if (!curlm) {
@@ -481,35 +488,46 @@ static apr_status_t md_curl_multi_perfor
while(1) {
while (1) {
/* fetch as many requests as nextreq gives us */
- rv = nextreq(&req, baton, http, requests->nelts);
-
- if (APR_SUCCESS == rv) {
- if (APR_SUCCESS != (rv = internals_setup(req))) {
- if (req->cb.on_status) req->cb.on_status(req, rv, req->cb.on_status_data);
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ if (http_spares->nelts > 0) {
+ sub_http = *(md_http_t **)(apr_array_pop(http_spares));
+ }
+ else {
+ rv = md_http_clone(&sub_http, p, http);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p,
"multi_perform[%d reqs]: setup failed", requests->nelts);
+ goto leave;
}
- else {
- APR_ARRAY_PUSH(requests, md_http_request_t*) = req;
- add_to_curlm(req, curlm);
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
- "multi_perform[%d reqs]: added request", requests->nelts);
- }
- continue;
}
- else if (APR_STATUS_IS_ENOENT(rv)) {
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p,
+
+ rv = nextreq(&req, baton, sub_http, requests->nelts);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p,
"multi_perform[%d reqs]: no more requests", requests->nelts);
if (!requests->nelts) {
goto leave;
}
break;
}
- else {
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ else if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
"multi_perform[%d reqs]: nextreq() failed", requests->nelts);
+ APR_ARRAY_PUSH(http_spares, md_http_t*) = sub_http;
goto leave;
}
+
+ if (APR_SUCCESS != (rv = internals_setup(req))) {
+ if (req->cb.on_status) req->cb.on_status(req, rv, req->cb.on_status_data);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: setup failed", requests->nelts);
+ APR_ARRAY_PUSH(http_spares, md_http_t*) = sub_http;
+ goto leave;
+ }
+
+ APR_ARRAY_PUSH(requests, md_http_request_t*) = req;
+ add_to_curlm(req, curlm);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: added request", requests->nelts);
}
mc = curl_multi_perform(curlm, &running);
@@ -544,9 +562,10 @@ static apr_status_t md_curl_multi_perfor
requests->nelts, req->id);
update_status(req);
fire_status(req, curl_status(curlmsg->data.result));
- remove_from_curlm(req, curlm);
md_array_remove(requests, req);
- md_http_req_destroy(req);
+ sub_http = req->http;
+ APR_ARRAY_PUSH(http_spares, md_http_t*) = sub_http;
+ remove_from_curlm_and_destroy(req, curlm);
}
else {
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p,
@@ -563,8 +582,9 @@ leave:
for (i = 0; i < requests->nelts; ++i) {
req = APR_ARRAY_IDX(requests, i, md_http_request_t*);
fire_status(req, APR_SUCCESS);
- remove_from_curlm(req, curlm);
- md_http_req_destroy(req);
+ sub_http = req->http;
+ APR_ARRAY_PUSH(http_spares, md_http_t*) = sub_http;
+ remove_from_curlm_and_destroy(req, curlm);
}
if (curlm) curl_multi_cleanup(curlm);
return rv;
@@ -585,7 +605,19 @@ static void md_curl_req_cleanup(md_http_
md_curl_internals_t *internals = req->internals;
if (internals) {
if (internals->curl) {
- curl_easy_cleanup(internals->curl);
+ CURL *curl = md_http_get_impl_data(req->http);
+ if (curl == internals->curl) {
+ /* NOP: we have this curl at the md_http_t already */
+ }
+ else if (!curl) {
+ /* no curl at the md_http_t yet, install this one */
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, req->pool, "register curl instance at http");
+ md_http_set_impl_data(req->http, internals->curl);
+ }
+ else {
+ /* There already is a curl at the md_http_t and it's not this one. */
+ curl_easy_cleanup(internals->curl);
+ }
}
if (internals->req_hdrs) curl_slist_free_all(internals->req_hdrs);
req->internals = NULL;
Modified: httpd/httpd/trunk/modules/md/md_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_http.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_http.c (original)
+++ httpd/httpd/trunk/modules/md/md_http.c Thu Aug 25 14:00:13 2022
@@ -92,6 +92,25 @@ apr_status_t md_http_create(md_http_t **
return APR_SUCCESS;
}
+apr_status_t md_http_clone(md_http_t **phttp,
+ apr_pool_t *p, md_http_t *source_http)
+{
+ apr_status_t rv;
+
+ rv = md_http_create(phttp, p, source_http->user_agent, source_http->proxy_url);
+ if (APR_SUCCESS == rv) {
+ (*phttp)->resp_limit = source_http->resp_limit;
+ (*phttp)->timeout = source_http->timeout;
+ if (source_http->unix_socket_path) {
+ (*phttp)->unix_socket_path = apr_pstrdup(p, source_http->unix_socket_path);
+ }
+ if (source_http->ca_file) {
+ (*phttp)->ca_file = apr_pstrdup(p, source_http->ca_file);
+ }
+ }
+ return rv;
+}
+
void md_http_set_impl_data(md_http_t *http, void *data)
{
http->impl_data = data;
@@ -183,7 +202,6 @@ static apr_status_t req_set_body_data(md
bbody = apr_brigade_create(req->pool, req->http->bucket_alloc);
rv = apr_brigade_write(bbody, NULL, NULL, body->data, body->len);
if (rv != APR_SUCCESS) {
- md_http_req_destroy(req);
return rv;
}
}
@@ -315,10 +333,16 @@ apr_status_t md_http_POSTd_create(md_htt
apr_status_t rv;
rv = req_create(&req, http, "POST", url, headers);
+ if (APR_SUCCESS != rv) goto cleanup;
+ rv = req_set_body_data(req, content_type, body);
+cleanup:
if (APR_SUCCESS == rv) {
- rv = req_set_body_data(req, content_type, body);
+ *preq = req;
+ }
+ else {
+ *preq = NULL;
+ if (req) md_http_req_destroy(req);
}
- *preq = (APR_SUCCESS == rv)? req : NULL;
return rv;
}
Modified: httpd/httpd/trunk/modules/md/md_http.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_http.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_http.h (original)
+++ httpd/httpd/trunk/modules/md/md_http.h Thu Aug 25 14:00:13 2022
@@ -88,6 +88,13 @@ apr_status_t md_http_create(md_http_t **
void md_http_set_response_limit(md_http_t *http, apr_off_t resp_limit);
/**
+ * Clone a http instance, inheriting all settings from source_http.
+ * The cloned instance is not tied in any way to the source.
+ */
+apr_status_t md_http_clone(md_http_t **phttp,
+ apr_pool_t *p, md_http_t *source_http);
+
+/**
* Set the timeout for the complete request. This needs to take everything from
* DNS looksups, to conntects, to transfer of all data into account and should
* be sufficiently large.
Modified: httpd/httpd/trunk/modules/md/md_log.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_log.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_log.h (original)
+++ httpd/httpd/trunk/modules/md/md_log.h Thu Aug 25 14:00:13 2022
@@ -38,6 +38,10 @@ typedef enum {
#define MD_LOG_MARK __FILE__,__LINE__
+#ifndef APLOGNO
+#define APLOGNO(n) "AH" #n ": "
+#endif
+
const char *md_log_level_name(md_log_level_t level);
int md_log_is_level(apr_pool_t *p, md_log_level_t level);
Modified: httpd/httpd/trunk/modules/md/md_reg.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_reg.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.c (original)
+++ httpd/httpd/trunk/modules/md/md_reg.c Thu Aug 25 14:00:13 2022
@@ -55,6 +55,8 @@ struct md_reg_t {
void *notify_ctx;
apr_time_t min_delay;
int retry_failover;
+ int use_store_locks;
+ apr_time_t lock_wait_timeout;
};
/**************************************************************************************************/
@@ -83,7 +85,8 @@ static apr_status_t load_props(md_reg_t
apr_status_t md_reg_create(md_reg_t **preg, apr_pool_t *p, struct md_store_t *store,
const char *proxy_url, const char *ca_file,
- apr_time_t min_delay, int retry_failover)
+ apr_time_t min_delay, int retry_failover,
+ int use_store_locks, apr_time_t lock_wait_timeout)
{
md_reg_t *reg;
apr_status_t rv;
@@ -100,6 +103,8 @@ apr_status_t md_reg_create(md_reg_t **pr
apr_pstrdup(p, ca_file) : NULL;
reg->min_delay = min_delay;
reg->retry_failover = retry_failover;
+ reg->use_store_locks = use_store_locks;
+ reg->lock_wait_timeout = lock_wait_timeout;
md_timeslice_create(®->renew_window, p, MD_TIME_LIFE_NORM, MD_TIME_RENEW_WINDOW_DEF);
md_timeslice_create(®->warn_window, p, MD_TIME_LIFE_NORM, MD_TIME_WARN_WINDOW_DEF);
@@ -1235,6 +1240,52 @@ apr_status_t md_reg_load_staging(md_reg_
return md_util_pool_vdo(run_load_staging, reg, p, md, env, result, NULL);
}
+apr_status_t md_reg_load_stagings(md_reg_t *reg, apr_array_header_t *mds,
+ apr_table_t *env, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+ md_t *md;
+ md_result_t *result;
+ int i;
+
+ for (i = 0; i < mds->nelts; ++i) {
+ md = APR_ARRAY_IDX(mds, i, md_t *);
+ result = md_result_md_make(p, md->name);
+ rv = md_reg_load_staging(reg, md, env, result, p);
+ if (APR_SUCCESS == rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p, APLOGNO(10068)
+ "%s: staged set activated", md->name);
+ }
+ else if (!APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, APLOGNO(10069)
+ "%s: error loading staged set", md->name);
+ }
+ }
+
+ return rv;
+}
+
+apr_status_t md_reg_lock_global(md_reg_t *reg, apr_pool_t *p)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ if (reg->use_store_locks) {
+ rv = md_store_lock_global(reg->store, p, reg->lock_wait_timeout);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
+ "unable to acquire global store lock");
+ }
+ }
+ return rv;
+}
+
+void md_reg_unlock_global(md_reg_t *reg, apr_pool_t *p)
+{
+ if (reg->use_store_locks) {
+ md_store_unlock_global(reg->store, p);
+ }
+}
+
apr_status_t md_reg_freeze_domains(md_reg_t *reg, apr_array_header_t *mds)
{
apr_status_t rv = APR_SUCCESS;
Modified: httpd/httpd/trunk/modules/md/md_reg.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_reg.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.h (original)
+++ httpd/httpd/trunk/modules/md/md_reg.h Thu Aug 25 14:00:13 2022
@@ -34,10 +34,18 @@ typedef struct md_reg_t md_reg_t;
/**
* Create the MD registry, using the pool and store.
+ * @param preg on APR_SUCCESS, the create md_reg_t
+ * @param pm memory pool to use for creation
+ * @param store the store to base on
+ * @param proxy_url optional URL of a proxy to use for requests
+ * @param ca_file optioinal CA trust anchor file to use
+ * @param min_delay minimum delay between renewal attempts for a domain
+ * @param retry_failover numer of failed renewals attempt to fail over to alternate ACME ca
*/
apr_status_t md_reg_create(md_reg_t **preg, apr_pool_t *pm, md_store_t *store,
const char *proxy_url, const char *ca_file,
- apr_time_t min_delay, int retry_failover);
+ apr_time_t min_delay, int retry_failover,
+ int use_store_locks, apr_time_t lock_wait_timeout);
md_store_t *md_reg_store_get(md_reg_t *reg);
@@ -270,9 +278,36 @@ apr_status_t md_reg_renew(md_reg_t *reg,
apr_status_t md_reg_load_staging(md_reg_t *reg, const md_t *md, struct apr_table_t *env,
struct md_result_t *result, apr_pool_t *p);
+/**
+ * Check given MDomains for new data in staging areas and, if it exists, load
+ * the new credentials. On encountering errors, leave the credentails as
+ * they are.
+ */
+apr_status_t md_reg_load_stagings(md_reg_t *reg, apr_array_header_t *mds,
+ apr_table_t *env, apr_pool_t *p);
+
void md_reg_set_renew_window_default(md_reg_t *reg, md_timeslice_t *renew_window);
void md_reg_set_warn_window_default(md_reg_t *reg, md_timeslice_t *warn_window);
struct md_job_t *md_reg_job_make(md_reg_t *reg, const char *mdomain, apr_pool_t *p);
+/**
+ * Acquire a cooperative, global lock on registry modifications. Will
+ * do nothing if locking is not configured.
+ *
+ * This will only prevent other children/processes/cluster nodes from
+ * doing the same and does not protect individual store functions from
+ * being called without it.
+ * @param reg the registy
+ * @param p memory pool to use
+ * @param max_wait maximum time to wait in order to acquire
+ * @return APR_SUCCESS when lock was obtained
+ */
+apr_status_t md_reg_lock_global(md_reg_t *reg, apr_pool_t *p);
+
+/**
+ * Realease the global registry lock. Will do nothing if there is no lock.
+ */
+void md_reg_unlock_global(md_reg_t *reg, apr_pool_t *p);
+
#endif /* mod_md_md_reg_h */
Modified: httpd/httpd/trunk/modules/md/md_store.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store.c (original)
+++ httpd/httpd/trunk/modules/md/md_store.c Thu Aug 25 14:00:13 2022
@@ -374,3 +374,12 @@ apr_status_t md_store_md_iter(md_store_m
return md_store_iter(insp_md, &ctx, store, p, group, pattern, MD_FN_MD, MD_SV_JSON);
}
+apr_status_t md_store_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait)
+{
+ return store->lock_global(store, p, max_wait);
+}
+
+void md_store_unlock_global(md_store_t *store, apr_pool_t *p)
+{
+ store->unlock_global(store, p);
+}
Modified: httpd/httpd/trunk/modules/md/md_store.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store.h (original)
+++ httpd/httpd/trunk/modules/md/md_store.h Thu Aug 25 14:00:13 2022
@@ -204,7 +204,23 @@ apr_status_t md_store_iter_names(md_stor
apr_time_t md_store_get_modified(md_store_t *store, md_store_group_t group,
const char *name, const char *aspect, apr_pool_t *p);
+/**
+ * Acquire a cooperative, global lock on store modifications.
+ * This will only prevent other children/processes/cluster nodes from
+ * doing the same and does not protect individual store functions from
+ * being called without it.
+ * @param store the store
+ * @param p memory pool to use
+ * @param max_wait maximum time to wait in order to acquire
+ * @return APR_SUCCESS when lock was obtained
+ */
+apr_status_t md_store_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait);
+
+/**
+ * Realease the global store lock. Will do nothing if there is no lock.
+ */
+void md_store_unlock_global(md_store_t *store, apr_pool_t *p);
/**************************************************************************************************/
/* Storage handling utils */
@@ -303,6 +319,8 @@ typedef apr_time_t md_store_get_modified
typedef apr_status_t md_store_remove_nms_cb(md_store_t *store, apr_pool_t *p,
apr_time_t modified, md_store_group_t group,
const char *name, const char *aspect);
+typedef apr_status_t md_store_lock_global_cb(md_store_t *store, apr_pool_t *p, apr_time_t max_wait);
+typedef void md_store_unlock_global_cb(md_store_t *store, apr_pool_t *p);
struct md_store_t {
md_store_save_cb *save;
@@ -317,6 +335,8 @@ struct md_store_t {
md_store_is_newer_cb *is_newer;
md_store_get_modified_cb *get_modified;
md_store_remove_nms_cb *remove_nms;
+ md_store_lock_global_cb *lock_global;
+ md_store_unlock_global_cb *unlock_global;
};
Modified: httpd/httpd/trunk/modules/md/md_store_fs.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_store_fs.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_store_fs.c (original)
+++ httpd/httpd/trunk/modules/md/md_store_fs.c Thu Aug 25 14:00:13 2022
@@ -39,6 +39,7 @@
/* file system based implementation of md_store_t */
#define MD_STORE_VERSION 3
+#define MD_FS_LOCK_NAME "store.lock"
typedef struct {
apr_fileperms_t dir;
@@ -60,6 +61,8 @@ struct md_store_fs_t {
int port_80;
int port_443;
+
+ apr_file_t *global_lock;
};
#define FS_STORE(store) (md_store_fs_t*)(((char*)store)-offsetof(md_store_fs_t, s))
@@ -101,6 +104,9 @@ static int fs_is_newer(md_store_t *store
static apr_time_t fs_get_modified(md_store_t *store, md_store_group_t group,
const char *name, const char *aspect, apr_pool_t *p);
+static apr_status_t fs_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait);
+static void fs_unlock_global(md_store_t *store, apr_pool_t *p);
+
static apr_status_t init_store_file(md_store_fs_t *s_fs, const char *fname,
apr_pool_t *p, apr_pool_t *ptemp)
{
@@ -296,7 +302,9 @@ apr_status_t md_store_fs_init(md_store_t
s_fs->s.is_newer = fs_is_newer;
s_fs->s.get_modified = fs_get_modified;
s_fs->s.remove_nms = fs_remove_nms;
-
+ s_fs->s.lock_global = fs_lock_global;
+ s_fs->s.unlock_global = fs_unlock_global;
+
/* by default, everything is only readable by the current user */
s_fs->def_perms.dir = MD_FPROT_D_UONLY;
s_fs->def_perms.file = MD_FPROT_F_UONLY;
@@ -1094,3 +1102,67 @@ static apr_status_t fs_rename(md_store_t
md_store_fs_t *s_fs = FS_STORE(store);
return md_util_pool_vdo(pfs_rename, s_fs, p, group, from, to, NULL);
}
+
+static apr_status_t fs_lock_global(md_store_t *store, apr_pool_t *p, apr_time_t max_wait)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+ apr_status_t rv;
+ const char *lpath;
+ apr_time_t end;
+
+ if (s_fs->global_lock) {
+ rv = APR_EEXIST;
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "already locked globally");
+ goto cleanup;
+ }
+
+ rv = md_util_path_merge(&lpath, p, s_fs->base, MD_FS_LOCK_NAME, NULL);
+ if (APR_SUCCESS != rv) goto cleanup;
+ end = apr_time_now() + max_wait;
+
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, p,
+ "acquire global lock: %s", lpath);
+ while (apr_time_now() < end) {
+ rv = apr_file_open(&s_fs->global_lock, lpath,
+ (APR_FOPEN_WRITE|APR_FOPEN_CREATE),
+ MD_FPROT_F_UALL_GREAD, p);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "unable to create/open lock file: %s",
+ lpath);
+ goto next_try;
+ }
+ rv = apr_file_lock(s_fs->global_lock,
+ APR_FLOCK_EXCLUSIVE|APR_FLOCK_NONBLOCK);
+ if (APR_SUCCESS == rv) {
+ goto cleanup;
+ }
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "unable to obtain lock on: %s",
+ lpath);
+
+ next_try:
+ if (s_fs->global_lock) {
+ apr_file_close(s_fs->global_lock);
+ s_fs->global_lock = NULL;
+ }
+ apr_sleep(apr_time_from_msec(100));
+ }
+ rv = APR_EGENERAL;
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, p,
+ "acquire global lock: %s", lpath);
+
+cleanup:
+ return rv;
+}
+
+static void fs_unlock_global(md_store_t *store, apr_pool_t *p)
+{
+ md_store_fs_t *s_fs = FS_STORE(store);
+
+ (void)p;
+ if (s_fs->global_lock) {
+ apr_file_close(s_fs->global_lock);
+ s_fs->global_lock = NULL;
+ }
+}
Modified: httpd/httpd/trunk/modules/md/md_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/md_version.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/md_version.h (original)
+++ httpd/httpd/trunk/modules/md/md_version.h Thu Aug 25 14:00:13 2022
@@ -27,7 +27,7 @@
* @macro
* Version number of the md module as c string
*/
-#define MOD_MD_VERSION "2.4.17"
+#define MOD_MD_VERSION "2.4.19"
/**
* @macro
@@ -35,7 +35,7 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_MD_VERSION_NUM 0x020410
+#define MOD_MD_VERSION_NUM 0x020413
#define MD_ACME_DEF_URL "https://acme-v02.api.letsencrypt.org/directory"
#define MD_TAILSCALE_DEF_URL "file://localhost/var/run/tailscale/tailscaled.sock"
Modified: httpd/httpd/trunk/modules/md/mod_md.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md.c Thu Aug 25 14:00:13 2022
@@ -713,27 +713,6 @@ static apr_status_t merge_mds_with_conf(
return rv;
}
-static void load_staged_data(md_mod_conf_t *mc, server_rec *s, apr_pool_t *p)
-{
- apr_status_t rv;
- md_t *md;
- md_result_t *result;
- int i;
-
- for (i = 0; i < mc->mds->nelts; ++i) {
- md = APR_ARRAY_IDX(mc->mds, i, md_t *);
- result = md_result_md_make(p, md->name);
- if (APR_SUCCESS == (rv = md_reg_load_staging(mc->reg, md, mc->env, result, p))) {
- ap_log_error( APLOG_MARK, APLOG_INFO, rv, s, APLOGNO(10068)
- "%s: staged set activated", md->name);
- }
- else if (!APR_STATUS_IS_ENOENT(rv)) {
- ap_log_error( APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10069)
- "%s: error loading staged set", md->name);
- }
- }
-}
-
static apr_status_t check_invalid_duplicates(server_rec *base_server)
{
server_rec *s;
@@ -891,7 +870,8 @@ static apr_status_t md_post_config_befor
if (APR_SUCCESS != rv) goto leave;
rv = md_reg_create(&mc->reg, p, store, mc->proxy_url, mc->ca_certs,
- mc->min_delay, mc->retry_failover);
+ mc->min_delay, mc->retry_failover,
+ mc->use_store_locks, mc->lock_wait_timeout);
if (APR_SUCCESS != rv) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10072) "setup md registry");
goto leave;
@@ -934,14 +914,24 @@ static apr_status_t md_post_config_befor
/*3*/
if (APR_SUCCESS != (rv = link_mds_to_servers(mc, s, p))) goto leave;
/*4*/
+ if (APR_SUCCESS != (rv = md_reg_lock_global(mc->reg, ptemp))) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10398)
+ "unable to obtain global registry lock, "
+ "renewed certificates may remain inactive on "
+ "this httpd instance!");
+ /* FIXME: or should we fail the server start/reload here? */
+ rv = APR_SUCCESS;
+ goto leave;
+ }
if (APR_SUCCESS != (rv = md_reg_sync_start(mc->reg, mc->mds, ptemp))) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10073)
"syncing %d mds to registry", mc->mds->nelts);
goto leave;
}
/*5*/
- load_staged_data(mc, s, p);
+ md_reg_load_stagings(mc->reg, mc->mds, mc->env, p);
leave:
+ md_reg_unlock_global(mc->reg, ptemp);
return rv;
}
Modified: httpd/httpd/trunk/modules/md/mod_md_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_config.c?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.c (original)
+++ httpd/httpd/trunk/modules/md/mod_md_config.c Thu Aug 25 14:00:13 2022
@@ -86,6 +86,8 @@ static md_mod_conf_t defmc = {
NULL, /* CA cert file to use */
apr_time_from_sec(5), /* minimum delay for retries */
13, /* retry_failover after 14 errors, with 5s delay ~ half a day */
+ 0, /* store locks, disabled by default */
+ apr_time_from_sec(5), /* max time to wait to obaint a store lock */
};
static md_timeslice_t def_renew_window = {
@@ -647,6 +649,36 @@ static const char *md_config_set_retry_f
return NULL;
}
+static const char *md_config_set_store_locks(cmd_parms *cmd, void *dc, const char *s)
+{
+ md_srv_conf_t *config = md_config_get(cmd->server);
+ const char *err = md_conf_check_location(cmd, MD_LOC_NOT_MD);
+ int use_store_locks;
+ apr_time_t wait_time = 0;
+
+ (void)dc;
+ if (err) {
+ return err;
+ }
+ else if (!apr_strnatcasecmp("off", s)) {
+ use_store_locks = 0;
+ }
+ else if (!apr_strnatcasecmp("on", s)) {
+ use_store_locks = 1;
+ }
+ else {
+ if (md_duration_parse(&wait_time, s, "s") != APR_SUCCESS) {
+ return "neither 'on', 'off' or a duration specified";
+ }
+ use_store_locks = (wait_time != 0);
+ }
+ config->mc->use_store_locks = use_store_locks;
+ if (wait_time) {
+ config->mc->lock_wait_timeout = wait_time;
+ }
+ return NULL;
+}
+
static const char *md_config_set_require_https(cmd_parms *cmd, void *dc, const char *value)
{
md_srv_conf_t *config = md_config_get(cmd->server);
@@ -1215,6 +1247,8 @@ const command_rec md_cmds[] = {
"Time length for first retry, doubled on every consecutive error."),
AP_INIT_TAKE1("MDRetryFailover", md_config_set_retry_failover, NULL, RSRC_CONF,
"The number of errors before a failover to another CA is triggered."),
+ AP_INIT_TAKE1("MDStoreLocks", md_config_set_store_locks, NULL, RSRC_CONF,
+ "Configure locking of store for updates."),
AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
};
Modified: httpd/httpd/trunk/modules/md/mod_md_config.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/md/mod_md_config.h?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.h (original)
+++ httpd/httpd/trunk/modules/md/mod_md_config.h Thu Aug 25 14:00:13 2022
@@ -72,6 +72,8 @@ struct md_mod_conf_t {
const char *ca_certs; /* root certificates to use for connections */
apr_time_t min_delay; /* minimum delay for retries */
int retry_failover; /* number of errors to trigger CA failover */
+ int use_store_locks; /* use locks when updating store */
+ apr_time_t lock_wait_timeout; /* fail after this time when unable to obtain lock */
};
typedef struct md_srv_conf_t {
Modified: httpd/httpd/trunk/test/modules/md/conftest.py
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/test/modules/md/conftest.py?rev=1903677&r1=1903676&r2=1903677&view=diff
==============================================================================
--- httpd/httpd/trunk/test/modules/md/conftest.py (original)
+++ httpd/httpd/trunk/test/modules/md/conftest.py Thu Aug 25 14:00:13 2022
@@ -51,6 +51,7 @@ def _session_scope(env):
'AH10170', # mod_md, wrong config, tested
'AH10171', # mod_md, wrong config, tested
'AH10373', # SSL errors on uncompleted handshakes
+ 'AH10398', # test on global store lock
])
env.httpd_error_log.add_ignored_patterns([
@@ -61,6 +62,7 @@ def _session_scope(env):
re.compile(r'.*problem\[urn:org:apache:httpd:log:AH\d+:].*'),
re.compile(r'.*Unsuccessful in contacting ACME server at :*'),
re.compile(r'.*test-md-720-002-\S+.org: dns-01 setup command failed .*'),
+ re.compile(r'.*AH\d*: unable to obtain global registry lock, .*'),
])
if env.lacks_ocsp():
env.httpd_error_log.add_ignored_patterns([
Added: httpd/httpd/trunk/test/modules/md/test_820_locks.py
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/test/modules/md/test_820_locks.py?rev=1903677&view=auto
==============================================================================
--- httpd/httpd/trunk/test/modules/md/test_820_locks.py (added)
+++ httpd/httpd/trunk/test/modules/md/test_820_locks.py Thu Aug 25 14:00:13 2022
@@ -0,0 +1,72 @@
+import os
+
+import pytest
+from filelock import Timeout, FileLock
+
+from .md_cert_util import MDCertUtil
+from .md_conf import MDConf
+from .md_env import MDTestEnv
+
+
+@pytest.mark.skipif(condition=not MDTestEnv.has_acme_server(),
+ reason="no ACME test server configured")
+class TestLocks:
+
+ @pytest.fixture(autouse=True, scope='class')
+ def _class_scope(self, env, acme):
+ env.APACHE_CONF_SRC = "data/test_auto"
+ acme.start(config='default')
+ env.check_acme()
+ env.clear_store()
+
+ @pytest.fixture(autouse=True, scope='function')
+ def _method_scope(self, env, request):
+ env.clear_store()
+ self.test_domain = env.get_request_domain(request)
+
+ def configure_httpd(self, env, domains, add_lines=""):
+ conf = MDConf(env)
+ conf.add(add_lines)
+ conf.add_md(domains)
+ conf.add_vhost(domains)
+ conf.install()
+
+ # normal renewal with store locks activated
+ def test_md_820_001(self, env):
+ domain = self.test_domain
+ self.configure_httpd(env, [domain], add_lines=[
+ "MDStoreLocks 1s"
+ ])
+ assert env.apache_restart() == 0
+ assert env.await_completion([domain])
+
+ # renewal, with global lock held during restert
+ def test_md_820_002(self, env):
+ domain = self.test_domain
+ self.configure_httpd(env, [domain], add_lines=[
+ "MDStoreLocks 1s"
+ ])
+ assert env.apache_restart() == 0
+ assert env.await_completion([domain])
+ # we have a cert now, add a dns name to force renewal
+ certa = MDCertUtil(env.store_domain_file(domain, 'pubcert.pem'))
+ self.configure_httpd(env, [domain, f"x.{domain}"], add_lines=[
+ "MDStoreLocks 1s"
+ ])
+ assert env.apache_restart() == 0
+ # await new cert, but do not restart, keeps the cert in staging
+ assert env.await_completion([domain], restart=False)
+ # obtain global lock and restart
+ lockfile = os.path.join(env.store_dir, "store.lock")
+ with FileLock(lockfile):
+ assert env.apache_restart() == 0
+ # lock should have prevented staging from being activated,
+ # meaning we will have the same cert
+ certb = MDCertUtil(env.store_domain_file(domain, 'pubcert.pem'))
+ assert certa.same_serial_as(certb)
+ # now restart without lock
+ assert env.apache_restart() == 0
+ certc = MDCertUtil(env.store_domain_file(domain, 'pubcert.pem'))
+ assert not certa.same_serial_as(certc)
+
+
Re: svn commit: r1903677 - in /httpd/httpd/trunk: changes-entries/ docs/manual/mod/ modules/md/ test/modules/md/
Posted by Stefan Eissing via dev <de...@httpd.apache.org>.
> Am 09.01.2023 um 22:14 schrieb Christophe JAILLET <ch...@wanadoo.fr>:
>
> Le 25/08/2022 à 16:00, icing@apache.org a écrit :
>> Author: icing
>> Date: Thu Aug 25 14:00:13 2022
>> New Revision: 1903677
>> URL: http://svn.apache.org/viewvc?rev=1903677&view=rev
>> Log:
>> mod_md v2.4.19 from github sync
>> *) mod_md: a new directive `MDStoreLocks` can be used on cluster
>> setups with a shared file system for `MDStoreDir` to order
>> activation of renewed certificates when several cluster nodes are
>> restarted at the same time. Store locks are not enabled by default.
>> Restored curl_easy cleanup behaviour from v2.4.14 and refactored
>> the use of curl_multi for OCSP requests to work with that.
>> Fixes <https://github.com/icing/mod_md/issues/293>.
>> Added:
>> httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
>> httpd/httpd/trunk/test/modules/md/test_820_locks.py
>> Modified:
>> httpd/httpd/trunk/docs/manual/mod/mod_md.xml
>> httpd/httpd/trunk/modules/md/md_curl.c
>> httpd/httpd/trunk/modules/md/md_http.c
>> httpd/httpd/trunk/modules/md/md_http.h
>> httpd/httpd/trunk/modules/md/md_log.h
>> httpd/httpd/trunk/modules/md/md_reg.c
>> httpd/httpd/trunk/modules/md/md_reg.h
>> httpd/httpd/trunk/modules/md/md_store.c
>> httpd/httpd/trunk/modules/md/md_store.h
>> httpd/httpd/trunk/modules/md/md_store_fs.c
>> httpd/httpd/trunk/modules/md/md_version.h
>> httpd/httpd/trunk/modules/md/mod_md.c
>> httpd/httpd/trunk/modules/md/mod_md_config.c
>> httpd/httpd/trunk/modules/md/mod_md_config.h
>> httpd/httpd/trunk/test/modules/md/conftest.py
>> Added: httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
>> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt?rev=1903677&view=auto
>> ==============================================================================
>> --- httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt (added)
>> +++ httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt Thu Aug 25 14:00:13 2022
>> @@ -0,0 +1,8 @@
>> + *) mod_md: a new directive `MDStoreLocks` can be used on cluster
>> + setups with a shared file system for `MDStoreDir` to order
>> + activation of renewed certificates when several cluster nodes are
>> + restarted at the same time. Store locks are not enabled by default.
>> +
>> + Restored curl_easy cleanup behaviour from v2.4.14 and refactored
>> + the use of curl_multi for OCSP requests to work with that.
>> + Fixes <https://github.com/icing/mod_md/issues/293>.
>> Modified: httpd/httpd/trunk/docs/manual/mod/mod_md.xml
>> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_md.xml?rev=1903677&r1=1903676&r2=1903677&view=diff
>> ==============================================================================
>> --- httpd/httpd/trunk/docs/manual/mod/mod_md.xml (original)
>> +++ httpd/httpd/trunk/docs/manual/mod/mod_md.xml Thu Aug 25 14:00:13 2022
>> @@ -1405,7 +1405,7 @@ MDMessageCmd /etc/apache/md-message
>> </usage>
>> </directivesynopsis>
>> - <directivesynopsis>
>> + <directivesynopsis>
>> <name>MDRetryFailover</name>
>> <description></description>
>> <syntax>MDRetryFailover <var>number</var></syntax>
>> @@ -1423,5 +1423,39 @@ MDMessageCmd /etc/apache/md-message
>> </p>
>> </usage>
>> </directivesynopsis>
>> +
>> + <directivesynopsis>
>> + <name>MDStoreLocks</name>
>> + <description></description>
>
> Hi,
>
> a description is missing.
> Not sure how to write it myself.
ChatGPT?
-.-
>
> CJ
>
>> + <syntax>MDStoreLocks on|off|<var>duration</var></syntax>
>> + <default>MDStoreLocks off</default>
>> + <contextlist>
>> + <context>server config</context>
>> + </contextlist>
>> + <compatibility>Available in version 2.4.55 and later</compatibility>
>> + <usage>
>> + <p>
>> + Enable this to use a lock file on server startup when
>> + <directive>MDStoreDir</directive> is synchronized with the server
>> + configuration and renewed certificates are activated.
>> + </p><p>
>> + Locking is intended for setups in a cluster that have a shared
>> + file system for MDStoreDir. It will protect the activation of
>> + renewed certificates when cluster nodes are restarted/reloaded
>> + at the same time. Under the condition that the shared file
>> + system does support file locking.
>> + </p><p>
>> + The default duration to obtain the lock is 5 seconds. If the log
>> + cannot be obtained, an error is logged and the server startup will
>> + continue. This may result in a cluster node to still use the
>> + previous certificate afterwards.
>> + </p><p>
>> + A higher timeout will reduce that likelihood, but may delay server
>> + startups/reloads in case the locks are not properly handled in
>> + the underlying file system. A lock should only be held by a
>> + httpd instance for a short duration.
>> + </p>
>> + </usage>
>> + </directivesynopsis>
>
Re: svn commit: r1903677 - in /httpd/httpd/trunk: changes-entries/ docs/manual/mod/ modules/md/ test/modules/md/
Posted by Christophe JAILLET <ch...@wanadoo.fr>.
Le 25/08/2022 à 16:00, icing@apache.org a écrit :
> Author: icing
> Date: Thu Aug 25 14:00:13 2022
> New Revision: 1903677
>
> URL: http://svn.apache.org/viewvc?rev=1903677&view=rev
> Log:
> mod_md v2.4.19 from github sync
>
> *) mod_md: a new directive `MDStoreLocks` can be used on cluster
> setups with a shared file system for `MDStoreDir` to order
> activation of renewed certificates when several cluster nodes are
> restarted at the same time. Store locks are not enabled by default.
>
> Restored curl_easy cleanup behaviour from v2.4.14 and refactored
> the use of curl_multi for OCSP requests to work with that.
> Fixes <https://github.com/icing/mod_md/issues/293>.
>
>
> Added:
> httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
> httpd/httpd/trunk/test/modules/md/test_820_locks.py
> Modified:
> httpd/httpd/trunk/docs/manual/mod/mod_md.xml
> httpd/httpd/trunk/modules/md/md_curl.c
> httpd/httpd/trunk/modules/md/md_http.c
> httpd/httpd/trunk/modules/md/md_http.h
> httpd/httpd/trunk/modules/md/md_log.h
> httpd/httpd/trunk/modules/md/md_reg.c
> httpd/httpd/trunk/modules/md/md_reg.h
> httpd/httpd/trunk/modules/md/md_store.c
> httpd/httpd/trunk/modules/md/md_store.h
> httpd/httpd/trunk/modules/md/md_store_fs.c
> httpd/httpd/trunk/modules/md/md_version.h
> httpd/httpd/trunk/modules/md/mod_md.c
> httpd/httpd/trunk/modules/md/mod_md_config.c
> httpd/httpd/trunk/modules/md/mod_md_config.h
> httpd/httpd/trunk/test/modules/md/conftest.py
>
> Added: httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt?rev=1903677&view=auto
> ==============================================================================
> --- httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt (added)
> +++ httpd/httpd/trunk/changes-entries/md_locks_and_fix.txt Thu Aug 25 14:00:13 2022
> @@ -0,0 +1,8 @@
> + *) mod_md: a new directive `MDStoreLocks` can be used on cluster
> + setups with a shared file system for `MDStoreDir` to order
> + activation of renewed certificates when several cluster nodes are
> + restarted at the same time. Store locks are not enabled by default.
> +
> + Restored curl_easy cleanup behaviour from v2.4.14 and refactored
> + the use of curl_multi for OCSP requests to work with that.
> + Fixes <https://github.com/icing/mod_md/issues/293>.
>
> Modified: httpd/httpd/trunk/docs/manual/mod/mod_md.xml
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_md.xml?rev=1903677&r1=1903676&r2=1903677&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/docs/manual/mod/mod_md.xml (original)
> +++ httpd/httpd/trunk/docs/manual/mod/mod_md.xml Thu Aug 25 14:00:13 2022
> @@ -1405,7 +1405,7 @@ MDMessageCmd /etc/apache/md-message
> </usage>
> </directivesynopsis>
>
> - <directivesynopsis>
> + <directivesynopsis>
> <name>MDRetryFailover</name>
> <description></description>
> <syntax>MDRetryFailover <var>number</var></syntax>
> @@ -1423,5 +1423,39 @@ MDMessageCmd /etc/apache/md-message
> </p>
> </usage>
> </directivesynopsis>
> +
> + <directivesynopsis>
> + <name>MDStoreLocks</name>
> + <description></description>
Hi,
a description is missing.
Not sure how to write it myself.
CJ
> + <syntax>MDStoreLocks on|off|<var>duration</var></syntax>
> + <default>MDStoreLocks off</default>
> + <contextlist>
> + <context>server config</context>
> + </contextlist>
> + <compatibility>Available in version 2.4.55 and later</compatibility>
> + <usage>
> + <p>
> + Enable this to use a lock file on server startup when
> + <directive>MDStoreDir</directive> is synchronized with the server
> + configuration and renewed certificates are activated.
> + </p><p>
> + Locking is intended for setups in a cluster that have a shared
> + file system for MDStoreDir. It will protect the activation of
> + renewed certificates when cluster nodes are restarted/reloaded
> + at the same time. Under the condition that the shared file
> + system does support file locking.
> + </p><p>
> + The default duration to obtain the lock is 5 seconds. If the log
> + cannot be obtained, an error is logged and the server startup will
> + continue. This may result in a cluster node to still use the
> + previous certificate afterwards.
> + </p><p>
> + A higher timeout will reduce that likelihood, but may delay server
> + startups/reloads in case the locks are not properly handled in
> + the underlying file system. A lock should only be held by a
> + httpd instance for a short duration.
> + </p>
> + </usage>
> + </directivesynopsis>