sense the system to use gpg1 when installed
[myplc.git] / plc.d / gpg
1 #!/bin/bash
2 #
3 # priority: 400
4 #
5 # Generate GPG keys
6 #
7 # Mark Huang <mlhuang@cs.princeton.edu>
8 # Copyright (C) 2006 The Trustees of Princeton University
9 #
10
11 # Source function library and configuration
12 . /etc/plc.d/functions
13 . /etc/planetlab/plc_config
14
15 ### IMPORTANT NOTE 2020 - feb
16 # when moving to fedora31 I run into this
17 # https://fedoraproject.org/wiki/Changes/GnuPG2_as_default_GPG_implementation
18 # which breaks the whole system for us because
19 # * gnupg2 key generation function won't work as expected
20 # * but with much wider impact, it turns out that private keys
21 #   are now stored in a completely different way, and this will affect
22 #   the way that particular location (typically /etc/planetlab/secring.gpg)
23 #   is both
24 #   * configured (as $PLC_ROOT_GPG_KEY) 
25 #   * and passed around (see the PLC.GPG module and its gpg_sign() function)
26
27 # so for now it looks MUCH EASIER to just get fedora to install gnupg1 
28 # instead of (or on top of) gnupg, and use gpg1 when available
29 # below is a leftover of the beginning of a code adaptation
30 # to gnupg2, that should work fine (took some time to get right actually)
31 # but this is currently unused 
32
33 # for now we run only with gpg1, but on recent systems it means 
34 # we need to invoke explicitly gpg1
35 type gpg1 >& /dev/null && GPG=gpg1 || GPG=gpg
36
37 # this is more for when we support both
38 # the default gpg command is version 1 up to f29, version 2 starts with f31 
39 GPG_MAJOR_VERSION=$($GPG --version | grep '^gpg' | cut -d' ' -f 3 | cut -d. -f1)
40
41 function generate_key_v1() {
42         local homedir=$1
43         $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes --gen-key << EOF
44 Key-Type: DSA
45 Key-Length: 1024
46 Subkey-Type: ELG-E
47 Subkey-Length: 1024
48 Name-Real: $PLC_NAME Central
49 Name-Comment: http://$PLC_WWW_HOST/
50 Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
51 Expire-Date: 0
52 %pubring $PLC_ROOT_GPG_KEY_PUB
53 %secring $PLC_ROOT_GPG_KEY
54 %commit
55 EOF
56 }
57
58 # this code should work allright as far as key generation, but as explained above
59 # moving to gnupg2 requires a lot more work all over the place...
60 function generate_key_v2() {
61         >&2 echo "it appears you have GPGv2 installed, myPLC is not ready for that !"
62         return 1
63
64         local homedir=$1
65         $GPG --homedir=$homedir --generate-key --batch << EOF
66 Key-Type: DSA
67 Key-Length: 1024
68 Subkey-Type: ELG-E
69 Subkey-Length: 1024
70 Name-Real: $PLC_NAME Central
71 Name-Comment: http://$PLC_WWW_HOST/
72 Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
73 Expire-Date: 0
74 %pubring $PLC_ROOT_GPG_KEY_PUB
75 %no-protection
76 %commit
77 EOF
78 }
79
80 # Be verbose
81 set -x
82
83 case "$1" in
84     start)
85         # Make temporary GPG home directory
86         homedir=$(mktemp -d /tmp/gpg.XXXXXX)
87
88         # in case a previous gpg invocation failed in some weird way
89         # and left behind a zero length gpg key (pub or priv).
90         if [ -f $PLC_ROOT_GPG_KEY_PUB -a ! -s $PLC_ROOT_GPG_KEY_PUB ] ; then
91             rm -f $PLC_ROOT_GPG_KEY_PUB 
92         fi
93         if [ -f $PLC_ROOT_GPG_KEY -a ! -s $PLC_ROOT_GPG_KEY ] ; then
94             rm -f $PLC_ROOT_GPG_KEY
95         fi
96
97         if [ ! -f $PLC_ROOT_GPG_KEY_PUB -o ! -f $PLC_ROOT_GPG_KEY ] ; then
98             # Generate new GPG keyring
99             MESSAGE=$"Generating GPG keys"
100             dialog "$MESSAGE"
101
102             mkdir -p $(dirname $PLC_ROOT_GPG_KEY_PUB)
103             mkdir -p $(dirname $PLC_ROOT_GPG_KEY)
104
105             # Temporarily replace /dev/random with /dev/urandom to
106             # avoid running out of entropy.
107             # (1 9 is /dev/urandom, 1 8 is /dev/random)
108             #
109             # a former version of this was rm'ing /dev/random and re-creating it afterwards
110             # however in 1.0.4 libvirt won't allow the use of mknod at all, so let's work around that
111             # by moving things around instead
112             #
113             # if we find this file it's probably that a previous run has failed..
114             [ -f /dev/random.preserve ] && { echo "Unexpected file /dev/random.preserve - exiting" ; exit 1; }
115             mv -f /dev/random /dev/random.preserve
116             # doesn't hurt to check 
117             check
118             ln -s /dev/urandom /dev/random
119             # again 
120             check
121                 if [ "$GPG_MAJOR_VERSION" == 1 ]; then
122                         generate_key_v1 $homedir
123                 else
124                         generate_key_v2 $homedir
125                 fi
126             check
127             mv -f /dev/random.preserve /dev/random
128             check
129         else
130             # Update GPG UID
131             MESSAGE=$"Updating GPG keys"
132             dialog "$MESSAGE"
133
134             # Get the current GPG fingerprint and comment
135             OLDIFS=$IFS
136             IFS=:
137             while read -a fields ; do
138                 if [ "${fields[0]}" = "pub" ] ; then
139                     fingerprint=${fields[4]}
140                     break
141                 fi
142             done < <(
143                 $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
144                     --no-default-keyring \
145                     --secret-keyring=$PLC_ROOT_GPG_KEY \
146                     --keyring=$PLC_ROOT_GPG_KEY_PUB \
147                     --list-public-keys --with-colons
148                 check
149             )
150             IFS=$OLDIFS
151
152             # Add a new UID if appropriate. GPG will detect and merge duplicates.
153             $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
154                 --no-default-keyring \
155                 --secret-keyring=$PLC_ROOT_GPG_KEY \
156                 --keyring=$PLC_ROOT_GPG_KEY_PUB \
157                 --command-fd 0 --status-fd 1 --edit-key $fingerprint <<EOF
158 adduid
159 $PLC_NAME Central
160 $PLC_MAIL_SUPPORT_ADDRESS
161 http://$PLC_WWW_HOST/
162 save
163 EOF
164             check
165         fi
166
167         # Install the key in the RPM database
168         mkdir -p /etc/pki/rpm-gpg
169         $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
170             --no-default-keyring \
171             --secret-keyring=$PLC_ROOT_GPG_KEY \
172             --keyring=$PLC_ROOT_GPG_KEY_PUB \
173             --export --armor >"/etc/pki/rpm-gpg/RPM-GPG-KEY-$PLC_NAME"
174         check
175         if rpm -q gpg-pubkey ; then
176             rpm --allmatches -e gpg-pubkey
177             check
178         fi
179         # starting with rpm-4.6, this fails when run a second time
180         # it would be complex to do this properly based on the filename, 
181         # as /etc/pki/rpm-gpg/ typically has many symlinks to the same file
182         # see also http://fedoranews.org/tchung/gpg/
183         # so just ignore the result
184         rpm --import /etc/pki/rpm-gpg/* || :
185         check
186
187         # Make GPG key readable by apache so that the API can sign peer requests
188         chown apache $PLC_ROOT_GPG_KEY
189         chmod 644 $PLC_ROOT_GPG_KEY_PUB
190         chmod 600 $PLC_ROOT_GPG_KEY
191         check
192
193         # Cleanup
194         rm -rf $homedir
195
196         result "$MESSAGE"
197         ;;
198 esac
199
200 exit $ERRORS