Merge branch 'master' of https://github.com/Neilpang/acme.sh
Conflicts: README.md dnsapi/README.md
This commit is contained in:
commit
ac3f0cb2a0
61
Dockerfile
Normal file
61
Dockerfile
Normal file
@ -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"]
|
||||||
429
README.md
429
README.md
@ -1,429 +0,0 @@
|
|||||||
# An ACME Shell script: acme.sh [](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://github.com/Neilpang/letest#here-are-the-latest-status)| Ubuntu
|
|
||||||
|2|[](https://github.com/Neilpang/letest#here-are-the-latest-status)| Debian
|
|
||||||
|3|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|CentOS
|
|
||||||
|4|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Windows (cygwin with curl, openssl and crontab included)
|
|
||||||
|5|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|FreeBSD
|
|
||||||
|6|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|pfsense
|
|
||||||
|7|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|openSUSE
|
|
||||||
|8|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Alpine Linux (with curl)
|
|
||||||
|9|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Archlinux
|
|
||||||
|10|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|fedora
|
|
||||||
|11|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Kali Linux
|
|
||||||
|12|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Oracle Linux
|
|
||||||
|13|[](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://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
|
|
||||||
|19|[](https://github.com/Neilpang/letest#here-are-the-latest-status)|Gentoo Linux
|
|
||||||
|20|[](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)
|
|
||||||
86
acme.sh
86
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=2.6.7
|
VER=2.6.9
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ __green() {
|
|||||||
if [ "$__INTERACTIVE" ]; then
|
if [ "$__INTERACTIVE" ]; then
|
||||||
printf '\033[1;31;32m'
|
printf '\033[1;31;32m'
|
||||||
fi
|
fi
|
||||||
printf -- "$1"
|
printf -- "%b" "$1"
|
||||||
if [ "$__INTERACTIVE" ]; then
|
if [ "$__INTERACTIVE" ]; then
|
||||||
printf '\033[0m'
|
printf '\033[0m'
|
||||||
fi
|
fi
|
||||||
@ -117,7 +117,7 @@ __red() {
|
|||||||
if [ "$__INTERACTIVE" ]; then
|
if [ "$__INTERACTIVE" ]; then
|
||||||
printf '\033[1;31;40m'
|
printf '\033[1;31;40m'
|
||||||
fi
|
fi
|
||||||
printf -- "$1"
|
printf -- "%b" "$1"
|
||||||
if [ "$__INTERACTIVE" ]; then
|
if [ "$__INTERACTIVE" ]; then
|
||||||
printf '\033[0m'
|
printf '\033[0m'
|
||||||
fi
|
fi
|
||||||
@ -166,7 +166,14 @@ _syslog() {
|
|||||||
fi
|
fi
|
||||||
_logclass="$1"
|
_logclass="$1"
|
||||||
shift
|
shift
|
||||||
logger -i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
|
if [ -z "$__logger_i" ]; then
|
||||||
|
if _contains "$(logger --help 2>&1)" "-i"; then
|
||||||
|
__logger_i="logger -i"
|
||||||
|
else
|
||||||
|
__logger_i="logger"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
$__logger_i -t "$PROJECT_NAME" -p "$_logclass" "$(_printargs "$@")" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
_log() {
|
_log() {
|
||||||
@ -437,19 +444,27 @@ if [ "$(printf '\x41')" != 'A' ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_h2b() {
|
_h2b() {
|
||||||
|
if _exists xxd; then
|
||||||
|
xxd -r -p
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
hex=$(cat)
|
hex=$(cat)
|
||||||
i=1
|
i=1
|
||||||
j=2
|
j=2
|
||||||
|
_debug2 _URGLY_PRINTF "$_URGLY_PRINTF"
|
||||||
_debug3 _URGLY_PRINTF "$_URGLY_PRINTF"
|
|
||||||
while true; do
|
|
||||||
if [ -z "$_URGLY_PRINTF" ]; then
|
if [ -z "$_URGLY_PRINTF" ]; then
|
||||||
|
while true; do
|
||||||
h="$(printf "%s" "$hex" | cut -c $i-$j)"
|
h="$(printf "%s" "$hex" | cut -c $i-$j)"
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
printf "\x$h%s"
|
printf "\x$h%s"
|
||||||
|
i="$(_math "$i" + 2)"
|
||||||
|
j="$(_math "$j" + 2)"
|
||||||
|
done
|
||||||
else
|
else
|
||||||
|
while true; do
|
||||||
ic="$(printf "%s" "$hex" | cut -c $i)"
|
ic="$(printf "%s" "$hex" | cut -c $i)"
|
||||||
jc="$(printf "%s" "$hex" | cut -c $j)"
|
jc="$(printf "%s" "$hex" | cut -c $j)"
|
||||||
if [ -z "$ic$jc" ]; then
|
if [ -z "$ic$jc" ]; then
|
||||||
@ -458,12 +473,11 @@ _h2b() {
|
|||||||
ic="$(_h_char_2_dec "$ic")"
|
ic="$(_h_char_2_dec "$ic")"
|
||||||
jc="$(_h_char_2_dec "$jc")"
|
jc="$(_h_char_2_dec "$jc")"
|
||||||
printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
|
printf '\'"$(printf "%o" "$(_math "$ic" \* 16 + $jc)")""%s"
|
||||||
fi
|
|
||||||
|
|
||||||
i="$(_math "$i" + 2)"
|
i="$(_math "$i" + 2)"
|
||||||
j="$(_math "$j" + 2)"
|
j="$(_math "$j" + 2)"
|
||||||
|
|
||||||
done
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_is_solaris() {
|
_is_solaris() {
|
||||||
@ -1102,12 +1116,13 @@ _readKeyLengthFromCSR() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
_outcsr="$(${ACME_OPENSSL_BIN:-openssl} req -noout -text -in "$_csrfile")"
|
_outcsr="$(${ACME_OPENSSL_BIN:-openssl} req -noout -text -in "$_csrfile")"
|
||||||
|
_debug2 _outcsr "$_outcsr"
|
||||||
if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
|
if _contains "$_outcsr" "Public Key Algorithm: id-ecPublicKey"; then
|
||||||
_debug "ECC CSR"
|
_debug "ECC CSR"
|
||||||
echo "$_outcsr" | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
|
echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
|
||||||
else
|
else
|
||||||
_debug "RSA CSR"
|
_debug "RSA CSR"
|
||||||
echo "$_outcsr" | _egrep_o "(^ *|^RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
|
echo "$_outcsr" | tr "\t" " " | _egrep_o "(^ *|RSA )Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1236,17 +1251,20 @@ createDomainKey() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
domain=$1
|
domain=$1
|
||||||
length=$2
|
_cdl=$2
|
||||||
|
|
||||||
if [ -z "$length" ]; then
|
if [ -z "$_cdl" ]; then
|
||||||
_debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH"
|
_debug "Use DEFAULT_DOMAIN_KEY_LENGTH=$DEFAULT_DOMAIN_KEY_LENGTH"
|
||||||
length="$DEFAULT_DOMAIN_KEY_LENGTH"
|
_cdl="$DEFAULT_DOMAIN_KEY_LENGTH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_initpath "$domain" "$length"
|
_initpath "$domain" "$_cdl"
|
||||||
|
|
||||||
if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then
|
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
|
else
|
||||||
if [ "$IS_RENEW" ]; then
|
if [ "$IS_RENEW" ]; then
|
||||||
_info "Domain key exists, skip"
|
_info "Domain key exists, skip"
|
||||||
@ -1846,6 +1864,24 @@ _saveaccountconf() {
|
|||||||
_save_conf "$ACCOUNT_CONF_PATH" "$1" "$2"
|
_save_conf "$ACCOUNT_CONF_PATH" "$1" "$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#key value
|
||||||
|
_saveaccountconf_mutable() {
|
||||||
|
_save_conf "$ACCOUNT_CONF_PATH" "SAVED_$1" "$2"
|
||||||
|
#remove later
|
||||||
|
_clearaccountconf "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
#key
|
||||||
|
_readaccountconf() {
|
||||||
|
_read_conf "$ACCOUNT_CONF_PATH" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
#key
|
||||||
|
_readaccountconf_mutable() {
|
||||||
|
_rac_key="$1"
|
||||||
|
_readaccountconf "SAVED_$_rac_key"
|
||||||
|
}
|
||||||
|
|
||||||
#_clearaccountconf key
|
#_clearaccountconf key
|
||||||
_clearaccountconf() {
|
_clearaccountconf() {
|
||||||
_clear_conf "$ACCOUNT_CONF_PATH" "$1"
|
_clear_conf "$ACCOUNT_CONF_PATH" "$1"
|
||||||
@ -2564,7 +2600,7 @@ _checkConf() {
|
|||||||
if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then
|
if [ ! -f "$2" ] && ! echo "$2" | grep '*$' >/dev/null && echo "$2" | grep '*' >/dev/null; then
|
||||||
_debug "wildcard"
|
_debug "wildcard"
|
||||||
for _w_f in $2; do
|
for _w_f in $2; do
|
||||||
if [ -f "$_w_f"] && _checkConf "$1" "$_w_f"; then
|
if [ -f "$_w_f" ] && _checkConf "$1" "$_w_f"; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@ -2598,10 +2634,10 @@ _checkConf() {
|
|||||||
_isRealNginxConf() {
|
_isRealNginxConf() {
|
||||||
_debug "_isRealNginxConf $1 $2"
|
_debug "_isRealNginxConf $1 $2"
|
||||||
if [ -f "$2" ]; then
|
if [ -f "$2" ]; then
|
||||||
for _fln in $(grep -n "^ *server_name.* $1" "$2" | cut -d : -f 1); do
|
for _fln in $(tr "\t" ' ' <"$2" | grep -n "^ *server_name.* $1" | cut -d : -f 1); do
|
||||||
_debug _fln "$_fln"
|
_debug _fln "$_fln"
|
||||||
if [ "$_fln" ]; then
|
if [ "$_fln" ]; then
|
||||||
_start=$(cat "$2" | _head_n "$_fln" | grep -n "^ *server *{" | _tail_n 1)
|
_start=$(tr "\t" ' ' <"$2" | _head_n "$_fln" | grep -n "^ *server *{" | _tail_n 1)
|
||||||
_debug "_start" "$_start"
|
_debug "_start" "$_start"
|
||||||
_start_n=$(echo "$_start" | cut -d : -f 1)
|
_start_n=$(echo "$_start" | cut -d : -f 1)
|
||||||
_start_nn=$(_math $_start_n + 1)
|
_start_nn=$(_math $_start_n + 1)
|
||||||
@ -2610,8 +2646,8 @@ _isRealNginxConf() {
|
|||||||
|
|
||||||
_left="$(sed -n "${_start_nn},99999p" "$2")"
|
_left="$(sed -n "${_start_nn},99999p" "$2")"
|
||||||
_debug2 _left "$_left"
|
_debug2 _left "$_left"
|
||||||
if echo "$_left" | grep -n "^ *server *{" >/dev/null; then
|
if echo "$_left" | tr "\t" ' ' | grep -n "^ *server *{" >/dev/null; then
|
||||||
_end=$(echo "$_left" | grep -n "^ *server *{" | _head_n 1)
|
_end=$(echo "$_left" | tr "\t" ' ' | grep -n "^ *server *{" | _head_n 1)
|
||||||
_debug "_end" "$_end"
|
_debug "_end" "$_end"
|
||||||
_end_n=$(echo "$_end" | cut -d : -f 1)
|
_end_n=$(echo "$_end" | cut -d : -f 1)
|
||||||
_debug "_end_n" "$_end_n"
|
_debug "_end_n" "$_end_n"
|
||||||
@ -3120,6 +3156,10 @@ issue() {
|
|||||||
_usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ "
|
_usage "Usage: $PROJECT_ENTRY --issue -d a.com -w /path/to/webroot/a.com/ "
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
_usage "Please specify at least one validation method: '--webroot', '--standalone', '--apache', '--nginx' or '--dns' etc."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
_web_roots="$1"
|
_web_roots="$1"
|
||||||
_main_domain="$2"
|
_main_domain="$2"
|
||||||
_alt_domains="$3"
|
_alt_domains="$3"
|
||||||
@ -3860,7 +3900,7 @@ renewAll() {
|
|||||||
return "$rc"
|
return "$rc"
|
||||||
else
|
else
|
||||||
_ret="$rc"
|
_ret="$rc"
|
||||||
_err "Error renew $d, Go ahead to next one."
|
_err "Error renew $d."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@ -21,8 +21,11 @@ acme.sh --deploy -d example.com --deploy-hook cpanel
|
|||||||
## 2. Deploy ssl cert on kong proxy engine based on api.
|
## 2. Deploy ssl cert on kong proxy engine based on api.
|
||||||
|
|
||||||
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
||||||
|
Currently supports Kong-v0.10.x.
|
||||||
|
|
||||||
(TODO)
|
```sh
|
||||||
|
acme.sh --deploy -d ftp.example.com --deploy-hook kong
|
||||||
|
```
|
||||||
|
|
||||||
## 3. Deploy the cert to remote server through SSH access.
|
## 3. Deploy the cert to remote server through SSH access.
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
# If certificate already exist it will update only cert and key not touching other parameter
|
||||||
# This deploy hook will deploy ssl cert on kong proxy engine based on api request_host parameter.
|
# If certificate doesn't exist it will only upload cert and key and not set other parameter
|
||||||
# Note that ssl plugin should be available on Kong instance
|
# Note that we deploy full chain
|
||||||
# The hook will match cdomain to request_host, in case of multiple domain it will always take the first
|
|
||||||
# one (acme.sh behaviour).
|
|
||||||
# If ssl config already exist it will update only cert and key not touching other parameter
|
|
||||||
# If ssl config doesn't exist it will only upload cert and key and not set other parameter
|
|
||||||
# Not that we deploy full chain
|
|
||||||
# See https://getkong.org/plugins/dynamic-ssl/ for other options
|
|
||||||
# Written by Geoffroi Genot <ggenot@voxbone.com>
|
# Written by Geoffroi Genot <ggenot@voxbone.com>
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
@ -31,14 +25,15 @@ kong_deploy() {
|
|||||||
_debug _cca "$_cca"
|
_debug _cca "$_cca"
|
||||||
_debug _cfullchain "$_cfullchain"
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
#Get uuid linked to the domain
|
#Get ssl_uuid linked to the domain
|
||||||
uuid=$(_get "$KONG_URL/apis?request_host=$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
ssl_uuid=$(_get "$KONG_URL/certificates/$_cdomain" | _normalizeJson | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
||||||
if [ -z "$uuid" ]; then
|
if [ -z "$ssl_uuid" ]; then
|
||||||
_err "Unable to get Kong uuid for domain $_cdomain"
|
_debug "Unable to get Kong ssl_uuid for domain $_cdomain"
|
||||||
_err "Make sure that KONG_URL is correctly configured"
|
_debug "Make sure that KONG_URL is correctly configured"
|
||||||
_err "Make sure that a Kong api request_host match the domain"
|
_debug "Make sure that a Kong certificate match the sni"
|
||||||
_err "Kong url: $KONG_URL"
|
_debug "Kong url: $KONG_URL"
|
||||||
return 1
|
_info "No existing certificate, creating..."
|
||||||
|
#return 1
|
||||||
fi
|
fi
|
||||||
#Save kong url if it's succesful (First run case)
|
#Save kong url if it's succesful (First run case)
|
||||||
_saveaccountconf KONG_URL "$KONG_URL"
|
_saveaccountconf KONG_URL "$KONG_URL"
|
||||||
@ -48,12 +43,14 @@ kong_deploy() {
|
|||||||
#Set Header
|
#Set Header
|
||||||
_H1="Content-Type: multipart/form-data; boundary=$delim"
|
_H1="Content-Type: multipart/form-data; boundary=$delim"
|
||||||
#Generate data for request (Multipart/form-data with mixed content)
|
#Generate data for request (Multipart/form-data with mixed content)
|
||||||
#set name to ssl
|
if [ -z "$ssl_uuid" ]; then
|
||||||
content="--$delim${nl}Content-Disposition: form-data; name=\"name\"${nl}${nl}ssl"
|
#set sni to domain
|
||||||
|
content="--$delim${nl}Content-Disposition: form-data; name=\"snis\"${nl}${nl}$_cdomain"
|
||||||
|
fi
|
||||||
#add key
|
#add key
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"key\"; filename=\"$(basename "$_ckey")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_ckey")"
|
||||||
#Add cert
|
#Add cert
|
||||||
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"config.cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
|
content="$content${nl}--$delim${nl}Content-Disposition: form-data; name=\"cert\"; filename=\"$(basename "$_cfullchain")\"${nl}Content-Type: application/octet-stream${nl}${nl}$(cat "$_cfullchain")"
|
||||||
#Close multipart
|
#Close multipart
|
||||||
content="$content${nl}--$delim--${nl}"
|
content="$content${nl}--$delim--${nl}"
|
||||||
#Convert CRLF
|
#Convert CRLF
|
||||||
@ -61,17 +58,16 @@ kong_deploy() {
|
|||||||
#DEBUG
|
#DEBUG
|
||||||
_debug header "$_H1"
|
_debug header "$_H1"
|
||||||
_debug content "$content"
|
_debug content "$content"
|
||||||
#Check if ssl plugins is aready enabled (if not => POST else => PATCH)
|
#Check if sslcreated (if not => POST else => PATCH)
|
||||||
ssl_uuid=$(_get "$KONG_URL/apis/$uuid/plugins" | _egrep_o '"id":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"[a-zA-Z0-9\-\,\"_\:]*"name":"ssl"' | _egrep_o '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
|
|
||||||
_debug ssl_uuid "$ssl_uuid"
|
|
||||||
if [ -z "$ssl_uuid" ]; then
|
if [ -z "$ssl_uuid" ]; then
|
||||||
#Post certificate to Kong
|
#Post certificate to Kong
|
||||||
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins" "" "POST")
|
response=$(_post "$content" "$KONG_URL/certificates" "" "POST")
|
||||||
else
|
else
|
||||||
#patch
|
#patch
|
||||||
response=$(_post "$content" "$KONG_URL/apis/$uuid/plugins/$ssl_uuid" "" "PATCH")
|
response=$(_post "$content" "$KONG_URL/certificates/$ssl_uuid" "" "PATCH")
|
||||||
fi
|
fi
|
||||||
if ! [ "$(echo "$response" | _egrep_o "ssl")" = "ssl" ]; then
|
if ! [ "$(echo "$response" | _egrep_o "created_at")" = "created_at" ]; then
|
||||||
_err "An error occurred with cert upload. Check response:"
|
_err "An error occurred with cert upload. Check response:"
|
||||||
_err "$response"
|
_err "$response"
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
474
dnsapi/README.md
474
dnsapi/README.md
@ -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
|
|
||||||
@ -88,12 +88,25 @@ _get_root() {
|
|||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
|
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
||||||
|
_debug "IsTruncated"
|
||||||
|
_nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
|
_debug "NextMarker" "$_nextMarker"
|
||||||
|
if aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"; then
|
||||||
|
_debug "Truncated request OK"
|
||||||
|
i=2
|
||||||
|
p=1
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
_err "Truncated request error."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
#not valid
|
#not valid
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$response" "<Name>$h.</Name>"; then
|
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"
|
_debug hostedzone "$hostedzone"
|
||||||
if [ -z "$hostedzone" ]; then
|
if [ -z "$hostedzone" ]; then
|
||||||
_err "Error, can not get hostedzone."
|
_err "Error, can not get hostedzone."
|
||||||
@ -208,6 +221,9 @@ aws_rest() {
|
|||||||
_debug _H2 "$_H2"
|
_debug _H2 "$_H2"
|
||||||
|
|
||||||
url="$AWS_URL/$ep"
|
url="$AWS_URL/$ep"
|
||||||
|
if [ "$qsr" ]; then
|
||||||
|
url="$AWS_URL/$ep?$qsr"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$mtd" = "GET" ]; then
|
if [ "$mtd" = "GET" ]; then
|
||||||
response="$(_get "$url")"
|
response="$(_get "$url")"
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -14,6 +14,8 @@ dns_cf_add() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
|
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
|
||||||
|
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
|
||||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||||
CF_Key=""
|
CF_Key=""
|
||||||
CF_Email=""
|
CF_Email=""
|
||||||
@ -29,8 +31,8 @@ dns_cf_add() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
#save the api key and email to the account conf file.
|
#save the api key and email to the account conf file.
|
||||||
_saveaccountconf CF_Key "$CF_Key"
|
_saveaccountconf_mutable CF_Key "$CF_Key"
|
||||||
_saveaccountconf CF_Email "$CF_Email"
|
_saveaccountconf_mutable CF_Email "$CF_Email"
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
@ -83,6 +85,17 @@ dns_cf_add() {
|
|||||||
dns_cf_rm() {
|
dns_cf_rm() {
|
||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
|
CF_Key="${CF_Key:-$(_readaccountconf_mutable CF_Key)}"
|
||||||
|
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
|
||||||
|
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||||
|
CF_Key=""
|
||||||
|
CF_Email=""
|
||||||
|
_err "You don't specify cloudflare api key and email yet."
|
||||||
|
_err "Please create you key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
_debug "First detect the root zone"
|
_debug "First detect the root zone"
|
||||||
if ! _get_root "$fulldomain"; then
|
if ! _get_root "$fulldomain"; then
|
||||||
_err "invalid domain"
|
_err "invalid domain"
|
||||||
|
|||||||
215
dnsapi/dns_dnsimple.sh
Normal file
215
dnsapi/dns_dnsimple.sh
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# DNSimple domain api
|
||||||
|
# https://github.com/pho3nixf1re/acme.sh/issues
|
||||||
|
#
|
||||||
|
# This is your oauth token which can be acquired on the account page. Please
|
||||||
|
# note that this must be an _account_ token and not a _user_ token.
|
||||||
|
# https://dnsimple.com/a/<your account id>/account/access_tokens
|
||||||
|
# DNSimple_OAUTH_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||||
|
|
||||||
|
DNSimple_API="https://api.dnsimple.com/v2"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_dnsimple_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
if [ -z "$DNSimple_OAUTH_TOKEN" ]; then
|
||||||
|
DNSimple_OAUTH_TOKEN=""
|
||||||
|
_err "You have not set the dnsimple oauth token yet."
|
||||||
|
_err "Please visit https://dnsimple.com/user to generate it."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# save the oauth token for later
|
||||||
|
_saveaccountconf DNSimple_OAUTH_TOKEN "$DNSimple_OAUTH_TOKEN"
|
||||||
|
|
||||||
|
if ! _get_account_id; then
|
||||||
|
_err "failed to retrive account id"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
||||||
|
|
||||||
|
if [ "$_records_count" = "0" ]; then
|
||||||
|
_info "Adding record"
|
||||||
|
if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
||||||
|
if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then
|
||||||
|
_info "Added"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Unexpected response while adding text record."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "Add txt record error."
|
||||||
|
else
|
||||||
|
_info "Updating record"
|
||||||
|
_extract_record_id "$_records" "$_sub_domain"
|
||||||
|
|
||||||
|
if _dnsimple_rest \
|
||||||
|
PATCH \
|
||||||
|
"$_account_id/zones/$_domain/records/$_record_id" \
|
||||||
|
"{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
|
||||||
|
|
||||||
|
_info "Updated!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "Update error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# fulldomain
|
||||||
|
dns_dnsimple_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
|
||||||
|
if ! _get_account_id; then
|
||||||
|
_err "failed to retrive account id"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_get_records "$_account_id" "$_domain" "$_sub_domain"
|
||||||
|
_extract_record_id "$_records" "$_sub_domain"
|
||||||
|
|
||||||
|
if [ "$_record_id" ]; then
|
||||||
|
|
||||||
|
if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then
|
||||||
|
_info "removed record" "$_record_id"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "failed to remove record" "$_record_id"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions bellow ##################################
|
||||||
|
# _acme-challenge.www.domain.com
|
||||||
|
# returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=2
|
||||||
|
previous=1
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
# not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _dnsimple_rest GET "$_account_id/zones/$h"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" 'not found'; then
|
||||||
|
_debug "$h not found"
|
||||||
|
else
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$previous)
|
||||||
|
_domain="$h"
|
||||||
|
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
previous="$i"
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns _account_id
|
||||||
|
_get_account_id() {
|
||||||
|
_debug "retrive account id"
|
||||||
|
if ! _dnsimple_rest GET "whoami"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"account\":null"; then
|
||||||
|
_err "no account associated with this token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "timeout"; then
|
||||||
|
_err "timeout retrieving account id"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_account_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"email\":" | cut -d: -f2 | cut -d, -f1)
|
||||||
|
_debug _account_id "$_account_id"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns
|
||||||
|
# _records
|
||||||
|
# _records_count
|
||||||
|
_get_records() {
|
||||||
|
account_id=$1
|
||||||
|
domain=$2
|
||||||
|
sub_domain=$3
|
||||||
|
|
||||||
|
_debug "fetching txt records"
|
||||||
|
_dnsimple_rest GET "$account_id/zones/$domain/records?per_page=100"
|
||||||
|
|
||||||
|
if ! _contains "$response" "\"id\":"; then
|
||||||
|
_err "failed to retrieve records"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_records_count=$(printf "%s" "$response" | _egrep_o "\"name\":\"$sub_domain\"" | wc -l | _egrep_o "[0-9]+")
|
||||||
|
_records=$response
|
||||||
|
_debug _records_count "$_records_count"
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns _record_id
|
||||||
|
_extract_record_id() {
|
||||||
|
_record_id=$(printf "%s" "$_records" | _egrep_o "\"id\":[^,]*,\"zone_id\":\"[^,]*\",\"parent_id\":null,\"name\":\"$_sub_domain\"" | cut -d: -f2 | cut -d, -f1)
|
||||||
|
_debug "_record_id" "$_record_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns response
|
||||||
|
_dnsimple_rest() {
|
||||||
|
method=$1
|
||||||
|
path="$2"
|
||||||
|
data="$3"
|
||||||
|
request_url="$DNSimple_API/$path"
|
||||||
|
_debug "$path"
|
||||||
|
|
||||||
|
export _H1="Accept: application/json"
|
||||||
|
export _H2="Authorization: Bearer $DNSimple_OAUTH_TOKEN"
|
||||||
|
|
||||||
|
if [ "$data" ] || [ "$method" = "DELETE" ]; then
|
||||||
|
_H1="Content-Type: application/json"
|
||||||
|
_debug data "$data"
|
||||||
|
response="$(_post "$data" "$request_url" "" "$method")"
|
||||||
|
else
|
||||||
|
response="$(_get "$request_url" "" "" "$method")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "error $request_url"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
216
dnsapi/dns_dynu.sh
Normal file
216
dnsapi/dns_dynu.sh
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -37,7 +37,7 @@ dns_gandi_livedns_add() {
|
|||||||
_debug sub_domain "$_sub_domain"
|
_debug sub_domain "$_sub_domain"
|
||||||
|
|
||||||
_gandi_livedns_rest PUT "domains/$_domain/records/$_sub_domain/TXT" "{\"rrset_ttl\": 300, \"rrset_values\":[\"$txtvalue\"]}" \
|
_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")"
|
&& _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
|
||||||
|
}
|
||||||
@ -119,7 +119,7 @@ dns_ovh_add() {
|
|||||||
|
|
||||||
_info "Checking authentication"
|
_info "Checking authentication"
|
||||||
|
|
||||||
response="$(_ovh_rest GET "domain/")"
|
response="$(_ovh_rest GET "domain")"
|
||||||
if _contains "$response" "INVALID_CREDENTIAL"; then
|
if _contains "$response" "INVALID_CREDENTIAL"; then
|
||||||
_err "The consumer key is invalid: $OVH_CK"
|
_err "The consumer key is invalid: $OVH_CK"
|
||||||
_err "Please retry to create a new one."
|
_err "Please retry to create a new one."
|
||||||
@ -191,7 +191,7 @@ _ovh_authentication() {
|
|||||||
_H3=""
|
_H3=""
|
||||||
_H4=""
|
_H4=""
|
||||||
|
|
||||||
_ovhdata='{"accessRules": [{"method": "GET","path": "/*"},{"method": "POST","path": "/*"},{"method": "PUT","path": "/*"},{"method": "DELETE","path": "/*"}],"redirection":"'$ovh_success'"}'
|
_ovhdata='{"accessRules": [{"method": "GET","path": "/auth/time"},{"method": "GET","path": "/domain"},{"method": "GET","path": "/domain/zone/*"},{"method": "GET","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/record"},{"method": "POST","path": "/domain/zone/*/refresh"},{"method": "PUT","path": "/domain/zone/*/record/*"}],"redirection":"'$ovh_success'"}'
|
||||||
|
|
||||||
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
|
response="$(_post "$_ovhdata" "$OVH_API/auth/credential")"
|
||||||
_debug3 response "$response"
|
_debug3 response "$response"
|
||||||
|
|||||||
149
dnsapi/dns_vscale.sh
Executable file
149
dnsapi/dns_vscale.sh
Executable file
@ -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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user