Skip to content

jmcore.secure_files

jmcore.secure_files

Private directory and atomic secret-file utilities.

Attributes

logger = logging.getLogger(__name__) module-attribute

Functions:

atomic_write_private(path: Path, data: bytes) -> None

Atomically write bytes without exposing a permissively-mode temporary file.

Source code in jmcore/src/jmcore/secure_files.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
def atomic_write_private(path: Path, data: bytes) -> None:
    """Atomically write bytes without exposing a permissively-mode temporary file."""
    _reject_parent_traversal(path)
    parent = path.parent
    if parent.is_symlink():
        raise OSError(f"refusing to use symlink as private directory: {parent}")
    if not parent.exists():
        ensure_private_directory(parent)

    fd, temp_name = tempfile.mkstemp(
        dir=parent,
        prefix=f".{path.name}.",
        suffix=".tmp",
    )
    temp_path = Path(temp_name)
    try:
        os.fchmod(fd, 0o600)
        with os.fdopen(fd, "wb") as temp_file:
            fd = -1
            temp_file.write(data)
            temp_file.flush()
            os.fsync(temp_file.fileno())
        os.replace(temp_path, path)
    finally:
        if fd >= 0:
            os.close(fd)
        with suppress(FileNotFoundError):
            temp_path.unlink()

atomic_write_sensitive_file(path: Path, data: bytes) -> None

Atomically update a sensitive file while preserving configured aliases.

Source code in jmcore/src/jmcore/secure_files.py
170
171
172
def atomic_write_sensitive_file(path: Path, data: bytes) -> None:
    """Atomically update a sensitive file while preserving configured aliases."""
    atomic_write_private(path.resolve(strict=False), data)

ensure_private_directory(path: Path) -> None

Create or tighten a secret-bearing directory to owner-only access.

Source code in jmcore/src/jmcore/secure_files.py
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
def ensure_private_directory(path: Path) -> None:
    """Create or tighten a secret-bearing directory to owner-only access."""
    _reject_parent_traversal(path)
    if path.is_symlink():
        raise OSError(f"refusing to use symlink as private directory: {path}")

    missing_parents: list[Path] = []
    parent = path.parent
    while not parent.exists():
        missing_parents.append(parent)
        if parent == parent.parent:
            break
        parent = parent.parent

    for parent in reversed(missing_parents):
        parent.mkdir(mode=0o700, exist_ok=True)
        _tighten_private_directory(parent)

    path.mkdir(mode=0o700, exist_ok=True)
    _tighten_private_directory(path)

ensure_private_file(path: Path) -> None

Tighten an existing regular secret file to owner-only access.

Source code in jmcore/src/jmcore/secure_files.py
 99
100
101
102
def ensure_private_file(path: Path) -> None:
    """Tighten an existing regular secret file to owner-only access."""
    fd = _open_private_regular_file(path)
    os.close(fd)

ensure_sensitive_directory(path: Path) -> None

Create a missing application directory privately without changing an existing one.

Source code in jmcore/src/jmcore/secure_files.py
112
113
114
115
116
def ensure_sensitive_directory(path: Path) -> None:
    """Create a missing application directory privately without changing an existing one."""
    resolved_path = path.resolve(strict=False)
    if not resolved_path.exists():
        ensure_private_directory(resolved_path)

ensure_sensitive_file(path: Path) -> None

Best-effort tighten a regular config or metadata file, following aliases.

Source code in jmcore/src/jmcore/secure_files.py
119
120
121
122
123
124
125
126
def ensure_sensitive_file(path: Path) -> None:
    """Best-effort tighten a regular config or metadata file, following aliases."""
    fd = _open_regular_file(
        path,
        follow_final_symlink=True,
        allow_unchanged_mode=True,
    )
    os.close(fd)

read_private_file(path: Path) -> bytes

Read and tighten a regular secret file through one no-follow descriptor.

Source code in jmcore/src/jmcore/secure_files.py
105
106
107
108
109
def read_private_file(path: Path) -> bytes:
    """Read and tighten a regular secret file through one no-follow descriptor."""
    fd = _open_private_regular_file(path)
    with os.fdopen(fd, "rb") as private_file:
        return private_file.read()

read_sensitive_file(path: Path) -> bytes

Read a regular config or metadata file, following aliases when configured.

Source code in jmcore/src/jmcore/secure_files.py
129
130
131
132
133
134
135
136
137
def read_sensitive_file(path: Path) -> bytes:
    """Read a regular config or metadata file, following aliases when configured."""
    fd = _open_regular_file(
        path,
        follow_final_symlink=True,
        allow_unchanged_mode=True,
    )
    with os.fdopen(fd, "rb") as sensitive_file:
        return sensitive_file.read()