Skip to content

Commit e6ab8fc

Browse files
potiukjedcunningham
authored andcommitted
Fix excessive permission changing for log task handler (#38164)
When log dir permission was changed by log handler, we've implemented also changing permissions of parent folders recursively, however it was quite a bit too much to change it for home directory where the log folder could have been created - because in some cases changing permissions might lead to unexpected side-effects - such as loosing ability to login to ssh server. Fixes: #38137 (cherry picked from commit 2c1d0f8)
1 parent 0e60195 commit e6ab8fc

File tree

2 files changed

+21
-48
lines changed

2 files changed

+21
-48
lines changed

airflow/utils/log/file_task_handler.py

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -159,31 +159,6 @@ def _ensure_ti(ti: TaskInstanceKey | TaskInstance, session) -> TaskInstance:
159159
raise AirflowException(f"Could not find TaskInstance for {ti}")
160160

161161

162-
def _change_directory_permissions_up(directory: Path, folder_permissions: int):
163-
"""
164-
Change permissions of the given directory and its parents.
165-
166-
Only attempt to change permissions for directories owned by the current user.
167-
168-
:param directory: directory to change permissions of (including parents)
169-
:param folder_permissions: permissions to set
170-
"""
171-
if directory.stat().st_uid == os.getuid():
172-
if directory.stat().st_mode % 0o1000 != folder_permissions % 0o1000:
173-
print(f"Changing {directory} permission to {folder_permissions}")
174-
try:
175-
directory.chmod(folder_permissions)
176-
except PermissionError as e:
177-
# In some circumstances (depends on user and filesystem) we might not be able to
178-
# change the permission for the folder (when the folder was created by another user
179-
# before or when the filesystem does not allow to change permission). We should not
180-
# fail in this case but rather ignore it.
181-
print(f"Failed to change {directory} permission to {folder_permissions}: {e}")
182-
return
183-
if directory.parent != directory:
184-
_change_directory_permissions_up(directory.parent, folder_permissions)
185-
186-
187162
class FileTaskHandler(logging.Handler):
188163
"""
189164
FileTaskHandler is a python log handler that handles and reads task instance logs.
@@ -481,7 +456,8 @@ def read(self, task_instance, try_number=None, metadata=None):
481456

482457
return logs, metadata_array
483458

484-
def _prepare_log_folder(self, directory: Path):
459+
@staticmethod
460+
def _prepare_log_folder(directory: Path, new_folder_permissions: int):
485461
"""
486462
Prepare the log folder and ensure its mode is as configured.
487463
@@ -505,11 +481,9 @@ def _prepare_log_folder(self, directory: Path):
505481
sure that the same group is set as default group for both - impersonated user and main airflow
506482
user.
507483
"""
508-
new_folder_permissions = int(
509-
conf.get("logging", "file_task_handler_new_folder_permissions", fallback="0o775"), 8
510-
)
511-
directory.mkdir(mode=new_folder_permissions, parents=True, exist_ok=True)
512-
_change_directory_permissions_up(directory, new_folder_permissions)
484+
for parent in reversed(directory.parents):
485+
parent.mkdir(mode=new_folder_permissions, exist_ok=True)
486+
directory.mkdir(mode=new_folder_permissions, exist_ok=True)
513487

514488
def _init_file(self, ti, *, identifier: str | None = None):
515489
"""
@@ -531,7 +505,10 @@ def _init_file(self, ti, *, identifier: str | None = None):
531505
# if this is true, we're invoked via set_context in the context of
532506
# setting up individual trigger logging. return trigger log path.
533507
full_path = self.add_triggerer_suffix(full_path=full_path, job_id=ti.triggerer_job.id)
534-
self._prepare_log_folder(Path(full_path).parent)
508+
new_folder_permissions = int(
509+
conf.get("logging", "file_task_handler_new_folder_permissions", fallback="0o775"), 8
510+
)
511+
self._prepare_log_folder(Path(full_path).parent, new_folder_permissions)
535512

536513
if not os.path.exists(full_path):
537514
open(full_path, "a").close()

tests/utils/test_log_handlers.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import os
2323
import re
2424
import shutil
25-
import tempfile
2625
from pathlib import Path
2726
from unittest import mock
2827
from unittest.mock import patch
@@ -42,7 +41,6 @@
4241
from airflow.utils.log.file_task_handler import (
4342
FileTaskHandler,
4443
LogType,
45-
_change_directory_permissions_up,
4644
_interleave_logs,
4745
_parse_timestamps_in_log_file,
4846
)
@@ -724,28 +722,26 @@ def test_interleave_logs_correct_ordering():
724722
assert sample_with_dupe == "\n".join(_interleave_logs(sample_with_dupe, "", sample_with_dupe))
725723

726724

727-
def test_permissions_for_new_directories():
728-
tmp_path = Path(tempfile.mkdtemp())
725+
def test_permissions_for_new_directories(tmpdir):
726+
tmpdir_path = Path(tmpdir)
729727
try:
730728
# Set umask to 0o027: owner rwx, group rx-w, other -rwx
731729
old_umask = os.umask(0o027)
732730
try:
733-
subdir = tmp_path / "subdir1" / "subdir2"
731+
base_dir = tmpdir_path / "base"
732+
base_dir.mkdir()
733+
log_dir = base_dir / "subdir1" / "subdir2"
734734
# force permissions for the new folder to be owner rwx, group -rxw, other -rwx
735735
new_folder_permissions = 0o700
736736
# default permissions are owner rwx, group rx-w, other -rwx (umask bit negative)
737737
default_permissions = 0o750
738-
subdir.mkdir(mode=new_folder_permissions, parents=True, exist_ok=True)
739-
assert subdir.exists()
740-
assert subdir.is_dir()
741-
assert subdir.stat().st_mode % 0o1000 == new_folder_permissions
742-
# initially parent permissions are as per umask
743-
assert subdir.parent.stat().st_mode % 0o1000 == default_permissions
744-
_change_directory_permissions_up(subdir, new_folder_permissions)
745-
assert subdir.stat().st_mode % 0o1000 == new_folder_permissions
746-
# now parent permissions are as per new_folder_permissions
747-
assert subdir.parent.stat().st_mode % 0o1000 == new_folder_permissions
738+
FileTaskHandler._prepare_log_folder(log_dir, new_folder_permissions)
739+
assert log_dir.exists()
740+
assert log_dir.is_dir()
741+
assert log_dir.stat().st_mode % 0o1000 == new_folder_permissions
742+
assert log_dir.parent.stat().st_mode % 0o1000 == new_folder_permissions
743+
assert base_dir.stat().st_mode % 0o1000 == default_permissions
748744
finally:
749745
os.umask(old_umask)
750746
finally:
751-
shutil.rmtree(tmp_path)
747+
shutil.rmtree(tmpdir_path)

0 commit comments

Comments
 (0)