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
-----------------------
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,
'protocol': spec.protocol,
# {{ 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 = {{ protocol }}
'certs/cert_file': ANY,
'certs/cert_key': ANY}}, ['secure_monitoring_stack:False'])
+ @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"
+ "apiVersion: 1\n\n"
+ 'deleteDatasources:\n\n'
+ 'datasources:\n\n'
+ " - name: 'Loki'\n"
+ " type: 'loki'\n"
+ " access: 'proxy'\n"
+ " url: ''\n"
+ ' basicAuth: false\n'
+ ' isDefault: false\n'
+ ' editable: false',
+ 'certs/cert_file': ANY,
+ 'certs/cert_key': ANY}}, ['secure_monitoring_stack:False'])
+
@patch("cephadm.serve.CephadmServe._run_cephadm")
def test_monitoring_ports(self, _run_cephadm, cephadm_module: CephadmOrchestrator):
_run_cephadm.side_effect = async_side_effect(('{}', '', 0))
]
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())
port: Optional[int] = None,
protocol: Optional[str] = 'https',
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,
custom_configs=custom_configs)
self.initial_admin_password = initial_admin_password
+ self.anonymous_access = anonymous_access
self.protocol = protocol
def validate(self) -> None:
err_msg = f"Invalid protocol '{self.protocol}'. Valid values are: 'http', 'https'."
raise SpecValidationError(err_msg)
+ 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)
(GrafanaSpec(protocol='-https'), True, '^Invalid protocol'),
(GrafanaSpec(protocol='http'), False, ''),
(GrafanaSpec(protocol='https'), False, ''),
+ (GrafanaSpec(anonymous_access=False), True, '^Either initial'), # we require inital_admin_password if anonymous_access is False
+ (GrafanaSpec(anonymous_access=False, initial_admin_password='test'), False, ''),
])
def test_apply_grafana(spec: GrafanaSpec, raise_exception: bool, msg: str):
if raise_exception:
service_type: grafana
service_name: grafana
spec:
+ anonymous_access: true
port: 1234
protocol: https
---
service_type: grafana
service_name: grafana
spec:
+ anonymous_access: true
initial_admin_password: secure
port: 1234
protocol: https