mirror of
				https://github.com/hiskang/acme.sh
				synced 2025-10-31 10:27:22 +00:00 
			
		
		
		
	Merge pull request #953 from angel333/master
Add DNS API script for Hurricane Electric DNS service
This commit is contained in:
		
						commit
						4af339424a
					
				| @ -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:  | ||||||
|  | |||||||
| @ -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: | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user