|
| 1 | +#!/bin/bash |
| 2 | +# info: check letsencrypt domain |
| 3 | +# options: USER DOMAIN |
| 4 | +# |
| 5 | +# The function check and validates domain with LetsEncript |
| 6 | + |
| 7 | + |
| 8 | +#----------------------------------------------------------# |
| 9 | +# Variable&Function # |
| 10 | +#----------------------------------------------------------# |
| 11 | + |
| 12 | +# Argument definition |
| 13 | +user=$1 |
| 14 | +domain=$(idn -t --quiet -u "$2" ) |
| 15 | +domain=$(echo $domain | tr '[:upper:]' '[:lower:]') |
| 16 | + |
| 17 | +# Includes |
| 18 | +source $VESTA/func/main.sh |
| 19 | +source $VESTA/conf/vesta.conf |
| 20 | + |
| 21 | +# encode base64 |
| 22 | +encode_base64() { |
| 23 | + cat |base64 |tr '+/' '-_' |tr -d '\r\n=' |
| 24 | +} |
| 25 | + |
| 26 | + |
| 27 | +#----------------------------------------------------------# |
| 28 | +# Verifications # |
| 29 | +#----------------------------------------------------------# |
| 30 | + |
| 31 | +check_args '2' "$#" 'USER DOMAIN' |
| 32 | +is_format_valid 'user' 'domain' |
| 33 | +is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM' |
| 34 | +is_object_valid 'user' 'USER' "$user" |
| 35 | +is_object_unsuspended 'user' 'USER' "$user" |
| 36 | +if [ ! -e "$USER_DATA/ssl/le.conf" ]; then |
| 37 | + check_result $E_NOTEXIST "LetsEncrypt key doesn't exist" |
| 38 | +fi |
| 39 | +check_domain=$(grep -w "$domain'" $USER_DATA/web.conf) |
| 40 | +if [ -z "$check_domain" ]; then |
| 41 | + check_result $E_NOTEXIST "domain $domain doesn't exist" |
| 42 | +fi |
| 43 | + |
| 44 | + |
| 45 | +#----------------------------------------------------------# |
| 46 | +# Action # |
| 47 | +#----------------------------------------------------------# |
| 48 | + |
| 49 | +source $USER_DATA/ssl/le.conf |
| 50 | +api='https://acme-v01.api.letsencrypt.org' |
| 51 | +r_domain=$(echo "$check_domain" |cut -f 2 -d \') |
| 52 | +key="$USER_DATA/ssl/user.key" |
| 53 | +exponent="$EXPONENT" |
| 54 | +modulus="$MODULUS" |
| 55 | +thumb="$THUMB" |
| 56 | + |
| 57 | +# Defining JWK header |
| 58 | +header='{"e":"'$exponent'","kty":"RSA","n":"'"$modulus"'"}' |
| 59 | +header='{"alg":"RS256","jwk":'"$header"'}' |
| 60 | + |
| 61 | +# Requesting nonce |
| 62 | +nonce=$(curl -s -I "$api/directory" |grep Nonce |cut -f2 -d \ |tr -d '\r\n') |
| 63 | +protected=$(echo -n '{"nonce":"'"$nonce"'"}' |encode_base64) |
| 64 | + |
| 65 | +# Defining ACME query (request challenge) |
| 66 | +query='{"resource":"new-authz","identifier"' |
| 67 | +query=$query':{"type":"dns","value":"'"$domain"'"}}' |
| 68 | +payload=$(echo -n "$query" |encode_base64) |
| 69 | +signature=$(printf "%s" "$protected.$payload" |\ |
| 70 | + openssl dgst -sha256 -binary -sign "$key" |encode_base64) |
| 71 | +data='{"header":'"$header"',"protected":"'"$protected"'",' |
| 72 | +data=$data'"payload":"'"$payload"'","signature":"'"$signature"'"}' |
| 73 | + |
| 74 | +# Sending request to LetsEncrypt API |
| 75 | +answer=$(curl -s -i -d "$data" "$api/acme/new-authz") |
| 76 | + |
| 77 | +# Checking http answer status |
| 78 | +status=$(echo "$answer" |grep HTTP/1.1 |tail -n1 |cut -f2 -d ' ') |
| 79 | +if [[ "$status" -ne "201" ]]; then |
| 80 | + check_result $E_CONNECT "LetsEncrypt challenge request $status" |
| 81 | +fi |
| 82 | + |
| 83 | +# Parsing domain nonce,token and uri |
| 84 | +nonce=$(echo "$answer" |grep Nonce |cut -f2 -d \ |tr -d '\r\n') |
| 85 | +protected=$(echo -n '{"nonce":"'"$nonce"'"}' |encode_base64) |
| 86 | +token=$(echo "$answer" |tr ',' '\n' |grep -A 3 http-01 |grep token) |
| 87 | +token=$(echo "$token" |cut -f 4 -d \") |
| 88 | +uri=$(echo "$answer" |tr ',' '\n' |grep -A 3 http-01 |grep uri) |
| 89 | +uri=$(echo "$uri" |cut -f 4 -d \") |
| 90 | + |
| 91 | +# Adding location wrapper for request challenge |
| 92 | +if [ "$WEB_SYSTEM" = 'nginx' ] || [ "$PROXY_SYSTEM" = 'nginx' ]; then |
| 93 | + conf="$HOMEDIR/$user/conf/web/nginx.$r_domain.conf_letsencrypt" |
| 94 | + if [ ! -e "$conf" ]; then |
| 95 | + echo 'location ~ "^/\.well-known/acme-challenge/(.*)$" {' > $conf |
| 96 | + echo ' default_type text/plain;' >> $conf |
| 97 | + echo ' return 200 "$1.'$thumb'";' >> $conf |
| 98 | + echo '}' >> $conf |
| 99 | + if [ ! -z "$PROXY_SYSTEM" ]; then |
| 100 | + $BIN/v-restart-proxy |
| 101 | + check_result $? "Proxy restart failed" >/dev/null |
| 102 | + else |
| 103 | + $BIN/v-restart-web |
| 104 | + check_result $? "Web restart failed" >/dev/null |
| 105 | + fi |
| 106 | + fi |
| 107 | +else |
| 108 | + acme="$HOMEDIR/$user/web/$r_domain/public_html/.well-known/acme-challenge" |
| 109 | + echo "$token" > $acme/$token.$thumb |
| 110 | + chown -R $user:$user $HOMEDIR/$user/web/$r_domain/public_html/.well-known |
| 111 | +fi |
| 112 | + |
| 113 | +# Defining ACME query (request validation) |
| 114 | +query='{"resource":"challenge","type":"http-01","keyAuthorization"' |
| 115 | +query=$query':"'$token.$thumb'","token":"'$token'"}' |
| 116 | +payload=$(echo -n "$query" |encode_base64) |
| 117 | +signature=$(printf "%s" "$protected.$payload" |\ |
| 118 | + openssl dgst -sha256 -binary -sign "$key" |encode_base64) |
| 119 | +data='{"header":'"$header"',"protected":"'"$protected"'",' |
| 120 | +data=$data'"payload":"'"$payload"'","signature":"'"$signature"'"}' |
| 121 | + |
| 122 | +# Sending request to LetsEncrypt API |
| 123 | +answer=$(curl -s -i -d "$data" "$uri") |
| 124 | + |
| 125 | +# Checking domain validation status |
| 126 | +status=$(echo $answer |tr ',' '\n' |grep status |cut -f 4 -d \") |
| 127 | +location=$(echo "$answer" |grep Location: |awk '{print $2}' |tr -d '\r\n') |
| 128 | +while [ "$status" = 'pending' ] ; do |
| 129 | + answer=$(curl -s -i "$location") |
| 130 | + status=$(echo "$answer" |tr ',' '\n' |grep status |cut -f 4 -d \") |
| 131 | +done |
| 132 | +if [ "$status" = 'invalid' ]; then |
| 133 | + detail="$(echo $answer |tr ',' '\n' |grep detail |cut -f 4 -d \")" |
| 134 | + check_result $E_CONNECT "$detail" |
| 135 | +fi |
| 136 | + |
| 137 | + |
| 138 | +#----------------------------------------------------------# |
| 139 | +# Vesta # |
| 140 | +#----------------------------------------------------------# |
| 141 | + |
| 142 | +# Logging |
| 143 | +log_event "$OK" "$ARGUMENTS" |
| 144 | + |
| 145 | +exit |
0 commit comments