mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-12-26 05:22:10 +08:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
267f283a31 | ||
|
|
3324c0ae79 | ||
|
|
811bff6db0 | ||
|
|
0c9546ccb0 | ||
|
|
7b16442656 | ||
|
|
b0070f03af | ||
|
|
08ee072f11 | ||
|
|
f3e4cea34f | ||
|
|
2d12b68952 | ||
|
|
1643b476eb | ||
|
|
5980ebc79a | ||
|
|
8371b030cf | ||
|
|
10afcaca2f | ||
|
|
2fb4b62330 | ||
|
|
cbcd7e0f86 | ||
|
|
df1c9d88a8 | ||
|
|
3aae1ae3d9 | ||
|
|
775bd1abd0 | ||
|
|
78009539d1 | ||
|
|
36246ad9ac | ||
|
|
e2053b22b4 | ||
|
|
dfdc402fbb | ||
|
|
73ba54a502 | ||
|
|
690a5e205d | ||
|
|
a6014bf04e | ||
|
|
d4d1f0f4a9 | ||
|
|
5fbc47eb3a | ||
|
|
6d4e903b08 | ||
|
|
66f08eb236 | ||
|
|
933c169da5 | ||
|
|
a8df88ab91 | ||
|
|
df9547ae39 | ||
|
|
d529eb6d00 | ||
|
|
fac1e367c9 | ||
|
|
31a5487cba | ||
|
|
43822d37a7 | ||
|
|
527dd31c70 | ||
|
|
e3c66532c5 | ||
|
|
22ea4004e1 | ||
|
|
d190a43e0a | ||
|
|
bd5e57d879 | ||
|
|
08928b486b | ||
|
|
75da0713d2 | ||
|
|
d35bf51780 | ||
|
|
ec603beeb0 | ||
|
|
7820467d59 | ||
|
|
fe09757cb3 | ||
|
|
1e6b68f5d1 | ||
|
|
f574e5813f | ||
|
|
30684246d2 | ||
|
|
8bdf5cf854 | ||
|
|
c93ec9331b | ||
|
|
0886e67df7 | ||
|
|
30de13b4df | ||
|
|
7a60c14b31 | ||
|
|
3ad08e9515 | ||
|
|
32fdc19697 | ||
|
|
c9c31c04c3 | ||
|
|
c3dd3ef0d7 | ||
|
|
fa989a554d | ||
|
|
4a4dacb52c | ||
|
|
dcf9cb581d | ||
|
|
1a6305c93f | ||
|
|
bdbf323fee | ||
|
|
7270f277a7 | ||
|
|
32dfc387c8 | ||
|
|
b3752e78b6 | ||
|
|
4c0d3f1b75 | ||
|
|
2e3cb75530 | ||
|
|
3e99ffe692 | ||
|
|
096d8992a1 | ||
|
|
0bbe6eef89 | ||
|
|
d0b748a4f2 | ||
|
|
58f41a194a | ||
|
|
d8d10bc478 | ||
|
|
61623d22d8 |
67
README.md
67
README.md
@@ -32,6 +32,8 @@ Wiki: https://github.com/Neilpang/acme.sh/wiki
|
||||
|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111
|
||||
|15|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD
|
||||
|16|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Mageia
|
||||
|17|-----| OpenWRT: Tested and working. See [wiki page](https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-OpenWRT)
|
||||
|18|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris
|
||||
|
||||
For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest):
|
||||
|
||||
@@ -44,17 +46,9 @@ https://github.com/Neilpang/acmetest
|
||||
3. Apache mode
|
||||
4. Dns mode
|
||||
|
||||
# Upgrade from 1.x to 2.x
|
||||
|
||||
You can simply uninstall 1.x and re-install 2.x.
|
||||
2.x is 100% compatible to 1.x. You will feel right at home as if nothing has changed.
|
||||
|
||||
# le.sh renamed to acme.sh NOW!
|
||||
|
||||
All configurations are 100% compatible between `le.sh` and `acme.sh`. You just need to uninstall `le.sh` and re-install `acme.sh` again.
|
||||
Nothing will be broken during the process.
|
||||
|
||||
# How to install
|
||||
# 1. How to install
|
||||
|
||||
### 1. Install online:
|
||||
|
||||
@@ -111,7 +105,7 @@ root@v1:~# acme.sh -h
|
||||
|
||||
```
|
||||
|
||||
# Just issue a cert:
|
||||
# 2. Just issue a cert:
|
||||
|
||||
**Example 1:** Single domain.
|
||||
|
||||
@@ -139,7 +133,7 @@ The issued cert will be renewed every 80 days automatically.
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
|
||||
# Install issued cert to apache/nginx etc.
|
||||
# 3. Install issued cert to apache/nginx etc.
|
||||
|
||||
After you issue a cert, you probably want to install the cert with your nginx/apache or other servers you may be using.
|
||||
|
||||
@@ -158,7 +152,7 @@ Install the issued cert/key to the production apache or nginx path.
|
||||
|
||||
The cert will be `renewed every 80 days by default` (which is configurable). Once the cert is renewed, the apache/nginx will be automatically reloaded by the command: `service apache2 reload` or `service nginx reload`.
|
||||
|
||||
# Use Standalone server to issue cert
|
||||
# 4. Use Standalone server to issue cert
|
||||
|
||||
**(requires you be root/sudoer, or you have permission to listen tcp 80 port)**
|
||||
|
||||
@@ -170,7 +164,7 @@ acme.sh --issue --standalone -d aa.com -d www.aa.com -d cp.aa.com
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
# Use Standalone tls server to issue cert
|
||||
# 5. Use Standalone tls server to issue cert
|
||||
|
||||
**(requires you be root/sudoer, or you have permission to listen tcp 443 port)**
|
||||
|
||||
@@ -184,7 +178,7 @@ acme.sh --issue --tls -d aa.com -d www.aa.com -d cp.aa.com
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
# Use Apache mode
|
||||
# 6. Use Apache mode
|
||||
|
||||
**(requires you be root/sudoer, since it is required to interact with apache server)**
|
||||
|
||||
@@ -200,7 +194,7 @@ acme.sh --issue --apache -d aa.com -d www.aa.com -d user.aa.com
|
||||
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
|
||||
|
||||
# Use DNS mode:
|
||||
# 7. Use DNS mode:
|
||||
|
||||
Support the `dns-01` challenge.
|
||||
|
||||
@@ -231,7 +225,7 @@ acme.sh --renew -d aa.com
|
||||
|
||||
Ok, it's finished.
|
||||
|
||||
# Automatic DNS API integration
|
||||
# 8. Automatic DNS API integration
|
||||
|
||||
If your DNS provider supports API access, we can use API to automatically issue the certs.
|
||||
|
||||
@@ -242,8 +236,10 @@ You don't have do anything manually!
|
||||
1. Cloudflare.com API
|
||||
2. Dnspod.cn API
|
||||
3. Cloudxns.com API
|
||||
4. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65
|
||||
5. lexicon dns api: https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api
|
||||
4. Godaddy.com API
|
||||
5. OVH, kimsufi, soyoustart and runabove API
|
||||
6. AWS Route 53, see: https://github.com/Neilpang/acme.sh/issues/65
|
||||
7. 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 are coming soon...
|
||||
@@ -252,7 +248,7 @@ If your DNS provider is not on the supported list above, you can write your own
|
||||
|
||||
For more details: [How to use dns api](dnsapi)
|
||||
|
||||
# Issue ECC certificate:
|
||||
# 9. Issue ECC certificate:
|
||||
|
||||
`Let's Encrypt` now can issue **ECDSA** certificates.
|
||||
|
||||
@@ -282,6 +278,35 @@ Valid values are:
|
||||
2. **ec-384 (secp384r1, "ECDSA P-384")**
|
||||
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)**
|
||||
|
||||
|
||||
# 10. How to renew the cert
|
||||
|
||||
No, you don't need to renew the certs manually. All the certs will be renewed automatically every 80 days.
|
||||
|
||||
However, you can also force to renew any cert:
|
||||
|
||||
```
|
||||
acme.sh --renew -d aa.com --force
|
||||
```
|
||||
|
||||
or, for ECC cert:
|
||||
```
|
||||
acme.sh --renew -d aa.com --force --ecc
|
||||
```
|
||||
|
||||
# 11. How to upgrade `acme.sh`
|
||||
acme.sh is in developing, it's strongly recommended to use the latest code.
|
||||
|
||||
You can update acme.sh to the latest code:
|
||||
```
|
||||
acme.sh --upgrade
|
||||
```
|
||||
|
||||
# 12. Issue a cert from existing CSR
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
||||
|
||||
|
||||
# Under the Hood
|
||||
|
||||
Speak ACME language using shell, directly to "Let's Encrypt".
|
||||
@@ -302,4 +327,8 @@ Please Star and Fork me.
|
||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcomed.
|
||||
|
||||
|
||||
# Donate
|
||||
1. PayPal: donate@acme.sh
|
||||
|
||||
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list)
|
||||
|
||||
|
||||
@@ -64,6 +64,34 @@ acme.sh --issue --dns dns_cx -d aa.com -d www.aa.com
|
||||
The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use Cloudxns.com api, it will reuse this key.
|
||||
|
||||
|
||||
## Use Godaddy.com domain api to automatically issue cert
|
||||
|
||||
We support Godaddy integeration.
|
||||
|
||||
First you need to login to your Godaddy account to get your api key and api secret.
|
||||
|
||||
https://developer.godaddy.com/keys/
|
||||
|
||||
Please Create a Production key, instead of a Test key.
|
||||
|
||||
|
||||
```
|
||||
export GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
|
||||
export GD_Secret="asdfsdafdsfdsfdsfdsfdsafd"
|
||||
|
||||
```
|
||||
|
||||
Ok, let's issue cert now:
|
||||
```
|
||||
acme.sh --issue --dns dns_gd -d aa.com -d www.aa.com
|
||||
```
|
||||
|
||||
The `GD_Key` and `GD_Secret` will be saved in `~/.acme.sh/account.conf`, when next time you use cloudflare api, it will reuse this key.
|
||||
|
||||
## Use OVH/kimsufi/soyoustart/runabove API
|
||||
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api
|
||||
|
||||
# Use custom api
|
||||
|
||||
@@ -72,7 +100,7 @@ If your api is not supported yet, you can write your own dns api.
|
||||
Let's assume you want to name it 'myapi',
|
||||
|
||||
1. Create a bash script named `~/.acme.sh/dns_myapi.sh`,
|
||||
2. In the scrypt, you must have a function named `dns_myapi_add()`. Which will be called by acme.sh to add dns records.
|
||||
2. In the script, you must have a function named `dns_myapi_add()`. Which will be called by acme.sh to add dns records.
|
||||
3. Then you can use your api to issue cert like:
|
||||
|
||||
```
|
||||
|
||||
@@ -43,7 +43,7 @@ dns_cf_add(){
|
||||
return 1
|
||||
fi
|
||||
|
||||
count=$(printf "$response" | grep -o \"count\":[^,]* | cut -d : -f 2)
|
||||
count=$(printf "%s\n" "$response" | _egrep_o \"count\":[^,]* | cut -d : -f 2)
|
||||
_debug count "$count"
|
||||
if [ "$count" = "0" ] ; then
|
||||
_info "Adding record"
|
||||
@@ -61,7 +61,7 @@ dns_cf_add(){
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "$response" | grep -o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \"| head -1)
|
||||
record_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \"| head -1)
|
||||
_debug "record_id" $record_id
|
||||
|
||||
_cf_rest PUT "zones/$_domain_id/dns_records/$record_id" "{\"id\":\"$record_id\",\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"zone_id\":\"$_domain_id\",\"zone_name\":\"$_domain\"}"
|
||||
@@ -103,7 +103,7 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if printf $response | grep \"name\":\"$h\" >/dev/null ; then
|
||||
_domain_id=$(printf "$response" | grep -o \"id\":\"[^\"]*\" | head -1 | cut -d : -f 2 | tr -d \")
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | head -1 | cut -d : -f 2 | tr -d \")
|
||||
if [ "$_domain_id" ] ; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
|
||||
@@ -69,7 +69,7 @@ existing_records() {
|
||||
return 1
|
||||
fi
|
||||
count=0
|
||||
seg=$(printf "$response" | grep -o "{[^{]*host\":\"$_sub_domain\"[^}]*}")
|
||||
seg=$(printf "%s\n" "$response" | _egrep_o "{[^{]*host\":\"$_sub_domain\"[^}]*}")
|
||||
_debug seg "$seg"
|
||||
if [ -z "$seg" ] ; then
|
||||
return 0
|
||||
@@ -77,7 +77,7 @@ existing_records() {
|
||||
|
||||
if printf "$response" | grep '"type":"TXT"' > /dev/null ; then
|
||||
count=1
|
||||
record_id=$(printf "$seg" | grep -o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
record_id=$(printf "%s\n" "$seg" | _egrep_o \"record_id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_debug record_id "$record_id"
|
||||
return 0
|
||||
fi
|
||||
@@ -145,9 +145,9 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "$h." >/dev/null ; then
|
||||
seg=$(printf "$response" | grep -o "{[^{]*$h\.[^}]*\}" )
|
||||
seg=$(printf "%s" "$response" | _egrep_o "{[^{]*\"$h\.\"[^}]*\}" )
|
||||
_debug seg "$seg"
|
||||
_domain_id=$(printf "$seg" | grep -o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_domain_id=$(printf "%s" "$seg" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ] ; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
|
||||
@@ -152,7 +152,7 @@ _get_root() {
|
||||
fi
|
||||
|
||||
if printf "$response" | grep "Action completed successful" >/dev/null ; then
|
||||
_domain_id=$(printf "$response" | grep -o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_domain_id=$(printf "%s\n" "$response" | _egrep_o \"id\":\"[^\"]*\" | cut -d : -f 2 | tr -d \")
|
||||
_debug _domain_id "$_domain_id"
|
||||
if [ "$_domain_id" ] ; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
|
||||
118
dnsapi/dns_gd.sh
Executable file
118
dnsapi/dns_gd.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#Godaddy domain api
|
||||
#
|
||||
#GD_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#GD_Secret="asdfsdfsfsdfsdfdfsdf"
|
||||
|
||||
|
||||
GD_Api="https://api.godaddy.com/v1"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_gd_add(){
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$GD_Key" ] || [ -z "$GD_Secret" ] ; then
|
||||
_err "You don't specify godaddy api key and secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf GD_Key "$GD_Key"
|
||||
_saveaccountconf GD_Secret "$GD_Secret"
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain ; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
|
||||
_info "Adding record"
|
||||
if _gd_rest PUT "domains/$_domain/records/TXT/$_sub_domain" "[{\"data\":\"$txtvalue\"}]"; then
|
||||
if [ "$response" = "{}" ] ; then
|
||||
_info "Added, sleeping 10 seconds"
|
||||
sleep 10
|
||||
#todo: check if the record takes effect
|
||||
return 0
|
||||
else
|
||||
_err "Add txt record error."
|
||||
_err "$response"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
#_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
|
||||
while [ '1' ] ; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
if [ -z "$h" ] ; then
|
||||
#not valid
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if ! _gd_rest GET "domains/$h" ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if printf "$response" | grep '"code":"NOT_FOUND"' >/dev/null ; then
|
||||
_debug "$h not found"
|
||||
else
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_gd_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
|
||||
_H1="Authorization: sso-key $GD_Key:$GD_Secret"
|
||||
_H2="Content-Type: application/json"
|
||||
|
||||
if [ "$data" ] ; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$GD_Api/$ep" "" $m)"
|
||||
else
|
||||
response="$(_get "$GD_Api/$ep")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ] ; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
302
dnsapi/dns_ovh.sh
Normal file
302
dnsapi/dns_ovh.sh
Normal file
@@ -0,0 +1,302 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
|
||||
#Applcation Key
|
||||
#OVH_AK="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||
#
|
||||
#Application Secret
|
||||
#OVH_AS="sdfsafsdfsdfdsfsdfsa"
|
||||
#
|
||||
#Consumer Key
|
||||
#OVH_CK="sdfsdfsdfsdfsdfdsf"
|
||||
|
||||
|
||||
#OVH_END_POINT=ovh-eu
|
||||
|
||||
|
||||
#'ovh-eu'
|
||||
OVH_EU='https://eu.api.ovh.com/1.0'
|
||||
|
||||
#'ovh-ca':
|
||||
OVH_CA='https://ca.api.ovh.com/1.0'
|
||||
|
||||
#'kimsufi-eu'
|
||||
KSF_EU='https://eu.api.kimsufi.com/1.0'
|
||||
|
||||
#'kimsufi-ca'
|
||||
KSF_CA='https://ca.api.kimsufi.com/1.0'
|
||||
|
||||
#'soyoustart-eu'
|
||||
SYS_EU='https://eu.api.soyoustart.com/1.0'
|
||||
|
||||
#'soyoustart-ca'
|
||||
SYS_CA='https://ca.api.soyoustart.com/1.0'
|
||||
|
||||
#'runabove-ca'
|
||||
RAV_CA='https://api.runabove.com/1.0'
|
||||
|
||||
|
||||
wiki="https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api"
|
||||
|
||||
ovh_success="https://github.com/Neilpang/acme.sh/wiki/OVH-Success"
|
||||
|
||||
|
||||
|
||||
_ovh_get_api() {
|
||||
_ogaep="$1"
|
||||
|
||||
case "${_ogaep}" in
|
||||
|
||||
ovh-eu|ovheu)
|
||||
printf "%s" $OVH_EU
|
||||
return
|
||||
;;
|
||||
ovh-ca|ovhca)
|
||||
printf "%s" $OVH_CA
|
||||
return
|
||||
;;
|
||||
kimsufi-eu|kimsufieu)
|
||||
printf "%s" $KSF_EU
|
||||
return
|
||||
;;
|
||||
kimsufi-ca|kimsufica)
|
||||
printf "%s" $KSF_CA
|
||||
return
|
||||
;;
|
||||
soyoustart-eu|soyoustarteu)
|
||||
printf "%s" $SYS_EU
|
||||
return
|
||||
;;
|
||||
soyoustart-ca|soyoustartca)
|
||||
printf "%s" $SYS_CA
|
||||
return
|
||||
;;
|
||||
runabove-ca|runaboveca)
|
||||
printf "%s" $RAV_CA
|
||||
return
|
||||
;;
|
||||
|
||||
|
||||
*)
|
||||
_err "Unknown parameter : $1"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||
dns_ovh_add(){
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
if [ -z "$OVH_AK" ] || [ -z "$OVH_AS" ] ; then
|
||||
_err "You don't specify OVH application key and application secret yet."
|
||||
_err "Please create you key and try again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
#save the api key and email to the account conf file.
|
||||
_saveaccountconf OVH_AK "$OVH_AK"
|
||||
_saveaccountconf OVH_AS "$OVH_AS"
|
||||
|
||||
|
||||
if [ -z "$OVH_END_POINT" ] ; then
|
||||
OVH_END_POINT="ovh-eu"
|
||||
fi
|
||||
_info "Using OVH endpoint: $OVH_END_POINT"
|
||||
if [ "$OVH_END_POINT" != "ovh-eu" ] ; then
|
||||
_saveaccountconf OVH_END_POINT "$OVH_END_POINT"
|
||||
fi
|
||||
|
||||
OVH_API="$(_ovh_get_api $OVH_END_POINT )"
|
||||
_debug OVH_API "$OVH_API"
|
||||
|
||||
if [ -z "$OVH_CK" ] ; then
|
||||
_info "OVH consumer key is empty, Let's get one:"
|
||||
if ! _ovh_authentication ; then
|
||||
_err "Can not get consumer key."
|
||||
fi
|
||||
#return and wait for retry.
|
||||
return 1;
|
||||
fi
|
||||
|
||||
|
||||
_info "Checking authentication"
|
||||
|
||||
response="$(_ovh_rest GET "domain/")"
|
||||
if _contains "$response" "INVALID_CREDENTIAL" ; then
|
||||
_err "The consumer key is invalid: $OVH_CK"
|
||||
_err "Please retry to create a new one."
|
||||
_clearaccountconf OVH_CK
|
||||
return 1
|
||||
fi
|
||||
_info "Consumer key is ok."
|
||||
|
||||
_debug "First detect the root zone"
|
||||
if ! _get_root $fulldomain ; then
|
||||
_err "invalid domain"
|
||||
return 1
|
||||
fi
|
||||
_debug _domain_id "$_domain_id"
|
||||
_debug _sub_domain "$_sub_domain"
|
||||
_debug _domain "$_domain"
|
||||
|
||||
_debug "Getting txt records"
|
||||
_ovh_rest GET "domain/zone/$_domain/record?fieldType=TXT&subDomain=$_sub_domain"
|
||||
|
||||
if _contains "$response" '\[\]' || _contains "$response" "This service does not exist" ; then
|
||||
_info "Adding record"
|
||||
if _ovh_rest POST "domain/zone/$_domain/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$_sub_domain\",\"target\":\"$txtvalue\",\"ttl\":60}"; then
|
||||
if _contains "$response" "$txtvalue" ; then
|
||||
_ovh_rest POST "domain/zone/$_domain/refresh"
|
||||
_debug "Refresh:$response"
|
||||
_info "Added, sleeping 10 seconds"
|
||||
sleep 10
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
_err "Add txt record error."
|
||||
else
|
||||
_info "Updating record"
|
||||
record_id=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 1)
|
||||
if [ -z "$record_id" ] ; then
|
||||
_err "Can not get record id."
|
||||
return 1
|
||||
fi
|
||||
_debug "record_id" $record_id
|
||||
|
||||
if _ovh_rest PUT "domain/zone/$_domain/record/$record_id" "{\"target\":\"$txtvalue\",\"subDomain\":\"$_sub_domain\",\"ttl\":60}" ; then
|
||||
if _contains "$response" "null" ; then
|
||||
_ovh_rest POST "domain/zone/$_domain/refresh"
|
||||
_debug "Refresh:$response"
|
||||
_info "Updated, sleeping 10 seconds"
|
||||
sleep 10
|
||||
return 0;
|
||||
fi
|
||||
fi
|
||||
_err "Update error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
|
||||
#################### Private functions bellow ##################################
|
||||
|
||||
_ovh_authentication() {
|
||||
|
||||
_H1="X-Ovh-Application: $OVH_AK"
|
||||
_H2="Content-type: application/json"
|
||||
_H3=""
|
||||
_H4=""
|
||||
|
||||
_ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}'
|
||||
|
||||
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
|
||||
_debug3 response "$response"
|
||||
validationUrl="$(echo "$response" | _egrep_o "validationUrl\":\"[^\"]*\"" | _egrep_o "http.*\"" | tr -d '"')"
|
||||
if [ -z "$validationUrl" ] ; then
|
||||
_err "Unable to get validationUrl"
|
||||
return 1
|
||||
fi
|
||||
_debug validationUrl "$validationUrl"
|
||||
|
||||
consumerKey="$(echo "$response" | _egrep_o "consumerKey\":\"[^\"]*\"" | cut -d : -f 2 | tr -d '"')"
|
||||
if [ -z "$consumerKey" ] ; then
|
||||
_err "Unable to get consumerKey"
|
||||
return 1
|
||||
fi
|
||||
_debug consumerKey "$consumerKey"
|
||||
|
||||
OVH_CK="$consumerKey"
|
||||
_saveaccountconf OVH_CK "$OVH_CK"
|
||||
|
||||
_info "Please open this link to do authentication: $(__green "$validationUrl" )"
|
||||
|
||||
_info "Here is a guide for you: $(__green "$wiki" )"
|
||||
_info "Please retry after the authentication is done."
|
||||
|
||||
}
|
||||
|
||||
|
||||
#_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
|
||||
while [ '1' ] ; do
|
||||
h=$(printf $domain | cut -d . -f $i-100)
|
||||
if [ -z "$h" ] ; then
|
||||
#not valid
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if ! _ovh_rest GET "domain/zone/$h" ; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _contains "$response" "This service does not exist" >/dev/null ; then
|
||||
_sub_domain=$(printf $domain | cut -d . -f 1-$p)
|
||||
_domain=$h
|
||||
return 0
|
||||
fi
|
||||
p=$i
|
||||
i=$(expr $i + 1)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
_ovh_timestamp() {
|
||||
_H1=""
|
||||
_H2=""
|
||||
_H3=""
|
||||
_H4=""
|
||||
_H5=""
|
||||
_get "$OVH_API/auth/time" "" 30
|
||||
}
|
||||
|
||||
_ovh_rest() {
|
||||
m=$1
|
||||
ep="$2"
|
||||
data="$3"
|
||||
_debug $ep
|
||||
|
||||
|
||||
_ovh_url="$OVH_API/$ep"
|
||||
_debug2 _ovh_url "$_ovh_url"
|
||||
_ovh_t="$(_ovh_timestamp)"
|
||||
_debug2 _ovh_t "$_ovh_t"
|
||||
_ovh_p="$OVH_AS+$OVH_CK+$m+$_ovh_url+$data+$_ovh_t"
|
||||
_debug _ovh_p "$_ovh_p"
|
||||
_ovh_hex="$(printf "%s" "$_ovh_p" | _digest sha1 hex)"
|
||||
_debug2 _ovh_hex "$_ovh_hex"
|
||||
|
||||
|
||||
_H1="X-Ovh-Application: $OVH_AK"
|
||||
_H2="X-Ovh-Signature: \$1\$$_ovh_hex"
|
||||
_debug2 _H2 "$_H2"
|
||||
_H3="X-Ovh-Timestamp: $_ovh_t"
|
||||
_H4="X-Ovh-Consumer: $OVH_CK"
|
||||
_H5="Content-Type: application/json;charset=utf-8"
|
||||
if [ "$data" ] || [ "$m" = "POST" ] || [ "$m" = "PUT" ] ; then
|
||||
_debug data "$data"
|
||||
response="$(_post "$data" "$_ovh_url" "" $m)"
|
||||
else
|
||||
response="$(_get "$_ovh_url")"
|
||||
fi
|
||||
|
||||
if [ "$?" != "0" ] ; then
|
||||
_err "error $ep"
|
||||
return 1
|
||||
fi
|
||||
_debug2 response "$response"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user