Skip to content

Commit

Permalink
[DPE-3297] Display audit logs in Canonical Observability Stack (#337)
Browse files Browse the repository at this point in the history
## Issue
A user\admin should be able to see audit logs in CoS

## Solution
As a first iteration of the feature - write audit logs to syslog 

<img width="1918" alt="Screenshot 2024-01-17 at 17 32 26"
src="https://github.com/canonical/mongodb-operator/assets/132273757/56be76fe-6233-4c88-818b-70cd14b1aba1">


<img width="1812" alt="Screenshot 2024-01-17 at 17 34 08"
src="https://github.com/canonical/mongodb-operator/assets/132273757/f45a7270-e100-454b-80af-707aeb52745e">
  • Loading branch information
dmitry-ratushnyy authored Jan 17, 2024
1 parent e199c17 commit f92c12f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 16 deletions.
20 changes: 14 additions & 6 deletions lib/charms/mongodb/v1/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 1
LIBPATCH = 2

# path to store mongodb ketFile
KEY_FILE = "keyFile"
Expand All @@ -44,11 +44,22 @@
MONGO_SHELL = "charmed-mongodb.mongosh"

DATA_DIR = "/var/lib/mongodb"
LOG_DIR = "/var/log/mongodb"
LOG_TO_SYSLOG = True
CONF_DIR = "/etc/mongod"
MONGODB_LOG_FILENAME = "mongodb.log"
logger = logging.getLogger(__name__)


def _get_logging_options(snap_install: bool) -> str:
# TODO sending logs to syslog until we have a separate mount point for logs
if LOG_TO_SYSLOG:
return ""
# in k8s the default logging options that are used for the vm charm are ignored and logs are
# the output of the container. To enable logging to a file it must be set explicitly
return f"--logpath={LOG_DIR}/{MONGODB_LOG_FILENAME}" if snap_install else ""


# noinspection GrazieInspection
def get_create_user_cmd(config: MongoDBConfiguration, mongo_path=MONGO_SHELL) -> List[str]:
"""Creates initial admin user for MongoDB.
Expand Down Expand Up @@ -130,9 +141,7 @@ def get_mongod_args(
"""
full_data_dir = f"{MONGODB_COMMON_DIR}{DATA_DIR}" if snap_install else DATA_DIR
full_conf_dir = f"{MONGODB_SNAP_DATA_DIR}{CONF_DIR}" if snap_install else CONF_DIR
# in k8s the default logging options that are used for the vm charm are ignored and logs are
# the output of the container. To enable logging to a file it must be set explicitly
logging_options = "" if snap_install else f"--logpath={full_data_dir}/{MONGODB_LOG_FILENAME}"
logging_options = _get_logging_options(snap_install)
cmd = [
# bind to localhost and external interfaces
"--bind_ip_all",
Expand All @@ -143,9 +152,8 @@ def get_mongod_args(
# for simplicity we run the mongod daemon on shards, configsvrs, and replicas on the same
# port
f"--port={Config.MONGODB_PORT}",
"--auditDestination=file",
"--auditDestination=syslog", # TODO sending logs to syslog until we have a separate mount point for logs
f"--auditFormat={Config.AuditLog.FORMAT}",
f"--auditPath={full_data_dir}/{Config.AuditLog.FILE_NAME}",
logging_options,
]
if auth:
Expand Down
4 changes: 2 additions & 2 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Config:
MONGODB_SNAP_DATA_DIR = "/var/snap/charmed-mongodb/current"
MONGOD_CONF_DIR = f"{MONGODB_SNAP_DATA_DIR}/etc/mongod"
MONGOD_CONF_FILE_PATH = f"{MONGOD_CONF_DIR}/mongod.conf"
SNAP_PACKAGES = [("charmed-mongodb", "6/edge", 87)]
SNAP_PACKAGES = [("charmed-mongodb", "6/edge", 93)]

# Keep these alphabetically sorted
class Actions:
Expand All @@ -29,7 +29,7 @@ class AuditLog:
"""Audit log related configuration."""

FORMAT = "JSON"
FILE_NAME = "audit.json"
FILE_NAME = "audit.log"

class Backup:
"""Backup related config for MongoDB Charm."""
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,12 @@ def juju_reports_one_primary(unit_messages):
await ops_test.model.destroy_unit(target_unit)


@pytest.mark.skip("Skipping until write to log files enabled")
async def test_audit_log(ops_test: OpsTest) -> None:
"""Test that audit log was created and contains actual audit data."""
app_name = await get_app_name(ops_test)
leader_unit = await find_unit(ops_test, leader=True, app_name=app_name)
audit_log_snap_path = "/var/snap/charmed-mongodb/common/var/lib/mongodb/audit.json"
audit_log_snap_path = "/var/snap/charmed-mongodb/common/var/log/mongodb/audit.log"
audit_log = check_output(
f"JUJU_MODEL={ops_test.model_full_name} juju ssh {leader_unit.name} 'sudo cat {audit_log_snap_path}'",
stderr=subprocess.PIPE,
Expand Down
10 changes: 3 additions & 7 deletions tests/unit/test_mongodb_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ def test_get_mongod_args(self):
"--replSet=my_repl_set",
"--dbpath=/var/snap/charmed-mongodb/common/var/lib/mongodb",
"--port=27017",
"--auditDestination=file",
"--auditDestination=syslog",
"--auditFormat=JSON",
"--auditPath=/var/snap/charmed-mongodb/common/var/lib/mongodb/audit.json",
"--auth",
"--clusterAuthMode=keyFile",
"--keyFile=/var/snap/charmed-mongodb/current/etc/mongod/keyFile",
Expand All @@ -39,9 +38,8 @@ def test_get_mongod_args(self):
"--replSet=my_repl_set",
"--dbpath=/var/snap/charmed-mongodb/common/var/lib/mongodb",
"--port=27017",
"--auditDestination=file",
"--auditDestination=syslog",
"--auditFormat=JSON",
"--auditPath=/var/snap/charmed-mongodb/common/var/lib/mongodb/audit.json",
]

self.assertEqual(
Expand All @@ -56,10 +54,8 @@ def test_get_mongod_args(self):
"--replSet=my_repl_set",
"--dbpath=/var/lib/mongodb",
"--port=27017",
"--auditDestination=file",
"--auditDestination=syslog",
"--auditFormat=JSON",
"--auditPath=/var/lib/mongodb/audit.json",
"--logpath=/var/lib/mongodb/mongodb.log",
]

self.assertEqual(
Expand Down

0 comments on commit f92c12f

Please sign in to comment.