automount_luks.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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. # print ("---> %s" % passphrase)
  61. except Exception as e:
  62. print(f"Failed to decrypt passphrase for {device}: {e}")
  63. continue
  64. # Unlock the LUKS device
  65. try:
  66. subprocess.run(
  67. ["cryptsetup", "luksOpen", device, f"{os.path.basename(device)}_crypt"],
  68. input=passphrase.encode(),
  69. check=True
  70. )
  71. print(f"Unlocked LUKS device: {device}")
  72. except subprocess.CalledProcessError as e:
  73. print(f"Failed to unlock {device}: {e}")
  74. continue
  75. # Mount the filesystem
  76. try:
  77. os.makedirs(mount_point, exist_ok=True)
  78. subprocess.run(
  79. ["mount", f"/dev/mapper/{os.path.basename(device)}_crypt", mount_point],
  80. check=True
  81. )
  82. print(f"Mounted {device} at {mount_point}")
  83. except subprocess.CalledProcessError as e:
  84. print(f"Failed to mount {device} at {mount_point}: {e}")
  85. continue
  86. def unmount_and_lock_filesystem(device_id):
  87. """
  88. Unmount and lock a filesystem given the device ID.
  89. """
  90. device = f"/dev/disk/by-uuid/{device_id}"
  91. crypt_device = f"/dev/mapper/{os.path.basename(device)}_crypt"
  92. # Get the mount point from the configuration file
  93. mount_point = get_mount_point(device_id)
  94. if not mount_point:
  95. print(f"Mount point for device '{device_id}' not found in configuration file.")
  96. return
  97. # Unmount the filesystem
  98. try:
  99. subprocess.run(["sudo", "umount", crypt_device], check=True)
  100. print(f"Unmounted filesystem: {crypt_device}")
  101. except subprocess.CalledProcessError as e:
  102. print(f"Failed to unmount filesystem {crypt_device}: {e}")
  103. return
  104. # Remove the mount point directory
  105. try:
  106. os.rmdir(mount_point)
  107. print(f"Removed mount point directory: {mount_point}")
  108. except OSError as e:
  109. print(f"Failed to remove mount point directory {mount_point}: {e}")
  110. # Lock the LUKS device
  111. try:
  112. subprocess.run(["sudo", "cryptsetup", "luksClose", f"{os.path.basename(device)}_crypt"], check=True)
  113. print(f"Locked LUKS device: {device}")
  114. except subprocess.CalledProcessError as e:
  115. print(f"Failed to lock LUKS device {device}: {e}")
  116. def close_all_filesystems():
  117. """
  118. Close all filesystems listed in the configuration file.
  119. """
  120. if not os.path.exists(CONFIG_FILE):
  121. print(f"Configuration file '{CONFIG_FILE}' not found!")
  122. return
  123. with open(CONFIG_FILE, "r") as f:
  124. for line in f:
  125. parts = line.strip().split()
  126. if len(parts) != 3:
  127. print(f"Skipping invalid line: {line}")
  128. continue
  129. uuid, _, _ = parts
  130. unmount_and_lock_filesystem(uuid)
  131. def main():
  132. """
  133. Main function to read the master passkey and mount LUKS filesystems.
  134. """
  135. parser = argparse.ArgumentParser(description="Automount LUKS filesystems.")
  136. parser.add_argument("-m", "--mount", action="store_true", help="Mount all LUKS devices")
  137. parser.add_argument("-c", "--close", help="Close a specific LUKS device", metavar="DEVICE_ID")
  138. parser.add_argument("-f", "--config", help="Specify a configuration file", metavar="CONFIG_FILE")
  139. parser.add_argument("-k", "--close-all", action="store_true", help="Close all LUKS devices")
  140. parser.add_argument("-n", "--new-config", action="store_true", help="Create a new luks_mount.conf file")
  141. args = parser.parse_args()
  142. global CONFIG_FILE
  143. if args.config:
  144. CONFIG_FILE = args.config
  145. if args.mount:
  146. mount_luks_filesystems()
  147. elif args.close:
  148. unmount_and_lock_filesystem(args.close)
  149. elif args.close_all:
  150. close_all_filesystems()
  151. elif args.new_config:
  152. create_luks_mount_config(config_file=CONFIG_FILE)
  153. else:
  154. parser.print_help()
  155. if __name__ == "__main__":
  156. main()