Browse Source
Merge branch 'master' of https://github.com/Neilpang/acme.sh
Merge branch 'master' of https://github.com/Neilpang/acme.sh
Conflicts: README.md dnsapi/README.mdpull/761/head
Luiz Gustavo Nascimento
8 years ago
16 changed files with 945 additions and 1213 deletions
-
61Dockerfile
-
429README.md
-
86acme.sh
-
5deploy/README.md
-
50deploy/kong.sh
-
474dnsapi/README.md
-
18dnsapi/dns_aws.sh
-
232dnsapi/dns_bluemix.sh
-
17dnsapi/dns_cf.sh
-
215dnsapi/dns_dnsimple.sh
-
216dnsapi/dns_dynu.sh
-
2dnsapi/dns_gandi_livedns.sh
-
158dnsapi/dns_nsone.sh
-
4dnsapi/dns_ovh.sh
-
149dnsapi/dns_vscale.sh
@ -0,0 +1,61 @@ |
|||||
|
FROM alpine |
||||
|
|
||||
|
RUN apk update -f \ |
||||
|
&& apk --no-cache add -f \ |
||||
|
openssl \ |
||||
|
curl \ |
||||
|
netcat-openbsd \ |
||||
|
&& rm -rf /var/cache/apk/* |
||||
|
|
||||
|
ENV LE_CONFIG_HOME /acme.sh |
||||
|
|
||||
|
ENV AUTO_UPGRADE 1 |
||||
|
|
||||
|
#Install |
||||
|
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) && rm -rf /install_acme.sh/ |
||||
|
|
||||
|
|
||||
|
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh |
||||
|
|
||||
|
RUN for verb in help \ |
||||
|
version \ |
||||
|
install \ |
||||
|
uninstall \ |
||||
|
upgrade \ |
||||
|
issue \ |
||||
|
signcsr \ |
||||
|
deploy \ |
||||
|
install-cert \ |
||||
|
renew \ |
||||
|
renew-all \ |
||||
|
revoke \ |
||||
|
remove \ |
||||
|
list \ |
||||
|
showcsr \ |
||||
|
install-cronjob \ |
||||
|
uninstall-cronjob \ |
||||
|
cron \ |
||||
|
toPkcs \ |
||||
|
toPkcs8 \ |
||||
|
update-account \ |
||||
|
register-account \ |
||||
|
create-account-key \ |
||||
|
create-domain-key \ |
||||
|
createCSR \ |
||||
|
deactivate \ |
||||
|
; do \ |
||||
|
printf -- "%b" "#!/usr/bin/env sh\n/root/.acme.sh/acme.sh --${verb} --config-home /acme.sh \"\$@\"" >/usr/local/bin/--${verb} && chmod +x /usr/local/bin/--${verb} \ |
||||
|
; done |
||||
|
|
||||
|
RUN printf "%b" '#!'"/usr/bin/env sh\n \ |
||||
|
if [ \"\$1\" = \"daemon\" ]; then \n \ |
||||
|
crond; tail -f /dev/null;\n \ |
||||
|
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"] |
@ -1,429 +0,0 @@ |
|||||
# 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) |
|
||||
- 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. |
|
||||
- Bash, dash and sh compatible. |
|
||||
- Simplest shell script for Let's Encrypt free certificate client. |
|
||||
- Purely written in Shell with no dependencies on python or the official Let's Encrypt client. |
|
||||
- Just one script to issue, renew and install your certificates automatically. |
|
||||
- DOES NOT require `root/sudoer` access. |
|
||||
|
|
||||
It's probably the `easiest&smallest&smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt. |
|
||||
|
|
||||
Wiki: https://github.com/Neilpang/acme.sh/wiki |
|
||||
|
|
||||
|
|
||||
Twitter: [@neilpangxa](https://twitter.com/neilpangxa) |
|
||||
|
|
||||
|
|
||||
# [中文说明](https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) |
|
||||
|
|
||||
# Who are using **acme.sh** |
|
||||
- [FreeBSD.org](https://blog.crashed.org/letsencrypt-in-freebsd-org/) |
|
||||
- [ruby-china.org](https://ruby-china.org/topics/31983) |
|
||||
- [Proxmox](https://pve.proxmox.com/wiki/HTTPS_Certificate_Configuration_(Version_4.x_and_newer)) |
|
||||
- [pfsense](https://github.com/pfsense/FreeBSD-ports/pull/89) |
|
||||
- [webfaction](https://community.webfaction.com/questions/19988/using-letsencrypt) |
|
||||
- [Loadbalancer.org](https://www.loadbalancer.org/blog/loadbalancer-org-with-lets-encrypt-quick-and-dirty) |
|
||||
- [discourse.org](https://meta.discourse.org/t/setting-up-lets-encrypt/40709) |
|
||||
- [Centminmod](http://centminmod.com/letsencrypt-acmetool-https.html) |
|
||||
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) |
|
||||
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) |
|
||||
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) |
|
||||
|
|
||||
# Tested OS |
|
||||
|
|
||||
| NO | Status| Platform| |
|
||||
|----|-------|---------| |
|
||||
|1|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/ubuntu-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu |
|
||||
|2|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/debian-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian |
|
||||
|3|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/centos-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS |
|
||||
|4|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/windows-cygwin.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included) |
|
||||
|5|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/freebsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD |
|
||||
|6|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/pfsense.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense |
|
||||
|7|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/opensuse-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE |
|
||||
|8|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/alpine-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl) |
|
||||
|9|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/base-archlinux.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux |
|
||||
|10|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/fedora-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora |
|
||||
|11|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/kalilinux-kali-linux-docker.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux |
|
||||
|12|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/oraclelinux-latest.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux |
|
||||
|13|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/proxmox.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)| Proxmox https://pve.proxmox.com/wiki/HTTPSCertificateConfiguration#Let.27s_Encrypt_using_acme.sh |
|
||||
|14|-----| Cloud Linux https://github.com/Neilpang/le/issues/111 |
|
||||
|15|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/openbsd.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|OpenBSD |
|
||||
|16|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/mageia.svg)](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://cdn.rawgit.com/Neilpang/acmetest/master/status/solaris.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|SunOS/Solaris |
|
||||
|19|[![](https://cdn.rawgit.com/Neilpang/acmetest/master/status/gentoo-stage3-amd64.svg)](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux |
|
||||
|20|[![Build Status](https://travis-ci.org/Neilpang/acme.sh.svg?branch=master)](https://travis-ci.org/Neilpang/acme.sh)|Mac OSX |
|
||||
|
|
||||
For all build statuses, check our [daily build project](https://github.com/Neilpang/acmetest): |
|
||||
|
|
||||
https://github.com/Neilpang/acmetest |
|
||||
|
|
||||
|
|
||||
# Supported modes |
|
||||
|
|
||||
- Webroot mode |
|
||||
- Standalone mode |
|
||||
- Apache mode |
|
||||
- Nginx mode ( Beta ) |
|
||||
- DNS mode |
|
||||
- [Stateless mode](https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode) |
|
||||
|
|
||||
|
|
||||
# 1. How to install |
|
||||
|
|
||||
### 1. Install online |
|
||||
|
|
||||
Check this project: https://github.com/Neilpang/get.acme.sh |
|
||||
|
|
||||
```bash |
|
||||
curl https://get.acme.sh | sh |
|
||||
``` |
|
||||
|
|
||||
Or: |
|
||||
|
|
||||
```bash |
|
||||
wget -O - https://get.acme.sh | sh |
|
||||
``` |
|
||||
|
|
||||
|
|
||||
### 2. Or, Install from git |
|
||||
|
|
||||
Clone this project and launch installation: |
|
||||
|
|
||||
```bash |
|
||||
git clone https://github.com/Neilpang/acme.sh.git |
|
||||
cd ./acme.sh |
|
||||
./acme.sh --install |
|
||||
``` |
|
||||
|
|
||||
You `don't have to be root` then, although `it is recommended`. |
|
||||
|
|
||||
Advanced Installation: https://github.com/Neilpang/acme.sh/wiki/How-to-install |
|
||||
|
|
||||
The installer will perform 3 actions: |
|
||||
|
|
||||
1. Create and copy `acme.sh` to your home dir (`$HOME`): `~/.acme.sh/`. |
|
||||
All certs will be placed in this folder too. |
|
||||
2. Create alias for: `acme.sh=~/.acme.sh/acme.sh`. |
|
||||
3. Create daily cron job to check and renew the certs if needed. |
|
||||
|
|
||||
Cron entry example: |
|
||||
|
|
||||
```bash |
|
||||
0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null |
|
||||
``` |
|
||||
|
|
||||
After the installation, you must close the current terminal and reopen it to make the alias take effect. |
|
||||
|
|
||||
Ok, you are ready to issue certs now. |
|
||||
|
|
||||
Show help message: |
|
||||
|
|
||||
``` |
|
||||
root@v1:~# acme.sh -h |
|
||||
``` |
|
||||
|
|
||||
# 2. Just issue a cert |
|
||||
|
|
||||
**Example 1:** Single domain. |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue -d example.com -w /home/wwwroot/example.com |
|
||||
``` |
|
||||
|
|
||||
**Example 2:** Multiple domains in the same cert. |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue -d example.com -d www.example.com -d cp.example.com -w /home/wwwroot/example.com |
|
||||
``` |
|
||||
|
|
||||
The parameter `/home/wwwroot/example.com` is the web root folder. You **MUST** have `write access` to this folder. |
|
||||
|
|
||||
Second argument **"example.com"** is the main domain you want to issue the cert for. |
|
||||
You must have at least one domain there. |
|
||||
|
|
||||
You must point and bind all the domains to the same webroot dir: `/home/wwwroot/example.com`. |
|
||||
|
|
||||
Generated/issued certs will be placed in `~/.acme.sh/example.com/` |
|
||||
|
|
||||
The issued cert will be renewed automatically every **60** days. |
|
||||
|
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert |
|
||||
|
|
||||
|
|
||||
# 3. Install the issued cert to Apache/Nginx etc. |
|
||||
|
|
||||
After you issue a cert, you probably want to install/copy the cert to your Apache/Nginx or other servers. |
|
||||
You **MUST** use this command to copy the certs to the target files, **DO NOT** use the certs files in **~/.acme.sh/** folder, they are for internal use only, the folder structure may change in the future. |
|
||||
|
|
||||
**Apache** example: |
|
||||
```bash |
|
||||
acme.sh --install-cert -d example.com \ |
|
||||
--cert-file /path/to/certfile/in/apache/cert.pem \ |
|
||||
--key-file /path/to/keyfile/in/apache/key.pem \ |
|
||||
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \ |
|
||||
--reloadcmd "service apache2 force-reload" |
|
||||
``` |
|
||||
|
|
||||
**Nginx** example: |
|
||||
```bash |
|
||||
acme.sh --install-cert -d example.com \ |
|
||||
--key-file /path/to/keyfile/in/nginx/key.pem \ |
|
||||
--fullchain-file /path/to/fullchain/nginx/cert.pem \ |
|
||||
--reloadcmd "service nginx force-reload" |
|
||||
``` |
|
||||
|
|
||||
Only the domain is required, all the other parameters are optional. |
|
||||
|
|
||||
The ownership and permission info of existing files are preserved. You may want to precreate the files to have defined ownership and permission. |
|
||||
|
|
||||
Install/copy the issued cert/key to the production Apache or Nginx path. |
|
||||
|
|
||||
The cert will be `renewed every **60** days by default` (which is configurable). Once the cert is renewed, the Apache/Nginx service will be restarted automatically by the command: `service apache2 restart` or `service nginx restart`. |
|
||||
|
|
||||
|
|
||||
# 4. Use Standalone server to issue cert |
|
||||
|
|
||||
**(requires you to be root/sudoer or have permission to listen on port 80 (TCP))** |
|
||||
|
|
||||
Port `80` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com |
|
||||
``` |
|
||||
|
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert |
|
||||
|
|
||||
|
|
||||
# 5. Use Standalone TLS server to issue cert |
|
||||
|
|
||||
**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))** |
|
||||
|
|
||||
acme.sh supports `tls-sni-01` validation. |
|
||||
|
|
||||
Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again. |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com |
|
||||
``` |
|
||||
|
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert |
|
||||
|
|
||||
|
|
||||
# 6. Use Apache mode |
|
||||
|
|
||||
**(requires you to be root/sudoer, since it is required to interact with Apache server)** |
|
||||
|
|
||||
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. |
|
||||
|
|
||||
Particularly, if you are running an Apache server, you should use Apache mode instead. This mode doesn't write any files to your web root folder. |
|
||||
|
|
||||
Just set string "apache" as the second argument and it will force use of apache plugin automatically. |
|
||||
|
|
||||
``` |
|
||||
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com |
|
||||
``` |
|
||||
|
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert |
|
||||
|
|
||||
# 7. Use Nginx mode |
|
||||
|
|
||||
**(requires you to be root/sudoer, since it is required to interact with Nginx server)** |
|
||||
|
|
||||
If you are running a web server, Apache or Nginx, it is recommended to use the `Webroot mode`. |
|
||||
|
|
||||
Particularly, if you are running an nginx server, you can use nginx mode instead. This mode doesn't write any files to your web root folder. |
|
||||
|
|
||||
Just set string "nginx" as the second argument. |
|
||||
|
|
||||
It will configure nginx server automatically to verify the domain and then restore the nginx config to the original version. |
|
||||
|
|
||||
So, the config is not changed. |
|
||||
|
|
||||
``` |
|
||||
acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com |
|
||||
``` |
|
||||
|
|
||||
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert |
|
||||
|
|
||||
# 8. Use DNS mode: |
|
||||
|
|
||||
Support the `dns-01` challenge. |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com |
|
||||
``` |
|
||||
|
|
||||
You should get an output like below: |
|
||||
|
|
||||
``` |
|
||||
Add the following txt record: |
|
||||
Domain:_acme-challenge.example.com |
|
||||
Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c |
|
||||
|
|
||||
Add the following txt record: |
|
||||
Domain:_acme-challenge.www.example.com |
|
||||
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
|
||||
|
|
||||
Please add those txt records to the domains. Waiting for the dns to take effect. |
|
||||
``` |
|
||||
|
|
||||
Then just rerun with `renew` argument: |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --renew -d example.com |
|
||||
``` |
|
||||
|
|
||||
Ok, it's finished. |
|
||||
|
|
||||
|
|
||||
# 9. Automatic DNS API integration |
|
||||
|
|
||||
If your DNS provider supports API access, we can use that API to automatically issue the certs. |
|
||||
|
|
||||
You don't have to do anything manually! |
|
||||
|
|
||||
### Currently acme.sh supports: |
|
||||
|
|
||||
1. CloudFlare.com API |
|
||||
1. DNSPod.cn 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. LuaDNS.com API |
|
||||
1. DNSMadeEasy.com API |
|
||||
1. nsupdate API |
|
||||
1. aliyun.com(阿里云) API |
|
||||
1. ISPConfig 3.1 API |
|
||||
1. Alwaysdata.com API |
|
||||
1. Linode.com API |
|
||||
1. FreeDNS (https://freedns.afraid.org/) |
|
||||
1. cyon.ch |
|
||||
1. Domain-Offensive/Resellerinterface/Domainrobot API |
|
||||
1. Gandi LiveDNS API |
|
||||
1. Knot DNS API |
|
||||
1. DigitalOcean API (native) |
|
||||
1. ClouDNS.net API |
|
||||
1. Infoblox NIOS API (https://www.infoblox.com/) |
|
||||
1. IBM Bluemix API (formerly SoftLayer) |
|
||||
|
|
||||
**More APIs coming soon...** |
|
||||
|
|
||||
If your DNS provider is not on the supported list above, you can write your own DNS API script easily. If you do, please consider submitting a [Pull Request](https://github.com/Neilpang/acme.sh/pulls) and contribute it to the project. |
|
||||
|
|
||||
For more details: [How to use DNS API](dnsapi) |
|
||||
|
|
||||
|
|
||||
# 10. Issue ECC certificates |
|
||||
|
|
||||
`Let's Encrypt` can now issue **ECDSA** certificates. |
|
||||
|
|
||||
And we support them too! |
|
||||
|
|
||||
Just set the `length` parameter with a prefix `ec-`. |
|
||||
|
|
||||
For example: |
|
||||
|
|
||||
### Single domain ECC certificate |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com --keylength ec-256 |
|
||||
``` |
|
||||
|
|
||||
### SAN multi domain ECC certificate |
|
||||
|
|
||||
```bash |
|
||||
acme.sh --issue -w /home/wwwroot/example.com -d example.com -d www.example.com --keylength ec-256 |
|
||||
``` |
|
||||
|
|
||||
Please look at the last parameter above. |
|
||||
|
|
||||
Valid values are: |
|
||||
|
|
||||
1. **ec-256 (prime256v1, "ECDSA P-256")** |
|
||||
2. **ec-384 (secp384r1, "ECDSA P-384")** |
|
||||
3. **ec-521 (secp521r1, "ECDSA P-521", which is not supported by Let's Encrypt yet.)** |
|
||||
|
|
||||
|
|
||||
# 11. How to renew the issued certs |
|
||||
|
|
||||
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. |
|
||||
|
|
||||
However, you can also force to renew any cert: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --renew -d example.com --force |
|
||||
``` |
|
||||
|
|
||||
or, for ECC cert: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --renew -d example.com --force --ecc |
|
||||
``` |
|
||||
|
|
||||
|
|
||||
# 12. How to upgrade `acme.sh` |
|
||||
|
|
||||
acme.sh is in constant development, so it's strongly recommended to use the latest code. |
|
||||
|
|
||||
You can update acme.sh to the latest code: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --upgrade |
|
||||
``` |
|
||||
|
|
||||
You can also enable auto upgrade: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --upgrade --auto-upgrade |
|
||||
``` |
|
||||
|
|
||||
Then **acme.sh** will be kept up to date automatically. |
|
||||
|
|
||||
Disable auto upgrade: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --upgrade --auto-upgrade 0 |
|
||||
``` |
|
||||
|
|
||||
|
|
||||
# 13. Issue a cert from an existing CSR |
|
||||
|
|
||||
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR |
|
||||
|
|
||||
|
|
||||
# 14. Under the Hood |
|
||||
|
|
||||
Speak ACME language using shell, directly to "Let's Encrypt". |
|
||||
|
|
||||
TODO: |
|
||||
|
|
||||
|
|
||||
# 15. Acknowledgments |
|
||||
|
|
||||
1. Acme-tiny: https://github.com/diafygi/acme-tiny |
|
||||
2. ACME protocol: https://github.com/ietf-wg-acme/acme |
|
||||
3. Certbot: https://github.com/certbot/certbot |
|
||||
|
|
||||
|
|
||||
# 16. License & Others |
|
||||
|
|
||||
License is GPLv3 |
|
||||
|
|
||||
Please Star and Fork me. |
|
||||
|
|
||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. |
|
||||
|
|
||||
|
|
||||
# 17. Donate |
|
||||
Your donation makes **acme.sh** better: |
|
||||
|
|
||||
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) |
|
||||
|
|
||||
[Donate List](https://github.com/Neilpang/acme.sh/wiki/Donate-list) |
|
@ -1,474 +0,0 @@ |
|||||
# How to use DNS API |
|
||||
|
|
||||
## 1. Use CloudFlare domain API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your CloudFlare account to get your API key. |
|
||||
|
|
||||
``` |
|
||||
export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" |
|
||||
export CF_Email="xxxx@sss.com" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_cf -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `CF_Key` and `CF_Email` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 2. Use DNSPod.cn domain API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your DNSPod account to get your API Key and ID. |
|
||||
|
|
||||
``` |
|
||||
export DP_Id="1234" |
|
||||
export DP_Key="sADDsdasdgdsf" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_dp -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `DP_Id` and `DP_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 3. Use CloudXNS.com domain API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your CloudXNS account to get your API Key and Secret. |
|
||||
|
|
||||
``` |
|
||||
export CX_Key="1234" |
|
||||
export CX_Secret="sADDsdasdgdsf" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_cx -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `CX_Key` and `CX_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 4. Use GoDaddy.com domain API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your GoDaddy account to get your API Key and 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 a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_gd -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `GD_Key` and `GD_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 5. Use PowerDNS embedded API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your PowerDNS account to enable the API and set your API-Token in the configuration. |
|
||||
|
|
||||
https://doc.powerdns.com/md/httpapi/README/ |
|
||||
|
|
||||
``` |
|
||||
export PDNS_Url="http://ns.example.com:8081" |
|
||||
export PDNS_ServerId="localhost" |
|
||||
export PDNS_Token="0123456789ABCDEF" |
|
||||
export PDNS_Ttl=60 |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_pdns -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `PDNS_Url`, `PDNS_ServerId`, `PDNS_Token` and `PDNS_Ttl` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 6. Use OVH/kimsufi/soyoustart/runabove API to automatically issue cert |
|
||||
|
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api |
|
||||
|
|
||||
|
|
||||
## 7. Use nsupdate to automatically issue cert |
|
||||
|
|
||||
First, generate a key for updating the zone |
|
||||
``` |
|
||||
b=$(dnssec-keygen -a hmac-sha512 -b 512 -n USER -K /tmp foo) |
|
||||
cat > /etc/named/keys/update.key <<EOF |
|
||||
key "update" { |
|
||||
algorithm hmac-sha512; |
|
||||
secret "$(awk '/^Key/{print $2}' /tmp/$b.private)"; |
|
||||
}; |
|
||||
EOF |
|
||||
rm -f /tmp/$b.{private,key} |
|
||||
``` |
|
||||
|
|
||||
Include this key in your named configuration |
|
||||
``` |
|
||||
include "/etc/named/keys/update.key"; |
|
||||
``` |
|
||||
|
|
||||
Next, configure your zone to allow dynamic updates. |
|
||||
|
|
||||
Depending on your named version, use either |
|
||||
``` |
|
||||
zone "example.com" { |
|
||||
type master; |
|
||||
allow-update { key "update"; }; |
|
||||
}; |
|
||||
``` |
|
||||
or |
|
||||
``` |
|
||||
zone "example.com" { |
|
||||
type master; |
|
||||
update-policy { |
|
||||
grant update subdomain example.com.; |
|
||||
}; |
|
||||
} |
|
||||
``` |
|
||||
|
|
||||
Finally, make the DNS server and update Key available to `acme.sh` |
|
||||
|
|
||||
``` |
|
||||
export NSUPDATE_SERVER="dns.example.com" |
|
||||
export NSUPDATE_KEY="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_nsupdate -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `NSUPDATE_SERVER` and `NSUPDATE_KEY` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 8. Use LuaDNS domain API |
|
||||
|
|
||||
Get your API token at https://api.luadns.com/settings |
|
||||
|
|
||||
``` |
|
||||
export LUA_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" |
|
||||
export LUA_Email="xxxx@sss.com" |
|
||||
``` |
|
||||
|
|
||||
To issue a cert: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_lua -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `LUA_Key` and `LUA_Email` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 9. Use DNSMadeEasy domain API |
|
||||
|
|
||||
Get your API credentials at https://cp.dnsmadeeasy.com/account/info |
|
||||
|
|
||||
``` |
|
||||
export ME_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" |
|
||||
export ME_Secret="qdfqsdfkjdskfj" |
|
||||
``` |
|
||||
|
|
||||
To issue a cert: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_me -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `ME_Key` and `ME_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
|
|
||||
## 10. Use Amazon Route53 domain API |
|
||||
|
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-Amazon-Route53-API |
|
||||
|
|
||||
``` |
|
||||
export AWS_ACCESS_KEY_ID=XXXXXXXXXX |
|
||||
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXX |
|
||||
``` |
|
||||
|
|
||||
To issue a cert: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_aws -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 11. Use Aliyun domain API to automatically issue cert |
|
||||
|
|
||||
First you need to login to your Aliyun account to get your API key. |
|
||||
[https://ak-console.aliyun.com/#/accesskey](https://ak-console.aliyun.com/#/accesskey) |
|
||||
|
|
||||
``` |
|
||||
export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje" |
|
||||
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_ali -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `Ali_Key` and `Ali_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 12. Use ISPConfig 3.1 API |
|
||||
|
|
||||
This only works for ISPConfig 3.1 (and newer). |
|
||||
|
|
||||
Create a Remote User in the ISPConfig Control Panel. The Remote User must have access to at least `DNS zone functions` and `DNS txt functions`. |
|
||||
|
|
||||
``` |
|
||||
export ISPC_User="xxx" |
|
||||
export ISPC_Password="xxx" |
|
||||
export ISPC_Api="https://ispc.domain.tld:8080/remote/json.php" |
|
||||
export ISPC_Api_Insecure=1 |
|
||||
``` |
|
||||
If you have installed ISPConfig on a different port, then alter the 8080 accordingly. |
|
||||
Leaver ISPC_Api_Insecure set to 1 if you have not a valid ssl cert for your installation. Change it to 0 if you have a valid ssl cert. |
|
||||
|
|
||||
To issue a cert: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_ispconfig -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `ISPC_User`, `ISPC_Password`, `ISPC_Api`and `ISPC_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 13. Use Alwaysdata domain API |
|
||||
|
|
||||
First you need to login to your Alwaysdata account to get your API Key. |
|
||||
|
|
||||
```sh |
|
||||
export AD_API_KEY="myalwaysdataapikey" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
|
|
||||
```sh |
|
||||
acme.sh --issue --dns dns_ad -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `AD_API_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused |
|
||||
when needed. |
|
||||
|
|
||||
## 14. Use Linode domain API |
|
||||
|
|
||||
First you need to login to your Linode account to get your API Key. |
|
||||
[https://manager.linode.com/profile/api](https://manager.linode.com/profile/api) |
|
||||
|
|
||||
Then add an API key with label *ACME* and copy the new key. |
|
||||
|
|
||||
```sh |
|
||||
export LINODE_API_KEY="..." |
|
||||
``` |
|
||||
|
|
||||
Due to the reload time of any changes in the DNS records, we have to use the `dnssleep` option to wait at least 15 minutes for the changes to take effect. |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
|
|
||||
```sh |
|
||||
acme.sh --issue --dns dns_linode --dnssleep 900 -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `LINODE_API_KEY` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 15. Use FreeDNS |
|
||||
|
|
||||
FreeDNS (https://freedns.afraid.org/) does not provide an API to update DNS records (other than IPv4 and IPv6 |
|
||||
dynamic DNS addresses). The acme.sh plugin therefore retrieves and updates domain TXT records by logging |
|
||||
into the FreeDNS website to read the HTML and posting updates as HTTP. The plugin needs to know your |
|
||||
userid and password for the FreeDNS website. |
|
||||
|
|
||||
```sh |
|
||||
export FREEDNS_User="..." |
|
||||
export FREEDNS_Password="..." |
|
||||
``` |
|
||||
|
|
||||
You need only provide this the first time you run the acme.sh client with FreeDNS validation and then again |
|
||||
whenever you change your password at the FreeDNS site. The acme.sh FreeDNS plugin does not store your userid |
|
||||
or password but rather saves an authentication token returned by FreeDNS in `~/.acme.sh/account.conf` and |
|
||||
reuses that when needed. |
|
||||
|
|
||||
Now you can issue a certificate. |
|
||||
|
|
||||
```sh |
|
||||
acme.sh --issue --dns dns_freedns -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
Note that you cannot use acme.sh automatic DNS validation for FreeDNS public domains or for a subdomain that |
|
||||
you create under a FreeDNS public domain. You must own the top level domain in order to automatically |
|
||||
validate with acme.sh at FreeDNS. |
|
||||
|
|
||||
## 16. Use cyon.ch |
|
||||
|
|
||||
You only need to set your cyon.ch login credentials. |
|
||||
If you also have 2 Factor Authentication (OTP) enabled, you need to set your secret token too and have `oathtool` installed. |
|
||||
|
|
||||
``` |
|
||||
export CY_Username="your_cyon_username" |
|
||||
export CY_Password="your_cyon_password" |
|
||||
export CY_OTP_Secret="your_otp_secret" # Only required if using 2FA |
|
||||
``` |
|
||||
|
|
||||
To issue a cert: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_cyon -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API |
|
||||
|
|
||||
You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`: |
|
||||
``` |
|
||||
export DO_PID="KD-1234567" |
|
||||
export DO_PW="cdfkjl3n2" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_do -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
## 18. Use Gandi LiveDNS API |
|
||||
|
|
||||
You must enable the new Gandi LiveDNS API first and the create your api key, See: http://doc.livedns.gandi.net/ |
|
||||
|
|
||||
``` |
|
||||
export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
## 19. Use Knot (knsupdate) DNS API to automatically issue cert |
|
||||
|
|
||||
First, generate a TSIG key for updating the zone. |
|
||||
|
|
||||
``` |
|
||||
keymgr tsig generate acme_key algorithm hmac-sha512 > /etc/knot/acme.key |
|
||||
``` |
|
||||
|
|
||||
Include this key in your knot configuration file. |
|
||||
|
|
||||
``` |
|
||||
include: /etc/knot/acme.key |
|
||||
``` |
|
||||
|
|
||||
Next, configure your zone to allow dynamic updates. |
|
||||
|
|
||||
Dynamic updates for the zone are allowed via proper ACL rule with the `update` action. For in-depth instructions, please see [Knot DNS's documentation](https://www.knot-dns.cz/documentation/). |
|
||||
|
|
||||
``` |
|
||||
acl: |
|
||||
- id: acme_acl |
|
||||
address: 192.168.1.0/24 |
|
||||
key: acme_key |
|
||||
action: update |
|
||||
|
|
||||
zone: |
|
||||
- domain: example.com |
|
||||
file: example.com.zone |
|
||||
acl: acme_acl |
|
||||
``` |
|
||||
|
|
||||
Finally, make the DNS server and TSIG Key available to `acme.sh` |
|
||||
|
|
||||
``` |
|
||||
export KNOT_SERVER="dns.example.com" |
|
||||
export KNOT_KEY=`grep \# /etc/knot/acme.key | cut -d' ' -f2` |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_knot -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
The `KNOT_SERVER` and `KNOT_KEY` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 20. Use DigitalOcean API (native) |
|
||||
|
|
||||
You need to obtain a read and write capable API key from your DigitalOcean account. See: https://www.digitalocean.com/help/api/ |
|
||||
|
|
||||
``` |
|
||||
export DO_API_KEY="75310dc4ca779ac39a19f6355db573b49ce92ae126553ebd61ac3a3ae34834cc" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_dgon -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
## 21. Use ClouDNS.net API |
|
||||
|
|
||||
You need to set the HTTP API user ID and password credentials. See: https://www.cloudns.net/wiki/article/42/ |
|
||||
|
|
||||
``` |
|
||||
export CLOUDNS_AUTH_ID=XXXXX |
|
||||
export CLOUDNS_AUTH_PASSWORD="YYYYYYYYY" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
## 22. Use Infoblox API |
|
||||
|
|
||||
First you need to create/obtain API credentials on your Infoblox appliance. |
|
||||
|
|
||||
``` |
|
||||
export Infoblox_Creds="username:password" |
|
||||
export Infoblox_Server="ip or fqdn of infoblox appliance" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_infoblox -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
Note: This script will automatically create and delete the ephemeral txt record. |
|
||||
The `Infoblox_Creds` and `Infoblox_Server` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. |
|
||||
|
|
||||
## 23. Use IBM Bluemix API (formerly SoftLayer) |
|
||||
|
|
||||
First you need to create/obtain API credentials on your IBM Bluemix account. |
|
||||
|
|
||||
``` |
|
||||
export BLUEMIX_USER="<username>" |
|
||||
export BLUEMIX_KEY="<api_key>" |
|
||||
``` |
|
||||
|
|
||||
Ok, let's issue a cert now: |
|
||||
``` |
|
||||
acme.sh --issue --dns dns_bluemix -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
# Use custom API |
|
||||
|
|
||||
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 script you must have a function named `dns_myapi_add()` which will be called by acme.sh to add the DNS records. |
|
||||
3. Then you can use your API to issue cert like this: |
|
||||
|
|
||||
``` |
|
||||
acme.sh --issue --dns dns_myapi -d example.com -d www.example.com |
|
||||
``` |
|
||||
|
|
||||
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh) |
|
||||
|
|
||||
|
|
||||
# Use lexicon DNS API |
|
||||
|
|
||||
https://github.com/Neilpang/acme.sh/wiki/How-to-use-lexicon-dns-api |
|
@ -1,232 +0,0 @@ |
|||||
#!/usr/bin/env sh |
|
||||
# |
|
||||
# DNS Integration for IBM Bluemix (formerly SoftLayer) |
|
||||
# |
|
||||
# Author: luizgn |
|
||||
# Based on sample from Neilpang |
|
||||
# Report Bugs here: https://github.com/luizgn/acme.sh |
|
||||
# |
|
||||
######## Public functions ##################### |
|
||||
|
|
||||
BLUEMIX_API_URL="https://${BLUEMIX_USER}:${BLUEMIX_KEY}@api.softlayer.com/rest/v3" |
|
||||
domainId= |
|
||||
domain= |
|
||||
host= |
|
||||
recordId= |
|
||||
|
|
||||
dns_bluemix_add() { |
|
||||
fulldomain=$1 |
|
||||
txtvalue=$2 |
|
||||
|
|
||||
_info "Attempting to add ${fulldomain} with ${txtvalue} into Bluemix's DNS." |
|
||||
|
|
||||
# Curl is required |
|
||||
if ! type curl >/dev/null; then |
|
||||
_err "curl missing. Please isntall curl" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# BLUEMIX_USER is required |
|
||||
if [[ -z "${BLUEMIX_USER}" ]]; then |
|
||||
_err "Environment variable BLUEMIX_USER not defined" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# BLUEMIX_KEY is required |
|
||||
if [[ -z "${BLUEMIX_KEY}" ]]; then |
|
||||
_err "Environment variable BLUEMIX_KEY not defined" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# Get right domain and domain id |
|
||||
getDomain ${fulldomain} |
|
||||
|
|
||||
# Did we find domain? |
|
||||
if [[ -z "${domain}" ]]; then |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# Check if this DNS entry already exists |
|
||||
getRecordId "${domainId}" "${host}" |
|
||||
|
|
||||
if [[ -z "${recordId}" ]]; then |
|
||||
# Create record if it doesn't exist |
|
||||
createTxtRecord "${domainId}" "${host}" "${txtvalue}" |
|
||||
else |
|
||||
# Update Record if it already exists |
|
||||
updateTxtRecord "${recordId}" "${txtvalue}" |
|
||||
fi |
|
||||
|
|
||||
|
|
||||
return 0 |
|
||||
} |
|
||||
|
|
||||
#Usage: fulldomain txtvalue |
|
||||
#Remove the txt record after validation. |
|
||||
dns_bluemix_rm() { |
|
||||
fulldomain=$1 |
|
||||
|
|
||||
_info "Attempting to delete ${fulldomain} from Bluemix" |
|
||||
|
|
||||
# Curl is required |
|
||||
if ! type curl >/dev/null; then |
|
||||
_err "curl missing. Please isntall curl" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# BLUEMIX_USER is required |
|
||||
if [[ -z "${BLUEMIX_USER}" ]]; then |
|
||||
_err "Environment variable BLUEMIX_USER not defined" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# BLUEMIX_KEY is required |
|
||||
if [[ -z "${BLUEMIX_KEY}" ]]; then |
|
||||
_err "Environment variable BLUEMIX_KEY not defined" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# Get Domain ID |
|
||||
getDomain ${fulldomain} |
|
||||
|
|
||||
if [[ -z "${domain}" ]]; then |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# Get DNS entry in this Domain |
|
||||
getRecordId "${domainId}" "${host}" |
|
||||
|
|
||||
if [[ -z "${recordId}" ]]; then |
|
||||
_info "recordId for ${fulldomain} not found." |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
# Remove record |
|
||||
deleteRecordId "${recordId}" |
|
||||
|
|
||||
return 0 |
|
||||
|
|
||||
} |
|
||||
|
|
||||
#################### Private functions below ################################## |
|
||||
|
|
||||
function getDomain { |
|
||||
fulldomain=$1 |
|
||||
|
|
||||
output=$(curl -s -X GET "${BLUEMIX_API_URL}/SoftLayer_Account/getDomains") |
|
||||
|
|
||||
if [[ "${output}" =~ '"error":"Access Denied. "' ]]; then |
|
||||
_err "Access Denied, check BLUEMIX_USER and BLUEMIX_KEY environment variables. Details: ${output}" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
for domain_item in $(echo "${output}" | awk 'BEGIN{RS=","}/"name"/' | cut -f4 -d'"'); do |
|
||||
if [[ "${fulldomain}" =~ ${domain_item}$ ]]; then |
|
||||
domain="${domain_item}" |
|
||||
break |
|
||||
fi |
|
||||
done |
|
||||
|
|
||||
if [[ -z "${domain}" ]]; then |
|
||||
_err "Domain for ${fulldomain} was not found in this Bluemix account" |
|
||||
return 1 |
|
||||
fi |
|
||||
|
|
||||
domainId=$(echo "${output}" | \ |
|
||||
awk -v DOMAIN=${domain} ' |
|
||||
BEGIN { |
|
||||
RS=","; |
|
||||
FS=":"; |
|
||||
} |
|
||||
{ |
|
||||
if($1~"\"id\"") { |
|
||||
id=$2; |
|
||||
} else if($1~"\"name\"") { |
|
||||
split($2,d,"\""); |
|
||||
domain=d[2]; |
|
||||
} |
|
||||
if($0~/\}$/ && domain==DOMAIN) { |
|
||||
print id; |
|
||||
} |
|
||||
} |
|
||||
') |
|
||||
|
|
||||
host=$(echo "${fulldomain}" | sed "s/\.${domain}\$//g") |
|
||||
|
|
||||
_debug "Host is ${host}, domain is ${domain} and domain id is ${domainId}" |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function getRecordId { |
|
||||
domainId=$1 |
|
||||
host=$2 |
|
||||
|
|
||||
output=$(curl -s -X GET "${BLUEMIX_API_URL}/SoftLayer_Dns_Domain/${domainId}/getResourceRecords") |
|
||||
|
|
||||
recordId=$(echo "${output}" | \ |
|
||||
awk -v HOST=${host} ' |
|
||||
BEGIN { |
|
||||
RS=","; |
|
||||
FS=":"; |
|
||||
} |
|
||||
{ |
|
||||
if($1=="\"host\"") { |
|
||||
host=$2; |
|
||||
} else if($1=="\"id\"") { |
|
||||
id=$2; |
|
||||
} |
|
||||
if($0~/[\}|\]]$/ && host==("\"" HOST "\"")) { |
|
||||
print id; |
|
||||
} |
|
||||
} |
|
||||
') |
|
||||
|
|
||||
_debug "RecordId is ${recordId}" |
|
||||
|
|
||||
} |
|
||||
|
|
||||
function createTxtRecord { |
|
||||
domainId=$1 |
|
||||
host=$2 |
|
||||
txtvalue=$3 |
|
||||
|
|
||||
payload="{\"parameters\":[{\"host\":\"${host}\",\"data\":\"${txtvalue}\",\"ttl\":\"900\",\"type\":\"txt\",\"domainId\":\"${domainId}\"}]}" |
|
||||
output=$(curl -s -X POST -d "${payload}" "${BLUEMIX_API_URL}/SoftLayer_Dns_Domain_ResourceRecord") |
|
||||
rc=$? |
|
||||
|
|
||||
if [[ "${rc}" == "0" && "${output}" =~ \"host\":\"${host}\" ]]; then |
|
||||
_info "${fulldomain} added into Bluemix's DNS." |
|
||||
_debug ${output} |
|
||||
else |
|
||||
_err "Error adding ${fulldomain} in Bluemix's DNS. Details: ${output}" |
|
||||
fi |
|
||||
} |
|
||||
|
|
||||
function updateTxtRecord { |
|
||||
recordId=$1 |
|
||||
txtvalue=$2 |
|
||||
|
|
||||
payload="{\"parameters\":[{\"data\":\"${txtvalue}\"}]}" |
|
||||
output=$(curl -s -X PUT -d "${payload}" "${BLUEMIX_API_URL}/SoftLayer_Dns_Domain_ResourceRecord/${recordId}") |
|
||||
rc=$? |
|
||||
|
|
||||
if [[ "${rc}" == "0" && "${output}" == "true" ]]; then |
|
||||
_info "${fulldomain} updated in Bluemix's DNS." |
|
||||
else |
|
||||
_err "Error adding ${fulldomain} in Bluemix's DNS. Details: ${output}" |
|
||||
fi |
|
||||
} |
|
||||
|
|
||||
function deleteRecordId { |
|
||||
recordId=$1 |
|
||||
|
|
||||
output=$(curl -s -X DELETE "${BLUEMIX_API_URL}/SoftLayer_Dns_Domain_ResourceRecord/${recordId}") |
|
||||
rc=$? |
|
||||
|
|
||||
if [[ "${rc}" == "0" && "${output}" == "true" ]]; then |
|
||||
_info "${fulldomain} deleted from Bluemix's DNS." |
|
||||
else |
|
||||
_err "Error deleting ${fulldomain}. Details: ${output}." |
|
||||
fi |
|
||||
} |
|
||||
|
|
@ -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 |
||||
|
} |
@ -0,0 +1,216 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
#Client ID |
||||
|
#Dynu_ClientId="0b71cae7-a099-4f6b-8ddf-94571cdb760d" |
||||
|
# |
||||
|
#Secret |
||||
|
#Dynu_Secret="aCUEY4BDCV45KI8CSIC3sp2LKQ9" |
||||
|
# |
||||
|
#Token |
||||
|
Dynu_Token="" |
||||
|
# |
||||
|
#Endpoint |
||||
|
Dynu_EndPoint="https://api.dynu.com/v1" |
||||
|
# |
||||
|
#Author: Dynu Systems, Inc. |
||||
|
#Report Bugs here: https://github.com/shar0119/acme.sh |
||||
|
# |
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_dynu_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if [ -z "$Dynu_ClientId" ] || [ -z "$Dynu_Secret" ]; then |
||||
|
Dynu_ClientId="" |
||||
|
Dynu_Secret="" |
||||
|
_err "Dynu client id and secret is not specified." |
||||
|
_err "Please create you API client id and secret and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#save the client id and secret to the account conf file. |
||||
|
_saveaccountconf Dynu_ClientId "$Dynu_ClientId" |
||||
|
_saveaccountconf Dynu_Secret "$Dynu_Secret" |
||||
|
|
||||
|
if [ -z "$Dynu_Token" ]; then |
||||
|
_info "Getting Dynu token." |
||||
|
if ! _dynu_authentication; then |
||||
|
_err "Can not get token." |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_debug "Detect root zone" |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Invalid domain." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug _node "$_node" |
||||
|
_debug _domain_name "$_domain_name" |
||||
|
|
||||
|
_info "Creating TXT record." |
||||
|
if ! _dynu_rest POST "dns/record/add" "{\"domain_name\":\"$_domain_name\",\"node_name\":\"$_node\",\"record_type\":\"TXT\",\"text_data\":\"$txtvalue\",\"state\":true,\"ttl\":90}"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _contains "$response" "text_data"; then |
||||
|
_err "Could not add TXT record." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
#Usage: rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_dynu_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if [ -z "$Dynu_ClientId" ] || [ -z "$Dynu_Secret" ]; then |
||||
|
Dynu_ClientId="" |
||||
|
Dynu_Secret="" |
||||
|
_err "Dynu client id and secret is not specified." |
||||
|
_err "Please create you API client id and secret and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#save the client id and secret to the account conf file. |
||||
|
_saveaccountconf Dynu_ClientId "$Dynu_ClientId" |
||||
|
_saveaccountconf Dynu_Secret "$Dynu_Secret" |
||||
|
|
||||
|
if [ -z "$Dynu_Token" ]; then |
||||
|
_info "Getting Dynu token." |
||||
|
if ! _dynu_authentication; then |
||||
|
_err "Can not get token." |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
_debug "Detect root zone." |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "Invalid domain." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug _node "$_node" |
||||
|
_debug _domain_name "$_domain_name" |
||||
|
|
||||
|
_info "Checking for TXT record." |
||||
|
if ! _get_recordid "$fulldomain" "$txtvalue"; then |
||||
|
_err "Could not get TXT record id." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if [ "$_dns_record_id" = "" ]; then |
||||
|
_err "TXT record not found." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_info "Removing TXT record." |
||||
|
if ! _delete_txt_record "$_dns_record_id"; then |
||||
|
_err "Could not remove TXT record $_dns_record_id." |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
######## Private functions below ################################## |
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _node=_acme-challenge.www |
||||
|
# _domain_name=domain.com |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
if ! _dynu_rest GET "dns/getroot/$domain"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _contains "$response" "domain_name"; then |
||||
|
_debug "Domain name not found." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_domain_name=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 1 | cut -d : -f 2 | cut -d '"' -f 2) |
||||
|
_node=$(printf "%s" "$response" | tr -d "{}" | cut -d , -f 3 | cut -d : -f 2 | cut -d '"' -f 2) |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_get_recordid() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if ! _dynu_rest GET "dns/record/get?hostname=$fulldomain&rrtype=TXT"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _contains "$response" "$txtvalue"; then |
||||
|
_dns_record_id=0 |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
_dns_record_id=$(printf "%s" "$response" | _egrep_o "{[^}]*}" | grep "\"text_data\":\"$txtvalue\"" | _egrep_o ",[^,]*," | grep ',"id":' | tr -d ",," | cut -d : -f 2) |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_delete_txt_record() { |
||||
|
_dns_record_id=$1 |
||||
|
|
||||
|
if ! _dynu_rest GET "dns/record/delete/$_dns_record_id"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if ! _contains "$response" "true"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_dynu_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
export _H1="Authorization: Bearer $Dynu_Token" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
|
||||
|
if [ "$data" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$Dynu_EndPoint/$ep" "" "$m")" |
||||
|
else |
||||
|
_info "Getting $Dynu_EndPoint/$ep" |
||||
|
response="$(_get "$Dynu_EndPoint/$ep")" |
||||
|
fi |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_dynu_authentication() { |
||||
|
realm="$(printf "%s" "$Dynu_ClientId:$Dynu_Secret" | _base64)" |
||||
|
|
||||
|
export _H1="Authorization: Basic $realm" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
|
||||
|
response="$(_get "$Dynu_EndPoint/oauth2/token")" |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "Authentication failed." |
||||
|
return 1 |
||||
|
fi |
||||
|
if _contains "$response" "accessToken"; then |
||||
|
Dynu_Token=$(printf "%s" "$response" | tr -d "[]" | cut -d , -f 2 | cut -d : -f 2 | cut -d '"' -f 2) |
||||
|
fi |
||||
|
if _contains "$Dynu_Token" "null"; then |
||||
|
Dynu_Token="" |
||||
|
fi |
||||
|
|
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -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 |
||||
|
} |
@ -0,0 +1,149 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
#This is the vscale.io api wrapper for acme.sh |
||||
|
# |
||||
|
#Author: Alex Loban |
||||
|
#Report Bugs here: https://github.com/LAV45/acme.sh |
||||
|
|
||||
|
#VSCALE_API_KEY="sdfsdfsdfljlbjkljlkjsdfoiwje" |
||||
|
VSCALE_API_URL="https://api.vscale.io/v1" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_vscale_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
if [ -z "$VSCALE_API_KEY" ]; then |
||||
|
VSCALE_API_KEY="" |
||||
|
_err "You didn't specify the VSCALE api key yet." |
||||
|
_err "Please create you key and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_saveaccountconf VSCALE_API_KEY "$VSCALE_API_KEY" |
||||
|
|
||||
|
_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" |
||||
|
|
||||
|
_vscale_tmpl_json="{\"type\":\"TXT\",\"name\":\"$_sub_domain.$_domain\",\"content\":\"$txtvalue\"}" |
||||
|
|
||||
|
if _vscale_rest POST "domains/$_domain_id/records/" "$_vscale_tmpl_json"; then |
||||
|
response=$(printf "%s\n" "$response" | _egrep_o "{\"error\": \".+\"" | cut -d : -f 2) |
||||
|
if [ -z "$response" ]; then |
||||
|
_info "txt record updated success." |
||||
|
return 0 |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#fulldomain txtvalue |
||||
|
dns_vscale_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_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" |
||||
|
_vscale_rest GET "domains/$_domain_id/records/" |
||||
|
|
||||
|
if [ -n "$response" ]; then |
||||
|
record_id=$(printf "%s\n" "$response" | _egrep_o "\"TXT\", \"id\": [0-9]+, \"name\": \"$_sub_domain.$_domain\"" | cut -d : -f 2 | tr -d ", \"name\"") |
||||
|
_debug record_id "$record_id" |
||||
|
if [ -z "$record_id" ]; then |
||||
|
_err "Can not get record id to remove." |
||||
|
return 1 |
||||
|
fi |
||||
|
if _vscale_rest DELETE "domains/$_domain_id/records/$record_id" && [ -z "$response" ]; then |
||||
|
_info "txt record deleted success." |
||||
|
return 0 |
||||
|
fi |
||||
|
_debug response "$response" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
#_acme-challenge.www.domain.com |
||||
|
#returns |
||||
|
# _sub_domain=_acme-challenge.www |
||||
|
# _domain=domain.com |
||||
|
# _domain_id=12345 |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=2 |
||||
|
p=1 |
||||
|
|
||||
|
if _vscale_rest GET "domains/"; then |
||||
|
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')" |
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
hostedzone="$(echo "$response" | _egrep_o "{.*\"name\":\s*\"$h\".*}")" |
||||
|
if [ "$hostedzone" ]; then |
||||
|
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "\"id\":\s*[0-9]+" | _head_n 1 | cut -d : -f 2 | tr -d \ ) |
||||
|
if [ "$_domain_id" ]; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
fi |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#method uri qstr data |
||||
|
_vscale_rest() { |
||||
|
mtd="$1" |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
|
||||
|
_debug mtd "$mtd" |
||||
|
_debug ep "$ep" |
||||
|
|
||||
|
export _H1="Accept: application/json" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
export _H3="X-Token: ${VSCALE_API_KEY}" |
||||
|
|
||||
|
if [ "$mtd" != "GET" ]; then |
||||
|
# both POST and DELETE. |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$VSCALE_API_URL/$ep" "" "$mtd")" |
||||
|
else |
||||
|
response="$(_get "$VSCALE_API_URL/$ep")" |
||||
|
fi |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue