mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 19:56:53 +00:00
Of the 76 open code scanning alerts, 39 point at code that can change. svc-ai-mcp-adapter: - A path argument that is empty or made only of dots is refused. Percent-encoding keeps a separator inside its segment, but "." and ".." need none, so an upstream that resolves dot segments could answer from a path the contract does not name. - parse_duration splits on the units. The pattern it used before rescanned a long run of digits from every start position. Tests and the README generators: - Every Jinja environment built with autoescape=False and a "noqa: S701" uses select_autoescape now, as six test modules and utils/templating/jinja.py already did. It escapes templates named *.html, *.htm and *.xml, which none of these call sites loads. - Dead code goes: a doubled "rel" block in the email lint, an unread _SKIP_DIRS, and a module that _resolve returned to no caller. - Two "except ...: pass" blocks become contextlib.suppress and assertRaises. - Nine test modules import unittest.mock one way instead of two, and one lookup test imports its module once. Closes #807 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
112 lines
3.9 KiB
Python
112 lines
3.9 KiB
Python
"""Whether GitLab announces SMTP AUTH, and on which listener.
|
|
|
|
Ruby's ``net/smtp`` authenticates whenever a ``user_name`` or ``password`` is
|
|
present, falling back to its default auth type — ``authentication: nil`` does
|
|
NOT switch it off. So on the provider's SSO relay, where port 25 offers no
|
|
AUTH at all, leaving the credentials in the hash makes every send die with
|
|
``503 5.5.1 AUTH not allowed`` while GitLab still reports the mail as queued.
|
|
The credentials therefore have to be omitted, not merely unaccompanied by an
|
|
auth type.
|
|
|
|
``tls`` and ``enable_starttls_auto`` are the other half: they are mutually
|
|
exclusive in ActionMailer, implicit TLS on 465 or STARTTLS on the relay.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import unittest
|
|
|
|
from jinja2 import Environment, StrictUndefined, select_autoescape
|
|
|
|
from utils.cache.files import read_text
|
|
|
|
from . import PROJECT_ROOT
|
|
|
|
TEMPLATE = (
|
|
PROJECT_ROOT
|
|
/ "roles"
|
|
/ "web-app-gitlab"
|
|
/ "templates"
|
|
/ "config"
|
|
/ "smtp_settings.rb.j2"
|
|
)
|
|
|
|
RELAY = {
|
|
"host": "mail.infinito.test",
|
|
"port": 25,
|
|
"username": "no-reply@infinito.test",
|
|
"password": "s3cr3t",
|
|
"domain": "infinito.test",
|
|
"auth": False,
|
|
"start_tls": True,
|
|
"tls": False,
|
|
}
|
|
SUBMISSION = dict(RELAY, port=465, auth=True, start_tls=False, tls=True)
|
|
|
|
|
|
def _render(email: dict, ca_file: str = "") -> str:
|
|
env = Environment(
|
|
trim_blocks=True,
|
|
lstrip_blocks=True,
|
|
undefined=StrictUndefined,
|
|
autoescape=select_autoescape(default_for_string=False),
|
|
)
|
|
env.filters["bool"] = bool
|
|
env.filters["ruby_dq"] = lambda value: '"' + str(value).replace('"', '\\"') + '"'
|
|
return env.from_string(read_text(TEMPLATE)).render(
|
|
GITLAB_EMAIL=email,
|
|
GITLAB_EMAIL_CA_FILE=ca_file,
|
|
)
|
|
|
|
|
|
class TestGitlabSmtpSettings(unittest.TestCase):
|
|
def test_verification_is_never_weakened(self):
|
|
"""An onion relay is handled by turning start_tls off in the email
|
|
lookup, not by telling Net::SMTP to skip peer verification."""
|
|
self.assertNotIn("openssl_verify_mode", _render(RELAY))
|
|
|
|
def test_our_own_ca_is_trusted_where_it_is_mounted(self):
|
|
rendered = _render(RELAY, ca_file="/tmp/infinito/ca/root-ca.crt")
|
|
self.assertIn('ca_file: "/tmp/infinito/ca/root-ca.crt"', rendered)
|
|
|
|
def test_without_our_ca_no_trust_store_override_is_emitted(self):
|
|
self.assertNotIn("ca_file", _render(RELAY))
|
|
|
|
def test_the_relay_carries_no_credentials_at_all(self):
|
|
rendered = _render(RELAY)
|
|
self.assertNotIn("user_name", rendered)
|
|
self.assertNotIn("password", rendered)
|
|
self.assertNotIn("s3cr3t", rendered)
|
|
|
|
def test_the_relay_announces_no_auth_type(self):
|
|
self.assertNotIn("authentication", _render(RELAY))
|
|
|
|
def test_authenticated_submission_still_sends_credentials(self):
|
|
rendered = _render(SUBMISSION)
|
|
self.assertIn('user_name: "no-reply@infinito.test"', rendered)
|
|
self.assertIn("authentication: :login", rendered)
|
|
|
|
def test_tls_and_starttls_are_never_both_on(self):
|
|
for email in (RELAY, SUBMISSION):
|
|
rendered = _render(email)
|
|
tls = re.search(r"^\s*tls:\s*(\w+)", rendered, re.MULTILINE).group(1)
|
|
starttls = re.search(
|
|
r"^\s*enable_starttls_auto:\s*(\w+)", rendered, re.MULTILINE
|
|
).group(1)
|
|
self.assertNotEqual((tls, starttls), ("true", "true"))
|
|
|
|
def test_the_relay_uses_starttls_and_the_submission_port_implicit_tls(self):
|
|
self.assertIn("enable_starttls_auto: true", _render(RELAY))
|
|
self.assertIn("tls: false", _render(RELAY))
|
|
self.assertIn("tls: true", _render(SUBMISSION))
|
|
|
|
def test_the_hash_stays_syntactically_valid_without_credentials(self):
|
|
rendered = _render(RELAY).strip()
|
|
self.assertTrue(rendered.endswith("}"))
|
|
self.assertNotIn(",\n}", rendered)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|