From 66026dfcfe6cb329868e5271f44825531fe87b62 Mon Sep 17 00:00:00 2001 From: coperni Date: Fri, 9 Sep 2022 09:30:16 -0400 Subject: [PATCH] Add Monitoring.http_address to expose Prometheus stats server (#993) * Allow stats server to listen on TCP port This commit allows the stats server to bind to the port for outside network sources to use (Kubernetes Service). * Add configuration item to bind monitoring address PR revision: Instead of exposing the monitoring address we opt to have users indicate via configuration option `Monitoring.http_address` the server address to bind to. --- CHANGELOG | 2 ++ grr/core/grr_response_core/config/logging.py | 5 ++++- grr/server/grr_response_server/base_stats_server.py | 4 +++- grr/server/grr_response_server/stats_server.py | 13 ++++++++----- grr/server/grr_response_server/stats_server_test.py | 4 ++-- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 80678432c0..5663dbc4d4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,8 @@ * Introduced Server.grr_binaries_readonly configuration option (set to False by default). When set to True, binaries and python hacks can't be overriden or deleted. +* Added configuration option Monitoring.http_address to specify server address + of stats server. Default value will remain 127.0.0.1. ## 3.4.3.1 diff --git a/grr/core/grr_response_core/config/logging.py b/grr/core/grr_response_core/config/logging.py index 18318a75ba..18940bd274 100644 --- a/grr/core/grr_response_core/config/logging.py +++ b/grr/core/grr_response_core/config/logging.py @@ -48,8 +48,11 @@ description="The email address to notify in an emergency.", default="grr-emergency@localhost")) +config_lib.DEFINE_string("Monitoring.http_address", "::1", + "IP address for stats monitoring server.") + config_lib.DEFINE_integer("Monitoring.http_port", 0, - "Port for stats monitoring server.") + "Port for stats monitoring server.") config_lib.DEFINE_integer( "Monitoring.http_port_max", None, diff --git a/grr/server/grr_response_server/base_stats_server.py b/grr/server/grr_response_server/base_stats_server.py index 17a5454fc2..0a22eb1643 100644 --- a/grr/server/grr_response_server/base_stats_server.py +++ b/grr/server/grr_response_server/base_stats_server.py @@ -28,12 +28,14 @@ class BaseStatsServer(metaclass=abc.ABCMeta): port: The TCP port that the server should listen to. """ - def __init__(self, port): + def __init__(self, address, port): """Instantiates a new BaseStatsServer. Args: + address: The IP address of the server to bind. port: The TCP port that the server should listen to. """ + self.address = address self.port = port @abc.abstractmethod diff --git a/grr/server/grr_response_server/stats_server.py b/grr/server/grr_response_server/stats_server.py index 7c95f2b27a..7319c18c57 100644 --- a/grr/server/grr_response_server/stats_server.py +++ b/grr/server/grr_response_server/stats_server.py @@ -31,20 +31,21 @@ class IPv6HTTPServer(http_server.HTTPServer): class StatsServer(base_stats_server.BaseStatsServer): """A statistics server that exposes a minimal, custom /varz route.""" - def __init__(self, port): + def __init__(self, address, port): """Instantiates a new StatsServer. Args: + address: The IP address of the server to bind. port: The TCP port that the server should listen to. """ - super().__init__(port) + super().__init__(address, port) self._http_server = None self._server_thread = None def Start(self): """Start HTTPServer.""" try: - self._http_server = IPv6HTTPServer(("::1", self.port), StatsServerHandler) + self._http_server = IPv6HTTPServer((self.address, self.port), StatsServerHandler) except socket.error as e: if e.errno == errno.EADDRINUSE: raise base_stats_server.PortInUseError(self.port) @@ -72,6 +73,8 @@ def InitializeStatsServerOnce(): a default one. """ + address = config.CONFIG["Monitoring.http_address"] + # Figure out which port to use. port = config.CONFIG["Monitoring.http_port"] if not port: @@ -99,8 +102,8 @@ def InitializeStatsServerOnce(): for port in range(port, max_port + 1): try: - logging.info("Starting monitoring server on port %d.", port) - server_obj = server_cls(port) + logging.info("Starting monitoring server on address %s and port %d.", address, port) + server_obj = server_cls(address, port) server_obj.Start() return except base_stats_server.PortInUseError as e: diff --git a/grr/server/grr_response_server/stats_server_test.py b/grr/server/grr_response_server/stats_server_test.py index c44ef64130..65192a148f 100644 --- a/grr/server/grr_response_server/stats_server_test.py +++ b/grr/server/grr_response_server/stats_server_test.py @@ -23,7 +23,7 @@ class StatsServerTest(base_stats_server_test.StatsServerTestMixin, test_lib.GRRBaseTest): def setUpStatsServer(self, port): - return stats_server.StatsServer(port) + return stats_server.StatsServer("::1", port) def testPrometheusIntegration(self): registry = prometheus_client.CollectorRegistry(auto_describe=True) @@ -38,7 +38,7 @@ def testPrometheusIntegration(self): with mock.patch.object(stats_server.StatsServerHandler, "registry", registry): - server = stats_server.StatsServer(port) + server = stats_server.StatsServer("::1", port) server.Start() self.addCleanup(server.Stop) res = requests.get("http://[::1]:{}/metrics".format(port))