mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-22 13:11:41 +00:00
commit
d0c97a589b
@ -4,6 +4,7 @@ RUN apk update -f \
|
||||
&& apk --no-cache add -f \
|
||||
openssl \
|
||||
coreutils \
|
||||
bind-tools \
|
||||
curl \
|
||||
socat \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
@ -327,6 +327,8 @@ You don't have to do anything manually!
|
||||
1. netcup DNS API (https://www.netcup.de)
|
||||
1. GratisDNS.dk (https://gratisdns.dk)
|
||||
1. Namecheap API (https://www.namecheap.com/)
|
||||
1. MyDNS.JP API (https://www.mydns.jp/)
|
||||
1. hosting.de (https://www.hosting.de)
|
||||
|
||||
And:
|
||||
|
||||
|
2
acme.sh
2
acme.sh
@ -5485,7 +5485,7 @@ Parameters:
|
||||
|
||||
--server SERVER ACME Directory Resource URI. (default: https://acme-v01.api.letsencrypt.org/directory)
|
||||
--accountconf Specifies a customized account config file.
|
||||
--home Specifies the home dir for $PROJECT_NAME .
|
||||
--home Specifies the home dir for $PROJECT_NAME.
|
||||
--cert-home Specifies the home dir to save all the certs, only valid for '--install' command.
|
||||
--config-home Specifies the home dir to save all the configurations.
|
||||
--useragent Specifies the user agent string. it will be saved for future use too.
|
||||
|
@ -1014,6 +1014,46 @@ Now you can issue a certificate.
|
||||
acme.sh --issue --dns dns_namecheap -d example.com -d *.example.com
|
||||
```
|
||||
|
||||
## 54. Use MyDNS.JP API
|
||||
|
||||
First, register to MyDNS.JP and get MasterID and Password.
|
||||
|
||||
```
|
||||
export MYDNSJP_MasterID=MasterID
|
||||
export MYDNSJP_Password=Password
|
||||
```
|
||||
|
||||
To issue a certificate:
|
||||
|
||||
```
|
||||
acme.sh --issue --dns dns_mydnsjp -d example.com -d www.example.com
|
||||
```
|
||||
The `MYDNSJP_MasterID` and `MYDNSJP_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
## 55. Use hosting.de API
|
||||
|
||||
Create an API key in your hosting.de account here: https://secure.hosting.de
|
||||
|
||||
The key needs the following rights:
|
||||
- DNS_ZONES_EDIT
|
||||
- DNS_ZONES_LIST
|
||||
|
||||
Set your API Key and endpoint:
|
||||
|
||||
```
|
||||
export HOSTINGDE_APIKEY='xxx'
|
||||
export HOSTINGDE_ENDPOINT='https://secure.hosting.de'
|
||||
```
|
||||
|
||||
The plugin can also be used for the http.net API. http.net customers have to set endpoint to https://partner.http.net.
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_hostingde -d example.com -d *.example.com
|
||||
```
|
||||
|
||||
The hosting.de API key and endpoint will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||
|
||||
# Use custom API
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
109
dnsapi/dns_hostingde.sh
Normal file
109
dnsapi/dns_hostingde.sh
Normal file
@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# hosting.de API
|
||||
|
||||
# Values to export:
|
||||
# export HOSTINGDE_ENDPOINT='https://secure.hosting.de'
|
||||
# export HOSTINGDE_APIKEY='xxxxx'
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
dns_hostingde_add() {
|
||||
fulldomain="${1}"
|
||||
txtvalue="${2}"
|
||||
_debug "Calling: _hostingde_addRecord() '${fulldomain}' '${txtvalue}'"
|
||||
_hostingde_apiKey && _hostingde_getZoneConfig && _hostingde_addRecord
|
||||
}
|
||||
|
||||
dns_hostingde_rm() {
|
||||
fulldomain="${1}"
|
||||
txtvalue="${2}"
|
||||
_debug "Calling: _hostingde_removeRecord() '${fulldomain}' '${txtvalue}'"
|
||||
_hostingde_apiKey && _hostingde_getZoneConfig && _hostingde_removeRecord
|
||||
}
|
||||
|
||||
#################### own Private functions below ##################################
|
||||
|
||||
_hostingde_apiKey() {
|
||||
HOSTINGDE_APIKEY="${HOSTINGDE_APIKEY:-$(_readaccountconf_mutable HOSTINGDE_APIKEY)}"
|
||||
if [ -z "$HOSTINGDE_APIKEY" ] || [ -z "$HOSTINGDE_ENDPOINT" ]; then
|
||||
HOSTINGDE_APIKEY=""
|
||||
HOSTINGDE_ENDPOINT=""
|
||||
_err "You haven't specified hosting.de API key or endpoint yet."
|
||||
_err "Please create your key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_saveaccountconf_mutable HOSTINGDE_APIKEY "$HOSTINGDE_APIKEY"
|
||||
_saveaccountconf_mutable HOSTINGDE_ENDPOINT "$HOSTINGDE_ENDPOINT"
|
||||
}
|
||||
|
||||
_hostingde_getZoneConfig() {
|
||||
_info "Getting ZoneConfig"
|
||||
curZone="${fulldomain#*.}"
|
||||
returnCode=1
|
||||
while _contains "${curZone}" "\\."; do
|
||||
curData="{\"filter\":{\"field\":\"zoneName\",\"value\":\"${curZone}\"},\"limit\":1,\"authToken\":\"${HOSTINGDE_APIKEY}\"}"
|
||||
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneConfigsFind")"
|
||||
_debug "Calling zoneConfigsFind: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneConfigsFind'"
|
||||
_debug "Result of zoneConfigsFind: '$curResult'"
|
||||
if _contains "${curResult}" '"status": "error"'; then
|
||||
if _contains "${curResult}" '"code": 10109'; then
|
||||
_err "The API-Key is invalid or could not be found"
|
||||
else
|
||||
_err "UNKNOWN API ERROR"
|
||||
fi
|
||||
returnCode=1
|
||||
break
|
||||
fi
|
||||
if _contains "${curResult}" '"totalEntries": 1'; then
|
||||
_info "Retrieved zone data."
|
||||
_debug "Zone data: '${curResult}'"
|
||||
|
||||
# read ZoneConfigId for later update
|
||||
zoneConfigId=$(echo "${curResult}" | _egrep_o '"id":.*' | cut -d ':' -f 2 | cut -d '"' -f 2)
|
||||
_debug "zoneConfigId '${zoneConfigId}'"
|
||||
returnCode=0
|
||||
break
|
||||
fi
|
||||
curZone="${curZone#*.}"
|
||||
done
|
||||
if [ $returnCode -ne 0 ]; then
|
||||
_info "ZoneEnd reached, Zone ${curZone} not found in hosting.de API"
|
||||
fi
|
||||
return $returnCode
|
||||
}
|
||||
|
||||
_hostingde_addRecord() {
|
||||
_info "Adding record to zone"
|
||||
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToAdd\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\",\"ttl\":3600}]}"
|
||||
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")"
|
||||
_debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'"
|
||||
_debug "Result of zoneUpdate: '$curResult'"
|
||||
if _contains "${curResult}" '"status": "error"'; then
|
||||
if _contains "${curResult}" '"code": 10109'; then
|
||||
_err "The API-Key is invalid or could not be found"
|
||||
else
|
||||
_err "UNKNOWN API ERROR"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_hostingde_removeRecord() {
|
||||
_info "Removing record from zone"
|
||||
curData="{\"authToken\":\"${HOSTINGDE_APIKEY}\",\"zoneConfig\":{\"id\":\"${zoneConfigId}\"},\"recordsToDelete\":[{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"\\\"${txtvalue}\\\"\"}]}"
|
||||
curResult="$(_post "${curData}" "${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate")"
|
||||
_debug "Calling zoneUpdate: '${curData}' '${HOSTINGDE_ENDPOINT}/api/dns/v1/json/zoneUpdate'"
|
||||
_debug "Result of zoneUpdate: '$curResult'"
|
||||
if _contains "${curResult}" '"status": "error"'; then
|
||||
if _contains "${curResult}" '"code": 10109'; then
|
||||
_err "The API-Key is invalid or could not be found"
|
||||
else
|
||||
_err "UNKNOWN API ERROR"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
210
dnsapi/dns_mydnsjp.sh
Executable file
210
dnsapi/dns_mydnsjp.sh
Executable file
@ -0,0 +1,210 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Here is a api script for MyDNS.JP.
|
||||
#This file name is "dns_mydnsjp.sh"
|
||||
#So, here must be a method dns_mydnsjp_add()
|
||||
#Which will be called by acme.sh to add the txt record to your api system.
|
||||
#returns 0 means success, otherwise error.
|
||||
#
|
||||
#Author: epgdatacapbon
|
||||
#Report Bugs here: https://github.com/epgdatacapbon/acme.sh
|
||||
#
|
||||
######## Public functions #####################
|
||||
|
||||
# Export MyDNS.JP MasterID and Password in following variables...
|
||||
# MYDNSJP_MasterID=MasterID
|
||||
# MYDNSJP_Password=Password
|
||||
|
||||
MYDNSJP_API="https://www.mydns.jp"
|
||||
|
||||
#Usage: dns_mydnsjp_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_mydnsjp_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Using mydnsjp"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
# Load the credentials from the account conf file
|
||||
MYDNSJP_MasterID="${MYDNSJP_MasterID:-$(_readaccountconf_mutable MYDNSJP_MasterID)}"
|
||||
MYDNSJP_Password="${MYDNSJP_Password:-$(_readaccountconf_mutable MYDNSJP_Password)}"
|
||||
if [ -z "$MYDNSJP_MasterID" ] || [ -z "$MYDNSJP_Password" ]; then
|
||||
MYDNSJP_MasterID=""
|
||||
MYDNSJP_Password=""
|
||||
_err "You don't specify mydnsjp api MasterID and Password yet."
|
||||
_err "Please export as MYDNSJP_MasterID / MYDNSJP_Password and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Save the credentials to the account conf file
|
||||
_saveaccountconf_mutable MYDNSJP_MasterID "$MYDNSJP_MasterID"
|
||||
_saveaccountconf_mutable MYDNSJP_Password "$MYDNSJP_Password"
|
||||
|
||||
_debug "First detect the root zone."
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if _mydnsjp_api "REGIST" "$_domain" "$txtvalue"; then
|
||||
if printf -- "%s" "$response" | grep "OK." >/dev/null; then
|
||||
_info "Added, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#Usage: fulldomain txtvalue
|
||||
#Remove the txt record after validation.
|
||||
dns_mydnsjp_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
_info "Removing TXT record"
|
||||
_debug fulldomain "$fulldomain"
|
||||
_debug txtvalue "$txtvalue"
|
||||
|
||||
# Load the credentials from the account conf file
|
||||
MYDNSJP_MasterID="${MYDNSJP_MasterID:-$(_readaccountconf_mutable MYDNSJP_MasterID)}"
|
||||
MYDNSJP_Password="${MYDNSJP_Password:-$(_readaccountconf_mutable MYDNSJP_Password)}"
|
||||
if [ -z "$MYDNSJP_MasterID" ] || [ -z "$MYDNSJP_Password" ]; then
|
||||
MYDNSJP_MasterID=""
|
||||
MYDNSJP_Password=""
|
||||
_err "You don't specify mydnsjp api MasterID and Password yet."
|
||||
_err "Please export as MYDNSJP_MasterID / MYDNSJP_Password and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root "$fulldomain"; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
if _mydnsjp_api "DELETE" "$_domain" "$txtvalue"; then
|
||||
if printf -- "%s" "$response" | grep "OK." >/dev/null; then
|
||||
_info "Deleted, OK"
|
||||
return 0
|
||||
else
|
||||
_err "Delete txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Delete txt record error."
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
# _acme-challenge.www.domain.com
|
||||
# returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
_get_root() {
|
||||
fulldomain=$1
|
||||
i=2
|
||||
p=1
|
||||
|
||||
# Get the root domain
|
||||
_mydnsjp_retrieve_domain
|
||||
if [ "$?" != "0" ]; then
|
||||
# not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
_domain=$(printf "%s" "$fulldomain" | cut -d . -f $i-100)
|
||||
|
||||
if [ -z "$_domain" ]; then
|
||||
# not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$_domain" = "$_root_domain" ]; then
|
||||
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-$p)
|
||||
return 0
|
||||
fi
|
||||
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Retrieve the root domain
|
||||
# returns 0 success
|
||||
_mydnsjp_retrieve_domain() {
|
||||
_debug "Login to MyDNS.JP"
|
||||
|
||||
response="$(_post "masterid=$MYDNSJP_MasterID&masterpwd=$MYDNSJP_Password" "$MYDNSJP_API/?MENU=100")"
|
||||
cookie="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2)"
|
||||
|
||||
# If cookies is not empty then logon successful
|
||||
if [ -z "$cookie" ]; then
|
||||
_err "Fail to get a cookie."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug "Retrieve DOMAIN INFO page"
|
||||
|
||||
export _H1="Cookie:${cookie}"
|
||||
|
||||
response="$(_get "$MYDNSJP_API/?MENU=300")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "Fail to retrieve DOMAIN INFO."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_root_domain=$(echo "$response" | grep "DNSINFO\[domainname\]" | sed 's/^.*value="\([^"]*\)".*/\1/')
|
||||
|
||||
# Logout
|
||||
response="$(_get "$MYDNSJP_API/?MENU=090")"
|
||||
|
||||
_debug _root_domain "$_root_domain"
|
||||
|
||||
if [ -z "$_root_domain" ]; then
|
||||
_err "Fail to get the root domain."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
_mydnsjp_api() {
|
||||
cmd=$1
|
||||
domain=$2
|
||||
txtvalue=$3
|
||||
|
||||
# Base64 encode the credentials
|
||||
credentials=$(printf "%s:%s" "$MYDNSJP_MasterID" "$MYDNSJP_Password" | _base64)
|
||||
|
||||
# Construct the HTTP Authorization header
|
||||
export _H1="Content-Type: application/x-www-form-urlencoded"
|
||||
export _H2="Authorization: Basic ${credentials}"
|
||||
|
||||
response="$(_post "CERTBOT_DOMAIN=$domain&CERTBOT_VALIDATION=$txtvalue&EDIT_CMD=$cmd" "$MYDNSJP_API/directedit.html")"
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
_debug2 response "$response"
|
||||
|
||||
return 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user