Restrict Secrets File Permissions with the chmod Script in Python
This script restricts a secrets file to 0600 permissions, rotates it to a dated backup, and creates a fresh protected file for secure automation workflows.
Python code
47 linesimport os
import sys
import stat
from pathlib import Path
def restrict_secrets_file(filepath: str) -> None:
"""Set restrictive permissions (0600) on a secrets file."""
path = Path(filepath).expanduser()
if not path.is_file():
raise FileNotFoundError(f"Secrets file not found: {path}")
# Set owner read/write only (0600)
path.chmod(stat.S_IRUSR | stat.S_IWUSR)
# Verify the change
mode = stat.S_IMODE(path.stat().st_mode)
print(f"Permissions set for {path}: {oct(mode)} ({mode:04o}")
def rotate_secrets(filepath: str) -> None:
"""Rotate secrets file to a dated backup and create a fresh protected file."""
path = Path(filepath).expanduser()
# Create timestamped backup
timestamp = path.stat().st_mtime
backup = path.with_suffix(path.suffix + f".bak-{int(timestamp)}")
path.rename(backup)
print(f"Backup created: {backup}")
# Create new empty file with restrictive permissions
path.touch(mode=0o600)
path.chmod(stat.S_IRUSR | stat.S_IWUSR)
print(f"New secrets file created: {path} (permissions: 0600)")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python rotation_script.py /path/to/secrets.txt")
sys.exit(1)
target = sys.argv[1]
try:
restrict_secrets_file(target)
rotate_secrets(target)
print("Secrets file rotation complete.")
except (FileNotFoundError, PermissionError, OSError) as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
Output
Permissions set for /tmp/secrets.txt: 0o600 (0600
Backup created: /tmp/secrets.txt.bak-1720000000
New secrets file created: /tmp/secrets.txt (permissions: 0600)
Secrets file rotation complete.
How it works
The stat module defines octal permission masks like S_IRUSR (owner read) and S_IWUSR (owner write), which combine to 0600. path.chmod applies the mode, and stat.S_IMODE extracts just the permission bits from the file's metadata for verification. String formatting with oct() and 04o displays the mode in a readable octal format. The rotation uses the file's modification timestamp to create a unique backup name, then touch with mode=0o600 creates a fresh empty file that is immediately protected.
Common mistakes
- Forgetting `Path.expanduser()` when the path contains a tilde (~)
- Using `os.chmod` without combining permission flags correctly
- Not verifying the permission change after `chmod`
- Overlooking the fact that `touch` with mode may be affected by umask
Variations
- Use `os.chmod(path, 0o600)` with `os.stat().st_mode` for a slightly older API
- Add `subprocess.run(["chmod", "600", path])` for complex ACL or extended attribute cases
Real-world use cases
- A cron job that rotates SSH private keys or API tokens and ensures new files are not world-readable.
- A deployment script that safely regenerates database credentials without exposing old content.
- A security audit tool that enforces 0600 permissions on `.env` or credential files across servers.
Sponsored
More from Automation & scripting
- Aggregate Log Errors Count by Hour in Python easy
- Automate Tweeting New Blog Posts in Python easy
- Automatically Clean Temporary Files from Applications Using Python medium
- Automatically Download the Latest Software Release from GitHub with Python medium
- Automatically Generate Charts from CSV Files with One Command medium
- Automatically Generate Hardware Inventory Reports in Python easy
Keep learning
Related tutorials and quizzes for this topic.