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. Name.com API | ||||||
| 1. Dyn Managed DNS API | 1. Dyn Managed DNS API | ||||||
| 1. Yandex PDD API (https://pdd.yandex.ru) | 1. Yandex PDD API (https://pdd.yandex.ru) | ||||||
|  | 1. Hurricane Electric DNS service (https://dns.he.net) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| And:  | And:  | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								acme.sh
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								acme.sh
									
									
									
									
									
								
							| @ -1182,6 +1182,28 @@ _ss() { | |||||||
|   return 1 |   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] | #domain [password] [isEcc] | ||||||
| toPkcs() { | toPkcs() { | ||||||
|   domain="$1" |   domain="$1" | ||||||
| @ -1195,11 +1217,7 @@ toPkcs() { | |||||||
| 
 | 
 | ||||||
|   _initpath "$domain" "$_isEcc" |   _initpath "$domain" "$_isEcc" | ||||||
| 
 | 
 | ||||||
|   if [ "$pfxPassword" ]; then |   _toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword" | ||||||
|     ${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 |  | ||||||
| 
 | 
 | ||||||
|   if [ "$?" = "0" ]; then |   if [ "$?" = "0" ]; then | ||||||
|     _info "Success, Pfx is exported to: $CERT_PFX_PATH" |     _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. | 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 | # Use custom API | ||||||
| 
 | 
 | ||||||
| If your API is not supported yet, you can write your own DNS 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" |   _parameters="&DomainID=$_domain_id" | ||||||
| 
 | 
 | ||||||
|   if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then |   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\".*}")" |     resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")" | ||||||
|     if [ "$resource" ]; then |     if [ "$resource" ]; then | ||||||
| @ -128,7 +128,7 @@ _get_root() { | |||||||
|   p=1 |   p=1 | ||||||
| 
 | 
 | ||||||
|   if _rest GET "domain.list"; then |   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 |     while true; do | ||||||
|       h=$(printf "%s" "$domain" | cut -d . -f $i-100) |       h=$(printf "%s" "$domain" | cut -d . -f $i-100) | ||||||
|       _debug h "$h" |       _debug h "$h" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user