mirror of
				https://github.com/hiskang/acme.sh
				synced 2025-10-31 18:37:30 +00:00 
			
		
		
		
	
						commit
						347dab0c14
					
				| @ -292,6 +292,7 @@ You don't have to do anything manually! | |||||||
| 
 | 
 | ||||||
| 1. CloudFlare.com API | 1. CloudFlare.com API | ||||||
| 1. DNSPod.cn API | 1. DNSPod.cn API | ||||||
|  | 1. DNSimple API | ||||||
| 1. CloudXNS.com API | 1. CloudXNS.com API | ||||||
| 1. GoDaddy.com API | 1. GoDaddy.com API | ||||||
| 1. OVH, kimsufi, soyoustart and runabove API | 1. OVH, kimsufi, soyoustart and runabove API | ||||||
| @ -315,6 +316,8 @@ You don't have to do anything manually! | |||||||
| 1. ClouDNS.net API | 1. ClouDNS.net API | ||||||
| 1. Infoblox NIOS API (https://www.infoblox.com/) | 1. Infoblox NIOS API (https://www.infoblox.com/) | ||||||
| 1. VSCALE (https://vscale.io/) | 1. VSCALE (https://vscale.io/) | ||||||
|  | 1. Dynu API (https://www.dynu.com) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| **More APIs coming soon...** | **More APIs coming soon...** | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,8 +21,11 @@ acme.sh --deploy -d example.com --deploy-hook cpanel | |||||||
| ## 2. Deploy ssl cert on kong proxy engine based on api. | ## 2. Deploy ssl cert on kong proxy engine based on api. | ||||||
| 
 | 
 | ||||||
| Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). | Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert). | ||||||
|  | Currently supports Kong-v0.10.x. | ||||||
| 
 | 
 | ||||||
| (TODO) | ```sh | ||||||
|  | acme.sh --deploy -d ftp.example.com --deploy-hook kong | ||||||
|  | ``` | ||||||
| 
 | 
 | ||||||
| ## 3. Deploy the cert to remote server through SSH access. | ## 3. Deploy the cert to remote server through SSH access. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,13 +1,7 @@ | |||||||
| #!/usr/bin/env sh | #!/usr/bin/env sh | ||||||
| 
 | # If certificate already exist it will update only cert and key not touching other parameter | ||||||
| # This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter. | # If certificate  doesn't exist it will only upload cert and key and not set other parameter | ||||||
| # Note that ssl plugin should be available on Kong instance | # Note that we deploy full chain | ||||||
| # The hook will match cdomain to request_host, in case of multiple domain it will always take the first |  | ||||||
| # one (acme.sh behaviour). |  | ||||||
| # If ssl config already exist it will update only cert and key not touching other parameter |  | ||||||
| # If ssl config doesn't exist it will only upload cert and key and not set other parameter |  | ||||||
| # Not that we deploy full chain |  | ||||||
| # See https://getkong.org/plugins/dynamic-ssl/ for other options |  | ||||||
| # Written by Geoffroi Genot <ggenot@voxbone.com> | # Written by Geoffroi Genot <ggenot@voxbone.com> | ||||||
| 
 | 
 | ||||||
| ########  Public functions ##################### | ########  Public functions ##################### | ||||||
| @ -31,14 +25,15 @@ kong_deploy() { | |||||||
|   _debug _cca "$_cca" |   _debug _cca "$_cca" | ||||||
|   _debug _cfullchain "$_cfullchain" |   _debug _cfullchain "$_cfullchain" | ||||||
| 
 | 
 | ||||||
|   #Get uuid linked to the domain |   #Get ssl_uuid linked to the domain | ||||||
|   uuid=$(_get "$KONG_URL/apis?request_host=$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') |   ssl_uuid=$(_get "$KONG_URL/certificates/$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') | ||||||
|   if [ -z "$uuid" ]; then |   if [ -z "$ssl_uuid" ]; then | ||||||
|     _err "Unable to get Kong uuid for domain $_cdomain" |     _debug "Unable to get Kong ssl_uuid for domain $_cdomain" | ||||||
|     _err "Make sure that KONG_URL is correctly configured" |     _debug "Make sure that KONG_URL is correctly configured" | ||||||
|     _err "Make sure that a Kong api request_host match the domain" |     _debug "Make sure that a Kong certificate match the sni" | ||||||
|     _err "Kong url: $KONG_URL" |     _debug "Kong url: $KONG_URL" | ||||||
|     return 1 |     _info "No existing certificate, creating..." | ||||||
|  |     #return 1 | ||||||
|   fi |   fi | ||||||
|   #Save kong url if it's succesful (First run case) |   #Save kong url if it's succesful (First run case) | ||||||
|   _saveaccountconf KONG_URL "$KONG_URL" |   _saveaccountconf KONG_URL "$KONG_URL" | ||||||
| @ -48,12 +43,14 @@ kong_deploy() { | |||||||
|   #Set Header |   #Set Header | ||||||
|   _H1="Content-Type: multipart/form-data; boundary=$delim" |   _H1="Content-Type: multipart/form-data; boundary=$delim" | ||||||
|   #Generate data for request (Multipart/form-data with mixed content) |   #Generate data for request (Multipart/form-data with mixed content) | ||||||
|   #set name to ssl |   if [ -z "$ssl_uuid" ]; then | ||||||
|   content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl" |     #set sni to domain | ||||||
|  |     content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain" | ||||||
|  |   fi | ||||||
|   #add key |   #add key | ||||||
|   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" |   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")" | ||||||
|   #Add cert |   #Add cert | ||||||
|   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" |   content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")" | ||||||
|   #Close multipart |   #Close multipart | ||||||
|   content="$content${nl}--$delim--${nl}" |   content="$content${nl}--$delim--${nl}" | ||||||
|   #Convert CRLF |   #Convert CRLF | ||||||
| @ -61,17 +58,16 @@ kong_deploy() { | |||||||
|   #DEBUG |   #DEBUG | ||||||
|   _debug header "$_H1" |   _debug header "$_H1" | ||||||
|   _debug content "$content" |   _debug content "$content" | ||||||
|   #Check if ssl plugins is aready enabled (if not => POST else => PATCH) |   #Check if sslcreated (if not => POST else => PATCH) | ||||||
|   ssl_uuid=$(_get "$KONG_URL/apis/$uuid/plugins" | _egrep_o '"id":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"[a-zA-Z0-9\-\,\"_\:]*"name":"ssl"' | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}') | 
 | ||||||
|   _debug ssl_uuid "$ssl_uuid" |  | ||||||
|   if [ -z "$ssl_uuid" ]; then |   if [ -z "$ssl_uuid" ]; then | ||||||
|     #Post certificate to Kong |     #Post certificate to Kong | ||||||
|     response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST") |     response=$(_post "$content" "$KONG_URL/certificates" "" "POST") | ||||||
|   else |   else | ||||||
|     #patch |     #patch | ||||||
|     response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH") |     response=$(_post "$content" "$KONG_URL/certificates/$ssl_uuid" "" "PATCH") | ||||||
|   fi |   fi | ||||||
|   if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then |   if ! [ "$(echo "$response" | _egrep_o "created_at")" = "created_at" ]; then | ||||||
|     _err "An error occurred with cert upload. Check response:" |     _err "An error occurred with cert upload. Check response:" | ||||||
|     _err "$response" |     _err "$response" | ||||||
|     return 1 |     return 1 | ||||||
|  | |||||||
| @ -468,6 +468,31 @@ acme.sh --issue --dns dns_dynu -d example.com -d www.example.com | |||||||
| 
 | 
 | ||||||
| The `Dynu_ClientId` and `Dynu_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. | The `Dynu_ClientId` and `Dynu_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. | ||||||
| 
 | 
 | ||||||
|  | ## 25. Use DNSimple API | ||||||
|  | 
 | ||||||
|  | First you need to login to your DNSimple account and generate a new oauth token. | ||||||
|  | 
 | ||||||
|  | https://dnsimple.com/a/{your account id}/account/access_tokens | ||||||
|  | 
 | ||||||
|  | Note that this is an _account_ token and not a user token. The account token is | ||||||
|  | needed to infer the `account_id` used in requests. A user token will not be able | ||||||
|  | to determine the correct account to use. | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | export DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | To issue the cert just specify the `dns_dnsimple` API. | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | acme.sh --issue --dns dns_dnsimple -d example.com | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The `DNSimple_OAUTH_TOKEN` will be saved in `~/.acme.sh/account.conf` and will | ||||||
|  | be reused when needed. | ||||||
|  | 
 | ||||||
|  | If you have any issues with this integration please report them to | ||||||
|  | https://github.com/pho3nixf1re/acme.sh/issues. | ||||||
| 
 | 
 | ||||||
| # Use custom API | # Use custom API | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										215
									
								
								dnsapi/dns_dnsimple.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								dnsapi/dns_dnsimple.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,215 @@ | |||||||
|  | #!/usr/bin/env sh | ||||||
|  | 
 | ||||||
|  | # DNSimple domain api | ||||||
|  | # https://github.com/pho3nixf1re/acme.sh/issues | ||||||
|  | # | ||||||
|  | # This is your oauth token which can be acquired on the account page. Please | ||||||
|  | # note that this must be an _account_ token and not a _user_ token. | ||||||
|  | # https://dnsimple.com/a/<your account id>/account/access_tokens | ||||||
|  | # DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" | ||||||
|  | 
 | ||||||
|  | DNSimple_API="https://api.dnsimple.com/v2" | ||||||
|  | 
 | ||||||
|  | ########  Public functions ##################### | ||||||
|  | 
 | ||||||
|  | # Usage: add  _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" | ||||||
|  | dns_dnsimple_add() { | ||||||
|  |   fulldomain=$1 | ||||||
|  |   txtvalue=$2 | ||||||
|  | 
 | ||||||
|  |   if [ -z "$DNSimple_OAUTH_TOKEN" ]; then | ||||||
|  |     DNSimple_OAUTH_TOKEN="" | ||||||
|  |     _err "You have not set the dnsimple oauth token yet." | ||||||
|  |     _err "Please visit https://dnsimple.com/user to generate it." | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   # save the oauth token for later | ||||||
|  |   _saveaccountconf DNSimple_OAUTH_TOKEN "$DNSimple_OAUTH_TOKEN" | ||||||
|  | 
 | ||||||
|  |   if ! _get_account_id; then | ||||||
|  |     _err "failed to retrive account id" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if ! _get_root "$fulldomain"; then | ||||||
|  |     _err "invalid domain" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   _get_records "$_account_id" "$_domain" "$_sub_domain" | ||||||
|  | 
 | ||||||
|  |   if [ "$_records_count" = "0" ]; then | ||||||
|  |     _info "Adding record" | ||||||
|  |     if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then | ||||||
|  |       if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then | ||||||
|  |         _info "Added" | ||||||
|  |         return 0 | ||||||
|  |       else | ||||||
|  |         _err "Unexpected response while adding text record." | ||||||
|  |         return 1 | ||||||
|  |       fi | ||||||
|  |     fi | ||||||
|  |     _err "Add txt record error." | ||||||
|  |   else | ||||||
|  |     _info "Updating record" | ||||||
|  |     _extract_record_id "$_records" "$_sub_domain" | ||||||
|  | 
 | ||||||
|  |     if _dnsimple_rest \ | ||||||
|  |       PATCH \ | ||||||
|  |       "$_account_id/zones/$_domain/records/$_record_id" \ | ||||||
|  |       "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then | ||||||
|  | 
 | ||||||
|  |       _info "Updated!" | ||||||
|  |       return 0 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     _err "Update error" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # fulldomain | ||||||
|  | dns_dnsimple_rm() { | ||||||
|  |   fulldomain=$1 | ||||||
|  | 
 | ||||||
|  |   if ! _get_account_id; then | ||||||
|  |     _err "failed to retrive account id" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if ! _get_root "$fulldomain"; then | ||||||
|  |     _err "invalid domain" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   _get_records "$_account_id" "$_domain" "$_sub_domain" | ||||||
|  |   _extract_record_id "$_records" "$_sub_domain" | ||||||
|  | 
 | ||||||
|  |   if [ "$_record_id" ]; then | ||||||
|  | 
 | ||||||
|  |     if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then | ||||||
|  |       _info "removed record" "$_record_id" | ||||||
|  |       return 0 | ||||||
|  |     fi | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   _err "failed to remove record" "$_record_id" | ||||||
|  |   return 1 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ####################  Private functions bellow ################################## | ||||||
|  | # _acme-challenge.www.domain.com | ||||||
|  | # returns | ||||||
|  | #   _sub_domain=_acme-challenge.www | ||||||
|  | #   _domain=domain.com | ||||||
|  | _get_root() { | ||||||
|  |   domain=$1 | ||||||
|  |   i=2 | ||||||
|  |   previous=1 | ||||||
|  |   while true; do | ||||||
|  |     h=$(printf "%s" "$domain" | cut -d . -f $i-100) | ||||||
|  |     if [ -z "$h" ]; then | ||||||
|  |       # not valid | ||||||
|  |       return 1 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     if ! _dnsimple_rest GET "$_account_id/zones/$h"; then | ||||||
|  |       return 1 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     if _contains "$response" 'not found'; then | ||||||
|  |       _debug "$h not found" | ||||||
|  |     else | ||||||
|  |       _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous) | ||||||
|  |       _domain="$h" | ||||||
|  | 
 | ||||||
|  |       _debug _domain "$_domain" | ||||||
|  |       _debug _sub_domain "$_sub_domain" | ||||||
|  | 
 | ||||||
|  |       return 0 | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     previous="$i" | ||||||
|  |     i=$(_math "$i" + 1) | ||||||
|  |   done | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # returns _account_id | ||||||
|  | _get_account_id() { | ||||||
|  |   _debug "retrive account id" | ||||||
|  |   if ! _dnsimple_rest GET "whoami"; then | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if _contains "$response" "\"account\":null"; then | ||||||
|  |     _err "no account associated with this token" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if _contains "$response" "timeout"; then | ||||||
|  |     _err "timeout retrieving account id" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   _account_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"email\":" | cut -d: -f2 | cut -d, -f1) | ||||||
|  |   _debug _account_id "$_account_id" | ||||||
|  | 
 | ||||||
|  |   return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # returns | ||||||
|  | #   _records | ||||||
|  | #   _records_count | ||||||
|  | _get_records() { | ||||||
|  |   account_id=$1 | ||||||
|  |   domain=$2 | ||||||
|  |   sub_domain=$3 | ||||||
|  | 
 | ||||||
|  |   _debug "fetching txt records" | ||||||
|  |   _dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100" | ||||||
|  | 
 | ||||||
|  |   if ! _contains "$response" "\"id\":"; then | ||||||
|  |     _err "failed to retrieve records" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   _records_count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$sub_domain\"" | wc -l | _egrep_o "[0-9]+") | ||||||
|  |   _records=$response | ||||||
|  |   _debug _records_count "$_records_count" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # returns _record_id | ||||||
|  | _extract_record_id() { | ||||||
|  |   _record_id=$(printf "%s" "$_records" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1) | ||||||
|  |   _debug "_record_id" "$_record_id" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # returns response | ||||||
|  | _dnsimple_rest() { | ||||||
|  |   method=$1 | ||||||
|  |   path="$2" | ||||||
|  |   data="$3" | ||||||
|  |   request_url="$DNSimple_API/$path" | ||||||
|  |   _debug "$path" | ||||||
|  | 
 | ||||||
|  |   export _H1="Accept: application/json" | ||||||
|  |   export _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN" | ||||||
|  | 
 | ||||||
|  |   if [ "$data" ] || [ "$method" = "DELETE" ]; then | ||||||
|  |     _H1="Content-Type: application/json" | ||||||
|  |     _debug data "$data" | ||||||
|  |     response="$(_post "$data" "$request_url" "" "$method")" | ||||||
|  |   else | ||||||
|  |     response="$(_get "$request_url" "" "" "$method")" | ||||||
|  |   fi | ||||||
|  | 
 | ||||||
|  |   if [ "$?" != "0" ]; then | ||||||
|  |     _err "error $request_url" | ||||||
|  |     return 1 | ||||||
|  |   fi | ||||||
|  |   _debug2 response "$response" | ||||||
|  |   return 0 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user