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.

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 13 views 0 copies

Python code

47 lines
Python 3.9+
import 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

stdout
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

  1. Use `os.chmod(path, 0o600)` with `os.stat().st_mode` for a slightly older API
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Automation & scripting

Related tutorials and quizzes for this topic.