clevis icon indicating copy to clipboard operation
clevis copied to clipboard

Support for a keyscript pin, which would call an executable to retrieve key material

Open turtlemonvh opened this issue 5 years ago • 5 comments

As a lower barrier to entry for integrations with custom sources of secret material, would the maintainers be open to a keyscript-like pin in clevis, mirroring the functionality of the same argument in crypttab?

https://manpages.debian.org/testing/cryptsetup/crypttab.5.en.html

This may allow integrations like #39 to be developed with less bloat to clevis core.

turtlemonvh avatar May 08 '20 15:05 turtlemonvh

Disclaimer: I'm not the clevis developer. If I read the documentation and old mailing list articles correctly, the keyscript feature is not supported by systemd and there hasn't quite been huge enthusiasm to rectify that situation. For the past five years. So is it readlly worth to support a feature that is dead as a doodoo and will forseable go away at some time in the near future?

Anyway, implementing this isn't really difficult since clevis-luks-unlock already has all the logic. Only difference: Print the plaintext instead of calling cryptsetup. Beware, it's completely untested. How to use (in case it's not obvious):

  • Patch clevis-luks-unlock
  • Copy, or better: Symlink as clevis-luks-keyscript. That name is important.
  • Configure that as keyscript in your /etc/crypttab.
--- /usr/bin/clevis-luks-unlock.orig
+++ /usr/bin/clevis-luks-unlock
@@ -55,8 +55,13 @@
 done
 
 if [ -z "$DEV" ]; then
-    echo "Did not specify a device!" >&2
-    usage
+    if [ "$(basename "$0")" = 'clevis-luks-keyscript' ] && [ "$CRYPTTAB_SOURCE" ] && [ -b "$CRYPTTAB_SOURCE" ] ; then
+        mode='keyscript'
+        DEV="$CRYPTTAB_SOURCE"
+    else
+        echo "Did not specify a device!" >&2
+        usage
+    fi
 fi
 
 if ! cryptsetup isLuks "$DEV"; then
@@ -111,6 +116,10 @@
 
         pt="$(luks1_decrypt -d $DEV -s $slot -u $UUID)" \
             || continue
+        if [ "$mode" = 'keyscript' ] ; then
+            printf '%s' "$pt"
+            exit 0
+        fi
         exec cryptsetup open -d- "$DEV" "$NAME" < <(
             echo -n "$pt"
         )
@@ -120,6 +129,10 @@
     while read -r id; do
         pt="$(luks2_decrypt --token-id "$id" "$DEV")" \
             || continue
+        if [ "$mode" = 'keyscript' ] ; then
+            printf '%s' "$pt"
+            exit 0
+        fi
         exec cryptsetup open -d- "$DEV" "$NAME" < <(
             echo -n "$pt"
         )

Cheers,

cbiedl avatar May 25 '20 18:05 cbiedl

Thanks for the details @cbiedl .

the keyscript feature is not supported by systemd and there hasn't quite been huge enthusiasm to rectify that situation

Yeah we've been running into this a bit at work recently while working to develop a simple integration with LUKS.

So is it readlly worth to support a feature that is dead as a doodoo and will forseable go away at some time in the near future?

If I'm reading you correctly here, I'm not proposing that clevis supports the LUKS keyscript functionality. Instead, I'm checking to see if clevis could have its own keyscript functionality via a pin, so something like this:

# Now: With tang, from the README
clevis luks bind -d /dev/sda tang '{"url": "http://server.local/key"}'

# What I want: With a `keyscript` option, where the script at the path simply returns a key
clevis luks bind -d /dev/sda keyscript '{"path": "/usr/local/bin/"}'

Reading through the code a bit more, it looks like this may be simpler than I originally expected.

The README mentions that the pins are plugins, but the nature of those plugins was unclear to me until I dug through the code. Now I see that a pin named keyscript would just require executables clevis-encrypt-keyscript and clevis-decrypt-keyscript on the path. From what I can tell those do need to return a valid formatted jwe (rather than some arbitrary ciphertext).

  • https://github.com/latchset/clevis/blob/v13/src/luks/clevis-luks-bind.in#L135-L136
    • just calls clevis encrypt
  • https://github.com/latchset/clevis/blob/v13/src/luks/clevis-luks-unlock.in#L81-L105
    • just calls clevis decrypt
  • https://github.com/latchset/clevis/blob/v13/src/clevis-decrypt#L44-L47
    • just calls clevis-decrypt-$pin
  • https://github.com/latchset/clevis/tree/master/src/pins/sss
    • see "test" configuration
    • just uses "clevis-decrypt-test" and "clevis-encrypt-test" bash functions
    • the "test" pin for clevis just returns jwe on encrypt and consumes on decrypt

I'll mess around with this a bit more and see I can build off the test pin to get a simple keyscript pin to behave.

turtlemonvh avatar May 31 '20 18:05 turtlemonvh

I have a prototype working here: https://github.com/turtlemonvh/clevis/tree/191/keyscript-pin0prototype/src/pins/keyscript

I used the example of the test example for the sss keyscript to build an example. I'm sure there are some silly things in there, but the scripts do seem to work.

The command works like this

# Encrypt
$ echo "hi there" | ./src/pins/keyscript/clevis-encrypt-keyscript '{"keyscript": "/tmp/keyscript"}' > keyscript.jwe
$ cat keyscript.jwe ; echo
eyJhbGciOiJkaXIiLCJjbGV2aXMiOnsiY2ZnIjp7ImtleXNjcmlwdCI6Ii90bXAva2V5c2NyaXB0In0sInBpbiI6ImtleXNjcmlwdCJ9LCJlbmMiOiJBMjU2R0NNIn0..9ZmxtknGj5qtka_P.DBq9JLBWRkMQ.ETuFwW5MG00lQuGT46uABg
$ cat keyscript.jwe | cut -d"." -f1 | jose b64 dec -i- ; echo
{"alg":"dir","clevis":{"cfg":{"keyscript":"/tmp/keyscript"},"pin":"keyscript"},"enc":"A256GCM"}

# Decrypt
$ cat keyscript.jwe | ./src/pins/keyscript/clevis-decrypt-keyscript
hi there

If there is interest in having this capability in clevis I can clean this up and even add on some options like passing arguments to the keyscript.

turtlemonvh avatar Jun 01 '20 16:06 turtlemonvh

Possibly I completely understood your initial request indeed. About authoring pins, I had created pull request earlier. Although you've already created something, it still might be of some value for you: https://github.com/latchset/clevis/pull/203/commits/22cb93d61f7c4cf60eb3ab0899c16d8a49905550

cbiedl avatar Jun 01 '20 17:06 cbiedl

That guide is awesome @cbiedl - thanks!

I hadn't gotten to the initramfs and dracut configuration yet, so that is especially helpful. Your "key in a file" pin looks very similar to my "keyscript" pin - that would have been good to find a few hours ago. :D

I'll read through your work on #203 in more detail (as well as your PR on #204) when I come back around to this.

turtlemonvh avatar Jun 01 '20 17:06 turtlemonvh