mirror of
				https://github.com/hiskang/acme.sh
				synced 2025-10-31 02:17:18 +00:00 
			
		
		
		
	
						commit
						3e0971c159
					
				| @ -338,6 +338,7 @@ You don't have to do anything manually! | ||||
| 1. Name.com API | ||||
| 1. Dyn Managed DNS API | ||||
| 1. Yandex PDD API (https://pdd.yandex.ru) | ||||
| 1. Hurricane Electric DNS service (https://dns.he.net) | ||||
| 
 | ||||
| 
 | ||||
| And:  | ||||
|  | ||||
							
								
								
									
										28
									
								
								acme.sh
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								acme.sh
									
									
									
									
									
								
							| @ -1182,6 +1182,28 @@ _ss() { | ||||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| #outfile key cert cacert [password [name [caname]]] | ||||
| _toPkcs() { | ||||
|   _cpfx="$1" | ||||
|   _ckey="$2" | ||||
|   _ccert="$3" | ||||
|   _cca="$4" | ||||
|   pfxPassword="$5" | ||||
|   pfxName="$6" | ||||
|   pfxCaname="$7" | ||||
| 
 | ||||
|   if [ "$pfxCaname" ]; then | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname" | ||||
|   elif [ "$pfxName" ]; then | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" | ||||
|   elif [ "$pfxPassword" ]; then | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" | ||||
|   else | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" | ||||
|   fi | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #domain [password] [isEcc] | ||||
| toPkcs() { | ||||
|   domain="$1" | ||||
| @ -1195,11 +1217,7 @@ toPkcs() { | ||||
| 
 | ||||
|   _initpath "$domain" "$_isEcc" | ||||
| 
 | ||||
|   if [ "$pfxPassword" ]; then | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword" | ||||
|   else | ||||
|     ${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" | ||||
|   fi | ||||
|   _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword" | ||||
| 
 | ||||
|   if [ "$?" = "0" ]; then | ||||
|     _info "Success, Pfx is exported to: $CERT_PFX_PATH" | ||||
|  | ||||
							
								
								
									
										100
									
								
								deploy/unifi.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								deploy/unifi.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| #Here is a script to deploy cert to unifi server. | ||||
| 
 | ||||
| #returns 0 means success, otherwise error. | ||||
| 
 | ||||
| #DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" | ||||
| #DEPLOY_UNIFI_KEYPASS="aircontrolenterprise" | ||||
| #DEPLOY_UNIFI_RELOAD="service unifi restart" | ||||
| 
 | ||||
| ########  Public functions ##################### | ||||
| 
 | ||||
| #domain keyfile certfile cafile fullchain | ||||
| unifi_deploy() { | ||||
|   _cdomain="$1" | ||||
|   _ckey="$2" | ||||
|   _ccert="$3" | ||||
|   _cca="$4" | ||||
|   _cfullchain="$5" | ||||
| 
 | ||||
|   _debug _cdomain "$_cdomain" | ||||
|   _debug _ckey "$_ckey" | ||||
|   _debug _ccert "$_ccert" | ||||
|   _debug _cca "$_cca" | ||||
|   _debug _cfullchain "$_cfullchain" | ||||
| 
 | ||||
|   if ! _exists keytool; then | ||||
|     _err "keytool not found" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore" | ||||
|   _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}" | ||||
|   DEFAULT_UNIFI_KEYPASS="aircontrolenterprise" | ||||
|   _unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}" | ||||
|   DEFAULT_UNIFI_RELOAD="service unifi restart" | ||||
|   _reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}" | ||||
| 
 | ||||
|   _debug _unifi_keystore "$_unifi_keystore" | ||||
|   if [ ! -f "$_unifi_keystore" ]; then | ||||
|     if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then | ||||
|       _err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE" | ||||
|       return 1 | ||||
|     else | ||||
|       _err "It seems that the specified unifi keystore is not valid, please check." | ||||
|       return 1 | ||||
|     fi | ||||
|   fi | ||||
|   if [ ! -w "$_unifi_keystore" ]; then | ||||
|     _err "The file $_unifi_keystore is not writable, please change the permission." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _info "Generate import pkcs12" | ||||
|   _import_pkcs12="$(_mktemp)" | ||||
|   _toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root | ||||
|   if [ "$?" != "0" ]; then | ||||
|     _err "Oops, error creating import pkcs12, please report bug to us." | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _info "Modify unifi keystore: $_unifi_keystore" | ||||
|   if keytool -importkeystore \ | ||||
|     -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \ | ||||
|     -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \ | ||||
|     -alias unifi -noprompt; then | ||||
|     _info "Import keystore success!" | ||||
|     rm "$_import_pkcs12" | ||||
|   else | ||||
|     _err "Import unifi keystore error, please report bug to us." | ||||
|     rm "$_import_pkcs12" | ||||
|     return 1 | ||||
|   fi | ||||
| 
 | ||||
|   _info "Run reload: $_reload" | ||||
|   if eval "$_reload"; then | ||||
|     _info "Reload success!" | ||||
|     if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then | ||||
|       _savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE" | ||||
|     else | ||||
|       _cleardomainconf DEPLOY_UNIFI_KEYSTORE | ||||
|     fi | ||||
|     if [ "$DEPLOY_UNIFI_KEYPASS" ]; then | ||||
|       _savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS" | ||||
|     else | ||||
|       _cleardomainconf DEPLOY_UNIFI_KEYPASS | ||||
|     fi | ||||
|     if [ "$DEPLOY_UNIFI_RELOAD" ]; then | ||||
|       _savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD" | ||||
|     else | ||||
|       _cleardomainconf DEPLOY_UNIFI_RELOAD | ||||
|     fi | ||||
|     return 0 | ||||
|   else | ||||
|     _err "Reload error" | ||||
|     return 1 | ||||
|   fi | ||||
|   return 0 | ||||
| 
 | ||||
| } | ||||
| @ -585,6 +585,25 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org | ||||
| 
 | ||||
| For issues, please report to https://github.com/non7top/acme.sh/issues. | ||||
| 
 | ||||
| # 31. Use Hurricane Electric | ||||
| 
 | ||||
| Hurricane Electric doesn't have an API so just set your login credentials like so: | ||||
| 
 | ||||
| ``` | ||||
| export HE_Username="yourusername" | ||||
| export HE_Password="password" | ||||
| ``` | ||||
| 
 | ||||
| Then you can issue your certificate: | ||||
| 
 | ||||
| ``` | ||||
| acme.sh --issue --dns dns_he -d example.com -d www.example.com | ||||
| ``` | ||||
| 
 | ||||
| The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. | ||||
| 
 | ||||
| Please report any issues to https://github.com/angel333/acme.sh or to <me@ondrejsimek.com>. | ||||
| 
 | ||||
| # Use custom API | ||||
| 
 | ||||
| If your API is not supported yet, you can write your own DNS API. | ||||
|  | ||||
							
								
								
									
										175
									
								
								dnsapi/dns_he.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										175
									
								
								dnsapi/dns_he.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,175 @@ | ||||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| ######################################################################## | ||||
| # Hurricane Electric hook script for acme.sh | ||||
| # | ||||
| # Environment variables: | ||||
| # | ||||
| #  - $HE_Username  (your dns.he.net username) | ||||
| #  - $HE_Password  (your dns.he.net password) | ||||
| # | ||||
| # Author: Ondrej Simek <me@ondrejsimek.com> | ||||
| # Git repo: https://github.com/angel333/acme.sh | ||||
| 
 | ||||
| #-- dns_he_add() - Add TXT record -------------------------------------- | ||||
| # Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..." | ||||
| 
 | ||||
| dns_he_add() { | ||||
|   _full_domain=$1 | ||||
|   _txt_value=$2 | ||||
|   _info "Using DNS-01 Hurricane Electric hook" | ||||
| 
 | ||||
|   if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then | ||||
|     HE_Username= | ||||
|     HE_Password= | ||||
|     _err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables." | ||||
|     return 1 | ||||
|   fi | ||||
|   _saveaccountconf HE_Username "$HE_Username" | ||||
|   _saveaccountconf HE_Password "$HE_Password" | ||||
| 
 | ||||
|   # Fills in the $_zone_id | ||||
|   _find_zone "$_full_domain" || return 1 | ||||
|   _debug "Zone id \"$_zone_id\" will be used." | ||||
| 
 | ||||
|   body="email=${HE_Username}&pass=${HE_Password}" | ||||
|   body="$body&account=" | ||||
|   body="$body&menu=edit_zone" | ||||
|   body="$body&Type=TXT" | ||||
|   body="$body&hosted_dns_zoneid=$_zone_id" | ||||
|   body="$body&hosted_dns_recordid=" | ||||
|   body="$body&hosted_dns_editzone=1" | ||||
|   body="$body&Priority=" | ||||
|   body="$body&Name=$_full_domain" | ||||
|   body="$body&Content=$_txt_value" | ||||
|   body="$body&TTL=300" | ||||
|   body="$body&hosted_dns_editrecord=Submit" | ||||
|   response="$(_post "$body" "https://dns.he.net/")" | ||||
|   exit_code="$?" | ||||
|   if [ "$exit_code" -eq 0 ]; then | ||||
|     _info "TXT record added successfuly." | ||||
|   else | ||||
|     _err "Couldn't add the TXT record." | ||||
|   fi | ||||
|   _debug2 response "$response" | ||||
|   return "$exit_code" | ||||
| } | ||||
| 
 | ||||
| #-- dns_he_rm() - Remove TXT record ------------------------------------ | ||||
| # Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..." | ||||
| 
 | ||||
| dns_he_rm() { | ||||
|   _full_domain=$1 | ||||
|   _txt_value=$2 | ||||
|   _info "Cleaning up after DNS-01 Hurricane Electric hook" | ||||
| 
 | ||||
|   # fills in the $_zone_id | ||||
|   _find_zone "$_full_domain" || return 1 | ||||
|   _debug "Zone id \"$_zone_id\" will be used." | ||||
| 
 | ||||
|   # Find the record id to clean | ||||
|   body="email=${HE_Username}&pass=${HE_Password}" | ||||
|   body="$body&hosted_dns_zoneid=$_zone_id" | ||||
|   body="$body&menu=edit_zone" | ||||
|   body="$body&hosted_dns_editzone=" | ||||
|   domain_regex="$(echo "$_full_domain" | sed 's/\./\\./g')" # escape dots | ||||
|   _record_id=$(_post "$body" "https://dns.he.net/" \ | ||||
|     | tr -d '\n' \ | ||||
|     | _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${domain_regex}','TXT'\)" \ | ||||
|     | _egrep_o "[0-9]+','${domain_regex}','TXT'\)$" \ | ||||
|     | _egrep_o "^[0-9]+" | ||||
|   ) | ||||
|   # The series of egreps above could have been done a bit shorter but | ||||
|   #  I wanted to double-check whether it's the correct record (in case | ||||
|   #  HE changes their website somehow). | ||||
| 
 | ||||
|   # Remove the record | ||||
|   body="email=${HE_Username}&pass=${HE_Password}" | ||||
|   body="$body&menu=edit_zone" | ||||
|   body="$body&hosted_dns_zoneid=$_zone_id" | ||||
|   body="$body&hosted_dns_recordid=$_record_id" | ||||
|   body="$body&hosted_dns_editzone=1" | ||||
|   body="$body&hosted_dns_delrecord=1" | ||||
|   body="$body&hosted_dns_delconfirm=delete" | ||||
|   _post "$body" "https://dns.he.net/" \ | ||||
|     | grep '<div id="dns_status" onClick="hideThis(this);">Successfully removed record.</div>' \ | ||||
|       >/dev/null | ||||
|   exit_code="$?" | ||||
|   if [ "$exit_code" -eq 0 ]; then | ||||
|     _info "Record removed successfuly." | ||||
|   else | ||||
|     _err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand." | ||||
|     return "$exit_code" | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| ########################## PRIVATE FUNCTIONS ########################### | ||||
| 
 | ||||
| #-- _find_zone() ------------------------------------------------------- | ||||
| # Returns the most specific zone found in administration interface. | ||||
| # | ||||
| # Example: | ||||
| # | ||||
| # _find_zone first.second.third.co.uk | ||||
| # | ||||
| # ... will return the first zone that exists in admin out of these: | ||||
| # - "first.second.third.co.uk" | ||||
| # - "second.third.co.uk" | ||||
| # - "third.co.uk" | ||||
| # - "co.uk" <-- unlikely | ||||
| # - "uk"    <-' | ||||
| # | ||||
| # (another approach would be something like this: | ||||
| #   https://github.com/hlandau/acme/blob/master/_doc/dns.hook | ||||
| #   - that's better if there are multiple pages. It's so much simpler. | ||||
| # ) | ||||
| 
 | ||||
| _find_zone() { | ||||
| 
 | ||||
|   _domain="$1" | ||||
| 
 | ||||
|   body="email=${HE_Username}&pass=${HE_Password}" | ||||
|   _matches=$(_post "$body" "https://dns.he.net/" \ | ||||
|     | _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+" | ||||
|   ) | ||||
|   # Zone names and zone IDs are in same order | ||||
|   _zone_ids=$(echo "$_matches" | cut -d '"' -f 5) | ||||
|   _zone_names=$(echo "$_matches" | cut -d '"' -f 3) | ||||
|   _debug2 "These are the zones on this HE account:" | ||||
|   _debug2 "$_zone_names" | ||||
|   _debug2 "And these are their respective IDs:" | ||||
|   _debug2 "$_zone_ids" | ||||
| 
 | ||||
|   # Walk through all possible zone names | ||||
|   _strip_counter=1 | ||||
|   while true; do | ||||
|     _attempted_zone=$(echo "$_domain" | cut -d . -f ${_strip_counter}-) | ||||
| 
 | ||||
|     # All possible zone names have been tried | ||||
|     if [ -z "$_attempted_zone" ]; then | ||||
|       _err "No zone for domain \"$_domain\" found." | ||||
|       return 1 | ||||
|     fi | ||||
| 
 | ||||
|     _debug "Looking for zone \"${_attempted_zone}\"" | ||||
| 
 | ||||
|     # Take care of "." and only match whole lines. Note that grep -F | ||||
|     # cannot be used because there's no way to make it match whole | ||||
|     # lines. | ||||
|     regex="^$(echo "$_attempted_zone" | sed 's/\./\\./g')$" | ||||
|     line_num=$(echo "$_zone_names" \ | ||||
|       | grep -n "$regex" \ | ||||
|       | cut -d : -f 1 | ||||
|     ) | ||||
| 
 | ||||
|     if [ -n "$line_num" ]; then | ||||
|       _zone_id=$(echo "$_zone_ids" | sed "${line_num}q;d") | ||||
|       _debug "Found relevant zone \"$_attempted_zone\" with id \"$_zone_id\" - will be used for domain \"$_domain\"." | ||||
|       return 0 | ||||
|     fi | ||||
| 
 | ||||
|     _debug "Zone \"$_attempted_zone\" doesn't exist, let's try a less specific zone." | ||||
|     _strip_counter=$(_math "$_strip_counter" + 1) | ||||
|   done | ||||
| } | ||||
| # vim: et:ts=2:sw=2: | ||||
| @ -68,7 +68,7 @@ dns_linode_rm() { | ||||
|   _parameters="&DomainID=$_domain_id" | ||||
| 
 | ||||
|   if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then | ||||
|     response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" | ||||
|     response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" | ||||
| 
 | ||||
|     resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" | ||||
|     if [ "$resource" ]; then | ||||
| @ -128,7 +128,7 @@ _get_root() { | ||||
|   p=1 | ||||
| 
 | ||||
|   if _rest GET "domain.list"; then | ||||
|     response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" | ||||
|     response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")" | ||||
|     while true; do | ||||
|       h=$(printf "%s" "$domain" | cut -d . -f $i-100) | ||||
|       _debug h "$h" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user