svn commit: r1935434 - in httpd/httpd/trunk: modules/md test/modules/md
[email protected] Tue, 16 Jun 2026 18:49:38 -0000
| Newsgroups | gmane.comp.apache.cvs |
|---|---|
| Message-ID | <178163577828.2517592.4623691656866597724@svn03-he-fi> |
Author: rjung
Date: Tue Jun 16 18:49:37 2026
New Revision: 1935434
Log:
mod_md: Support CA-specific HTTP proxy settings
Allow the MDHttpProxy setting to be set per MDomain.
The global MDHttpProxy setting is used by default.
Add integration tests.
Merge from icing/md:
https://github.com/icing/mod_md/commit/f08cd11251dd73e8038b557cc56e828ac4c70f50
Modified:
httpd/httpd/trunk/modules/md/md.h
httpd/httpd/trunk/modules/md/md_acme.c
httpd/httpd/trunk/modules/md/md_acme_drive.c
httpd/httpd/trunk/modules/md/md_core.c
httpd/httpd/trunk/modules/md/md_http.c
httpd/httpd/trunk/modules/md/md_reg.c
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/md_conf.py
httpd/httpd/trunk/test/modules/md/test_702_auto.py
Modified: httpd/httpd/trunk/modules/md/md.h
==============================================================================
--- httpd/httpd/trunk/modules/md/md.h Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md.h Tue Jun 16 18:49:37 2026 (r1935434)
@@ -100,6 +100,7 @@ struct md_t {
struct apr_array_header_t *acme_tls_1_domains; /* domains supporting "acme-tls/1" protocol */
const char *dns01_cmd; /* DNS challenge command, override global command */
+ const char *proxy_url; /* Proxy URL, override global command */
const struct md_srv_conf_t *sc; /* server config where it was defined or NULL */
const char *defn_name; /* config file this MD was defined */
@@ -185,6 +186,7 @@ struct md_t {
#define MD_KEY_PROFILE "profile"
#define MD_KEY_PROFILE_MANDATORY "profile-mandatory"
#define MD_KEY_PROTO "proto"
+#define MD_KEY_PROXY_URL "proxy-url"
#define MD_KEY_READY "ready"
#define MD_KEY_REGISTRATION "registration"
#define MD_KEY_RENEW "renew"
Modified: httpd/httpd/trunk/modules/md/md_acme.c
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md_acme.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -647,7 +647,7 @@ apr_status_t md_acme_create(md_acme_t **
acme->p = p;
acme->user_agent = apr_psprintf(p, "%s mod_md/%s",
base_product, MOD_MD_VERSION);
- acme->proxy_url = proxy_url? apr_pstrdup(p, proxy_url) : NULL;
+ acme->proxy_url = apr_pstrdup(p, proxy_url);
acme->max_retries = 99;
acme->ca_file = ca_file;
Modified: httpd/httpd/trunk/modules/md/md_acme_drive.c
==============================================================================
--- httpd/httpd/trunk/modules/md/md_acme_drive.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md_acme_drive.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -771,7 +771,8 @@ static apr_status_t acme_renew(md_proto_
md_result_activity_printf(result, "Contacting ACME server for %s at %s",
d->md->name, ca_effective);
if (APR_SUCCESS != (rv = md_acme_create(&ad->acme, d->p, ca_effective,
- d->proxy_url, d->ca_file))) {
+ ad->md->proxy_url ? ad->md->proxy_url : d->proxy_url,
+ d->ca_file))) {
md_result_printf(result, rv, "setup ACME communications");
md_result_log(result, MD_LOG_ERR);
goto out;
@@ -1033,7 +1034,8 @@ static apr_status_t acme_preload(md_prot
}
if (APR_SUCCESS != (rv = md_acme_create(&acme, d->p, md->ca_effective,
- d->proxy_url, d->ca_file))) {
+ d->md->proxy_url ? d->md->proxy_url : d->proxy_url,
+ d->ca_file))) {
md_result_set(result, rv, "error setting up acme");
goto leave;
}
@@ -1142,7 +1144,8 @@ static apr_status_t acme_get_ari(md_prot
}
if (APR_SUCCESS != (rv = md_acme_create(&ad->acme, d->p, ca_effective,
- d->proxy_url, d->ca_file))) {
+ d->md->proxy_url ? d->md->proxy_url : d->proxy_url,
+ d->ca_file))) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, d->p,
"create ACME communications");
goto out;
Modified: httpd/httpd/trunk/modules/md/md_core.c
==============================================================================
--- httpd/httpd/trunk/modules/md/md_core.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md_core.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -258,6 +258,7 @@ md_t *md_clone(apr_pool_t *p, const md_t
md->acme_tls_1_domains = md_array_str_compact(p, src->acme_tls_1_domains, 0);
md->stapling = src->stapling;
if (src->dns01_cmd) md->dns01_cmd = apr_pstrdup(p, src->dns01_cmd);
+ if (src->proxy_url) md->proxy_url = apr_pstrdup(p, src->proxy_url);
if (src->cert_files) md->cert_files = md_array_str_clone(p, src->cert_files);
if (src->pkey_files) md->pkey_files = md_array_str_clone(p, src->pkey_files);
}
@@ -315,6 +316,7 @@ md_json_t *md_to_json(const md_t *md, ap
if (md->pkey_files) md_json_setsa(md->pkey_files, json, MD_KEY_PKEY_FILES, NULL);
md_json_setb(md->stapling > 0, json, MD_KEY_STAPLING, NULL);
if (md->dns01_cmd) md_json_sets(md->dns01_cmd, json, MD_KEY_CMD_DNS01, NULL);
+ if (md->proxy_url) md_json_sets(md->proxy_url, json, MD_KEY_PROXY_URL, NULL);
if (md->ca_eab_kid && strcmp("none", md->ca_eab_kid)) {
md_json_sets(md->ca_eab_kid, json, MD_KEY_EAB, MD_KEY_KID, NULL);
if (md->ca_eab_hmac) md_json_sets(md->ca_eab_hmac, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
@@ -384,6 +386,7 @@ md_t *md_from_json(md_json_t *json, apr_
}
md->stapling = (int)md_json_getb(json, MD_KEY_STAPLING, NULL);
md->dns01_cmd = md_json_dups(p, json, MD_KEY_CMD_DNS01, NULL);
+ md->proxy_url = md_json_dups(p, json, MD_KEY_PROXY_URL, NULL);
if (md_json_has_key(json, MD_KEY_EAB, NULL)) {
md->ca_eab_kid = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_KID, NULL);
md->ca_eab_hmac = md_json_dups(p, json, MD_KEY_EAB, MD_KEY_HMAC, NULL);
Modified: httpd/httpd/trunk/modules/md/md_http.c
==============================================================================
--- httpd/httpd/trunk/modules/md/md_http.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md_http.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -82,7 +82,7 @@ apr_status_t md_http_create(md_http_t **
http->pool = p;
http->impl = cur_impl;
http->user_agent = apr_pstrdup(p, user_agent);
- http->proxy_url = proxy_url? apr_pstrdup(p, proxy_url) : NULL;
+ http->proxy_url = apr_pstrdup(p, proxy_url);
http->bucket_alloc = apr_bucket_alloc_create(p);
if (!http->bucket_alloc) {
return APR_EGENERAL;
Modified: httpd/httpd/trunk/modules/md/md_reg.c
==============================================================================
--- httpd/httpd/trunk/modules/md/md_reg.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/md_reg.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -110,7 +110,7 @@ apr_status_t md_reg_create(md_reg_t **pr
reg->certs = apr_hash_make(p);
reg->can_http = 1;
reg->can_https = 1;
- reg->proxy_url = proxy_url? apr_pstrdup(p, proxy_url) : NULL;
+ reg->proxy_url = apr_pstrdup(p, proxy_url);
reg->ca_file = (ca_file && apr_cstr_casecmp("none", ca_file))?
apr_pstrdup(p, ca_file) : NULL;
reg->min_delay = min_delay;
Modified: httpd/httpd/trunk/modules/md/mod_md.c
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/mod_md.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -855,6 +855,7 @@ static apr_status_t md_post_config_befor
apr_status_t rv = APR_SUCCESS;
int dry_run = 0, log_level = APLOG_DEBUG;
md_store_t *store;
+ const char *proxy_url;
apr_pool_userdata_get(&data, mod_md_init_key, s->process->pool);
if (data == NULL) {
@@ -893,7 +894,9 @@ static apr_status_t md_post_config_befor
rv = setup_store(&store, mc, p, s);
if (APR_SUCCESS != rv) goto leave;
- rv = md_reg_create(&mc->reg, p, store, mc->proxy_url, mc->ca_certs,
+ proxy_url = apr_table_get(mc->env, MD_KEY_PROXY_URL);
+
+ rv = md_reg_create(&mc->reg, p, store, proxy_url, mc->ca_certs,
mc->min_delay, mc->retry_failover,
mc->use_store_locks, mc->lock_wait_timeout);
if (APR_SUCCESS != rv) {
@@ -903,7 +906,7 @@ static apr_status_t md_post_config_befor
/* renew on 30% remaining /*/
rv = md_ocsp_reg_make(&mc->ocsp, p, store, mc->ocsp_renew_window,
- AP_SERVER_BASEVERSION, mc->proxy_url,
+ AP_SERVER_BASEVERSION, proxy_url,
mc->min_delay);
if (APR_SUCCESS != rv) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10196) "setup ocsp registry");
Modified: httpd/httpd/trunk/modules/md/mod_md_config.c
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.c Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/mod_md_config.c Tue Jun 16 18:49:37 2026 (r1935434)
@@ -61,7 +61,6 @@ static md_mod_conf_t defmc = {
#else
MD_DEFAULT_BASE_DIR,
#endif
- NULL, /* proxy url for outgoing http */
NULL, /* md_reg_t */
NULL, /* md_ocsp_reg_t */
80, /* local http: port */
@@ -127,6 +126,7 @@ static md_srv_conf_t defconf = {
1, /* staple others */
1, /* ACME ARI renewals */
NULL, /* dns01_cmd */
+ NULL, /* proxy URL */
NULL, /* currently defined md */
NULL, /* assigned md, post config */
0, /* is_ssl, set during mod_ssl post_config */
@@ -185,6 +185,7 @@ static void srv_conf_props_clear(md_srv_
sc->staple_others = DEF_VAL;
sc->ari_renewals = DEF_VAL;
sc->dns01_cmd = NULL;
+ sc->proxy_url = NULL;
}
static void srv_conf_props_copy(md_srv_conf_t *to, const md_srv_conf_t *from)
@@ -209,6 +210,7 @@ static void srv_conf_props_copy(md_srv_c
to->staple_others = from->staple_others;
to->ari_renewals = from->ari_renewals;
to->dns01_cmd = from->dns01_cmd;
+ to->proxy_url = from->proxy_url;
}
static void srv_conf_props_apply(md_t *md, const md_srv_conf_t *from, apr_pool_t *p)
@@ -236,6 +238,7 @@ static void srv_conf_props_apply(md_t *m
if (from->ari_renewals != DEF_VAL) md->ari_renewals = from->ari_renewals;
if (from->stapling != DEF_VAL) md->stapling = from->stapling;
if (from->dns01_cmd) md->dns01_cmd = from->dns01_cmd;
+ if (from->proxy_url) md->proxy_url = from->proxy_url;
}
void *md_config_create_svr(apr_pool_t *pool, server_rec *s)
@@ -285,6 +288,7 @@ static void *md_config_merge(apr_pool_t
nsc->staple_others = (add->staple_others != DEF_VAL)? add->staple_others : base->staple_others;
nsc->ari_renewals = (add->ari_renewals != DEF_VAL)? add->ari_renewals : base->ari_renewals;
nsc->dns01_cmd = (add->dns01_cmd)? add->dns01_cmd : base->dns01_cmd;
+ nsc->proxy_url = (add->proxy_url)? add->proxy_url : base->proxy_url;
nsc->current = NULL;
return nsc;
@@ -865,14 +869,20 @@ static const char *md_config_set_proxy(c
md_srv_conf_t *sc = md_config_get(cmd->server);
const char *err;
- if ((err = md_conf_check_location(cmd, MD_LOC_NOT_MD))) {
+ if ((err = md_conf_check_location(cmd, MD_LOC_ALL))) {
return err;
}
md_util_abs_http_uri_check(cmd->pool, value, &err);
if (err) {
return err;
}
- sc->mc->proxy_url = value;
+
+ if (inside_md_section(cmd)) {
+ sc->proxy_url = value;
+ } else {
+ apr_table_set(sc->mc->env, MD_KEY_PROXY_URL, value);
+ }
+
(void)arg;
return NULL;
}
@@ -1471,8 +1481,6 @@ const char *md_config_gets(const md_srv_
return sc->ca_proto? sc->ca_proto : defconf.ca_proto;
case MD_CONFIG_BASE_DIR:
return sc->mc->base_dir;
- case MD_CONFIG_PROXY:
- return sc->mc->proxy_url;
case MD_CONFIG_CA_AGREEMENT:
return sc->ca_agreement? sc->ca_agreement : defconf.ca_agreement;
case MD_CONFIG_NOTIFY_CMD:
Modified: httpd/httpd/trunk/modules/md/mod_md_config.h
==============================================================================
--- httpd/httpd/trunk/modules/md/mod_md_config.h Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/modules/md/mod_md_config.h Tue Jun 16 18:49:37 2026 (r1935434)
@@ -32,7 +32,6 @@ typedef enum {
MD_CONFIG_RENEW_WINDOW,
MD_CONFIG_WARN_WINDOW,
MD_CONFIG_TRANSITIVE,
- MD_CONFIG_PROXY,
MD_CONFIG_REQUIRE_HTTPS,
MD_CONFIG_MUST_STAPLE,
MD_CONFIG_NOTIFY_CMD,
@@ -53,7 +52,6 @@ typedef struct md_mod_conf_t md_mod_conf
struct md_mod_conf_t {
apr_array_header_t *mds; /* all md_t* defined in the config, shared */
const char *base_dir; /* base dir for store */
- const char *proxy_url; /* proxy url to use (or NULL) */
struct md_reg_t *reg; /* md registry instance */
struct md_ocsp_reg_t *ocsp; /* ocsp status registry */
@@ -115,6 +113,7 @@ typedef struct md_srv_conf_t {
int ari_renewals; /* ACME ARI extension enabled */
const char *dns01_cmd; /* DNS challenge command, override global command */
+ const char *proxy_url; /* Proxy URL, override global command */
md_t *current; /* md currently defined in <MDomainSet xxx> section */
struct apr_array_header_t *assigned; /* post_config: MDs that apply to this server */
Modified: httpd/httpd/trunk/test/modules/md/md_conf.py
==============================================================================
--- httpd/httpd/trunk/test/modules/md/md_conf.py Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/test/modules/md/md_conf.py Tue Jun 16 18:49:37 2026 (r1935434)
@@ -46,7 +46,7 @@ class MDConf(HttpdConf):
" ProxyRequests On",
" ProxyVia On",
" # be totally open",
- " AllowCONNECT 0-56535",
+ " AllowCONNECT 0-65535",
" <Proxy *>",
" # No require or other restrictions, this is just a test server",
" </Proxy>",
Modified: httpd/httpd/trunk/test/modules/md/test_702_auto.py
==============================================================================
--- httpd/httpd/trunk/test/modules/md/test_702_auto.py Tue Jun 16 18:35:00 2026 (r1935433)
+++ httpd/httpd/trunk/test/modules/md/test_702_auto.py Tue Jun 16 18:49:37 2026 (r1935434)
@@ -297,6 +297,55 @@ class TestAutov2:
assert env.apache_restart() == 0, f'{env.apachectl_stderr}'
env.check_md_complete(domain)
+ # Specify a valid http proxy for a single MDomain
+ def test_md_702_008b(self, env):
+ domain = self.test_domain
+ domains = [domain]
+ #
+ conf = MDConf(env, admin=f"admin@{domain}", proxy=True)
+ conf.add_drive_mode("always")
+ conf.start_md(domains)
+ conf.add(f" MDHttpProxy http://localhost:{env.proxy_port}")
+ conf.end_md()
+ conf.install()
+ #
+ # - restart (-> drive), check that md is in store
+ assert env.apache_restart() == 0, f'{env.apachectl_stderr}'
+ assert env.await_completion([domain])
+ assert env.apache_restart() == 0, f'{env.apachectl_stderr}'
+ env.check_md_complete(domain)
+
+ # Specify a non-working http proxy for MDomain A and a valid http proxy for MDomain B
+ def test_md_702_008c(self, env):
+ domain_a = f"a{self.test_domain}"
+ domain_b = f"b{self.test_domain}"
+ conf = MDConf(env, admin=f"admin@{domain_a}", proxy=True)
+ conf.start_md([domain_a])
+ conf.add(f" MDHttpProxy http://localhost:1")
+ conf.end_md()
+ conf.add_vhost(domains=[domain_a])
+ conf.start_md([domain_b])
+ conf.add(f" MDHttpProxy http://localhost:{env.proxy_port}")
+ conf.end_md()
+ conf.add_vhost(domains=[domain_b])
+ conf.install()
+ assert env.apache_restart() == 0, f'{env.apachectl_stderr}'
+ assert env.await_completion([domain_b], restart=False)
+ md = env.await_error(domain_a)
+ assert md
+ assert md['renewal']['errors'] > 0
+ assert md['renewal']['last']['status-description'] == 'Connection refused'
+ assert 'account' not in md['ca']
+ #
+ env.httpd_error_log.ignore_recent(
+ lognos = [
+ "AH10056" # Unsuccessful in contacting ACME server
+ ],
+ matches = [
+ r'.*Unsuccessful in contacting ACME server at .*'
+ ]
+ )
+
# Force cert renewal due to critical remaining valid duration
# Assert that new cert activation is delayed
def test_md_702_009(self, env, acme):