Merge remote-tracking branch 'upstream/dev' into panos-ecc-fix
						commit
						62a2ce1d35
					
				
							
								
								
									
										24
									
								
								acme.sh
								
								
								
								
							
							
						
						
									
										24
									
								
								acme.sh
								
								
								
								
							|  | @ -1,6 +1,6 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| VER=3.0.6 | ||||
| VER=3.0.7 | ||||
| 
 | ||||
| PROJECT_NAME="acme.sh" | ||||
| 
 | ||||
|  | @ -2116,6 +2116,7 @@ _send_signed_request() { | |||
|   if [ -z "$keyfile" ]; then | ||||
|     keyfile="$ACCOUNT_KEY_PATH" | ||||
|   fi | ||||
|   _debug "=======Begin Send Signed Request=======" | ||||
|   _debug url "$url" | ||||
|   _debug payload "$payload" | ||||
| 
 | ||||
|  | @ -2277,7 +2278,7 @@ _setopt() { | |||
|   if [ ! -f "$__conf" ]; then | ||||
|     touch "$__conf" | ||||
|   fi | ||||
|   if [ -n "$(tail -c 1 <"$__conf")" ]; then | ||||
|   if [ -n "$(tail -c1 <"$__conf")" ]; then | ||||
|     echo >>"$__conf" | ||||
|   fi | ||||
| 
 | ||||
|  | @ -4602,9 +4603,10 @@ issue() { | |||
|         _d="*.$_d" | ||||
|       fi | ||||
|       _debug2 _d "$_d" | ||||
|       _authorizations_map="$_d,$response | ||||
|       _authorizations_map="$_d,$response#$_authz_url | ||||
| $_authorizations_map" | ||||
|     done | ||||
| 
 | ||||
|     _debug2 _authorizations_map "$_authorizations_map" | ||||
| 
 | ||||
|     _index=0 | ||||
|  | @ -4656,7 +4658,8 @@ $_authorizations_map" | |||
|         _on_issue_err "$_post_hook" | ||||
|         return 1 | ||||
|       fi | ||||
| 
 | ||||
|       _authz_url="$(echo "$_candidates" | sed "s/$_idn_d,//" | _egrep_o "#.*" | sed "s/^#//")" | ||||
|       _debug _authz_url "$_authz_url" | ||||
|       if [ -z "$thumbprint" ]; then | ||||
|         thumbprint="$(__calc_account_thumbprint)" | ||||
|       fi | ||||
|  | @ -4708,7 +4711,7 @@ $_authorizations_map" | |||
|         _debug keyauthorization "$keyauthorization" | ||||
|       fi | ||||
| 
 | ||||
|       dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot" | ||||
|       dvlist="$d$sep$keyauthorization$sep$uri$sep$vtype$sep$_currentRoot$sep$_authz_url" | ||||
|       _debug dvlist "$dvlist" | ||||
| 
 | ||||
|       vlist="$vlist$dvlist$dvsep" | ||||
|  | @ -4725,6 +4728,7 @@ $_authorizations_map" | |||
|       keyauthorization=$(echo "$ventry" | cut -d "$sep" -f 2) | ||||
|       vtype=$(echo "$ventry" | cut -d "$sep" -f 4) | ||||
|       _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) | ||||
|       _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) | ||||
|       _debug d "$d" | ||||
|       if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then | ||||
|         _debug "$d is already verified, skip $vtype." | ||||
|  | @ -4850,7 +4854,7 @@ $_authorizations_map" | |||
|     uri=$(echo "$ventry" | cut -d "$sep" -f 3) | ||||
|     vtype=$(echo "$ventry" | cut -d "$sep" -f 4) | ||||
|     _currentRoot=$(echo "$ventry" | cut -d "$sep" -f 5) | ||||
| 
 | ||||
|     _authz_url=$(echo "$ventry" | cut -d "$sep" -f 6) | ||||
|     if [ "$keyauthorization" = "$STATE_VERIFIED" ]; then | ||||
|       _info "$d is already verified, skip $vtype." | ||||
|       continue | ||||
|  | @ -4860,6 +4864,7 @@ $_authorizations_map" | |||
|     _debug "d" "$d" | ||||
|     _debug "keyauthorization" "$keyauthorization" | ||||
|     _debug "uri" "$uri" | ||||
|     _debug "_authz_url" "$_authz_url" | ||||
|     removelevel="" | ||||
|     token="$(printf "%s" "$keyauthorization" | cut -d '.' -f 1)" | ||||
| 
 | ||||
|  | @ -4967,6 +4972,7 @@ $_authorizations_map" | |||
|       MAX_RETRY_TIMES=30 | ||||
|     fi | ||||
| 
 | ||||
|     _debug "Lets check the status of the authz" | ||||
|     while true; do | ||||
|       waittimes=$(_math "$waittimes" + 1) | ||||
|       if [ "$waittimes" -ge "$MAX_RETRY_TIMES" ]; then | ||||
|  | @ -5014,9 +5020,9 @@ $_authorizations_map" | |||
|         break | ||||
|       fi | ||||
| 
 | ||||
|       if [ "$status" = "pending" ]; then | ||||
|       if _contains "$status" "pending"; then | ||||
|         _info "Pending, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" | ||||
|       elif [ "$status" = "processing" ]; then | ||||
|       elif _contains "$status" "processing"; then | ||||
|         _info "Processing, The CA is processing your order, please just wait. ($waittimes/$MAX_RETRY_TIMES)" | ||||
|       else | ||||
|         _err "$d:Verify error:$response" | ||||
|  | @ -5029,7 +5035,7 @@ $_authorizations_map" | |||
|       _sleep 2 | ||||
|       _debug "checking" | ||||
| 
 | ||||
|       _send_signed_request "$uri" | ||||
|       _send_signed_request "$_authz_url" | ||||
| 
 | ||||
|       if [ "$?" != "0" ]; then | ||||
|         _err "$d:Verify error:$response" | ||||
|  |  | |||
|  | @ -1,34 +1,35 @@ | |||
| #!/usr/bin/env sh | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # Here is a script to deploy cert to Synology DSM | ||||
| # | ||||
| # It requires following environment variables: | ||||
| # | ||||
| # SYNO_Username - Synology Username to login (must be an administrator) | ||||
| # SYNO_Password - Synology Password to login | ||||
| # SYNO_Certificate - Certificate description to target for replacement | ||||
| # | ||||
| # The following environmental variables may be set if you don't like their | ||||
| # default values: | ||||
| # | ||||
| # SYNO_Scheme - defaults to http | ||||
| # SYNO_Hostname - defaults to localhost | ||||
| # SYNO_Port - defaults to 5000 | ||||
| # SYNO_DID - device ID to skip OTP - defaults to empty | ||||
| # SYNO_TOTP_SECRET - TOTP secret to generate OTP - defaults to empty | ||||
| # | ||||
| ################################################################################ | ||||
| # ACME.sh 3rd party deploy plugin for Synology DSM | ||||
| ################################################################################ | ||||
| # Authors: Brian Hartvigsen (creator), https://github.com/tresni | ||||
| #          Martin Arndt (contributor), https://troublezone.net/ | ||||
| # Updated: 2023-07-03 | ||||
| # Issues:  https://github.com/acmesh-official/acme.sh/issues/2727 | ||||
| ################################################################################ | ||||
| # Usage: | ||||
| # 1. export SYNO_Username="adminUser" | ||||
| # 2. export SYNO_Password="adminPassword" | ||||
| # Optional exports (shown values are the defaults): | ||||
| # - export SYNO_Certificate="" to replace a specific certificate via description | ||||
| # - export SYNO_Scheme="http" | ||||
| # - export SYNO_Hostname="localhost" | ||||
| # - export SYNO_Port="5000" | ||||
| # - export SYNO_Device_Name="CertRenewal" - required for skipping 2FA-OTP | ||||
| # - export SYNO_Device_ID=""              - required for skipping 2FA-OTP | ||||
| # 3. acme.sh --deploy --deploy-hook synology_dsm -d example.com | ||||
| ################################################################################ | ||||
| # Dependencies: | ||||
| # ------------- | ||||
| # - jq and curl | ||||
| # - oathtool (When using 2 Factor Authentication and SYNO_TOTP_SECRET is set) | ||||
| # | ||||
| #returns 0 means success, otherwise error. | ||||
| 
 | ||||
| ########  Public functions ##################### | ||||
| # - jq & curl | ||||
| ################################################################################ | ||||
| # Return value: | ||||
| # 0 means success, otherwise error. | ||||
| ################################################################################ | ||||
| 
 | ||||
| ########## Public functions #################################################### | ||||
| #domain keyfile certfile cafile fullchain | ||||
| synology_dsm_deploy() { | ||||
| 
 | ||||
|   _cdomain="$1" | ||||
|   _ckey="$2" | ||||
|   _ccert="$3" | ||||
|  | @ -36,39 +37,46 @@ synology_dsm_deploy() { | |||
| 
 | ||||
|   _debug _cdomain "$_cdomain" | ||||
| 
 | ||||
|   # Get Username and Password, but don't save until we successfully authenticate | ||||
|   # Get username & password, but don't save until we authenticated successfully | ||||
|   _getdeployconf SYNO_Username | ||||
|   _getdeployconf SYNO_Password | ||||
|   _getdeployconf SYNO_Create | ||||
|   _getdeployconf SYNO_DID | ||||
|   _getdeployconf SYNO_TOTP_SECRET | ||||
|   _getdeployconf SYNO_Device_Name | ||||
|   _getdeployconf SYNO_Device_ID | ||||
|   if [ -z "${SYNO_Username:-}" ] || [ -z "${SYNO_Password:-}" ]; then | ||||
|     _err "SYNO_Username & SYNO_Password must be set" | ||||
|     return 1 | ||||
|   fi | ||||
|   if [ -n "${SYNO_Device_Name:-}" ] && [ -z "${SYNO_Device_ID:-}" ]; then | ||||
|     _err "SYNO_Device_Name set, but SYNO_Device_ID is empty" | ||||
|     return 1 | ||||
|   fi | ||||
|   _debug2 SYNO_Username "$SYNO_Username" | ||||
|   _secure_debug2 SYNO_Password "$SYNO_Password" | ||||
|   _debug2 SYNO_Create "$SYNO_Create" | ||||
|   _debug2 SYNO_Device_Name "$SYNO_Device_Name" | ||||
|   _secure_debug2 SYNO_Device_ID "$SYNO_Device_ID" | ||||
| 
 | ||||
|   # Optional scheme, hostname, and port for Synology DSM | ||||
|   # Optional scheme, hostname & port for Synology DSM | ||||
|   _getdeployconf SYNO_Scheme | ||||
|   _getdeployconf SYNO_Hostname | ||||
|   _getdeployconf SYNO_Port | ||||
| 
 | ||||
|   # default vaules for scheme, hostname, and port | ||||
|   # defaulting to localhost and http because it's localhost... | ||||
|   # Default values for scheme, hostname & port | ||||
|   # Defaulting to localhost & http, because it's localhost… | ||||
|   [ -n "${SYNO_Scheme}" ] || SYNO_Scheme="http" | ||||
|   [ -n "${SYNO_Hostname}" ] || SYNO_Hostname="localhost" | ||||
|   [ -n "${SYNO_Port}" ] || SYNO_Port="5000" | ||||
| 
 | ||||
|   _savedeployconf SYNO_Scheme "$SYNO_Scheme" | ||||
|   _savedeployconf SYNO_Hostname "$SYNO_Hostname" | ||||
|   _savedeployconf SYNO_Port "$SYNO_Port" | ||||
| 
 | ||||
|   _debug2 SYNO_Scheme "$SYNO_Scheme" | ||||
|   _debug2 SYNO_Hostname "$SYNO_Hostname" | ||||
|   _debug2 SYNO_Port "$SYNO_Port" | ||||
| 
 | ||||
|   # Get the certificate description, but don't save it until we verfiy it's real | ||||
|   # Get the certificate description, but don't save it until we verify it's real | ||||
|   _getdeployconf SYNO_Certificate | ||||
|   _debug SYNO_Certificate "${SYNO_Certificate:-}" | ||||
| 
 | ||||
|  | @ -87,49 +95,72 @@ synology_dsm_deploy() { | |||
|   _debug3 response "$response" | ||||
|   _debug3 api_version "$api_version" | ||||
| 
 | ||||
|   # Login, get the token from JSON and session id from cookie | ||||
|   # Login, get the session ID & SynoToken from JSON | ||||
|   _info "Logging into $SYNO_Hostname:$SYNO_Port" | ||||
|   encoded_username="$(printf "%s" "$SYNO_Username" | _url_encode)" | ||||
|   encoded_password="$(printf "%s" "$SYNO_Password" | _url_encode)" | ||||
| 
 | ||||
|   otp_code="" | ||||
|   # START - DEPRECATED, only kept for legacy compatibility reasons | ||||
|   if [ -n "$SYNO_TOTP_SECRET" ]; then | ||||
|     _info "WARNING: Usage of SYNO_TOTP_SECRET is deprecated!" | ||||
|     _info "         See synology_dsm.sh script or ACME.sh Wiki page for details:" | ||||
|     _info "         https://github.com/acmesh-official/acme.sh/wiki/Synology-NAS-Guide" | ||||
|     DEPRECATED_otp_code="" | ||||
|     if _exists oathtool; then | ||||
|       otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" | ||||
|       DEPRECATED_otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)" | ||||
|     else | ||||
|       _err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET" | ||||
|       return 1 | ||||
|     fi | ||||
| 
 | ||||
|     if [ -n "$SYNO_DID" ]; then | ||||
|       _H1="Cookie: did=$SYNO_DID" | ||||
|       export _H1 | ||||
|       _debug3 H1 "${_H1}" | ||||
|     fi | ||||
| 
 | ||||
|     response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$DEPRECATED_otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") | ||||
|     _debug3 response "$response" | ||||
|   # END - DEPRECATED, only kept for legacy compatibility reasons | ||||
|   # Get device ID if still empty first, otherwise log in right away | ||||
|   elif [ -z "${SYNO_Device_ID:-}" ]; then | ||||
|     printf "Enter OTP code for user '%s': " "$SYNO_Username" | ||||
|     read -r otp_code | ||||
|     if [ -z "${SYNO_Device_Name:-}" ]; then | ||||
|       printf "Enter device name or leave empty for default (CertRenewal): " | ||||
|       read -r SYNO_Device_Name | ||||
|       [ -n "${SYNO_Device_Name}" ] || SYNO_Device_Name="CertRenewal" | ||||
|     fi | ||||
| 
 | ||||
|     response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&otp_code=$otp_code&enable_syno_token=yes&enable_device_token=yes&device_name=$SYNO_Device_Name") | ||||
|     _debug3 response "$response" | ||||
|     SYNO_Device_ID=$(echo "$response" | grep "device_id" | sed -n 's/.*"device_id" *: *"\([^"]*\).*/\1/p') | ||||
|     _secure_debug2 SYNO_Device_ID "$SYNO_Device_ID" | ||||
|   else | ||||
|     response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=login&format=sid&account=$encoded_username&passwd=$encoded_password&enable_syno_token=yes&device_name=$SYNO_Device_Name&device_id=$SYNO_Device_ID") | ||||
|     _debug3 response "$response" | ||||
|   fi | ||||
| 
 | ||||
|   if [ -n "$SYNO_DID" ]; then | ||||
|     _H1="Cookie: did=$SYNO_DID" | ||||
|     export _H1 | ||||
|     _debug3 H1 "${_H1}" | ||||
|   fi | ||||
| 
 | ||||
|   response=$(_post "method=login&account=$encoded_username&passwd=$encoded_password&api=SYNO.API.Auth&version=$api_version&enable_syno_token=yes&otp_code=$otp_code&device_name=certrenewal&device_id=$SYNO_DID" "$_base_url/webapi/auth.cgi?enable_syno_token=yes") | ||||
|   sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') | ||||
|   token=$(echo "$response" | grep "synotoken" | sed -n 's/.*"synotoken" *: *"\([^"]*\).*/\1/p') | ||||
|   _debug3 response "$response" | ||||
|   _debug token "$token" | ||||
| 
 | ||||
|   if [ -z "$token" ]; then | ||||
|     _err "Unable to authenticate to $SYNO_Hostname:$SYNO_Port using $SYNO_Scheme." | ||||
|     _err "Check your username and password." | ||||
|     _err "If two-factor authentication is enabled for the user, set SYNO_TOTP_SECRET." | ||||
|   _debug "Session ID" "$sid" | ||||
|   _debug SynoToken "$token" | ||||
|   if [ -z "$SYNO_DID" ] && [ -z "$SYNO_Device_ID" ] || [ -z "$sid" ] || [ -z "$token" ]; then | ||||
|     _err "Unable to authenticate to $_base_url - check your username & password." | ||||
|     _err "If two-factor authentication is enabled for the user, set SYNO_Device_ID." | ||||
|     return 1 | ||||
|   fi | ||||
|   sid=$(echo "$response" | grep "sid" | sed -n 's/.*"sid" *: *"\([^"]*\).*/\1/p') | ||||
| 
 | ||||
|   _H1="X-SYNO-TOKEN: $token" | ||||
|   export _H1 | ||||
|   _debug2 H1 "${_H1}" | ||||
| 
 | ||||
|   # Now that we know the username and password are good, save them | ||||
|   # Now that we know the username & password are good, save them | ||||
|   _savedeployconf SYNO_Username "$SYNO_Username" | ||||
|   _savedeployconf SYNO_Password "$SYNO_Password" | ||||
|   _savedeployconf SYNO_DID "$SYNO_DID" | ||||
|   _savedeployconf SYNO_TOTP_SECRET "$SYNO_TOTP_SECRET" | ||||
|   _savedeployconf SYNO_Device_Name "$SYNO_Device_Name" | ||||
|   _savedeployconf SYNO_Device_ID "$SYNO_Device_ID" | ||||
| 
 | ||||
|   _info "Getting certificates in Synology DSM" | ||||
|   response=$(_post "api=SYNO.Core.Certificate.CRT&method=list&version=1&_sid=$sid" "$_base_url/webapi/entry.cgi") | ||||
|  | @ -140,11 +171,11 @@ synology_dsm_deploy() { | |||
|   _debug2 id "$id" | ||||
| 
 | ||||
|   if [ -z "$id" ] && [ -z "${SYNO_Create:-}" ]; then | ||||
|     _err "Unable to find certificate: $SYNO_Certificate and \$SYNO_Create is not set" | ||||
|     _err "Unable to find certificate: $SYNO_Certificate & \$SYNO_Create is not set" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   # we've verified this certificate description is a thing, so save it | ||||
|   # We've verified this certificate description is a thing, so save it | ||||
|   _savedeployconf SYNO_Certificate "$SYNO_Certificate" "base64" | ||||
| 
 | ||||
|   _info "Generate form POST request" | ||||
|  | @ -156,10 +187,10 @@ synology_dsm_deploy() { | |||
|   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"id\"${nl}${nl}$id" | ||||
|   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"desc\"${nl}${nl}${SYNO_Certificate}" | ||||
|   if echo "$response" | sed -n "s/.*\"desc\":\"$escaped_certificate\",\([^{]*\).*/\1/p" | grep -- 'is_default":true' >/dev/null; then | ||||
|     _debug2 default "this is the default certificate" | ||||
|     _debug2 default "This is the default certificate" | ||||
|     content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"as_default\"${nl}${nl}true" | ||||
|   else | ||||
|     _debug2 default "this is NOT the default certificate" | ||||
|     _debug2 default "This is NOT the default certificate" | ||||
|   fi | ||||
|   content="$content${nl}--$delim--${nl}" | ||||
|   content="$(printf "%b_" "$content")" | ||||
|  | @ -171,13 +202,23 @@ synology_dsm_deploy() { | |||
| 
 | ||||
|   if ! echo "$response" | grep '"error":' >/dev/null; then | ||||
|     if echo "$response" | grep '"restart_httpd":true' >/dev/null; then | ||||
|       _info "http services were restarted" | ||||
|       _info "Restarting HTTP services succeeded" | ||||
|     else | ||||
|       _info "http services were NOT restarted" | ||||
|       _info "Restarting HTTP services failed" | ||||
|     fi | ||||
| 
 | ||||
|     _logout | ||||
|     return 0 | ||||
|   else | ||||
|     _err "Unable to update certificate, error code $response" | ||||
|     _logout | ||||
|     return 1 | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| ####################  Private functions below ################################## | ||||
| _logout() { | ||||
|   # Logout to not occupy a permanent session, e.g. in DSM's "Connected Users" widget | ||||
|   response=$(_get "$_base_url/webapi/entry.cgi?api=SYNO.API.Auth&version=$api_version&method=logout") | ||||
|   _debug3 response "$response" | ||||
| } | ||||
|  |  | |||
|  | @ -1,46 +1,46 @@ | |||
| #!/usr/bin/env sh | ||||
| #This file name is "dns_1984hosting.sh" | ||||
| #So, here must be a method dns_1984hosting_add() | ||||
| #Which will be called by acme.sh to add the txt record to your api system. | ||||
| #returns 0 means success, otherwise error. | ||||
| # This file name is "dns_1984hosting.sh" | ||||
| # So, here must be a method dns_1984hosting_add() | ||||
| # Which will be called by acme.sh to add the txt record to your api system. | ||||
| # returns 0 means success, otherwise error. | ||||
| 
 | ||||
| #Author: Adrian Fedoreanu | ||||
| #Report Bugs here: https://github.com/acmesh-official/acme.sh | ||||
| # Author: Adrian Fedoreanu | ||||
| # Report Bugs here: https://github.com/acmesh-official/acme.sh | ||||
| # or here... https://github.com/acmesh-official/acme.sh/issues/2851 | ||||
| # | ||||
| ########  Public functions ##################### | ||||
| 
 | ||||
| ######## Public functions ##################### | ||||
| 
 | ||||
| # Export 1984HOSTING username and password in following variables | ||||
| # | ||||
| #  One984HOSTING_Username=username | ||||
| #  One984HOSTING_Password=password | ||||
| # | ||||
| # sessionid cookie is saved in ~/.acme.sh/account.conf | ||||
| # username/password need to be set only when changed. | ||||
| # username/password and csrftoken/sessionid cookies are saved in ~/.acme.sh/account.conf | ||||
| 
 | ||||
| #Usage: dns_1984hosting_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | ||||
| # Usage: dns_1984hosting_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | ||||
| # Add a text record. | ||||
| dns_1984hosting_add() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
| 
 | ||||
|   _info "Add TXT record using 1984Hosting" | ||||
|   _info "Add TXT record using 1984Hosting." | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
| 
 | ||||
|   if ! _1984hosting_login; then | ||||
|     _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file" | ||||
|     _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug "First detect the root zone" | ||||
|   _debug "First detect the root zone." | ||||
|   if ! _get_root "$fulldomain"; then | ||||
|     _err "invalid domain" "$fulldomain" | ||||
|     _err "Invalid domain '$fulldomain'." | ||||
|     return 1 | ||||
|   fi | ||||
|   _debug _sub_domain "$_sub_domain" | ||||
|   _debug _domain "$_domain" | ||||
| 
 | ||||
|   _debug "Add TXT record $fulldomain with value '$txtvalue'" | ||||
|   _debug "Add TXT record $fulldomain with value '$txtvalue'." | ||||
|   value="$(printf '%s' "$txtvalue" | _url_encode)" | ||||
|   url="https://1984.hosting/domains/entry/" | ||||
| 
 | ||||
|  | @ -53,93 +53,97 @@ dns_1984hosting_add() { | |||
|   _debug2 postdata "$postdata" | ||||
| 
 | ||||
|   _authpost "$postdata" "$url" | ||||
|   response="$(echo "$_response" | _normalizeJson)" | ||||
|   _debug2 response "$response" | ||||
| 
 | ||||
|   if _contains "$response" '"haserrors": true'; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post" | ||||
|   if _contains "$_response" '"haserrors": true'; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain bad RC from _post." | ||||
|     return 1 | ||||
|   elif _contains "$response" "html>"; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file" | ||||
|   elif _contains "$_response" "html>"; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain. Check $HTTP_HEADER file." | ||||
|     return 1 | ||||
|   elif _contains "$response" '"auth": false'; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie" | ||||
|   elif _contains "$_response" '"auth": false'; then | ||||
|     _err "1984Hosting failed to add TXT record for $_sub_domain. Invalid or expired cookie." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _info "Added acme challenge TXT record for $fulldomain at 1984Hosting" | ||||
|   _info "Added acme challenge TXT record for $fulldomain at 1984Hosting." | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| #Usage: fulldomain txtvalue | ||||
| #Remove the txt record after validation. | ||||
| # Usage: fulldomain txtvalue | ||||
| # Remove the txt record after validation. | ||||
| dns_1984hosting_rm() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
| 
 | ||||
|   _info "Delete TXT record using 1984Hosting" | ||||
|   _info "Delete TXT record using 1984Hosting." | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
| 
 | ||||
|   if ! _1984hosting_login; then | ||||
|     _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file" | ||||
|     _err "1984Hosting login failed for user $One984HOSTING_Username. Check $HTTP_HEADER file." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _debug "First detect the root zone" | ||||
|   _debug "First detect the root zone." | ||||
|   if ! _get_root "$fulldomain"; then | ||||
|     _err "invalid domain" "$fulldomain" | ||||
|     _err "Invalid domain '$fulldomain'." | ||||
|     return 1 | ||||
|   fi | ||||
|   _debug _sub_domain "$_sub_domain" | ||||
|   _debug _domain "$_domain" | ||||
|   _debug "Delete $fulldomain TXT record" | ||||
|   _debug "Delete $fulldomain TXT record." | ||||
| 
 | ||||
|   url="https://1984.hosting/domains" | ||||
|   if ! _get_zone_id "$url" "$_domain"; then | ||||
|     _err "invalid zone" "$_domain" | ||||
|     _err "Invalid zone '$_domain'." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _htmlget "$url/$_zone_id" "$txtvalue" | ||||
|   _debug2 _response "$_response" | ||||
|   entry_id="$(echo "$_response" | _egrep_o 'entry_[0-9]+' | sed 's/entry_//')" | ||||
|   _debug2 entry_id "$entry_id" | ||||
|   if [ -z "$entry_id" ]; then | ||||
|     _err "Error getting TXT entry_id for $1" | ||||
|     _err "Error getting TXT entry_id for $1." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _authpost "entry=$entry_id" "$url/delentry/" | ||||
|   response="$(echo "$_response" | _normalizeJson)" | ||||
|   _debug2 response "$response" | ||||
| 
 | ||||
|   if ! _contains "$response" '"ok": true'; then | ||||
|     _err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post" | ||||
|   if ! _contains "$_response" '"ok": true'; then | ||||
|     _err "1984Hosting failed to delete TXT record for $entry_id bad RC from _post." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting" | ||||
|   _info "Deleted acme challenge TXT record for $fulldomain at 1984Hosting." | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| ####################  Private functions below ################################## | ||||
| 
 | ||||
| # usage: _1984hosting_login username password | ||||
| # returns 0 success | ||||
| _1984hosting_login() { | ||||
|   if ! _check_credentials; then return 1; fi | ||||
| 
 | ||||
|   if _check_cookies; then | ||||
|     _debug "Already logged in" | ||||
|     _debug "Already logged in." | ||||
|     return 0 | ||||
|   fi | ||||
| 
 | ||||
|   _debug "Login to 1984Hosting as user $One984HOSTING_Username" | ||||
|   _debug "Login to 1984Hosting as user $One984HOSTING_Username." | ||||
|   username=$(printf '%s' "$One984HOSTING_Username" | _url_encode) | ||||
|   password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) | ||||
|   url="https://1984.hosting/accounts/checkuserauth/" | ||||
| 
 | ||||
|   _get "https://1984.hosting/accounts/login/" | grep "csrfmiddlewaretoken" | ||||
|   csrftoken="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" | ||||
|   sessionid="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'sessionid=[^;]*;' | tr -d ';')" | ||||
| 
 | ||||
|   if [ -z "$csrftoken" ] || [ -z "$sessionid" ]; then | ||||
|     _err "One or more cookies are empty: '$csrftoken', '$sessionid'." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   export _H1="Cookie: $csrftoken; $sessionid" | ||||
|   export _H2="Referer: https://1984.hosting/accounts/login/" | ||||
|   csrf_header=$(echo "$csrftoken" | sed 's/csrftoken=//' | _head_n 1) | ||||
|   export _H3="X-CSRFToken: $csrf_header" | ||||
| 
 | ||||
|   response="$(_post "username=$username&password=$password&otpkey=" $url)" | ||||
|   response="$(echo "$response" | _normalizeJson)" | ||||
|   _debug2 response "$response" | ||||
|  | @ -149,6 +153,8 @@ _1984hosting_login() { | |||
|     One984HOSTING_CSRFTOKEN_COOKIE="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _egrep_o 'csrftoken=[^;]*;' | tr -d ';')" | ||||
|     export One984HOSTING_SESSIONID_COOKIE | ||||
|     export One984HOSTING_CSRFTOKEN_COOKIE | ||||
|     _saveaccountconf_mutable One984HOSTING_Username "$One984HOSTING_Username" | ||||
|     _saveaccountconf_mutable One984HOSTING_Password "$One984HOSTING_Password" | ||||
|     _saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE" | ||||
|     _saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE" | ||||
|     return 0 | ||||
|  | @ -157,9 +163,13 @@ _1984hosting_login() { | |||
| } | ||||
| 
 | ||||
| _check_credentials() { | ||||
|   One984HOSTING_Username="${One984HOSTING_Username:-$(_readaccountconf_mutable One984HOSTING_Username)}" | ||||
|   One984HOSTING_Password="${One984HOSTING_Password:-$(_readaccountconf_mutable One984HOSTING_Password)}" | ||||
|   if [ -z "$One984HOSTING_Username" ] || [ -z "$One984HOSTING_Password" ]; then | ||||
|     One984HOSTING_Username="" | ||||
|     One984HOSTING_Password="" | ||||
|     _clearaccountconf_mutable One984HOSTING_Username | ||||
|     _clearaccountconf_mutable One984HOSTING_Password | ||||
|     _err "You haven't specified 1984Hosting username or password yet." | ||||
|     _err "Please export as One984HOSTING_Username / One984HOSTING_Password and try again." | ||||
|     return 1 | ||||
|  | @ -171,42 +181,43 @@ _check_cookies() { | |||
|   One984HOSTING_SESSIONID_COOKIE="${One984HOSTING_SESSIONID_COOKIE:-$(_readaccountconf_mutable One984HOSTING_SESSIONID_COOKIE)}" | ||||
|   One984HOSTING_CSRFTOKEN_COOKIE="${One984HOSTING_CSRFTOKEN_COOKIE:-$(_readaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE)}" | ||||
|   if [ -z "$One984HOSTING_SESSIONID_COOKIE" ] || [ -z "$One984HOSTING_CSRFTOKEN_COOKIE" ]; then | ||||
|     _debug "No cached cookie(s) found" | ||||
|     _debug "No cached cookie(s) found." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _authget "https://1984.hosting/accounts/loginstatus/" | ||||
|   if _contains "$response" '"ok": true'; then | ||||
|     _debug "Cached cookies still valid" | ||||
|   if _contains "$_response" '"ok": true'; then | ||||
|     _debug "Cached cookies still valid." | ||||
|     return 0 | ||||
|   fi | ||||
|   _debug "Cached cookies no longer valid" | ||||
| 
 | ||||
|   _debug "Cached cookies no longer valid. Clearing cookies." | ||||
|   One984HOSTING_SESSIONID_COOKIE="" | ||||
|   One984HOSTING_CSRFTOKEN_COOKIE="" | ||||
|   _saveaccountconf_mutable One984HOSTING_SESSIONID_COOKIE "$One984HOSTING_SESSIONID_COOKIE" | ||||
|   _saveaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE "$One984HOSTING_CSRFTOKEN_COOKIE" | ||||
|   _clearaccountconf_mutable One984HOSTING_SESSIONID_COOKIE | ||||
|   _clearaccountconf_mutable One984HOSTING_CSRFTOKEN_COOKIE | ||||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| #_acme-challenge.www.domain.com | ||||
| #returns | ||||
| # _sub_domain=_acme-challenge.www | ||||
| # _domain=domain.com | ||||
| # _acme-challenge.www.domain.com | ||||
| # Returns | ||||
| #  _sub_domain=_acme-challenge.www | ||||
| #  _domain=domain.com | ||||
| _get_root() { | ||||
|   domain="$1" | ||||
|   i=1 | ||||
|   p=1 | ||||
|   while true; do | ||||
|     h=$(printf "%s" "$domain" | cut -d . -f $i-100) | ||||
|     h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) | ||||
| 
 | ||||
|     # not valid | ||||
|     if [ -z "$h" ]; then | ||||
|       #not valid | ||||
|       return 1 | ||||
|     fi | ||||
| 
 | ||||
|     _authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." | ||||
|     if _contains "$_response" "serial" && ! _contains "$_response" "null"; then | ||||
|       _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) | ||||
|       _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-"$p") | ||||
|       _domain="$h" | ||||
|       return 0 | ||||
|     fi | ||||
|  | @ -216,46 +227,47 @@ _get_root() { | |||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| #usage: _get_zone_id url domain.com | ||||
| #returns zone id for domain.com | ||||
| # Usage: _get_zone_id url domain.com | ||||
| # Returns zone id for domain.com | ||||
| _get_zone_id() { | ||||
|   url=$1 | ||||
|   domain=$2 | ||||
|   _htmlget "$url" "$domain" | ||||
|   _debug2 _response "$_response" | ||||
|   _zone_id="$(echo "$_response" | _egrep_o 'zone\/[0-9]+' | _head_n 1)" | ||||
|   _debug2 _zone_id "$_zone_id" | ||||
|   if [ -z "$_zone_id" ]; then | ||||
|     _err "Error getting _zone_id for $2" | ||||
|     _err "Error getting _zone_id for $2." | ||||
|     return 1 | ||||
|   fi | ||||
|   return 0 | ||||
| } | ||||
| 
 | ||||
| # add extra headers to request | ||||
| # Add extra headers to request | ||||
| _authget() { | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" | ||||
|   _response=$(_get "$1" | _normalizeJson) | ||||
|   _debug2 _response "$_response" | ||||
| } | ||||
| 
 | ||||
| # truncate huge HTML response | ||||
| # echo: Argument list too long | ||||
| # Truncate huge HTML response | ||||
| # Echo: Argument list too long | ||||
| _htmlget() { | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" | ||||
|   _response=$(_get "$1" | grep "$2") | ||||
|   if _contains "$_response" "@$2"; then | ||||
|     _response=$(echo "$_response" | grep -v "[@]" | _head_n 1) | ||||
|   fi | ||||
|   _debug2 _response "$_response" | ||||
| } | ||||
| 
 | ||||
| # add extra headers to request | ||||
| # Add extra headers to request | ||||
| _authpost() { | ||||
|   url="https://1984.hosting/domains" | ||||
|   _get_zone_id "$url" "$_domain" | ||||
|   csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")" | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" | ||||
|   export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE; $One984HOSTING_SESSIONID_COOKIE" | ||||
|   export _H2="Referer: https://1984.hosting/domains/$_zone_id" | ||||
|   export _H3="X-CSRFToken: $csrf_header" | ||||
|   _response=$(_post "$1" "$2") | ||||
|   _response="$(_post "$1" "$2" | _normalizeJson)" | ||||
|   _debug2 _response "$_response" | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,89 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| #Here is a sample custom api script. | ||||
| #This file name is "dns_bookmyname.sh" | ||||
| #So, here must be a method   dns_bookmyname_add() | ||||
| #Which will be called by acme.sh to add the txt record to your api system. | ||||
| #returns 0 means success, otherwise error. | ||||
| # | ||||
| #Author: Neilpang | ||||
| #Report Bugs here: https://github.com/acmesh-official/acme.sh | ||||
| # | ||||
| ########  Public functions ##################### | ||||
| 
 | ||||
| # Please Read this guide first: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide | ||||
| 
 | ||||
| # BookMyName urls: | ||||
| # https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=add&value="XXXXXXXX"' | ||||
| # https://BOOKMYNAME_USERNAME:BOOKMYNAME_PASSWORD@www.bookmyname.com/dyndns/?hostname=_acme-challenge.domain.tld&type=txt&ttl=300&do=remove&value="XXXXXXXX"' | ||||
| 
 | ||||
| # Output: | ||||
| #good: update done, cid 123456, domain id 456789, type txt, ip XXXXXXXX | ||||
| #good: remove done 1, cid 123456, domain id 456789, ttl 300, type txt, ip XXXXXXXX | ||||
| 
 | ||||
| # Be careful, BMN DNS servers can be slow to pick up changes; using dnssleep is thus advised. | ||||
| 
 | ||||
| # Usage: | ||||
| # export BOOKMYNAME_USERNAME="ABCDE-FREE" | ||||
| # export BOOKMYNAME_PASSWORD="MyPassword" | ||||
| # /usr/local/ssl/acme.sh/acme.sh --dns dns_bookmyname --dnssleep 600 --issue -d domain.tld | ||||
| 
 | ||||
| #Usage: dns_bookmyname_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | ||||
| dns_bookmyname_add() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
|   _info "Using bookmyname" | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
| 
 | ||||
|   BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}" | ||||
|   BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}" | ||||
| 
 | ||||
|   if [ -z "$BOOKMYNAME_USERNAME" ] || [ -z "$BOOKMYNAME_PASSWORD" ]; then | ||||
|     BOOKMYNAME_USERNAME="" | ||||
|     BOOKMYNAME_PASSWORD="" | ||||
|     _err "You didn't specify BookMyName username and password yet." | ||||
|     _err "Please specify them and try again." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   #save the credentials to the account conf file. | ||||
|   _saveaccountconf_mutable BOOKMYNAME_USERNAME "$BOOKMYNAME_USERNAME" | ||||
|   _saveaccountconf_mutable BOOKMYNAME_PASSWORD "$BOOKMYNAME_PASSWORD" | ||||
| 
 | ||||
|   uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" | ||||
|   data="?hostname=${fulldomain}&type=TXT&ttl=300&do=add&value=${txtvalue}" | ||||
|   result="$(_get "${uri}${data}")" | ||||
|   _debug "Result: $result" | ||||
| 
 | ||||
|   if ! _startswith "$result" 'good: update done, cid '; then | ||||
|     _err "Can't add $fulldomain" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #Usage: fulldomain txtvalue | ||||
| #Remove the txt record after validation. | ||||
| dns_bookmyname_rm() { | ||||
|   fulldomain=$1 | ||||
|   txtvalue=$2 | ||||
|   _info "Using bookmyname" | ||||
|   _debug fulldomain "$fulldomain" | ||||
|   _debug txtvalue "$txtvalue" | ||||
| 
 | ||||
|   BOOKMYNAME_USERNAME="${BOOKMYNAME_USERNAME:-$(_readaccountconf_mutable BOOKMYNAME_USERNAME)}" | ||||
|   BOOKMYNAME_PASSWORD="${BOOKMYNAME_PASSWORD:-$(_readaccountconf_mutable BOOKMYNAME_PASSWORD)}" | ||||
| 
 | ||||
|   uri="https://${BOOKMYNAME_USERNAME}:${BOOKMYNAME_PASSWORD}@www.bookmyname.com/dyndns/" | ||||
|   data="?hostname=${fulldomain}&type=TXT&ttl=300&do=remove&value=${txtvalue}" | ||||
|   result="$(_get "${uri}${data}")" | ||||
|   _debug "Result: $result" | ||||
| 
 | ||||
|   if ! _startswith "$result" 'good: remove done 1, cid '; then | ||||
|     _info "Can't remove $fulldomain" | ||||
|   fi | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| ####################  Private functions below ################################## | ||||
|  | @ -107,7 +107,7 @@ _loopia_load_config() { | |||
|   fi | ||||
| 
 | ||||
|   if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then | ||||
|     _err "Password contains quoute or double quoute and this is not supported by dns_loopia.sh" | ||||
|     _err "Password contains a quotation mark or double quotation marks and this is not supported by dns_loopia.sh" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,225 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| # | ||||
| #AWS_ACCESS_KEY_ID="sdfsdfsdfljlbjkljlkjsdfoiwje" | ||||
| # | ||||
| #AWS_SECRET_ACCESS_KEY="xxxxxxx" | ||||
| # | ||||
| #AWS_SES_REGION="us-east-1" | ||||
| # | ||||
| #AWS_SES_TO="xxxx@xxx.com" | ||||
| # | ||||
| #AWS_SES_FROM="xxxx@cccc.com" | ||||
| # | ||||
| #AWS_SES_FROM_NAME="Something something" | ||||
| #This is the Amazon SES api wrapper for acme.sh | ||||
| AWS_WIKI="https://docs.aws.amazon.com/ses/latest/dg/send-email-api.html" | ||||
| 
 | ||||
| aws_ses_send() { | ||||
|   _subject="$1" | ||||
|   _content="$2" | ||||
|   _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped | ||||
|   _debug "_statusCode" "$_statusCode" | ||||
| 
 | ||||
|   AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}" | ||||
|   AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}" | ||||
|   AWS_SES_REGION="${AWS_SES_REGION:-$(_readaccountconf_mutable AWS_SES_REGION)}" | ||||
| 
 | ||||
|   if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then | ||||
|     _use_container_role || _use_instance_role | ||||
|   fi | ||||
| 
 | ||||
|   if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then | ||||
|     AWS_ACCESS_KEY_ID="" | ||||
|     AWS_SECRET_ACCESS_KEY="" | ||||
|     _err "You haven't specified the aws SES api key id and and api key secret yet." | ||||
|     _err "Please create your key and try again. see $(__green $AWS_WIKI)" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   if [ -z "$AWS_SES_REGION" ]; then | ||||
|     AWS_SES_REGION="" | ||||
|     _err "You haven't specified the aws SES api region yet." | ||||
|     _err "Please specify your region and try again. see https://docs.aws.amazon.com/general/latest/gr/ses.html" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   #save for future use, unless using a role which will be fetched as needed | ||||
|   if [ -z "$_using_role" ]; then | ||||
|     _saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID" | ||||
|     _saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY" | ||||
|   fi | ||||
| 
 | ||||
|   AWS_SES_TO="${AWS_SES_TO:-$(_readaccountconf_mutable AWS_SES_TO)}" | ||||
|   if [ -z "$AWS_SES_TO" ]; then | ||||
|     AWS_SES_TO="" | ||||
|     _err "You didn't specify an email to AWS_SES_TO receive messages." | ||||
|     return 1 | ||||
|   fi | ||||
|   _saveaccountconf_mutable AWS_SES_TO "$AWS_SES_TO" | ||||
| 
 | ||||
|   AWS_SES_FROM="${AWS_SES_FROM:-$(_readaccountconf_mutable AWS_SES_FROM)}" | ||||
|   if [ -z "$AWS_SES_FROM" ]; then | ||||
|     AWS_SES_FROM="" | ||||
|     _err "You didn't specify an email to AWS_SES_FROM receive messages." | ||||
|     return 1 | ||||
|   fi | ||||
|   _saveaccountconf_mutable AWS_SES_FROM "$AWS_SES_FROM" | ||||
| 
 | ||||
|   AWS_SES_FROM_NAME="${AWS_SES_FROM_NAME:-$(_readaccountconf_mutable AWS_SES_FROM_NAME)}" | ||||
|   _saveaccountconf_mutable AWS_SES_FROM_NAME "$AWS_SES_FROM_NAME" | ||||
| 
 | ||||
|   AWS_SES_SENDFROM="$AWS_SES_FROM_NAME <$AWS_SES_FROM>" | ||||
| 
 | ||||
|   AWS_SES_ACTION="Action=SendEmail" | ||||
|   AWS_SES_SOURCE="Source=$AWS_SES_SENDFROM" | ||||
|   AWS_SES_TO="Destination.ToAddresses.member.1=$AWS_SES_TO" | ||||
|   AWS_SES_SUBJECT="Message.Subject.Data=$_subject" | ||||
|   AWS_SES_MESSAGE="Message.Body.Text.Data=$_content" | ||||
| 
 | ||||
|   _data="${AWS_SES_ACTION}&${AWS_SES_SOURCE}&${AWS_SES_TO}&${AWS_SES_SUBJECT}&${AWS_SES_MESSAGE}" | ||||
| 
 | ||||
|   response="$(aws_rest POST "" "" "$_data")" | ||||
| } | ||||
| 
 | ||||
| _use_metadata() { | ||||
|   _aws_creds="$( | ||||
|     _get "$1" "" 1 | | ||||
|       _normalizeJson | | ||||
|       tr '{,}' '\n' | | ||||
|       while read -r _line; do | ||||
|         _key="$(echo "${_line%%:*}" | tr -d '"')" | ||||
|         _value="${_line#*:}" | ||||
|         _debug3 "_key" "$_key" | ||||
|         _secure_debug3 "_value" "$_value" | ||||
|         case "$_key" in | ||||
|         AccessKeyId) echo "AWS_ACCESS_KEY_ID=$_value" ;; | ||||
|         SecretAccessKey) echo "AWS_SECRET_ACCESS_KEY=$_value" ;; | ||||
|         Token) echo "AWS_SESSION_TOKEN=$_value" ;; | ||||
|         esac | ||||
|       done | | ||||
|       paste -sd' ' - | ||||
|   )" | ||||
|   _secure_debug "_aws_creds" "$_aws_creds" | ||||
| 
 | ||||
|   if [ -z "$_aws_creds" ]; then | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   eval "$_aws_creds" | ||||
|   _using_role=true | ||||
| } | ||||
| 
 | ||||
| #method uri qstr data | ||||
| aws_rest() { | ||||
|   mtd="$1" | ||||
|   ep="$2" | ||||
|   qsr="$3" | ||||
|   data="$4" | ||||
| 
 | ||||
|   _debug mtd "$mtd" | ||||
|   _debug ep "$ep" | ||||
|   _debug qsr "$qsr" | ||||
|   _debug data "$data" | ||||
| 
 | ||||
|   CanonicalURI="/$ep" | ||||
|   _debug2 CanonicalURI "$CanonicalURI" | ||||
| 
 | ||||
|   CanonicalQueryString="$qsr" | ||||
|   _debug2 CanonicalQueryString "$CanonicalQueryString" | ||||
| 
 | ||||
|   RequestDate="$(date -u +"%Y%m%dT%H%M%SZ")" | ||||
|   _debug2 RequestDate "$RequestDate" | ||||
| 
 | ||||
|   #RequestDate="20161120T141056Z" ############## | ||||
| 
 | ||||
|   export _H1="x-amz-date: $RequestDate" | ||||
| 
 | ||||
|   aws_host="email.$AWS_SES_REGION.amazonaws.com" | ||||
|   CanonicalHeaders="host:$aws_host\nx-amz-date:$RequestDate\n" | ||||
|   SignedHeaders="host;x-amz-date" | ||||
|   if [ -n "$AWS_SESSION_TOKEN" ]; then | ||||
|     export _H3="x-amz-security-token: $AWS_SESSION_TOKEN" | ||||
|     CanonicalHeaders="${CanonicalHeaders}x-amz-security-token:$AWS_SESSION_TOKEN\n" | ||||
|     SignedHeaders="${SignedHeaders};x-amz-security-token" | ||||
|   fi | ||||
|   _debug2 CanonicalHeaders "$CanonicalHeaders" | ||||
|   _debug2 SignedHeaders "$SignedHeaders" | ||||
| 
 | ||||
|   RequestPayload="$data" | ||||
|   _debug2 RequestPayload "$RequestPayload" | ||||
| 
 | ||||
|   Hash="sha256" | ||||
| 
 | ||||
|   CanonicalRequest="$mtd\n$CanonicalURI\n$CanonicalQueryString\n$CanonicalHeaders\n$SignedHeaders\n$(printf "%s" "$RequestPayload" | _digest "$Hash" hex)" | ||||
|   _debug2 CanonicalRequest "$CanonicalRequest" | ||||
| 
 | ||||
|   HashedCanonicalRequest="$(printf "$CanonicalRequest%s" | _digest "$Hash" hex)" | ||||
|   _debug2 HashedCanonicalRequest "$HashedCanonicalRequest" | ||||
| 
 | ||||
|   Algorithm="AWS4-HMAC-SHA256" | ||||
|   _debug2 Algorithm "$Algorithm" | ||||
| 
 | ||||
|   RequestDateOnly="$(echo "$RequestDate" | cut -c 1-8)" | ||||
|   _debug2 RequestDateOnly "$RequestDateOnly" | ||||
| 
 | ||||
|   Region="$AWS_SES_REGION" | ||||
|   Service="ses" | ||||
| 
 | ||||
|   CredentialScope="$RequestDateOnly/$Region/$Service/aws4_request" | ||||
|   _debug2 CredentialScope "$CredentialScope" | ||||
| 
 | ||||
|   StringToSign="$Algorithm\n$RequestDate\n$CredentialScope\n$HashedCanonicalRequest" | ||||
| 
 | ||||
|   _debug2 StringToSign "$StringToSign" | ||||
| 
 | ||||
|   kSecret="AWS4$AWS_SECRET_ACCESS_KEY" | ||||
| 
 | ||||
|   #kSecret="wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" ############################ | ||||
| 
 | ||||
|   _secure_debug2 kSecret "$kSecret" | ||||
| 
 | ||||
|   kSecretH="$(printf "%s" "$kSecret" | _hex_dump | tr -d " ")" | ||||
|   _secure_debug2 kSecretH "$kSecretH" | ||||
| 
 | ||||
|   kDateH="$(printf "$RequestDateOnly%s" | _hmac "$Hash" "$kSecretH" hex)" | ||||
|   _debug2 kDateH "$kDateH" | ||||
| 
 | ||||
|   kRegionH="$(printf "$Region%s" | _hmac "$Hash" "$kDateH" hex)" | ||||
|   _debug2 kRegionH "$kRegionH" | ||||
| 
 | ||||
|   kServiceH="$(printf "$Service%s" | _hmac "$Hash" "$kRegionH" hex)" | ||||
|   _debug2 kServiceH "$kServiceH" | ||||
| 
 | ||||
|   kSigningH="$(printf "%s" "aws4_request" | _hmac "$Hash" "$kServiceH" hex)" | ||||
|   _debug2 kSigningH "$kSigningH" | ||||
| 
 | ||||
|   signature="$(printf "$StringToSign%s" | _hmac "$Hash" "$kSigningH" hex)" | ||||
|   _debug2 signature "$signature" | ||||
| 
 | ||||
|   Authorization="$Algorithm Credential=$AWS_ACCESS_KEY_ID/$CredentialScope, SignedHeaders=$SignedHeaders, Signature=$signature" | ||||
|   _debug2 Authorization "$Authorization" | ||||
| 
 | ||||
|   _H2="Authorization: $Authorization" | ||||
|   _debug _H2 "$_H2" | ||||
| 
 | ||||
|   url="https://$aws_host/$ep" | ||||
|   if [ "$qsr" ]; then | ||||
|     url="https://$aws_host/$ep?$qsr" | ||||
|   fi | ||||
| 
 | ||||
|   if [ "$mtd" = "GET" ]; then | ||||
|     response="$(_get "$url")" | ||||
|   else | ||||
|     response="$(_post "$data" "$url")" | ||||
|   fi | ||||
| 
 | ||||
|   _ret="$?" | ||||
|   _debug2 response "$response" | ||||
|   if [ "$_ret" = "0" ]; then | ||||
|     if _contains "$response" "<ErrorResponse"; then | ||||
|       _err "Response error:$response" | ||||
|       return 1 | ||||
|     fi | ||||
|   fi | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 sg1888
						sg1888