automount_luks.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import os
  2. import subprocess
  3. from crypt_tools import decrypt_passphrase, create_luks_mount_config
  4. import argparse
  5. # Configuration file containing encrypted LUKS passphrases
  6. CONFIG_FILE = "luks_mount.conf"
  7. def get_device_uuid(device):
  8. """
  9. Get the UUID of a device using blkid.
  10. """
  11. try:
  12. output = subprocess.check_output(["blkid", "-o", "value", "-s", "UUID", device])
  13. return output.decode().strip()
  14. except subprocess.CalledProcessError as e:
  15. print(f"Failed to get UUID for {device}: {e}")
  16. return None
  17. def get_mount_point(device_id):
  18. """
  19. Get the mount point for a given device ID from the configuration file.
  20. """
  21. if not os.path.exists(CONFIG_FILE):
  22. print(f"Configuration file '{CONFIG_FILE}' not found!")
  23. return None
  24. with open(CONFIG_FILE, "r") as f:
  25. for line in f:
  26. if line.startswith("#") or len(line) == 0:
  27. continue
  28. parts = line.strip().split()
  29. if len(parts) != 3:
  30. continue
  31. uuid, mount_point, _ = parts
  32. if uuid == device_id:
  33. return mount_point
  34. return None
  35. def mount_luks_filesystems():
  36. """
  37. Read the configuration file, decrypt the LUKS passphrases, and mount the filesystems.
  38. """
  39. if not os.path.exists(CONFIG_FILE):
  40. print(f"Configuration file '{CONFIG_FILE}' not found!")
  41. return
  42. with open(CONFIG_FILE, "r") as f:
  43. for line in f:
  44. if line.startswith("#") or len(line) == 0:
  45. continue
  46. # Parse the configuration line: uuid mount_point encrypted_passphrase
  47. parts = line.strip().split()
  48. if len(parts) != 3:
  49. print(f"Skipping invalid line: {line}")
  50. continue
  51. uuid, mount_point, encrypted_passphrase = parts
  52. # Get the device path from the UUID
  53. device = f"/dev/disk/by-uuid/{uuid}"
  54. if not os.path.exists(device):
  55. print(f"Device '{device}' not found!")
  56. continue
  57. # Decrypt the LUKS passphrase using the master passkey
  58. try:
  59. passphrase = decrypt_passphrase(encrypted_passphrase, private_key_file="private_key.pem")
  60. except Exception as e:
  61. print(f"Failed to decrypt passphrase for {device}: {e}")
  62. continue
  63. # Unlock the LUKS device
  64. try:
  65. subprocess.run(
  66. ["cryptsetup", "luksOpen", device, f"{os.path.basename(device)}_crypt"],
  67. input=passphrase.encode(),
  68. check=True
  69. )
  70. print(f"Unlocked LUKS device: {device}")
  71. except subprocess.CalledProcessError as e:
  72. print(f"Failed to unlock {device}: {e}")
  73. continue
  74. # Mount the filesystem
  75. try:
  76. os.makedirs(mount_point, exist_ok=True)
  77. subprocess.run(
  78. ["mount", f"/dev/mapper/{os.path.basename(device)}_crypt", mount_point],
  79. check=True
  80. )
  81. print(f"Mounted {device} at {mount_point}")
  82. except subprocess.CalledProcessError as e:
  83. print(f"Failed to mount {device} at {mount_point}: {e}")
  84. continue
  85. def unmount_and_lock_filesystem(device_id):
  86. """
  87. Unmount and lock a filesystem given the device ID.
  88. """
  89. device = f"/dev/disk/by-uuid/{device_id}"
  90. crypt_device = f"/dev/mapper/{os.path.basename(device)}_crypt"
  91. # Get the mount point from the configuration file
  92. mount_point = get_mount_point(device_id)
  93. if not mount_point:
  94. print(f"Mount point for device '{device_id}' not found in configuration file.")
  95. return
  96. # Unmount the filesystem
  97. try:
  98. subprocess.run(["sudo", "umount", crypt_device], check=True)
  99. print(f"Unmounted filesystem: {crypt_device}")
  100. except subprocess.CalledProcessError as e:
  101. print(f"Failed to unmount filesystem {crypt_device}: {e}")
  102. return
  103. # Remove the mount point directory
  104. try:
  105. os.rmdir(mount_point)
  106. print(f"Removed mount point directory: {mount_point}")
  107. except OSError as e:
  108. print(f"Failed to remove mount point directory {mount_point}: {e}")
  109. # Lock the LUKS device
  110. try:
  111. subprocess.run(["sudo", "cryptsetup", "luksClose", f"{os.path.basename(device)}_crypt"], check=True)
  112. print(f"Locked LUKS device: {device}")
  113. except subprocess.CalledProcessError as e:
  114. print(f"Failed to lock LUKS device {device}: {e}")
  115. def close_all_filesystems():
  116. """
  117. Close all filesystems listed in the configuration file.
  118. """
  119. if not os.path.exists(CONFIG_FILE):
  120. print(f"Configuration file '{CONFIG_FILE}' not found!")
  121. return
  122. with open(CONFIG_FILE, "r") as f:
  123. for line in f:
  124. parts = line.strip().split()
  125. if len(parts) != 3:
  126. print(f"Skipping invalid line: {line}")
  127. continue
  128. uuid, _, _ = parts
  129. unmount_and_lock_filesystem(uuid)
  130. def main():
  131. """
  132. Main function to read the master passkey and mount LUKS filesystems.
  133. """
  134. parser = argparse.ArgumentParser(description="Automount LUKS filesystems.")
  135. parser.add_argument("-m", "--mount", action="store_true", help="Mount all LUKS devices")
  136. parser.add_argument("-c", "--close", help="Close a specific LUKS device", metavar="DEVICE_ID")
  137. parser.add_argument("-f", "--config", help="Specify a configuration file", metavar="CONFIG_FILE")
  138. parser.add_argument("-k", "--close-all", action="store_true", help="Close all LUKS devices")
  139. parser.add_argument("-n", "--new-config", action="store_true", help="Create a new luks_mount.conf file")
  140. args = parser.parse_args()
  141. global CONFIG_FILE
  142. if args.config:
  143. CONFIG_FILE = args.config
  144. if args.mount:
  145. mount_luks_filesystems()
  146. elif args.close:
  147. unmount_and_lock_filesystem(args.close)
  148. elif args.close_all:
  149. close_all_filesystems()
  150. elif args.new_config:
  151. create_luks_mount_config(config_file=CONFIG_FILE)
  152. else:
  153. parser.print_help()
  154. if __name__ == "__main__":
  155. main()