fix(ops): bridge production metrics securely
This commit is contained in:
@@ -37,9 +37,21 @@ scrape_configs:
|
||||
"""
|
||||
|
||||
PROMETHEUS_SNIPPET = """ - job_name: 'ewoooc-app'
|
||||
scheme: http
|
||||
metrics_path: /metrics
|
||||
static_configs:
|
||||
- targets: ['mo.wooo.work']
|
||||
- targets: ['172.20.0.1:9191']
|
||||
"""
|
||||
|
||||
NGINX_BRIDGE = """server {
|
||||
listen 172.20.0.1:9191;
|
||||
server_name ewooooc-metrics.internal;
|
||||
location = /metrics {
|
||||
allow 172.16.0.0/12;
|
||||
deny all;
|
||||
proxy_pass https://192.168.0.188/metrics;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@@ -65,6 +77,16 @@ def test_render_prometheus_config_is_idempotent():
|
||||
assert rendered.count("job_name: 'ewoooc-app'") == 1
|
||||
|
||||
|
||||
def test_render_standalone_nginx_bridge_is_idempotent():
|
||||
from services.metrics_edge_controlled_apply_service import render_nginx_config
|
||||
|
||||
rendered = render_nginx_config("", NGINX_BRIDGE)
|
||||
second = render_nginx_config(rendered, NGINX_BRIDGE)
|
||||
|
||||
assert rendered == second
|
||||
assert rendered.count("listen 172.20.0.1:9191") == 1
|
||||
|
||||
|
||||
def test_build_plan_is_no_write_and_commit_safe(tmp_path: Path):
|
||||
from services.metrics_edge_controlled_apply_service import build_metrics_edge_plan
|
||||
|
||||
@@ -91,6 +113,19 @@ def test_build_plan_is_no_write_and_commit_safe(tmp_path: Path):
|
||||
assert paths["nginx_config"].read_text(encoding="utf-8") == NGINX_CONFIG
|
||||
|
||||
|
||||
def test_prometheus_write_preserves_bind_mount_inode(tmp_path: Path):
|
||||
from services.metrics_edge_controlled_apply_service import _inplace_write
|
||||
|
||||
config = tmp_path / "prometheus.yml"
|
||||
config.write_text(PROMETHEUS_CONFIG, encoding="utf-8")
|
||||
inode_before = config.stat().st_ino
|
||||
|
||||
_inplace_write(config, "global:\n scrape_interval: 30s\n")
|
||||
|
||||
assert config.stat().st_ino == inode_before
|
||||
assert config.read_text(encoding="utf-8") == "global:\n scrape_interval: 30s\n"
|
||||
|
||||
|
||||
def test_render_rejects_incomplete_templates():
|
||||
from services.metrics_edge_controlled_apply_service import (
|
||||
render_nginx_config,
|
||||
|
||||
@@ -28,7 +28,8 @@ def test_metrics_network_classifier_is_deny_by_default():
|
||||
assert is_internal_metrics_request("172.20.0.4") is True
|
||||
assert is_internal_metrics_request("127.0.0.1", "172.20.0.4") is True
|
||||
assert is_internal_metrics_request("127.0.0.1", "203.0.113.10") is False
|
||||
assert is_internal_metrics_request("127.0.0.1", "192.168.0.110") is False
|
||||
assert is_internal_metrics_request("127.0.0.1", "192.168.0.110") is True
|
||||
assert is_internal_metrics_request("127.0.0.1", "192.168.0.111") is False
|
||||
assert is_internal_metrics_request("203.0.113.10", "172.20.0.4") is False
|
||||
assert is_internal_metrics_request("127.0.0.1", "not-an-ip") is False
|
||||
|
||||
@@ -44,37 +45,45 @@ def test_metrics_route_denies_public_and_lan_but_allows_internal_transport():
|
||||
lan = client.get(
|
||||
"/metrics",
|
||||
environ_base={"REMOTE_ADDR": "127.0.0.1"},
|
||||
headers={"X-Real-IP": "192.168.0.110"},
|
||||
headers={"X-Real-IP": "192.168.0.111"},
|
||||
)
|
||||
internal = client.get(
|
||||
"/metrics",
|
||||
environ_base={"REMOTE_ADDR": "127.0.0.1"},
|
||||
headers={"X-Real-IP": "172.20.0.4"},
|
||||
)
|
||||
monitoring = client.get(
|
||||
"/metrics",
|
||||
environ_base={"REMOTE_ADDR": "127.0.0.1"},
|
||||
headers={"X-Real-IP": "192.168.0.110"},
|
||||
)
|
||||
direct = client.get("/metrics", environ_base={"REMOTE_ADDR": "172.18.0.5"})
|
||||
|
||||
assert public.status_code == 404
|
||||
assert public.get_json() == {"error": "not_found"}
|
||||
assert lan.status_code == 404
|
||||
assert internal.status_code == 200
|
||||
assert monitoring.status_code == 200
|
||||
assert direct.status_code == 200
|
||||
|
||||
|
||||
def test_source_owned_edge_and_prometheus_templates_are_closed_by_default():
|
||||
nginx = (ROOT / "monitoring/edge/ewoooc_metrics_nginx_location.conf").read_text(
|
||||
nginx = (ROOT / "monitoring/edge/ewoooc_metrics_nginx_bridge.conf").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
prometheus = (ROOT / "monitoring/edge/ewoooc_prometheus_scrape.yml").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
assert "listen 172.20.0.1:9191;" in nginx
|
||||
assert "location = /metrics" in nginx
|
||||
assert "allow 172.16.0.0/12;" in nginx
|
||||
assert "deny all;" in nginx
|
||||
assert "proxy_pass http://127.0.0.1:5003/metrics;" in nginx
|
||||
assert "proxy_pass https://192.168.0.188/metrics;" in nginx
|
||||
assert "proxy_ssl_verify on;" in nginx
|
||||
assert "job_name: 'ewoooc-app'" in prometheus
|
||||
assert "metrics_path: /metrics" in prometheus
|
||||
assert "targets: ['mo.wooo.work']" in prometheus
|
||||
assert "targets: ['172.20.0.1:9191']" in prometheus
|
||||
|
||||
|
||||
def test_monitoring_compose_has_no_plaintext_admin_password_or_public_prometheus_port():
|
||||
|
||||
Reference in New Issue
Block a user