Add Prometheus TLS support
This implements support for connecting to Prometheus with TLS. Because we now have 4 prometheus related config options, I moved them all under a new config group called 'prometheus'. Cursor was used to generate first version of the unit tests. I then went through them and manually adjusted them as needed. Assisted-By: Cursor with claude-4-sonnet model Change-Id: Ia859551e7e403eba09117e77d747652f5aa38e8f Signed-off-by: Jaromir Wysoglad <jwysogla@redhat.com>
This commit is contained in:
@@ -19,19 +19,32 @@ from wsme import exc
|
||||
from observabilityclient import prometheus_client
|
||||
from observabilityclient import rbac as obsc_rbac
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_utils import netutils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
OPTS = [
|
||||
|
||||
PROMETHEUS_OPTS = [
|
||||
cfg.StrOpt(
|
||||
'prometheus_host',
|
||||
'host',
|
||||
default="localhost",
|
||||
help="The host of Prometheus"),
|
||||
cfg.PortOpt(
|
||||
'prometheus_port',
|
||||
'port',
|
||||
default=9090,
|
||||
help="The port of Prometheus"),
|
||||
# TODO(jwysogla): TLS Prometheus options
|
||||
cfg.StrOpt(
|
||||
'ca_file',
|
||||
help="Path to a CA cert for establishing TLS connections to "
|
||||
"Prometheus. This is optional, if this isn't set, then "
|
||||
"default system CA certificates will be used."
|
||||
),
|
||||
cfg.BoolOpt(
|
||||
'use_tls',
|
||||
default=False,
|
||||
help="Whether TLS should be used when connecting to Prometheus."
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
@@ -42,11 +55,28 @@ class ServerSideError(exc.ClientSideError):
|
||||
|
||||
class Base(rest.RestController):
|
||||
def create_prometheus_client(self, conf):
|
||||
# TODO(jwysogla): Handle TLS
|
||||
prometheus_host = netutils.escape_ipv6(conf.prometheus_host)
|
||||
prometheus_port = conf.prometheus_port
|
||||
url = f"{prometheus_host}:{prometheus_port}"
|
||||
host = netutils.escape_ipv6(conf.prometheus.host)
|
||||
port = conf.prometheus.port
|
||||
ca_file = conf.prometheus.ca_file
|
||||
use_tls = conf.prometheus.use_tls
|
||||
|
||||
if ca_file and not use_tls:
|
||||
LOG.warning("CA file specified but TLS disabled - "
|
||||
"CA file will be ignored")
|
||||
|
||||
url = f"{host}:{port}"
|
||||
self.prometheus_client = prometheus_client.PrometheusAPIClient(url)
|
||||
|
||||
if use_tls:
|
||||
if ca_file:
|
||||
LOG.debug("TLS for Prometheus connection enabled with CA "
|
||||
"file: %s", ca_file)
|
||||
self.prometheus_client.set_ca_cert(ca_file)
|
||||
else:
|
||||
LOG.debug("TLS for Prometheus connection enabled with system "
|
||||
"default CA certificates")
|
||||
self.prometheus_client.set_ca_cert(True)
|
||||
|
||||
super(object, self).__init__()
|
||||
|
||||
def process_matches(self, matches, privileged, project_id):
|
||||
|
@@ -36,6 +36,7 @@ OPTS = [
|
||||
def list_opts():
|
||||
return [
|
||||
('DEFAULT',
|
||||
itertools.chain(OPTS,
|
||||
aetos.controllers.api.v1.base.OPTS)),
|
||||
itertools.chain(OPTS)),
|
||||
('prometheus',
|
||||
itertools.chain(aetos.controllers.api.v1.base.PROMETHEUS_OPTS)),
|
||||
]
|
||||
|
0
aetos/tests/unit/__init__.py
Normal file
0
aetos/tests/unit/__init__.py
Normal file
85
aetos/tests/unit/test_base_controller.py
Normal file
85
aetos/tests/unit/test_base_controller.py
Normal file
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# Copyright 2025 Red Hat, Inc
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import fixture as fixture_config
|
||||
|
||||
from aetos.controllers.api.v1 import base
|
||||
from aetos.tests import base as test_base
|
||||
|
||||
|
||||
class TestBaseController(test_base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.controller = base.Base()
|
||||
self.conf = self.useFixture(fixture_config.Config()).conf
|
||||
self.conf.register_opts(base.PROMETHEUS_OPTS, group='prometheus')
|
||||
|
||||
def test_create_prometheus_client_without_tls(self):
|
||||
"""Test prometheus client creation without TLS"""
|
||||
with mock.patch(
|
||||
'observabilityclient.prometheus_client.PrometheusAPIClient'
|
||||
) as mock_client:
|
||||
self.controller.create_prometheus_client(self.conf)
|
||||
|
||||
mock_client.assert_called_once_with('localhost:9090')
|
||||
# Verify set_ca_cert was not called
|
||||
mock_client.return_value.set_ca_cert.assert_not_called()
|
||||
|
||||
def test_create_prometheus_client_with_tls_custom_ca(self):
|
||||
"""Test prometheus client creation with TLS with custom CA"""
|
||||
# Create a temporary CA file
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.pem',
|
||||
delete=False) as f:
|
||||
cert_content = ("-----BEGIN CERTIFICATE-----\n"
|
||||
"test_ca_content\n"
|
||||
"-----END CERTIFICATE-----")
|
||||
f.write(cert_content)
|
||||
ca_file_path = f.name
|
||||
|
||||
try:
|
||||
self.conf.set_override('ca_file', ca_file_path, group='prometheus')
|
||||
self.conf.set_override('use_tls', True, group='prometheus')
|
||||
|
||||
with mock.patch(
|
||||
'observabilityclient.prometheus_client.PrometheusAPIClient'
|
||||
) as mock_client:
|
||||
self.controller.create_prometheus_client(self.conf)
|
||||
|
||||
mock_client.assert_called_once_with('localhost:9090')
|
||||
|
||||
# Verify set_ca_cert was called with the correct file path
|
||||
mock_client.return_value.set_ca_cert.assert_called_once_with(
|
||||
ca_file_path)
|
||||
finally:
|
||||
os.unlink(ca_file_path)
|
||||
|
||||
def test_create_prometheus_client_with_tls_default_ca(self):
|
||||
"""Test prometheus client creation with TLS with default CA"""
|
||||
self.conf.set_override('use_tls', True, group='prometheus')
|
||||
|
||||
with mock.patch(
|
||||
'observabilityclient.prometheus_client.PrometheusAPIClient'
|
||||
) as mock_client:
|
||||
self.controller.create_prometheus_client(self.conf)
|
||||
|
||||
mock_client.assert_called_once_with('localhost:9090')
|
||||
|
||||
# Verify set_ca_cert was called with True
|
||||
mock_client.return_value.set_ca_cert.assert_called_once_with(True)
|
@@ -1,13 +1,13 @@
|
||||
2. Edit the ``/etc/aetos/aetos.conf`` file and complete the following
|
||||
actions:
|
||||
|
||||
* In the ``[DEFAULT]`` section, configure prometheus access:
|
||||
* In the ``[prometheus]`` section, configure prometheus access:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[DEFAULT]
|
||||
prometheus_host=localhost
|
||||
prometheus_port=9090
|
||||
[prometheus]
|
||||
host=localhost
|
||||
port=9090
|
||||
|
||||
* In the ``[DEFAULT]`` and ``[keystone_authtoken]`` sections,
|
||||
configure Identity service access:
|
||||
|
Reference in New Issue
Block a user