]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/cephadm: allow configuring anonymous access for grafana 51617/head
authorAdam King <adking@redhat.com>
Tue, 21 Mar 2023 18:12:03 +0000 (14:12 -0400)
committerAdam King <adking@redhat.com>
Thu, 25 May 2023 15:39:34 +0000 (11:39 -0400)
In case users want to not allow anonymous viewers
to view the grafana dashboard but don't want to use
a full custom config

Fixes: https://tracker.ceph.com/issues/59117
Signed-off-by: Adam King <adking@redhat.com>
(cherry picked from commit e6690dde7b384d7d13e1a17119c648acfadee638)

doc/cephadm/services/monitoring.rst
src/pybind/mgr/cephadm/services/monitoring.py
src/pybind/mgr/cephadm/templates/services/grafana/grafana.ini.j2
src/pybind/mgr/cephadm/tests/test_services.py
src/pybind/mgr/cephadm/tests/test_spec.py
src/python-common/ceph/deployment/service_spec.py
src/python-common/ceph/tests/test_service_spec.py

index f7a6e19abbcdb835f0c40ea95be476513cb1364d..3cbc8b594f0933529f911b0f7f660863a575f5df 100644 (file)
@@ -458,6 +458,28 @@ Then apply this specification:
 Grafana will now create an admin user called ``admin`` with the
 given password.
 
+Turning off anonymous access
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, cephadm allows anonymous users (users who have not provided any
+login information) limited, viewer only access to the grafana dashboard. In
+order to set up grafana to only allow viewing from logged in users, you can
+set ``anonymous_access: False`` in your grafana spec.
+
+.. code-block:: yaml
+
+  service_type: grafana
+  placement:
+    hosts:
+    - host1
+  spec:
+    anonymous_access: False
+    initial_admin_password: "mypassword"
+
+Since deploying grafana with anonymous access set to false without an initial
+admin password set would make the dashboard inaccessible, cephadm requires
+setting the ``initial_admin_password`` when ``anonymous_access`` is set to false.
+
 
 Setting up Alertmanager
 -----------------------
index 37c44a8304e6c3d6c9b96f955ba7cd56ea8d34fe..2a707f4de9461317e798baf2b63a1e5f3bbde7a4 100644 (file)
@@ -77,6 +77,7 @@ class GrafanaService(CephadmService):
             GrafanaSpec, self.mgr.spec_store.active_specs[daemon_spec.service_name])
         grafana_ini = self.mgr.template.render(
             'services/grafana/grafana.ini.j2', {
+                'anonymous_access': spec.anonymous_access,
                 'initial_admin_password': spec.initial_admin_password,
                 'http_port': daemon_spec.ports[0] if daemon_spec.ports else self.DEFAULT_SERVICE_PORT,
                 'http_addr': daemon_spec.ip if daemon_spec.ip else ''
index e7e81d89a4b6f682a471e442a04dfee69e83d8ee..05c5b33ce6c344fc4a9f39e03b142333057fe93e 100644 (file)
@@ -1,10 +1,12 @@
 # {{ cephadm_managed }}
 [users]
   default_theme = light
+{% if anonymous_access %}
 [auth.anonymous]
   enabled = true
   org_name = 'Main Org.'
   org_role = 'Viewer'
+{% endif %}
 [server]
   domain = 'bootstrap.storage.lab'
   protocol = https
index 978d980995c0fffdc64d61f9f8bd47e1350a050d..c10b394be393edea4611fa97500ad07225544299 100644 (file)
@@ -729,6 +729,56 @@ class TestMonitoring:
                                 'certs/cert_file': ANY,
                                 'certs/cert_key': ANY}}, [])
 
+    @patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}'))
+    def test_grafana_no_anon_access(self, cephadm_module: CephadmOrchestrator):
+        # with anonymous_access set to False, expecting the [auth.anonymous] section
+        # to not be present in the grafana config. Note that we require an initial_admin_password
+        # to be provided when anonymous_access is False
+        with with_host(cephadm_module, 'test'):
+            with with_service(cephadm_module, ServiceSpec('mgr')) as _, \
+                    with_service(cephadm_module, GrafanaSpec(anonymous_access=False, initial_admin_password='secure')):
+                out = cephadm_module.cephadm_services['grafana'].generate_config(
+                    CephadmDaemonDeploySpec('test', 'daemon', 'grafana'))
+                assert out == (
+                    {
+                        'files':
+                            {
+                                'grafana.ini':
+                                    '# This file is generated by cephadm.\n'
+                                    '[users]\n'
+                                    '  default_theme = light\n'
+                                    '[server]\n'
+                                    "  domain = 'bootstrap.storage.lab'\n"
+                                    '  protocol = https\n'
+                                    '  cert_file = /etc/grafana/certs/cert_file\n'
+                                    '  cert_key = /etc/grafana/certs/cert_key\n'
+                                    '  http_port = 3000\n'
+                                    '  http_addr = \n'
+                                    '[snapshots]\n'
+                                    '  external_enabled = false\n'
+                                    '[security]\n'
+                                    '  admin_user = admin\n'
+                                    '  admin_password = secure\n'
+                                    '  cookie_secure = true\n'
+                                    '  cookie_samesite = none\n'
+                                    '  allow_embedding = true',
+                                'provisioning/datasources/ceph-dashboard.yml':
+                                    "# This file is generated by cephadm.\n"
+                                    'deleteDatasources:\n\n'
+                                    "  - name: 'Loki'\n"
+                                    '    orgId: 2\n\n'
+                                    'datasources:\n\n'
+                                    "  - name: 'Loki'\n"
+                                    "    type: 'loki'\n"
+                                    "    access: 'proxy'\n"
+                                    '    orgId: 2\n'
+                                    "    url: ''\n"
+                                    '    basicAuth: false\n'
+                                    '    isDefault: true\n'
+                                    '    editable: false',
+                                'certs/cert_file': ANY,
+                                'certs/cert_key': ANY}}, [])
+
     @patch("cephadm.serve.CephadmServe._run_cephadm")
     def test_monitoring_ports(self, _run_cephadm, cephadm_module: CephadmOrchestrator):
         _run_cephadm.side_effect = async_side_effect(('{}', '', 0))
index c89d3b6c1ca6443f60737a26ecaae8e53e1293b9..c1125f698a5b63da394db7d2dba195a72913235c 100644 (file)
@@ -116,6 +116,7 @@ def test_spec_octopus(spec_json):
                 ]
         j_c.pop('objectstore', None)
         j_c.pop('filter_logic', None)
+        j_c.pop('anonymous_access', None)
         return j_c
 
     assert spec_json == convert_to_old_style_json(spec.to_json())
index 0eefc0f11d3ff4d604a2f33a2e2be80f3d4711e2..7556d788a27e7a959c3d4639e6a45a430adfa109 100644 (file)
@@ -1283,6 +1283,7 @@ class GrafanaSpec(MonitoringSpec):
                  networks: Optional[List[str]] = None,
                  port: Optional[int] = None,
                  initial_admin_password: Optional[str] = None,
+                 anonymous_access: Optional[bool] = True,
                  extra_container_args: Optional[List[str]] = None,
                  extra_entrypoint_args: Optional[List[str]] = None,
                  custom_configs: Optional[List[CustomConfig]] = None,
@@ -1296,6 +1297,13 @@ class GrafanaSpec(MonitoringSpec):
             custom_configs=custom_configs)
 
         self.initial_admin_password = initial_admin_password
+        self.anonymous_access = anonymous_access
+
+        if not self.anonymous_access and not self.initial_admin_password:
+            err_msg = ('Either initial_admin_password must be set or anonymous_access '
+                       'must be set to true. Otherwise the grafana dashboard will '
+                       'be inaccessible.')
+            raise SpecValidationError(err_msg)
 
 
 yaml.add_representer(GrafanaSpec, ServiceSpec.yaml_representer)
index 28dc1680f0f0c8d4069955568f7178e22d122d7f..3531b01edf1daa3b326fd120734a68b6dc399a60 100644 (file)
@@ -43,9 +43,6 @@ def test_parse_host_placement_specs(test_input, expected, require_network):
 
     assert ret == HostPlacementSpec.from_json(ret.to_json())
 
-
-
-
 @pytest.mark.parametrize(
     "test_input,expected",
     [
@@ -249,11 +246,13 @@ spec:
 service_type: grafana
 service_name: grafana
 spec:
+  anonymous_access: true
   port: 1234
 ---
 service_type: grafana
 service_name: grafana
 spec:
+  anonymous_access: true
   initial_admin_password: secure
   port: 1234
 ---