Skip to content

Commit

Permalink
Issue 2375 - CLI - Healthcheck - revise and add new checks
Browse files Browse the repository at this point in the history
Description:

Add check for

- unauthorized binds are allowed
- Access log buffering is disabled
- Make mapping tree check more robust for case

relates: #2375

Reviewed by: spichugi(Thanks!)
  • Loading branch information
mreynolds389 committed Jun 23, 2023
1 parent 98644dc commit 835f12b
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 28 deletions.
80 changes: 77 additions & 3 deletions dirsrvtests/tests/suites/healthcheck/health_config_test.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2022 Red Hat, Inc.
# Copyright (C) 2023 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
Expand All @@ -11,7 +11,7 @@
import os
import subprocess

from lib389.backend import Backends
from lib389.backend import Backends, DatabaseConfig
from lib389.cos import CosTemplates, CosPointerDefinitions
from lib389.dbgen import dbgen_users
from lib389.idm.account import Accounts
Expand Down Expand Up @@ -112,6 +112,7 @@ def test_healthcheck_logging_format_should_be_revised(topology_st):

log.info('Set nsslapd-logging-hr-timestamps-enabled to off')
standalone.config.set('nsslapd-logging-hr-timestamps-enabled', 'off')
standalone.config.set("nsslapd-accesslog-logbuffering", "on")

run_healthcheck_and_flush_log(topology_st, standalone, json=False, searched_code=RET_CODE)
run_healthcheck_and_flush_log(topology_st, standalone, json=True, searched_code=RET_CODE)
Expand Down Expand Up @@ -359,6 +360,7 @@ def test_healthcheck_low_disk_space(topology_st):
RET_CODE = 'DSDSLE0001'

standalone = topology_st.standalone
standalone.config.set("nsslapd-accesslog-logbuffering", "on")
file = '{}/foo'.format(standalone.ds_paths.log_dir)

log.info('Count the disk space to allocate')
Expand Down Expand Up @@ -406,10 +408,13 @@ def test_healthcheck_notes_unindexed_search(topology_st, setup_ldif):
standalone = topology_st.standalone

log.info('Delete the previous access logs')
topology_st.standalone.deleteAccessLogs()
standalone.deleteAccessLogs()

log.info('Set nsslapd-accesslog-logbuffering to off')
standalone.config.set("nsslapd-accesslog-logbuffering", "off")
db_cfg = DatabaseConfig(standalone)
db_cfg.set([('nsslapd-idlistscanlimit', '100')])


log.info('Stopping the server and running offline import...')
standalone.stop()
Expand All @@ -424,6 +429,8 @@ def test_healthcheck_notes_unindexed_search(topology_st, setup_ldif):
log.info('Check that access log contains "notes=A"')
assert standalone.ds_access_log.match(r'.*notes=A.*')

standalone.config.set("nsslapd-accesslog-logbuffering", "on")

run_healthcheck_and_flush_log(topology_st, standalone, RET_CODE, json=False)
run_healthcheck_and_flush_log(topology_st, standalone, RET_CODE, json=True)

Expand Down Expand Up @@ -459,6 +466,8 @@ def test_healthcheck_notes_unknown_attribute(topology_st, setup_ldif):

log.info('Set nsslapd-accesslog-logbuffering to off')
standalone.config.set("nsslapd-accesslog-logbuffering", "off")
db_cfg = DatabaseConfig(standalone)
db_cfg.set([('nsslapd-idlistscanlimit', '100')])

log.info('Stopping the server and running offline import...')
standalone.stop()
Expand All @@ -473,9 +482,74 @@ def test_healthcheck_notes_unknown_attribute(topology_st, setup_ldif):
log.info('Check that access log contains "notes=F"')
assert standalone.ds_access_log.match(r'.*notes=F.*')

standalone.config.set("nsslapd-accesslog-logbuffering", "on")
run_healthcheck_and_flush_log(topology_st, standalone, RET_CODE, json=False)
run_healthcheck_and_flush_log(topology_st, standalone, RET_CODE, json=True)

def test_healthcheck_unauth_binds(topology_st):
"""Check if HealthCheck returns DSCLE0003 code when unauthorized binds are
allowed
:id: 13b88a3b-0dc5-4ce9-9fbf-058ad072339b
:setup: Standalone instance
:steps:
1. Create DS instance
2. Set nsslapd-allow-unauthenticated-binds to on
3. Use HealthCheck without --json option
4. Use HealthCheck with --json option
:expectedresults:
1. Success
2. Success
3. Healthcheck reports DSCLE0003
4. Healthcheck reports DSCLE0003
"""

RET_CODE = 'DSCLE0003'

inst = topology_st.standalone

log.info('nsslapd-allow-unauthenticated-binds to on')
inst.config.set("nsslapd-allow-unauthenticated-binds", "on")

run_healthcheck_and_flush_log(topology_st, inst, RET_CODE, json=False)
run_healthcheck_and_flush_log(topology_st, inst, RET_CODE, json=True)

# reset setting
log.info('Reset nsslapd-allow-unauthenticated-binds to off')
inst.config.set("nsslapd-allow-unauthenticated-binds", "off")

def test_healthcheck_accesslog_buffering(topology_st):
"""Check if HealthCheck returns DSCLE0004 code when acccess log biffering
is disabled
:id: 5a6512fd-1c7b-4557-9278-45150423148b
:setup: Standalone instance
:steps:
1. Create DS instance
2. Set nsslapd-accesslog-logbuffering to off
3. Use HealthCheck without --json option
4. Use HealthCheck with --json option
:expectedresults:
1. Success
2. Success
3. Healthcheck reports DSCLE0004
4. Healthcheck reports DSCLE0004
"""

RET_CODE = 'DSCLE0004'

inst = topology_st.standalone

log.info('nsslapd-accesslog-logbuffering to off')
inst.config.set("nsslapd-accesslog-logbuffering", "off")

run_healthcheck_and_flush_log(topology_st, inst, RET_CODE, json=False)
run_healthcheck_and_flush_log(topology_st, inst, RET_CODE, json=True)

# reset setting
log.info('Reset nsslapd-accesslog-logbuffering to on')
inst.config.set("nsslapd-accesslog-logbuffering", "on")


if __name__ == '__main__':
# Run isolated
Expand Down
15 changes: 13 additions & 2 deletions dirsrvtests/tests/suites/healthcheck/healthcheck_test.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2020 Red Hat, Inc.
# Copyright (C) 2023 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
Expand Down Expand Up @@ -87,6 +87,7 @@ def test_healthcheck_disabled_suffix(topology_st):
mts = MappingTrees(topology_st.standalone)
mt = mts.get(DEFAULT_SUFFIX)
mt.replace("nsslapd-state", "disabled")
topology_st.standalone.config.set("nsslapd-accesslog-logbuffering", "on")

run_healthcheck_and_flush_log(topology_st, topology_st.standalone, RET_CODE, json=False)
run_healthcheck_and_flush_log(topology_st, topology_st.standalone, RET_CODE, json=True)
Expand Down Expand Up @@ -184,6 +185,8 @@ def test_healthcheck_list_errors(topology_st):
'DSCERTLE0002 :: Certificate expired',
'DSCLE0001 :: Different log timestamp format',
'DSCLE0002 :: Weak passwordStorageScheme',
'DSCLE0003 :: Unauthorized Binds Allowed',
'DSCLE0004 :: Access Log buffering disabled',
'DSCLLE0001 :: Changelog trimming not configured',
'DSDSLE0001 :: Low disk space',
'DSELE0001 :: Weak TLS protocol version',
Expand Down Expand Up @@ -228,6 +231,8 @@ def test_healthcheck_check_option(topology_st):

output_list = ['config:hr_timestamp',
'config:passwordscheme',
# 'config:accesslog_buffering', Skip test access log buffering is disabled
'config:unauth_binds',
'backends:userroot:cl_trimming',
'backends:userroot:mappingtree',
'backends:userroot:search',
Expand All @@ -236,9 +241,11 @@ def test_healthcheck_check_option(topology_st):
'fschecks:file_perms',
'refint:attr_indexes',
'refint:update_delay',
'memberof:member_attr_indexes',
'monitor-disk-space:disk_space',
'replication:agmts_status',
'replication:conflicts',
'replication:no_ruv',
'dseldif:nsstate',
'tls:certificate_expiration',
'logs:notes']
Expand Down Expand Up @@ -306,6 +313,8 @@ def test_healthcheck_replication(topology_m2):
# If we don't set changelog trimming, we will get error DSCLLE0001
set_changelog_trimming(M1)
set_changelog_trimming(M2)
M1.config.set("nsslapd-accesslog-logbuffering", "on")
M2.config.set("nsslapd-accesslog-logbuffering", "on")

log.info('Run healthcheck for supplier1')
run_healthcheck_and_flush_log(topology_m2, M1, CMD_OUTPUT, json=False)
Expand Down Expand Up @@ -345,6 +354,8 @@ def test_healthcheck_replication_tls(topology_m2):
M2.enable_tls()

log.info('Run healthcheck for supplier1')
M1.config.set("nsslapd-accesslog-logbuffering", "on")
M2.config.set("nsslapd-accesslog-logbuffering", "on")
run_healthcheck_and_flush_log(topology_m2, M1, CMD_OUTPUT, json=False)
run_healthcheck_and_flush_log(topology_m2, M1, JSON_OUTPUT, json=True)

Expand Down Expand Up @@ -397,7 +408,7 @@ def test_healthcheck_backend_missing_mapping_tree(topology_st):
mts.create(properties={
'cn': DEFAULT_SUFFIX,
'nsslapd-state': 'backend',
'nsslapd-backend': 'userRoot',
'nsslapd-backend': 'USERROOT',
})

run_healthcheck_and_flush_log(topology_st, standalone, CMD_OUTPUT, json=False)
Expand Down
36 changes: 18 additions & 18 deletions src/cockpit/389-console/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/lib389/lib389/backend.py
Expand Up @@ -498,11 +498,11 @@ def _lint_mappingtree(self):
* missing indices if we are local and have log access?
"""
# Check for the missing mapping tree.
suffix = self.get_attr_val_utf8('nsslapd-suffix')
suffix = self.get_attr_val_utf8_l('nsslapd-suffix')
bename = self.lint_uid()
try:
mt = self._mts.get(suffix)
if mt.get_attr_val_utf8('nsslapd-backend') != bename and mt.get_attr_val_utf8('nsslapd-state') != 'backend':
if mt.get_attr_val_utf8_l('nsslapd-backend') != bename.lower() and mt.get_attr_val_utf8('nsslapd-state') != 'backend':
raise ldap.NO_SUCH_OBJECT("We have a matching suffix, but not a backend or correct database name.")
except ldap.NO_SUCH_OBJECT:
result = DSBLE0001
Expand Down
24 changes: 22 additions & 2 deletions src/lib389/lib389/config.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2020 Red Hat, Inc.
# Copyright (C) 2023 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
Expand All @@ -22,7 +22,9 @@
from lib389 import Entry
from lib389._mapped_object import DSLdapObject
from lib389.utils import ensure_bytes, selinux_label_port, selinux_present
from lib389.lint import DSCLE0001, DSCLE0002, DSELE0001
from lib389.lint import (
DSCLE0001, DSCLE0002, DSCLE0003, DSCLE0004, DSELE0001
)

class Config(DSLdapObject):
"""
Expand Down Expand Up @@ -219,6 +221,24 @@ def _lint_passwordscheme(self):
report['check'] = "config:passwordscheme"
yield report

def _lint_unauth_binds(self):
# Allow unauthenticated binds
unauthbinds = self.get_attr_val_utf8_l('nsslapd-allow-unauthenticated-binds')
if unauthbinds == "on":
report = copy.deepcopy(DSCLE0003)
report['fix'] = report['fix'].replace('YOUR_INSTANCE', self._instance.serverid)
report['check'] = "config:unauthorizedbinds"
yield report

def _lint_accesslog_buffering(self):
# access log buffering
buffering = self.get_attr_val_utf8_l('nsslapd-accesslog-logbuffering')
if buffering == "off":
report = copy.deepcopy(DSCLE0004)
report['fix'] = report['fix'].replace('YOUR_INSTANCE', self._instance.serverid)
report['check'] = "config:accesslogbuffering"
yield report

def disable_plaintext_port(self):
"""
Configure the server to not-provide the plaintext port.
Expand Down
32 changes: 31 additions & 1 deletion src/lib389/lib389/lint.py
@@ -1,5 +1,5 @@
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2022 Red Hat, Inc.
# Copyright (C) 2023 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
Expand Down Expand Up @@ -113,6 +113,36 @@
# dsconf slapd-YOUR_INSTANCE config replace passwordStorageScheme=PBKDF2-SHA512 nsslapd-rootpwstoragescheme=PBKDF2-SHA512"""
}

DSCLE0003 = {
'dsle': 'DSCLE0003',
'severity': 'MEDIUM',
'description': 'Unauthorized Binds Allowed',
'items': ['cn=config', ],
'detail': """nsslapd-allow-unauthenticated-binds is set to 'on' this can
lead to unexpected results with clients and potential security issues
""",
'fix': """Set nsslapd-allow-unauthenticated-binds to off.
You can use 'dsconf' to set this attribute. Here is an example:
# dsconf slapd-YOUR_INSTANCE config replace nsslapd-allow-unauthenticated-binds=off"""
}

DSCLE0004 = {
'dsle': 'DSCLE0004',
'severity': 'LOW',
'description': 'Access Log buffering disabled',
'items': ['cn=config', ],
'detail': """nsslapd-accesslog-logbuffering is set to 'off' this will cause high
disk IO and can significantly impact server performance. This should only be used
for debug purposes
""",
'fix': """Set nsslapd-accesslog-logbuffering to 'on'.
You can use 'dsconf' to set this attribute. Here is an example:
# dsconf slapd-YOUR_INSTANCE config replace nsslapd-accesslog-logbuffering=on
"""
}

# Security checks
DSELE0001 = {
'dsle': 'DSELE0001',
Expand Down

0 comments on commit 835f12b

Please sign in to comment.