diff options
-rw-r--r-- | README | 16 | ||||
-rwxr-xr-x | luksbackup.sh | 133 |
2 files changed, 149 insertions, 0 deletions
@@ -0,0 +1,16 @@ | |||
1 | |||
2 | luksbackup: a tool for backing up GnuPG keys and entire directories to luks-encrypted devices | ||
3 | |||
4 | * You will probably need to run this as root. | ||
5 | |||
6 | * Note that device names should not include the /dev/ prefix. | ||
7 | They are assumed to only consist of the last part, i.e. 'sdb1'. | ||
8 | |||
9 | * Backing up private keys | ||
10 | ** Use the -k flag to back up your private GnuPG keys to a 'gnupg' directory on the target devices | ||
11 | usage: ./luksbackup.sh -k device1 device2 ... | ||
12 | |||
13 | * Backing up a directory | ||
14 | ** Use the -d flag to back up a directory | ||
15 | usage: ./luksbackup.sh -d srcdir device1 device2 ... | ||
16 | |||
diff --git a/luksbackup.sh b/luksbackup.sh new file mode 100755 index 0000000..74414cc --- /dev/null +++ b/luksbackup.sh | |||
@@ -0,0 +1,133 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # two operating modes | ||
4 | MODE_KEY=1 | ||
5 | MODE_DIR=2 | ||
6 | |||
7 | # holds the current operating mode (see above) | ||
8 | CURRENT_MODE=0 | ||
9 | |||
10 | # root path wherein device-specific mountpoints will be created | ||
11 | MOUNTROOT=$HOME/luksbackup_$(date +%s) | ||
12 | |||
13 | # source directory when operating in dir mode | ||
14 | SOURCE_DIR="" | ||
15 | |||
16 | print_usage() { | ||
17 | echo "" | ||
18 | echo "luksbackup: a tool for backing up GnuPG keys and entire directories to luks-encrypted devices" | ||
19 | echo "" | ||
20 | echo "* You will probably need to run this as root." | ||
21 | echo "" | ||
22 | echo "* Note that device names should not include the /dev/ prefix." | ||
23 | echo " They are assumed to only consist of the last part, i.e. 'sdb1'." | ||
24 | echo "" | ||
25 | echo "* Backing up private keys" | ||
26 | echo "** Use the -k flag to back up your private GnuPG keys to a 'gnupg' directory on the target devices" | ||
27 | echo " usage: ./luksbackup.sh -k device1 device2 ..." | ||
28 | echo "" | ||
29 | echo "* Backing up a directory" | ||
30 | echo "** Use the -d flag to back up a directory" | ||
31 | echo " usage: ./luksbackup.sh -d srcdir device1 device2 ..." | ||
32 | echo "" | ||
33 | } | ||
34 | |||
35 | set_key_mode() { | ||
36 | CURRENT_MODE=$MODE_KEY | ||
37 | } | ||
38 | |||
39 | set_dir_mode() { | ||
40 | CURRENT_MODE=$MODE_DIR | ||
41 | SOURCE_DIR=$1 | ||
42 | |||
43 | # verify that source directory exists | ||
44 | if [ ! -d $SOURCE_DIR ]; | ||
45 | then | ||
46 | echo "Directory $SOURCE_DIR doesn't exist! Exiting..." >&2 | ||
47 | exit 1 | ||
48 | fi | ||
49 | } | ||
50 | |||
51 | backup_dir() { | ||
52 | outfile=$1 | ||
53 | echo "Archiving $SOURCE_DIR to $outfile" | ||
54 | tar -C $SOURCE_DIR -cf - . | xz -9e -T 0 -c - > $outfile | ||
55 | } | ||
56 | |||
57 | backup_keys() { | ||
58 | outfile=$1 | ||
59 | tmpdir="/tmp/luksbackup_keys_$(date +%s)" | ||
60 | |||
61 | # create temporary output directory | ||
62 | mkdir -p $tmpdir | ||
63 | |||
64 | # export all the available secret keys | ||
65 | for key in $(gpg --list-secret-keys | grep -oE '[A-Z0-9]{40,}'); | ||
66 | do | ||
67 | echo "Backing up key $key" | ||
68 | gpg -a -o $tmpdir/$key.asc --export-secret-key $key | ||
69 | done | ||
70 | |||
71 | tar -C $tmpdir -cf - . | xz -9e -T 0 -c - > $outfile | ||
72 | |||
73 | rm -rf $tmpdir | ||
74 | } | ||
75 | |||
76 | # parse command-line arguments | ||
77 | while getopts ':d:hk' opt; | ||
78 | do | ||
79 | case $opt in | ||
80 | (k) set_key_mode && shift 1 && break;; | ||
81 | (d) set_dir_mode $OPTARG && shift 2 && break;; | ||
82 | (*|h|help) print_usage && exit 0;; | ||
83 | esac | ||
84 | done | ||
85 | |||
86 | # verify that a valid operation mode was selected | ||
87 | if [ $CURRENT_MODE -eq 0 ] || [ $CURRENT_MODE -gt 2 ]; | ||
88 | then | ||
89 | echo "Invalid argument(s). Exiting..." >&2 | ||
90 | exit 1 | ||
91 | fi | ||
92 | |||
93 | # iterate over the rest of the arguments, assumed to be device names | ||
94 | for arg; | ||
95 | do | ||
96 | device=$arg | ||
97 | |||
98 | cryptpart=cryptusb_$device | ||
99 | mountpoint=$MOUNTROOT/$device | ||
100 | |||
101 | # open the device | ||
102 | sudo cryptsetup open /dev/$device $cryptpart | ||
103 | |||
104 | if [ $? -ne 0 ]; | ||
105 | then | ||
106 | echo "Could not open device $device. Skipping..." | ||
107 | continue; | ||
108 | fi | ||
109 | |||
110 | # mount the luks partition | ||
111 | mkdir -p $mountpoint | ||
112 | sudo mount /dev/mapper/$cryptpart $mountpoint | ||
113 | |||
114 | if [ $? -eq 0 ]; # only try creating backup if mounting succeeded | ||
115 | then | ||
116 | # print mountpoints | ||
117 | echo "Mounted /dev/$device ($cryptpart) -> $mountpoint" | ||
118 | |||
119 | # perform operation based on selected mode | ||
120 | case $CURRENT_MODE in | ||
121 | ($MODE_DIR) backup_dir "$mountpoint/backup_$(date +%s).tar.xz";; | ||
122 | ($MODE_KEY) backup_keys "$mountpoint/keys_$(date +%s).tar.xz";; | ||
123 | esac | ||
124 | |||
125 | # unmount the luks partition | ||
126 | sudo umount $mountpoint | ||
127 | fi | ||
128 | |||
129 | sudo cryptsetup close $cryptpart | ||
130 | done | ||
131 | |||
132 | # clean up root path where devices were mounted | ||
133 | rm -rf $MOUNTROOT | ||