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 */
#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"
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;
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;
}
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;
}
}
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;
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);
}
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);
}
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);
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;
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;
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) {
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) {
/* 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");
#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 */
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 */
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)
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)
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)
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;
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;
}
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:
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,
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 */
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 */
" 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>",
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):