mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-28 16:01:43 +00:00
Merge remote-tracking branch 'upstream/master' into ssh-deploy
This commit is contained in:
commit
6093a4f9f8
10
Dockerfile
10
Dockerfile
@ -4,17 +4,17 @@ RUN apk update -f \
|
||||
&& apk --no-cache add -f \
|
||||
openssl \
|
||||
curl \
|
||||
netcat-openbsd
|
||||
netcat-openbsd \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ENV LE_CONFIG_HOME /acme.sh
|
||||
|
||||
ENV AUTO_UPGRADE 1
|
||||
|
||||
#Install
|
||||
RUN mkdir -p /install_acme.sh/
|
||||
ADD ./ /install_acme.sh/
|
||||
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh)
|
||||
RUN rm -rf /install_acme.sh/
|
||||
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
||||
|
||||
|
||||
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh
|
||||
|
||||
@ -55,5 +55,7 @@ else \n \
|
||||
/root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \
|
||||
fi" >/entry.sh && chmod +x /entry.sh
|
||||
|
||||
VOLUME /acme.sh
|
||||
|
||||
ENTRYPOINT ["/entry.sh"]
|
||||
CMD ["--help"]
|
||||
|
22
README.md
22
README.md
@ -1,4 +1,6 @@
|
||||
# An ACME Shell script: acme.sh [![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)
|
||||
|
||||
[![Join the chat at https://gitter.im/acme-sh/Lobby](https://badges.gitter.im/acme-sh/Lobby.svg)](https://gitter.im/acme-sh/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
- An ACME protocol client written purely in Shell (Unix shell) language.
|
||||
- Full ACME protocol implementation.
|
||||
- Simple, powerful and very easy to use. You only need 3 minutes to learn it.
|
||||
@ -8,6 +10,7 @@
|
||||
- Just one script to issue, renew and install your certificates automatically.
|
||||
- DOES NOT require `root/sudoer` access.
|
||||
- Docker friendly
|
||||
- IPv6 support
|
||||
|
||||
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
|
||||
|
||||
@ -304,17 +307,14 @@ You don't have to do anything manually!
|
||||
|
||||
1. CloudFlare.com API
|
||||
1. DNSPod.cn API
|
||||
1. DNSimple API
|
||||
1. CloudXNS.com API
|
||||
1. GoDaddy.com API
|
||||
1. OVH, kimsufi, soyoustart and runabove API
|
||||
1. AWS Route 53
|
||||
1. PowerDNS.com API
|
||||
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
(DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
|
||||
1. OVH, kimsufi, soyoustart and runabove API
|
||||
1. nsupdate API
|
||||
1. LuaDNS.com API
|
||||
1. DNSMadeEasy.com API
|
||||
1. nsupdate API
|
||||
1. AWS Route 53
|
||||
1. aliyun.com(阿里云) API
|
||||
1. ISPConfig 3.1 API
|
||||
1. Alwaysdata.com API
|
||||
@ -329,6 +329,16 @@ You don't have to do anything manually!
|
||||
1. Infoblox NIOS API (https://www.infoblox.com/)
|
||||
1. VSCALE (https://vscale.io/)
|
||||
1. Dynu API (https://www.dynu.com)
|
||||
1. DNSimple API
|
||||
1. NS1.com API
|
||||
|
||||
|
||||
|
||||
And:
|
||||
|
||||
1. lexicon DNS API: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
(DigitalOcean, DNSimple, DNSMadeEasy, DNSPark, EasyDNS, Namesilo, NS1, PointHQ, Rage4 and Vultr etc.)
|
||||
|
||||
|
||||
|
||||
**More APIs coming soon...**
|
||||
|
40
acme.sh
40
acme.sh
@ -444,19 +444,27 @@ if [ "$(printf '\x41')" != 'A' ]; then
|
||||
fi
|
||||
|
||||
_h2b() {
|
||||
if _exists xxd; then
|
||||
xxd -r -p
|
||||
return
|
||||
fi
|
||||
|
||||
hex=$(cat)
|
||||
i=1
|
||||
j=2
|
||||
|
||||
_debug3 _URGLY_PRINTF "$_URGLY_PRINTF"
|
||||
while true; do
|
||||
if [ -z "$_URGLY_PRINTF" ]; then
|
||||
_debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
|
||||
if [ -z "$_URGLY_PRINTF" ]; then
|
||||
while true; do
|
||||
h="$(printf "%s" "$hex" | cut -c $i-$j)"
|
||||
if [ -z "$h" ]; then
|
||||
break
|
||||
fi
|
||||
printf "\x$h%s"
|
||||
else
|
||||
i="$(_math "$i" + 2)"
|
||||
j="$(_math "$j" + 2)"
|
||||
done
|
||||
else
|
||||
while true; do
|
||||
ic="$(printf "%s" "$hex" | cut -c $i)"
|
||||
jc="$(printf "%s" "$hex" | cut -c $j)"
|
||||
if [ -z "$ic$jc" ]; then
|
||||
@ -465,12 +473,11 @@ _h2b() {
|
||||
ic="$(_h_char_2_dec "$ic")"
|
||||
jc="$(_h_char_2_dec "$jc")"
|
||||
printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
|
||||
fi
|
||||
i="$(_math "$i" + 2)"
|
||||
j="$(_math "$j" + 2)"
|
||||
done
|
||||
fi
|
||||
|
||||
i="$(_math "$i" + 2)"
|
||||
j="$(_math "$j" + 2)"
|
||||
|
||||
done
|
||||
}
|
||||
|
||||
_is_solaris() {
|
||||
@ -1244,17 +1251,20 @@ createDomainKey() {
|
||||
fi
|
||||
|
||||
domain=$1
|
||||
length=$2
|
||||
_cdl=$2
|
||||
|
||||
if [ -z "$length" ]; then
|
||||
if [ -z "$_cdl" ]; then
|
||||
_debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH"
|
||||
length="$DEFAULT_DOMAIN_KEY_LENGTH"
|
||||
_cdl="$DEFAULT_DOMAIN_KEY_LENGTH"
|
||||
fi
|
||||
|
||||
_initpath "$domain" "$length"
|
||||
_initpath "$domain" "$_cdl"
|
||||
|
||||
if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then
|
||||
_createkey "$length" "$CERT_KEY_PATH"
|
||||
if _createkey "$_cdl" "$CERT_KEY_PATH"; then
|
||||
_savedomainconf Le_Keylength "$_cdl"
|
||||
_info "The domain key is here: $(__green $CERT_KEY_PATH)"
|
||||
fi
|
||||
else
|
||||
if [ "$IS_RENEW" ]; then
|
||||
_info "Domain key exists, skip"
|
||||
|
@ -494,6 +494,17 @@ be reused when needed.
|
||||
If you have any issues with this integration please report them to
|
||||
https://github.com/pho3nixf1re/acme.sh/issues.
|
||||
|
||||
## 26. Use NS1.com API
|
||||
|
||||
```
|
||||
export NS1_Key="fdmlfsdklmfdkmqsdfk"
|
||||
```
|
||||
|
||||
Ok, let's issue a cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_nsone -d example.com -d www.example.com
|
||||
```
|
||||
|
||||
# Use custom API
|
||||
|
||||
If your API is not supported yet, you can write your own DNS API.
|
||||
|
@ -106,7 +106,7 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if _contains "$response" "<Name>$h.</Name>"; then
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<.HostedZone>")"
|
||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
|
||||
_debug hostedzone "$hostedzone"
|
||||
if [ -z "$hostedzone" ]; then
|
||||
_err "Error, can not get hostedzone."
|
||||
|
@ -37,7 +37,7 @@ dns_gandi_livedns_add() {
|
||||
_debug sub_domain "$_sub_domain"
|
||||
|
||||
_gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" \
|
||||
&& _contains "$response" '{"message": "Zone Record Created"}' \
|
||||
&& _contains "$response" '{"message": "DNS Record Created"}' \
|
||||
&& _info "Add $(__green "success")"
|
||||
}
|
||||
|
||||
|
158
dnsapi/dns_nsone.sh
Normal file
158
dnsapi/dns_nsone.sh
Normal file
@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# bug reports to dev@1e.ca
|
||||
|
||||
#
|
||||
#NS1_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
|
||||
NS1_Api="https://api.nsone.net/v1"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_nsone_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$NS1_Key" ]; then
|
||||
NS1_Key=""
|
||||
_err "You didn't specify nsone dns api key yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf NS1_Key "$NS1_Key"
|
||||
|
||||
_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"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_nsone_rest GET "zones/${_domain}"
|
||||
|
||||
if ! _contains "$response" "\"records\":"; then
|
||||
_err "Error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"domain\":\"$fulldomain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ")
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Adding record"
|
||||
|
||||
if _nsone_rest PUT "zones/$_domain/$fulldomain/TXT" "{\"answers\":[{\"answer\":[\"$txtvalue\"]}],\"type\":\"TXT\",\"domain\":\"$fulldomain\",\"zone\":\"$_domain\"}"; then
|
||||
if _contains "$response" "$fulldomain"; then
|
||||
_info "Added"
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o "\"domain\":\"$fulldomain.\",[^{]*\"type\":\"TXT\",\"id\":\"[^,]*\"" | _head_n 1 | cut -d: -f7 | cut -d, -f1)
|
||||
_debug "record_id" "$record_id"
|
||||
|
||||
_nsone_rest POST "zones/$_domain/$fulldomain/TXT" "{\"answers\": [{\"answer\": [\"$txtvalue\"]}],\"type\": \"TXT\",\"domain\":\"$fulldomain\",\"zone\": \"$_domain\"}"
|
||||
if [ "$?" = "0" ] && _contains "$response" "$fulldomain"; then
|
||||
_info "Updated!"
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
fi
|
||||
_err "Update error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#fulldomain
|
||||
dns_nsone_rm() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
_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"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_nsone_rest GET "zones/${_domain}/$fulldomain/TXT"
|
||||
|
||||
count=$(printf "%s\n" "$response" | _egrep_o "\"domain\":\"$fulldomain\",.*\"type\":\"TXT\"" | wc -l | tr -d " ")
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ]; then
|
||||
_info "Don't need to remove."
|
||||
else
|
||||
if ! _nsone_rest DELETE "zones/${_domain}/$fulldomain/TXT"; then
|
||||
_err "Delete record error."
|
||||
return 1
|
||||
fi
|
||||
_contains "$response" ""
|
||||
fi
|
||||
}
|
||||
|
||||
#################### Private functions below ##################################
|
||||
#_acme-challenge.www.domain.com
|
||||
#returns
|
||||
# _sub_domain=_acme-challenge.www
|
||||
# _domain=domain.com
|
||||
# _domain_id=sdjkglgdfewsdfg
|
||||
_get_root() {
|
||||
domain=$1
|
||||
i=2
|
||||
p=1
|
||||
if ! _nsone_rest GET "zones"; then
|
||||
return 1
|
||||
fi
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug h "$h"
|
||||
if [ -z "$h" ]; then
|
||||
#not valid
|
||||
return 1
|
||||
fi
|
||||
|
||||
if _contains "$response" "\"zone\":\"$h\""; then
|
||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||
_domain="$h"
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_nsone_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug "$ep"
|
||||
|
||||
export _H1="Accept: application/json"
|
||||
export _H2="X-NSONE-Key: $NS1_Key"
|
||||
if [ "$m" != "GET" ]; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$NS1_Api/$ep" "" "$m")"
|
||||
else
|
||||
response="$(_get "$NS1_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ]; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user