luks-detached-header.rst 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ================================
  2. LUKS volume with detached header
  3. ================================
  4. Introduction
  5. ============
  6. This document gives an overview of the design of LUKS volume with detached
  7. header and how to use it.
  8. Background
  9. ==========
  10. The LUKS format has ability to store the header in a separate volume from
  11. the payload. We could extend the LUKS driver in QEMU to support this use
  12. case.
  13. Normally a LUKS volume has a layout:
  14. ::
  15. +-----------------------------------------------+
  16. | | | |
  17. disk | header | key material | disk payload data |
  18. | | | |
  19. +-----------------------------------------------+
  20. With a detached LUKS header, you need 2 disks so getting:
  21. ::
  22. +--------------------------+
  23. disk1 | header | key material |
  24. +--------------------------+
  25. +---------------------+
  26. disk2 | disk payload data |
  27. +---------------------+
  28. There are a variety of benefits to doing this:
  29. * Secrecy - the disk2 cannot be identified as containing LUKS
  30. volume since there's no header
  31. * Control - if access to the disk1 is restricted, then even
  32. if someone has access to disk2 they can't unlock
  33. it. Might be useful if you have disks on NFS but
  34. want to restrict which host can launch a VM
  35. instance from it, by dynamically providing access
  36. to the header to a designated host
  37. * Flexibility - your application data volume may be a given
  38. size and it is inconvenient to resize it to
  39. add encryption.You can store the LUKS header
  40. separately and use the existing storage
  41. volume for payload
  42. * Recovery - corruption of a bit in the header may make the
  43. entire payload inaccessible. It might be
  44. convenient to take backups of the header. If
  45. your primary disk header becomes corrupt, you
  46. can unlock the data still by pointing to the
  47. backup detached header
  48. Architecture
  49. ============
  50. Take the qcow2 encryption, for example. The architecture of the
  51. LUKS volume with detached header is shown in the diagram below.
  52. There are two children of the root node: a file and a header.
  53. Data from the disk payload is stored in the file node. The
  54. LUKS header and key material are located in the header node,
  55. as previously mentioned.
  56. ::
  57. +-----------------------------+
  58. Root node | foo[luks] |
  59. +-----------------------------+
  60. | |
  61. file | header |
  62. | |
  63. +---------------------+ +------------------+
  64. Child node |payload-format[qcow2]| |header-format[raw]|
  65. +---------------------+ +------------------+
  66. | |
  67. file | file |
  68. | |
  69. +----------------------+ +---------------------+
  70. Child node |payload-protocol[file]| |header-protocol[file]|
  71. +----------------------+ +---------------------+
  72. | |
  73. | |
  74. | |
  75. Host storage Host storage
  76. Usage
  77. =====
  78. Create a LUKS disk with a detached header using qemu-img
  79. --------------------------------------------------------
  80. Shell commandline::
  81. # qemu-img create --object secret,id=sec0,data=abc123 -f luks \
  82. -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
  83. -o detached-header=true test-header.img
  84. # qemu-img create -f qcow2 test-payload.qcow2 200G
  85. # qemu-img info 'json:{"driver":"luks","file":{"filename": \
  86. "test-payload.img"},"header":{"filename":"test-header.img"}}'
  87. Set up a VM's LUKS volume with a detached header
  88. ------------------------------------------------
  89. Qemu commandline::
  90. # qemu-system-x86_64 ... \
  91. -object '{"qom-type":"secret","id":"libvirt-3-format-secret", \
  92. "data":"abc123"}' \
  93. -blockdev '{"driver":"file","filename":"/path/to/test-header.img", \
  94. "node-name":"libvirt-1-storage"}' \
  95. -blockdev '{"node-name":"libvirt-1-format","read-only":false, \
  96. "driver":"raw","file":"libvirt-1-storage"}' \
  97. -blockdev '{"driver":"file","filename":"/path/to/test-payload.qcow2", \
  98. "node-name":"libvirt-2-storage"}' \
  99. -blockdev '{"node-name":"libvirt-2-format","read-only":false, \
  100. "driver":"qcow2","file":"libvirt-2-storage"}' \
  101. -blockdev '{"node-name":"libvirt-3-format","driver":"luks", \
  102. "file":"libvirt-2-format","header":"libvirt-1-format","key-secret": \
  103. "libvirt-3-format-secret"}' \
  104. -device '{"driver":"virtio-blk-pci","bus":XXX,"addr":YYY,"drive": \
  105. "libvirt-3-format","id":"virtio-disk1"}'
  106. Add LUKS volume to a VM with a detached header
  107. ----------------------------------------------
  108. 1. object-add the secret for decrypting the cipher stored in
  109. LUKS header above::
  110. # virsh qemu-monitor-command vm '{"execute":"object-add", \
  111. "arguments":{"qom-type":"secret", "id": \
  112. "libvirt-4-format-secret", "data":"abc123"}}'
  113. 2. block-add the protocol node for LUKS header::
  114. # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
  115. "arguments":{"node-name":"libvirt-1-storage", "driver":"file", \
  116. "filename": "/path/to/test-header.img" }}'
  117. 3. block-add the raw-drived node for LUKS header::
  118. # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
  119. "arguments":{"node-name":"libvirt-1-format", "driver":"raw", \
  120. "file":"libvirt-1-storage"}}'
  121. 4. block-add the protocol node for disk payload image::
  122. # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
  123. "arguments":{"node-name":"libvirt-2-storage", "driver":"file", \
  124. "filename":"/path/to/test-payload.qcow2"}}'
  125. 5. block-add the qcow2-drived format node for disk payload data::
  126. # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
  127. "arguments":{"node-name":"libvirt-2-format", "driver":"qcow2", \
  128. "file":"libvirt-2-storage"}}'
  129. 6. block-add the luks-drived format node to link the qcow2 disk
  130. with the LUKS header by specifying the field "header"::
  131. # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
  132. "arguments":{"node-name":"libvirt-3-format", "driver":"luks", \
  133. "file":"libvirt-2-format", "header":"libvirt-1-format", \
  134. "key-secret":"libvirt-2-format-secret"}}'
  135. 7. hot-plug the virtio-blk device finally::
  136. # virsh qemu-monitor-command vm '{"execute":"device_add", \
  137. "arguments": {"driver":"virtio-blk-pci", \
  138. "drive": "libvirt-3-format", "id":"virtio-disk2"}}
  139. TODO
  140. ====
  141. 1. Support the shared detached LUKS header within the VM.