diff --git a/deploy/nginx/renew_certificate.py b/deploy/nginx/renew_certificate.py index f0365606..8007e519 100644 --- a/deploy/nginx/renew_certificate.py +++ b/deploy/nginx/renew_certificate.py @@ -29,6 +29,8 @@ def challenge_arguments(): return ['--dns', dns_provider()] if method != 'http': raise RuntimeError('验证方式必须为 dns 或 http,不允许自动回退到停机验证') + if '*.solit.cn' in DOMAINS: + raise RuntimeError('泛域名证书必须使用 DNS 验证,不能使用 HTTP 验证') private = ROOT.lstat() if (ROOT.resolve(strict=True) != ROOT or not stat.S_ISDIR(private.st_mode) or private.st_uid != 0 or private.st_mode & 0o077): diff --git a/test/deployment/test_certificate_webroot.py b/test/deployment/test_certificate_webroot.py index 5f09df9c..1799fe90 100644 --- a/test/deployment/test_certificate_webroot.py +++ b/test/deployment/test_certificate_webroot.py @@ -26,6 +26,7 @@ class WebrootTests(unittest.TestCase): path.chmod(0o755) for context in (patch.object(renew, 'WEBROOT', self.webroot), patch.object(renew, 'ROOT', self.directory), + patch.object(renew, 'DOMAINS', ('solit.cn', 'web.solit.cn')), patch.dict(os.environ, {'SMAIL_ACME_CHALLENGE': 'http'}, clear=True)): context.start() self.addCleanup(context.stop) @@ -68,6 +69,11 @@ class WebrootTests(unittest.TestCase): def test_http_explicitly_uses_existing_webroot(self): self.assertEqual(renew.challenge_arguments(), ['--http', '--http.webroot', str(self.webroot)]) + def test_wildcard_certificate_rejects_http_challenge(self): + with patch.object(renew, 'DOMAINS', ('solit.cn', '*.solit.cn')): + with self.assertRaisesRegex(RuntimeError, '泛域名证书必须使用 DNS 验证'): + renew.challenge_arguments() + def test_due_http_success_reuses_key_without_port_binding(self): self.assertTrue(any(command[0].endswith('/lego') for command in self.execute())) diff --git a/test/deployment/webroot_renewal_drill.py b/test/deployment/webroot_renewal_drill.py index 8f63188b..123d3d90 100644 --- a/test/deployment/webroot_renewal_drill.py +++ b/test/deployment/webroot_renewal_drill.py @@ -42,6 +42,8 @@ def main(): args = parser.parse_args() if not args.confirm_staging_challenge or os.geteuid() != 0 or run('hostname') != 'ikun2': parser.error('只允许在 47 服务器明确执行测试 CA 的全新 HTTP 挑战') + if '*.solit.cn' in renew.DOMAINS: + parser.error('当前泛域名证书必须使用 DNS-01,不能执行 HTTP-01 演练') if file_state(CONFIG)['sha256'] != CONFIG_SHA: parser.error('Nginx 配置与已审查模板不符,停止演练') memory = dict(line.split(':', 1) for line in Path('/proc/meminfo').read_text().splitlines())