]> WPIA git - infra.git/commitdiff
add: script for an admin to manage certificates
authorFelix Dörre <felix@dogcraft.de>
Sun, 16 Jul 2017 20:34:55 +0000 (22:34 +0200)
committerFelix Dörre <felix@dogcraft.de>
Sun, 23 Jul 2017 17:15:52 +0000 (19:15 +0200)
Change-Id: Ie85f6686f1e04314aafc0726704d5406968cc1e7

commands
manager/.gitignore
manager/admin-manage-certificates [new file with mode: 0755]
manager/config

index 6f6d00d7d19d1e7b74010adc4996e1b10db61b6b..ef9ba7cb5bef0817e262e524c71d568c79400b18 100755 (executable)
--- a/commands
+++ b/commands
@@ -57,9 +57,9 @@ if [[ $com == "update certs" || $com == "force update certs" ]]; then
     rmdir $folder
 elif [[ $com == "reload certs" ]]; then
     sudo puppet apply /etc/puppet/code/environments/production/manifests --verbose
-    sudo lxc-attach -n front-nginx -- puppet agent --verbose --test
-    sudo lxc-attach -n quiz -- puppet agent --verbose --test
-    sudo lxc-attach -n gigi -- puppet agent --verbose --test
+    sudo lxc-attach -n front-nginx -- puppet agent --verbose --onetime
+    sudo lxc-attach -n quiz -- puppet agent --verbose --onetime
+    sudo lxc-attach -n gigi -- puppet agent --verbose --onetime
 elif [[ $com == "update crls" ]]; then
     if ! tar xv -C /data/crl; then
         echo "requiring tar"
index 4b5bdb34b40cb2606939bf61a4871535b3cd8b58..f19bffcf61014de91cbaf3627ecb34de45aeffa1 100644 (file)
@@ -6,3 +6,6 @@
 /vm-key
 /vm-key.pub
 /root.crt
+/admin-key
+/admin-key.pub
+/.tmpdata
diff --git a/manager/admin-manage-certificates b/manager/admin-manage-certificates
new file mode 100755 (executable)
index 0000000..2a6c4c0
--- /dev/null
@@ -0,0 +1,131 @@
+#!/bin/bash
+targetHost=$1
+targetHost=${targetHost%/}
+source config
+source "$targetHost/config"
+
+if [[ ! -f admin-key ]]; then
+    ssh-keygen -t ed25519 -N "" -f admin-key
+    printf >&2 'Warning: generated admin-key without passphrase\n'
+fi
+
+if [[ "$2" == "install" ]]; then
+    ssh_target "cat >> modules/hop/files/authorized_keys <<< 'command=\"/home/admin/commands\",restrict,pty $(cat admin-key.pub)'"
+    ssh_target -t 'sudo lxc-attach -n hop -- bash -c "ssh-keyscan -H 10.0.3.1 > /home/admin/.ssh/known_hosts"'
+    ssh_target -t 'sudo lxc-attach -n hop -- puppet agent --test --verbose'
+    exit 0;
+fi
+
+
+read_admin_email
+read_admin_password
+
+echo -n "cat >> modules/hop/files/authorized_keys <<< 'command=\"/home/admin/commands\",restrict,pty $(cat admin-key.pub)' && "
+echo -n 'sudo lxc-attach -n hop -- bash -c "ssh-keyscan -H 10.0.3.1 > /home/admin/.ssh/known_hosts" && '
+echo 'sudo lxc-attach -n hop -- puppet agent --test --verbose'
+read -p "Keys installed? " _
+folder=.tmpdata
+mkdir -p $folder
+function csrf {
+    grep csrf | ${1:-cat}  | ${2:-cat} | sed "s/.*value='\([^']*\)'.*/\\1/"
+}
+
+[[ -f root.crt ]] || curl -s "http://www.$domain/roots?pem" > root.crt
+echo "Opening Gigi connection"
+rm -f $folder/cookie-jar
+csrf=$(mcurl login -c $folder/cookie-jar|csrf)
+if ! [[ -f $folder/cookie-jar ]]; then
+    echo "Need cookies." >&2
+    exit 1;
+fi
+mcurl login --data-urlencode "username=$admin_email" --data-urlencode "password=$admin_password" --data-urlencode "csrf=$csrf" -c $folder/cookie-jar > /dev/null
+
+csrf=$(mcurl account/details | csrf "tail -n 1")
+mcurl account/details --data "orgaForm=orga&org%3A3=yes&csrf=$csrf"
+echo "Gigi is ready"
+function issue0 {
+    options=$1
+    csr=$2
+    csrf=$(mcurl "account/certs/new" | csrf "head -n 1")
+
+    encoded=$(cat "$csr" | tr '\n' '?' | sed "s/=/%3D/g;s/+/%2B/g;s/\?/%0A/g")
+
+    mcurl account/certs/new -d "CSR=$encoded&process=Next&csrf=$csrf" > /dev/null
+
+    serial=$(mcurl account/certs/new -d "$options&OU=&hash_alg=SHA256&validFrom=now&validity=2y&login=1&description=&process=Issue+Certificate&csrf=$csrf" -v 2>&1 | tee $folder/certlog | grep "< Location: " | sed "s_.*/\([a-f0-9]*\)[^0-9]*_\1_")
+    echo "Certificate: $serial"
+    if [[ $serial != "" ]]; then
+        mcurl "account/certs/$serial.crt?chain&noAnchor" > $folder/cert.crt
+        return 0;
+    else
+        return 1;
+    fi
+}
+force=""
+if [[ "$2" == "force" ]]; then
+    force="force "
+fi
+coproc {
+    admin_ssh "${force}update certs"
+    read -r end
+}
+updated="false"
+while true; do
+    read -r line <&${COPROC[0]} || break;
+    echo "Command: $line"
+    if [[ "$line" = "SKIP "* ]]; then
+        echo "Skipping: $line"
+    elif [[ "$line" = "ISSUE "* ]]; then
+        openssl req -out $folder/web.req <&${COPROC[0]}
+        echo "CSR received, contacting Gigi"
+        options="profile=server-orga&CN=&SANs=quiz.$domain"
+        case ${line#ISSUE } in
+            "modules/gigi/files/gigi")
+                options="profile=server-orga&CN=&SANs=www.$domain%0Asecure.$domain%0Astatic.$domain%0Aapi.$domain%0A"
+                ;;
+            "modules/pootle/files/web")
+                options="profile=server-orga&CN=&SANs=pootle.$domain"
+                ;;
+            "modules/gigi/files/client")
+                options="profile=mail-orga&CN=&SANs=gigi@$domain"
+                ;;
+            "modules/quiz/files/web")
+                options="profile=server-orga&CN=&SANs=quiz.$domain"
+                ;;
+            "modules/gitweb/files/web")
+                options="profile=server-orga&CN=&SANs=code.$domain"
+                ;;
+            "modules/quiz/files/client")
+                options="profile=client-orga&CN=Quiz+Api+User&SANs=quiz@$domain"
+                ;;
+            *)
+                echo "Unknown certificate in $line, rejecting"
+                echo "FAIL" >&${COPROC[1]}
+                continue;
+                ;;
+        esac
+        if issue0 "$options" $folder/web.req; then
+            echo "gigi issued successfully"
+            echo "SUCCESS" >&${COPROC[1]}
+            updated="true"
+            cnt=$(grep "BEGIN CERTIFICATE" $folder/cert.crt | wc -l)
+            echo "chain of length $cnt"
+            echo "$cnt" >&${COPROC[1]}
+            cat $folder/cert.crt >&${COPROC[1]}
+            read -r reply <&${COPROC[0]};
+            echo $reply
+        else
+            echo "FAIL" >&${COPROC[1]}
+        fi
+    elif [[ "$line" = "DONE" ]]; then
+        sleep 1
+        break;
+    fi
+done
+echo "end process" >&${COPROC[1]}
+cat <&${COPROC[0]}
+mcurl logout > /dev/null
+
+if [[ "$updated" == "true" ]]; then
+    admin_ssh -t "reload certs"
+fi
index 6625d0d892a1bc609578026a69cffc4c41796ef5..e0e675390226afb857d2f1c3fa91144a29d47d77 100755 (executable)
@@ -64,3 +64,25 @@ function read_activation_link {
     read -rp "Link: " link
     printf '%s\n' "$link"
 }
+
+# Assign to the variable "admin_email" the email address of the gigi user account that should issue certificates for the system.
+function read_admin_email {
+    read -rp "Gigi user account email for certificates: " admin_email
+}
+
+# Assign to the variable "admin_password" the password of the gigi user account that should issue certificates for the system.
+function read_admin_password {
+    read -rsp "Gigi password: " admin_password
+}
+
+# Connect to gigi using $1 as local url part, the remaining args as additional curl arguments, "root.crt" as root certificate, "$folder/cookie-jar" as cookie-jar.
+function mcurl {
+    local url="$1"
+    shift
+    curl -s --cacert root.crt -b $folder/cookie-jar "https://www.$domain/$url" "$@"
+}
+
+# Connect via ssh into the "hop" container.
+function admin_ssh {
+    ssh -i admin-key -p 2222 "admin@$to" "$@"
+}