diff --git a/test/deployment/nginx_certificate_cutover.py b/test/deployment/nginx_certificate_cutover.py index 55c8649..8a6842f 100644 --- a/test/deployment/nginx_certificate_cutover.py +++ b/test/deployment/nginx_certificate_cutover.py @@ -117,8 +117,8 @@ def main(): parser.error('线上配置与已审查版本不符') proposed = (evidence / 'smail.conf').read_bytes() expected = previous.replace( - b'/var/lib/smail-acme-tls/certificates/solit.cn.crt', b'/opt/smail/ssl/custom.crt').replace( - b'/var/lib/smail-acme-tls/certificates/solit.cn.key', b'/opt/smail/ssl/custom.key') + b'/var/lib/smail-acme-tls/certificates/cdis.cn.crt', b'/opt/smail/ssl/custom.crt').replace( + b'/var/lib/smail-acme-tls/certificates/cdis.cn.key', b'/opt/smail/ssl/custom.key') if proposed != expected or proposed == previous: parser.error('候选配置必须且只能改变 Smail 证书读取路径') run('nginx', '-t') @@ -158,21 +158,21 @@ def main(): try: scripts = Scripts() - scripts.feed(request('mail.solit.cn', 443).decode('utf-8')) + scripts.feed(request('mail.cdis.cn', 443).decode('utf-8')) if not scripts.paths: raise RuntimeError('未找到用于既有连接测试的真实静态资源') asset = args.asset_path or scripts.paths[0] - expected_body = request('mail.solit.cn', 443, asset) + expected_body = request('mail.cdis.cn', 443, asset) if len(expected_body) < 65536: raise RuntimeError('静态资源过小,无法进行本次下载连续性检查') - for host, port in (('mail.solit.cn', 443), ('web.apmmk.cn', 443)): + for host, port in (('mail.cdis.cn', 443), ('web.cdis.cn', 443)): thread = threading.Thread(target=monitor, args=(host, port)) thread.start() threads.append(thread) time.sleep(2) if len(report['samples']) < 4 or any(not item['ok'] for item in report['samples']): raise RuntimeError('迁移前连续探测未通过') - secure, response = request('mail.solit.cn', 443, asset, slow=True) + secure, response = request('mail.cdis.cn', 443, asset, slow=True) pending = (secure, response) prefix = response.read(1024) report['connectionOpenedBeforeReload'] = True diff --git a/test/deployment/renewal_drill.py b/test/deployment/renewal_drill.py index a5a9ef4..63539d5 100644 --- a/test/deployment/renewal_drill.py +++ b/test/deployment/renewal_drill.py @@ -15,7 +15,7 @@ from unittest.mock import patch SERVER = 'https://acme-staging-v02.api.letsencrypt.org/directory' SOURCE = Path('/usr/local/libexec/smail-acme/renew_certificate.py') LEGACY_SOURCE_SHA256 = '6d0abbe9466f8becd61b1cb3c750bfffb938d16c5a9bcae0b96d1451227d4216' -DOMAINS = {'solit.cn', 'mail.solit.cn', 'smtp.solit.cn', 'imap.solit.cn', 'pop.solit.cn'} +DOMAINS = {'cdis.cn', 'mail.cdis.cn', 'smtp.cdis.cn', 'imap.cdis.cn', 'pop.cdis.cn'} RUN = subprocess.run @@ -59,14 +59,14 @@ def main(): run(['nginx', '-t'], check=True) run(['systemctl', 'is-active', '--quiet', 'nginx'], check=True) - certificate = stage / 'certificates/solit.cn.crt' - key = stage / 'certificates/solit.cn.key' + certificate = stage / 'certificates/cdis.cn.crt' + key = stage / 'certificates/cdis.cn.key' old_certificate = digest(certificate) old_key = digest(key) protected = [Path('/opt/smail/smail'), Path('/opt/smail/smail-admin'), Path('/opt/smail/ssl/custom.crt'), Path('/opt/smail/ssl/custom.key'), - Path('/var/lib/smail-acme-tls/certificates/solit.cn.crt'), - Path('/var/lib/smail-acme-tls/certificates/solit.cn.key')] + Path('/var/lib/smail-acme-tls/certificates/cdis.cn.crt'), + Path('/var/lib/smail-acme-tls/certificates/cdis.cn.key')] protected.extend(sorted(Path('/etc/nginx/conf.d').glob('*.conf'))) before = {path: digest(path) for path in protected} spec = importlib.util.spec_from_file_location('production_renew', SOURCE) diff --git a/test/deployment/test_certificate_renewal.py b/test/deployment/test_certificate_renewal.py index 6162af4..84abc3d 100644 --- a/test/deployment/test_certificate_renewal.py +++ b/test/deployment/test_certificate_renewal.py @@ -161,7 +161,7 @@ class DeploymentTests(unittest.TestCase): '-subj', '/CN=Smail isolated test CA', '-addext', 'keyUsage=critical,keyCertSign,cRLSign') cls.real_run('openssl', 'req', '-new', '-newkey', 'rsa:2048', '-nodes', - '-keyout', str(cls.key), '-out', str(cls.csr), '-subj', '/CN=solit.cn', + '-keyout', str(cls.key), '-out', str(cls.csr), '-subj', '/CN=cdis.cn', '-addext', 'basicConstraints=critical,CA:FALSE', '-addext', 'keyUsage=critical,digitalSignature,keyEncipherment', '-addext', 'extendedKeyUsage=serverAuth', @@ -180,9 +180,9 @@ class DeploymentTests(unittest.TestCase): self.backups = self.directory / 'backups' for directory in (self.source, self.target, self.backups): directory.mkdir(mode=0o700) - for path, value in ((self.source / 'solit.cn.crt', self.new.read_bytes()), - (self.source / 'solit.cn.key', self.key.read_bytes()), - (self.source / 'solit.cn.issuer.crt', self.ca.read_bytes()), + for path, value in ((self.source / 'cdis.cn.crt', self.new.read_bytes()), + (self.source / 'cdis.cn.key', self.key.read_bytes()), + (self.source / 'cdis.cn.issuer.crt', self.ca.read_bytes()), (self.target / 'custom.crt', self.old.read_bytes()), (self.target / 'custom.key', self.key.read_bytes())): path.write_bytes(value) @@ -235,20 +235,20 @@ class DeploymentTests(unittest.TestCase): self.assertEqual(path.stat().st_mode & 0o077, 0) def test_unchanged_certificate_checks_live_without_reload(self): - (self.source / 'solit.cn.crt').write_bytes(self.old.read_bytes()) + (self.source / 'cdis.cn.crt').write_bytes(self.old.read_bytes()) deploy.main() self.assertNotIn(('systemctl', 'reload', 'nginx'), self.calls) self.live.assert_called_once() def test_interrupted_publish_is_reconciled_when_files_already_match(self): - (self.source / 'solit.cn.crt').write_bytes(self.old.read_bytes()) + (self.source / 'cdis.cn.crt').write_bytes(self.old.read_bytes()) self.live.side_effect = [RuntimeError('上次重载前中断'), None] deploy.main() self.assertEqual(self.calls.count(('systemctl', 'reload', 'nginx')), 1) self.assertEqual(self.live.call_count, 2) def test_failed_reconciliation_does_not_report_success(self): - (self.source / 'solit.cn.crt').write_bytes(self.old.read_bytes()) + (self.source / 'cdis.cn.crt').write_bytes(self.old.read_bytes()) self.live.side_effect = RuntimeError('线上证书不匹配') with self.assertRaisesRegex(RuntimeError, '线上证书不匹配'): deploy.main() @@ -271,13 +271,13 @@ class DeploymentTests(unittest.TestCase): def test_short_lived_certificate_is_rejected(self): self.real_run('openssl', 'x509', '-req', '-in', str(self.csr), '-CA', str(self.ca), '-CAkey', str(self.ca_key), '-set_serial', '3', '-days', '1', - '-copy_extensions', 'copy', '-out', str(self.source / 'solit.cn.crt')) + '-copy_extensions', 'copy', '-out', str(self.source / 'cdis.cn.crt')) with self.assertRaises(subprocess.CalledProcessError): deploy.main() self.assert_old_untouched() def test_mismatched_key_is_rejected(self): - (self.source / 'solit.cn.key').write_bytes(self.ca_key.read_bytes()) + (self.source / 'cdis.cn.key').write_bytes(self.ca_key.read_bytes()) with self.assertRaisesRegex(RuntimeError, '不匹配'): deploy.main() self.assert_old_untouched() @@ -289,7 +289,7 @@ class DeploymentTests(unittest.TestCase): self.assertEqual((self.target / 'custom.crt').read_bytes(), self.old.read_bytes()) def test_nginx_still_using_candidate_is_rejected(self): - self.config += 'ssl_certificate ' + str(self.source / 'solit.cn.crt') + ';\n' + self.config += 'ssl_certificate ' + str(self.source / 'cdis.cn.crt') + ';\n' with self.assertRaisesRegex(RuntimeError, '签发目录'): deploy.main() self.assert_old_untouched() @@ -325,7 +325,7 @@ class DeploymentTests(unittest.TestCase): self.live.assert_called_with(deploy.fingerprint(self.old)) def test_unreadable_private_permissions_are_rejected(self): - (self.source / 'solit.cn.key').chmod(0o644) + (self.source / 'cdis.cn.key').chmod(0o644) with self.assertRaisesRegex(RuntimeError, '权限'): deploy.main() self.assert_old_untouched() @@ -353,7 +353,7 @@ class DeploymentTests(unittest.TestCase): validate = deploy.validate def mutate(snapshot): - (self.source / 'solit.cn.crt').write_bytes(b'changed-after-snapshot') + (self.source / 'cdis.cn.crt').write_bytes(b'changed-after-snapshot') validate(snapshot) with patch.object(deploy, 'validate', side_effect=mutate): @@ -372,7 +372,7 @@ class DeploymentTests(unittest.TestCase): for name in ('client_body', 'proxy', 'fastcgi', 'uwsgi', 'scgi')) + 'server {\n' + 'listen 127.0.0.1:18443 ssl;\nlisten 127.0.0.1:18002 ssl;\n' - + 'server_name mail.solit.cn;\n' + self.config + + 'server_name mail.cdis.cn;\n' + self.config + 'location / { return 200 "ready"; }\n}\n}\n', encoding='utf-8') arguments = ('nginx', '-c', str(configuration), '-p', str(self.directory)) @@ -402,7 +402,7 @@ class DeploymentTests(unittest.TestCase): deploy.main() self.real_verify(deploy.fingerprint(self.new)) self.assertIsNone(process.poll()) - (self.source / 'solit.cn.crt').write_bytes(self.old.read_bytes()) + (self.source / 'cdis.cn.crt').write_bytes(self.old.read_bytes()) attempted = False def fail_after_live_update(expected): diff --git a/test/deployment/test_certificate_webroot.py b/test/deployment/test_certificate_webroot.py index 1799fe9..704d376 100644 --- a/test/deployment/test_certificate_webroot.py +++ b/test/deployment/test_certificate_webroot.py @@ -26,7 +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.object(renew, 'DOMAINS', ('cdis.cn', 'web.cdis.cn')), patch.dict(os.environ, {'SMAIL_ACME_CHALLENGE': 'http'}, clear=True)): context.start() self.addCleanup(context.stop) @@ -70,7 +70,7 @@ class WebrootTests(unittest.TestCase): 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 patch.object(renew, 'DOMAINS', ('cdis.cn', '*.cdis.cn')): with self.assertRaisesRegex(RuntimeError, '泛域名证书必须使用 DNS 验证'): renew.challenge_arguments() diff --git a/test/deployment/test_domain_acceptance.py b/test/deployment/test_domain_acceptance.py index 69657d9..540e582 100644 --- a/test/deployment/test_domain_acceptance.py +++ b/test/deployment/test_domain_acceptance.py @@ -12,15 +12,15 @@ RENEWAL = (ROOT / 'deploy/nginx/renew_certificate.py').read_text(encoding='utf-8 class DomainAcceptanceTest(unittest.TestCase): def test_web_domain_is_the_only_public_web_proxy(self): - self.assertIn('server_name web.solit.cn;', NGINX) - self.assertIn('proxy_ssl_name web.solit.cn;', NGINX) - self.assertIn('return 308 https://web.solit.cn$request_uri;', NGINX) - self.assertNotIn('return 308 https://mail.solit.cn$request_uri;', NGINX) + self.assertIn('server_name __SMAIL_WEB_DOMAIN__;', NGINX) + self.assertIn('proxy_ssl_name __SMAIL_WEB_DOMAIN__;', NGINX) + self.assertIn('return 308 https://__SMAIL_WEB_DOMAIN__$request_uri;', NGINX) + self.assertNotIn('return 308 https://__SMAIL_MAIL_DOMAIN__$request_uri;', NGINX) def test_certificate_requests_root_and_wildcard(self): - self.assertIn("DOMAINS = ('solit.cn', '*.solit.cn')", CERTIFICATE) - self.assertIn("CERTIFICATE_SNI = 'web.solit.cn'", CERTIFICATE) - self.assertIn("'web.solit.cn'", CERTIFICATE) + self.assertIn("DOMAINS = ('cdis.cn', '*.cdis.cn')", CERTIFICATE) + self.assertIn("CERTIFICATE_SNI = 'web.cdis.cn'", CERTIFICATE) + self.assertIn("'web.cdis.cn'", CERTIFICATE) self.assertIn('DOMAINS = deploy.DOMAINS', RENEWAL) diff --git a/test/deployment/test_nginx_redirect_acceptance.py b/test/deployment/test_nginx_redirect_acceptance.py index 7517790..c7783dc 100644 --- a/test/deployment/test_nginx_redirect_acceptance.py +++ b/test/deployment/test_nginx_redirect_acceptance.py @@ -11,7 +11,7 @@ import verify_nginx_tls as verify class RedirectAcceptanceTest(unittest.TestCase): - expected = 'https://web.solit.cn/acceptance?x=1' + expected = 'https://web.cdis.cn/acceptance?x=1' def check(self, first, second): results = {'checks': []} @@ -29,12 +29,12 @@ class RedirectAcceptanceTest(unittest.TestCase): self.assertEqual(self.check(self.response(), self.response()), []) def test_internal_https_port_is_failure(self): - failures = self.check(self.response(), self.response('https://web.solit.cn:8002/acceptance?x=1')) + failures = self.check(self.response(), self.response('https://web.cdis.cn:8002/acceptance?x=1')) self.assertEqual(len(failures), 1) self.assertEqual(failures[0]['port'], 8001) def test_public_port_does_not_skip_validation(self): - failures = self.check(self.response('http://web.solit.cn/acceptance?x=1'), self.response()) + failures = self.check(self.response('http://web.cdis.cn/acceptance?x=1'), self.response()) self.assertEqual([item['port'] for item in failures], [80]) def test_missing_location_records_failure(self): @@ -46,7 +46,7 @@ class RedirectAcceptanceTest(unittest.TestCase): self.assertEqual(failures[0]['actualStatus'], 200) def test_path_and_query_must_be_preserved(self): - for location in ('https://web.solit.cn/', 'https://web.solit.cn/acceptance', + for location in ('https://web.cdis.cn/', 'https://web.cdis.cn/acceptance', 'https://other.invalid/acceptance?x=1'): with self.subTest(location=location): self.assertTrue(self.check(self.response(), self.response(location))) diff --git a/test/deployment/verify_nginx_tls.py b/test/deployment/verify_nginx_tls.py index 1e2feab..f368591 100644 --- a/test/deployment/verify_nginx_tls.py +++ b/test/deployment/verify_nginx_tls.py @@ -11,7 +11,7 @@ import ssl import subprocess -HOST = 'web.solit.cn' +HOST = 'web.cdis.cn' CONTEXT = ssl.create_default_context() @@ -47,9 +47,9 @@ def main(): leaf = subprocess.run(['openssl', 'x509', '-in', '/opt/smail/ssl/custom.crt', '-outform', 'DER'], check=True, capture_output=True).stdout expected = hashlib.sha256(leaf).hexdigest() - for port, host in [(443, HOST), (443, 'solit.cn'), (443, 'mail.solit.cn'), - (8002, HOST), (465, 'smtp.solit.cn'), - (993, 'imap.solit.cn'), (995, 'pop.solit.cn')]: + for port, host in [(443, HOST), (443, 'cdis.cn'), (443, 'mail.cdis.cn'), + (8002, HOST), (465, 'smtp.cdis.cn'), + (993, 'imap.cdis.cn'), (995, 'pop.cdis.cn')]: with socket.create_connection(('127.0.0.1', port), timeout=10) as raw: with CONTEXT.wrap_socket(raw, server_hostname=host) as stream: actual = hashlib.sha256(stream.getpeercert(binary_form=True)).hexdigest() @@ -59,7 +59,7 @@ def main(): for port in (25, 587): with smtplib.SMTP(timeout=10) as client: assert client.connect('127.0.0.1', port)[0] == 220 - client._host = 'smtp.solit.cn' + client._host = 'smtp.cdis.cn' assert client.ehlo('localhost')[0] == 250 assert not client.has_extn('auth'), 'plaintext AUTH advertised' assert client.has_extn('starttls') @@ -87,7 +87,7 @@ def main(): raise AssertionError('unknown SNI accepted') root = json.loads(Path('/opt/smail/config/config.json').read_text()) assert root['http']['port'] == 8001 and root['http']['httpsPort'] == 8002 - assert root['security']['webAuthnRpOrigins'] == ['https://web.solit.cn'] + assert root['security']['webAuthnRpOrigins'] == ['https://web.cdis.cn'] results['fingerprintSHA256'] = expected results['status'] = 'failed' if results['failures'] else 'passed' print(json.dumps(results, ensure_ascii=False, indent=2)) diff --git a/test/deployment/webroot_renewal_drill.py b/test/deployment/webroot_renewal_drill.py index 123d3d9..7f1497f 100644 --- a/test/deployment/webroot_renewal_drill.py +++ b/test/deployment/webroot_renewal_drill.py @@ -42,7 +42,7 @@ 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: + if '*.cdis.cn' in renew.DOMAINS: parser.error('当前泛域名证书必须使用 DNS-01,不能执行 HTTP-01 演练') if file_state(CONFIG)['sha256'] != CONFIG_SHA: parser.error('Nginx 配置与已审查模板不符,停止演练') @@ -80,7 +80,7 @@ def main(): Path('/usr/local/libexec/smail-acme/deploy_certificate.py'), Path('/etc/systemd/system/smail-certificate-renew.service')] protected.extend(sorted(Path('/etc/nginx/conf.d').glob('*.conf'))) - protected.extend(sorted(Path('/var/lib/smail-acme-tls/certificates').glob('solit.cn.*'))) + protected.extend(sorted(Path('/var/lib/smail-acme-tls/certificates').glob('cdis.cn.*'))) before = {str(path): file_state(path) for path in protected} before_services = service_state() challenge_dir = renew.WEBROOT / '.well-known/acme-challenge' @@ -92,7 +92,7 @@ def main(): stop = threading.Event() def sample(): - for host in ('mail.solit.cn', 'web.apmmk.cn'): + for host in ('mail.cdis.cn', 'web.cdis.cn'): value = {'host': host, 'timeUTC': datetime.now(timezone.utc).isoformat()} try: value['bytes'] = len(monitor.request(host, 443)) @@ -135,8 +135,8 @@ def main(): result = subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, timeout=630) report['exitCode'] = result.returncode assert result.returncode == 0, '全新 HTTP 挑战失败,日志已保留' - certificate = state / 'certificates/solit.cn.crt' - key = state / 'certificates/solit.cn.key' + certificate = state / 'certificates/cdis.cn.crt' + key = state / 'certificates/cdis.cn.key' public_cert = run('openssl', 'x509', '-in', str(certificate), '-pubkey', '-noout') public_key = run('openssl', 'pkey', '-in', str(key), '-pubout') assert public_cert == public_key