Skip to content

Commit

Permalink
fix: Don't loosen the permissions of the log file
Browse files Browse the repository at this point in the history
Previous implementations loosened permissions in non-default scenarios.

Fixes GH-4243
  • Loading branch information
holmanb committed Nov 24, 2023
1 parent 1639168 commit 5cb8a84
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
15 changes: 14 additions & 1 deletion cloudinit/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os
import sys
from collections import namedtuple
from contextlib import suppress
from typing import Dict, Iterable, List, Optional, Set

from cloudinit import (
Expand Down Expand Up @@ -219,13 +220,25 @@ def purge_cache(self, rm_instance_lnk=False):
def initialize(self):
self._initialize_filesystem()

@staticmethod
def _get_strictest_mode(mode_1: int, mode_2: int) -> int:
return mode_1 & mode_2

def _initialize_filesystem(self):
mode = 0o640

util.ensure_dirs(self._initial_subdirs())
log_file = util.get_cfg_option_str(self.cfg, "def_log_file")
if log_file:
# At this point the log file should have already been created
# in the setupLogging function of log.py
util.ensure_file(log_file, mode=0o640, preserve_mode=False)
with suppress(OSError):
mode = self._get_strictest_mode(
0o640, util.get_permissions(log_file)
)

# set file mode to the strictest of 0o640 and the current mode
util.ensure_file(log_file, mode, preserve_mode=False)
perms = self.cfg.get("syslog_fix_perms")
if not perms:
perms = {}
Expand Down
45 changes: 33 additions & 12 deletions tests/unittests/test_stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,23 +622,44 @@ def test_log_files_existence_is_ensured_if_configured(self, init, tmpdir):
# Assert we create it 0o640 by default if it doesn't already exist
assert 0o640 == stat.S_IMODE(log_file.stat().mode)

def test_existing_file_permissions(self, init, tmpdir):
@pytest.mark.parametrize(
"input, expected",
[
(0o777, 0o640),
(0o640, 0o640),
(0o606, 0o600),
(0o501, 0o400),
],
)
def test_existing_file_permissions(self, init, tmpdir, input, expected):
"""Test file permissions are set as expected.
CIS Hardening requires 640 permissions. These permissions are
currently hardcoded on every boot, but if there's ever a reason
to change this, we need to then ensure that they
are *not* set every boot.
CIS Hardening requires file mode 0o640 or stricter. Set the
permissions to the least common denominator of 0o640 and the current
mode.
See https://bugs.launchpad.net/cloud-init/+bug/1900837.
"""
log_file = tmpdir.join("cloud-init.log")
log_file.ensure()
# Use a mode that will never be made the default so this test will
# always be valid
log_file.chmod(0o606)
log_file.chmod(input)
init._cfg = {"def_log_file": str(log_file)}

init._initialize_filesystem()

assert 0o640 == stat.S_IMODE(log_file.stat().mode)
with mock.patch.object(stages.util, "ensure_file") as ensure:
init._initialize_filesystem()
assert expected == ensure.call_args[0][1]


@pytest.mark.parametrize(
"mode_1, mode_2, expected",
[
(0o777, 0o640, 0o640),
(0o640, 0o777, 0o640),
(0o640, 0o541, 0o440),
(0o111, 0o050, 0o010),
(0o631, 0o640, 0o600),
(0o661, 0o640, 0o640),
(0o453, 0o611, 0o411),
],
)
def test_strictest_permissions(mode_1, mode_2, expected):
assert expected == stages.Init._get_strictest_mode(mode_1, mode_2)

0 comments on commit 5cb8a84

Please sign in to comment.