Browse Source

Merge remote-tracking branch 'firstrepo/master' into patch-1

# Conflicts:
#	getssl
pull/443/head
cbdweb 6 years ago
parent
commit
7019f775f4
69 changed files with 4324 additions and 1413 deletions
  1. +4
    -2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. +82
    -0
      .github/workflows/run-all-tests.yml
  3. +17
    -0
      .github/workflows/shellcheck.yml
  4. +31
    -0
      .github/workflows/stale2.yml
  5. +16
    -9
      CONTRIBUTING.md
  6. +138
    -55
      README.md
  7. +1
    -1
      dns_scripts/dns_add_challtestsrv
  8. +103
    -0
      dns_scripts/dns_add_clouddns
  9. +19
    -0
      dns_scripts/dns_add_duckdns
  10. +13
    -11
      dns_scripts/dns_add_nsupdate
  11. +0
    -0
      dns_scripts/dns_del_challtestsrv
  12. +110
    -0
      dns_scripts/dns_del_clouddns
  13. +12
    -0
      dns_scripts/dns_del_duckdns
  14. +13
    -11
      dns_scripts/dns_del_nsupdate
  15. +702
    -0
      dns_scripts/dns_freedns.sh
  16. +1
    -1
      dns_scripts/dns_route53.py
  17. +3
    -14
      docker-compose.yml
  18. +1328
    -1099
      getssl
  19. +40
    -0
      test/1-simple-http01-dig.bats
  20. +40
    -0
      test/1-simple-http01-nslookup.bats
  21. +35
    -0
      test/1-simple-http01.bats
  22. +22
    -0
      test/10-mixed-case-staging.bats
  23. +41
    -0
      test/10-mixed-case.bats
  24. +63
    -0
      test/11-test--install.bats
  25. +20
    -0
      test/11-test-no-domain-storage.bats
  26. +53
    -0
      test/2-simple-dns01-dig.bats
  27. +42
    -0
      test/2-simple-dns01-nslookup.bats
  28. +65
    -0
      test/3-dual-rsa-ecdsa.bats
  29. +45
    -0
      test/4-more-than-10-hosts.bats
  30. +57
    -0
      test/5-secp384-http01.bats
  31. +48
    -0
      test/6-dual-rsa-ecdsa-copy-2-locations.bats
  32. +30
    -0
      test/7-staging-dns01-dig.bats
  33. +45
    -0
      test/7-staging-dns01-nslookup.bats
  34. +62
    -0
      test/8-staging-ecdsa.bats
  35. +60
    -0
      test/9-multiple-domains-dns01.bats
  36. +32
    -0
      test/9-test--all.bats
  37. +22
    -0
      test/Dockerfile-alpine
  38. +24
    -0
      test/Dockerfile-centos6
  39. +20
    -0
      test/Dockerfile-centos7
  40. +28
    -0
      test/Dockerfile-centos7-staging
  41. +20
    -0
      test/Dockerfile-debian
  42. +0
    -22
      test/Dockerfile-rhel6
  43. +16
    -13
      test/Dockerfile-ubuntu
  44. +30
    -0
      test/Dockerfile-ubuntu-staging
  45. +25
    -0
      test/Dockerfile-ubuntu16
  46. +27
    -0
      test/Dockerfile-ubuntu18
  47. +35
    -0
      test/README-Testing.md
  48. +0
    -20
      test/README.md
  49. +30
    -0
      test/debug-test.sh
  50. +11
    -0
      test/restart-nginx
  51. +54
    -0
      test/run-test.cmd
  52. +42
    -38
      test/run-test.sh
  53. +14
    -0
      test/test-config/alpine-supervisord.conf
  54. +39
    -0
      test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg
  55. +6
    -25
      test/test-config/getssl-dns01.cfg
  56. +45
    -0
      test/test-config/getssl-etc-template.cfg
  57. +28
    -0
      test/test-config/getssl-http01-10-hosts.cfg
  58. +32
    -0
      test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg
  59. +33
    -0
      test/test-config/getssl-http01-dual-rsa-ecdsa.cfg
  60. +31
    -0
      test/test-config/getssl-http01-no-domain-storage.cfg
  61. +32
    -0
      test/test-config/getssl-http01-secp384.cfg
  62. +32
    -0
      test/test-config/getssl-http01-secp521.cfg
  63. +5
    -29
      test/test-config/getssl-http01.cfg
  64. +39
    -0
      test/test-config/getssl-ignore-directory-domain.cfg
  65. +38
    -0
      test/test-config/getssl-multiple-domains-dns01.cfg
  66. +37
    -0
      test/test-config/getssl-staging-dns01.cfg
  67. +37
    -0
      test/test-config/nginx-centos7.conf
  68. +0
    -63
      test/test-config/nginx-ubuntu-no-ssl
  69. +99
    -0
      test/test_helper.bash

+ 4
- 2
.github/ISSUE_TEMPLATE/bug_report.md View File

@ -12,6 +12,7 @@ A clear and concise description of what the bug is.
**To Reproduce** **To Reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
@ -21,8 +22,9 @@ Steps to reproduce the behavior:
A clear and concise description of what you expected to happen. A clear and concise description of what you expected to happen.
**Operating system (please complete the following information):** **Operating system (please complete the following information):**
- OS: [e.g. Debian 9, Ubuntu 18.04, freeBSD ]
- Bash Version [e.g. GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)]
- OS: [e.g. Debian 9, Ubuntu 18.04, freeBSD ]
- Bash Version [e.g. GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

+ 82
- 0
.github/workflows/run-all-tests.yml View File

@ -0,0 +1,82 @@
name: Run all tests
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
test-alpine:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Alpine
run: test/run-test.sh alpine
test-centos6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on CentOS6
run: test/run-test.sh centos6
test-centos7:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on CentOS7
run: test/run-test.sh centos7
test-centos7-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on CentOS7 against Staging using DuckDNS
run: test/run-test.sh centos7-staging
test-debian:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Debian
run: test/run-test.sh debian
test-ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Ubuntu
run: test/run-test.sh ubuntu
test-ubuntu16:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Ubuntu16
run: test/run-test.sh ubuntu16
test-ubuntu18:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Ubuntu18
run: test/run-test.sh ubuntu18
test-ubuntu-staging:
needs: test-centos7-staging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build the docker-compose stack
run: docker-compose up -d --build
- name: Run test suite on Ubuntu against Staging using DuckDNS
run: test/run-test.sh ubuntu-staging

+ 17
- 0
.github/workflows/shellcheck.yml View File

@ -0,0 +1,17 @@
name: shellcheck
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Lint check
uses: azohra/shell-linter@v0.3.0
with:
path: "getssl"

+ 31
- 0
.github/workflows/stale2.yml View File

@ -0,0 +1,31 @@
on:
schedule:
- cron: "0 0 * * *"
name: Run Stale Bot on Issue Comments
jobs:
build:
name: stale
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: stale
uses: gatsbyjs/stale@master
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DRY_RUN: true
DAYS_BEFORE_STALE: 60
DAYS_BEFORE_CLOSE: 30
STALE_ISSUE_LABEL: 'stale'
STALE_PR_LABEL: 'stale'
OPERATIONS_PER_RUN: 30
STALE_ISSUE_MESSAGE: 'This issue will be closed as no updates for 60 days'
CLOSE_MESSAGE: 'Closing stale issue after 90 days of inactivity'
EXEMPT_ISSUE_LABELS: |
bug
documentation
enhancement
feature
help wanted
rfc

+ 16
- 9
CONTRIBUTING.md View File

@ -1,24 +1,31 @@
# How to contribute # How to contribute
If you are happy writing in bash, please create a PR for any changes you'd like to see included (or bug fixes).
If you are happy writing in bash, please create a PR for any changes
you'd like to see included (or bug fixes).
If you aren't happy writing in bash, please open an issue with as much detail as possible about the issue or what you'd like to see added / improved.
If you aren't happy writing in bash, please open an issue with as much
detail as possible about the issue or what you'd like to see added /
improved.
## Submitting changes ## Submitting changes
Please update the 'revision history' and version number at the top of the code (without this I can't easily do a merge)
Please update the 'revision history' and version number at the top of
the code (without this I can't easily do a merge)
Please update just one issue per PR. If there are multiple issues, please provide separate PR's one per issue.
Please update just one issue per PR. If there are multiple issues,
please provide separate PR's one per issue.
## Coding conventions ## Coding conventions
Please see the guidelines at https://github.com/srvrco/getssl/wiki/Bash-Style-guide
Please see the guidelines at <https://github.com/srvrco/getssl/wiki/Bash-Style-guide>
## Testing ## Testing
Please test with [shellcheck](https://github.com/koalaman/shellcheck), although this will also be tested on github ( via travis) on all PRs.
Please test with [shellcheck](https://github.com/koalaman/shellcheck),
although this will also be tested on github (via travis) on all PRs.
Please remember that the system is used across a wide range of platforms, so if you have access to multiple operating systems, please test on all.
Please remember that the system is used across a wide range of
platforms, so if you have access to multiple operating systems, please
test on all.
Thanks :)
Thanks :)

+ 138
- 55
README.md View File

@ -1,44 +1,87 @@
![Run all tests](https://github.com/srvrco/getssl/workflows/Run%20all%20tests/badge.svg) ![shellcheck](https://github.com/srvrco/getssl/workflows/shellcheck/badge.svg)
# getssl # getssl
Obtain SSL certificates from the letsencrypt.org ACME server. Suitable for automating the process on remote servers.
Obtain SSL certificates from the letsencrypt.org ACME server. Suitable
for automating the process on remote servers.
## Upgrading from ACME v01 to ACME v02
Find the following line in your `getssl.cfg` file:
```CA="https://acme-v01.api.letsencrypt.org"```
and change it to:
```CA="https://acme-v02.api.letsencrypt.org"```
## Features ## Features
* **Bash** - It runs on virtually all unix machines, including BSD, most Linux distributions, macOS.
* **Get certificates for remote servers** - The tokens used to provide validation of domain ownership, and the certificates themselves can be automatically copied to remote servers (via ssh, sftp or ftp for tokens). The script doesn't need to run on the server itself. This can be useful if you don't have access to run such scripts on the server itself, e.g. if it's a shared server.
* **Runs as a daily cron** - so certificates will be automatically renewed when required.
* **Bash** - It runs on virtually all unix machines, including BSD, most
Linux distributions, macOS.
* **Get certificates for remote servers** - The tokens used to provide
validation of domain ownership, and the certificates themselves can be
automatically copied to remote servers (via ssh, sftp or ftp for
tokens). The script doesn't need to run on the server itself. This can
be useful if you don't have access to run such scripts on the server
itself, e.g. if it's a shared server.
* **Runs as a daily cron** - so certificates will be automatically
renewed when required.
* **Automatic certificate renewals** * **Automatic certificate renewals**
* **Checks certificates are correctly loaded**. After installation of a new certificate it will test the port specified ( see [Server-Types](#server-types) for options ) that the certificate is actually being used correctly.
* **Automatically updates** - The script can automatically update itself with bug fixes etc if required.
* **Extensively configurable** - With a simple configuration file for each certificate it is possible to configure it exactly for your needs, whether a simple single domain or multiple domains across multiple servers on the same certificate.
* **Checks certificates are correctly loaded** - After installation of a
new certificate it will test the port specified ( see
[Server-Types](#server-types) for options ) that the certificate is
actually being used correctly.
* **Automatically updates** - The script can automatically update itself
with bug fixes etc if required.
* **Extensively configurable** - With a simple configuration file for
each certificate it is possible to configure it exactly for your
needs, whether a simple single domain or multiple domains across
multiple servers on the same certificate.
* **Supports http and dns challenges** - Full ACME implementation * **Supports http and dns challenges** - Full ACME implementation
* **Simple and easy to use** * **Simple and easy to use**
* **Detailed debug info** - Whilst it shouldn't be needed, detailed debug information is available.
* **Reload services** - After a new certificate is obtained then the relevant services (e.g. apache/nginx/postfix) can be reloaded.
* **Detailed debug info** - Whilst it shouldn't be needed, detailed
debug information is available.
* **Reload services** - After a new certificate is obtained then the
relevant services (e.g. apache/nginx/postfix) can be reloaded.
* **ACME v1 and V2** - Supports both ACME versions 1 and 2 * **ACME v1 and V2** - Supports both ACME versions 1 and 2
## Installation ## Installation
Since the script is only one file, you can use the following command for a quick installation of GetSSL only:
```
Since the script is only one file, you can use the following command for
a quick installation of GetSSL only:
```sh
curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl ; chmod 700 getssl curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl > getssl ; chmod 700 getssl
``` ```
This will copy the getssl Bash script to the current location and change the permissions to make it executable for you.
For a more comprehensive installation (e.g. install also helper scripts) use the provided Makefile with each release tarball. Use the `install` target.
This will copy the getssl Bash script to the current location and change
the permissions to make it executable for you.
For a more comprehensive installation (e.g. install also helper scripts)
use the provided Makefile with each release tarball. Use the `install`
target.
You'll find the latest version in the git repository: You'll find the latest version in the git repository:
```
```sh
git clone https://github.com/srvrco/getssl.git git clone https://github.com/srvrco/getssl.git
``` ```
For Arch Linux there are packages in the AUR, see [here](https://aur.archlinux.org/packages/getssl/) and [there](https://aur.archlinux.org/packages/getssl-git/).
For Arch Linux there are packages in the AUR, see
[here](https://aur.archlinux.org/packages/getssl/) and
[there](https://aur.archlinux.org/packages/getssl-git/).
If you use puppet, there is a [GetSSL Puppet module](https://github.com/dthielking/puppet_getssl) by dthielking
If you use puppet, there is a [GetSSL Puppet
module](https://github.com/dthielking/puppet_getssl) by dthielking
## Overview ## Overview
GetSSL was written in standard bash ( so it can be run on a server, a desktop computer, or even a virtualbox) and add the checks, and certificates to a remote server ( providing you have a ssh with key, sftp or ftp access to the remote server).
GetSSL was written in standard bash ( so it can be run on a server, a
desktop computer, or even a virtualbox) and add the checks, and
certificates to a remote server ( providing you have a ssh with key,
sftp or ftp access to the remote server).
```
```getssl
getssl ver. 2.02 getssl ver. 2.02
Obtain SSL certificates from the letsencrypt.org ACME server Obtain SSL certificates from the letsencrypt.org ACME server
@ -63,27 +106,36 @@ Options:
Once you have obtained the script (see Installation above), the next step is to use Once you have obtained the script (see Installation above), the next step is to use
```./getssl -c yourdomain.com```
```sh
./getssl -c yourdomain.com
```
where yourdomain.com is the primary domain name that you want to create a certificate for. This will create the following folders and files.
where yourdomain.com is the primary domain name that you want to create
a certificate for. This will create the following folders and files.
```
```sh
~/.getssl ~/.getssl
~/.getssl/getssl.cfg ~/.getssl/getssl.cfg
~/.getssl/yourdomain.com ~/.getssl/yourdomain.com
~/.getssl/yourdomain.com/getssl.cfg ~/.getssl/yourdomain.com/getssl.cfg
``` ```
You can then edit ~/.getssl/getssl.cfg to set the values you want as the default for the majority of your certificates.
You can then edit `~/.getssl/getssl.cfg` to set the values you want as the
default for the majority of your certificates.
Then edit ~/.getssl/yourdomain.com/getssl.cfg to have the values you want for this specific domain (make sure to uncomment and specify correct `ACL` option, since it is required).
Then edit `~/.getssl/yourdomain.com/getssl.cfg` to have the values you
want for this specific domain (make sure to uncomment and specify
correct `ACL` option, since it is required).
You can then just run;
You can then just run:
```getssl yourdomain.com ```
and it should run, providing output like;
```sh
getssl yourdomain.com
``` ```
and it should run, providing output like:
```sh
Registering account Registering account
Verify each domain Verify each domain
Verifying yourdomain.com Verifying yourdomain.com
@ -98,35 +150,46 @@ copying private key to ssh:server5:/home/yourdomain/ssl/domain.key
copying CA certificate to ssh:server5:/home/yourdomain/ssl/chain.crt copying CA certificate to ssh:server5:/home/yourdomain/ssl/chain.crt
reloading SSL services reloading SSL services
``` ```
**This will (by default) use the staging server, so should give you a certificate that isn't trusted ( Fake Let's Encrypt).**
**This will (by default) use the staging server, so should give you a
certificate that isn't trusted ( Fake Let's Encrypt).**
Change the server in your config file to get a fully valid certificate. Change the server in your config file to get a fully valid certificate.
**Note:** Verification is done via port 80 (http), port 443 (https) or dns. The certificate can be used (and checked with getssl) on alternate ports.
**Note:** Verification is done via port 80 (http), port 443 (https) or
dns. The certificate can be used (and checked with getssl) on alternate
ports.
## Automating updates ## Automating updates
I use the following cron I use the following cron
```
```cron
23 5 * * * /root/scripts/getssl -u -a -q 23 5 * * * /root/scripts/getssl -u -a -q
``` ```
The cron will automatically update getssl and renew any certificates, only giving output if there are issues / errors.
The cron will automatically update getssl and renew any certificates,
only giving output if there are issues / errors.
* The -u flag updates getssl if there is a more recent version available. * The -u flag updates getssl if there is a more recent version available.
* The -a flag automatically renews any certificates that are due for renewal. * The -a flag automatically renews any certificates that are due for renewal.
* The -q flag is "quiet" so that it only outputs and emails me if there was an error / issue.
* The -q flag is "quiet" so that it only outputs and emails me if there
was an error / issue.
## Structure ## Structure
The design aim was to provide flexibility in running the code. The default working directory is ~/.getssl ( which can be modified via the command line)
The design aim was to provide flexibility in running the code. The
default working directory is `~/.getssl` (which can be modified via the
command line).
Within the **working directory** is a config file, getssl.cfg which is a simple bash file containing variables, an example of which is
Within the **working directory** is a config file `getssl.cfg` which is a
simple bash file containing variables, an example of which is:
```
```getssl
# Uncomment and modify any variables you need # Uncomment and modify any variables you need
# The staging server is best for testing (hence set as default) # The staging server is best for testing (hence set as default)
CA="https://acme-staging.api.letsencrypt.org"
CA="https://acme-staging-v02.api.letsencrypt.org"
# This server issues full certificates, however has rate limits # This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
#CA="https://acme-v02.api.letsencrypt.org"
AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
@ -143,17 +206,19 @@ RENEW_ALLOW="30"
SSLCONF="/usr/lib/ssl/openssl.cnf" SSLCONF="/usr/lib/ssl/openssl.cnf"
``` ```
then, within the **working directory** there will be a folder for each certificate (based on its domain name). Within that folder will be a config file (again called getssl.cfg). An example of which is;
then, within the **working directory** there will be a folder for each
certificate (based on its domain name). Within that folder will be a
config file (again called `getssl.cfg`). An example of which is:
```
```getssl
# Uncomment and modify any variables you need # Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details # see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs # see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
# #
# The staging server is best for testing # The staging server is best for testing
#CA="https://acme-staging.api.letsencrypt.org"
#CA="https://acme-staging-v02.api.letsencrypt.org"
# This server issues full certificates, however has rate limits # This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
#CA="https://acme-v02.api.letsencrypt.org"
#AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf" #AGREEMENT="https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf"
@ -195,24 +260,32 @@ RELOAD_CMD="service apache2 reload"
#CHECK_REMOTE="true" #CHECK_REMOTE="true"
``` ```
If a location for a file starts with ssh: it is assumed the next part of the file is the hostname, followed by a colon, and then the path.
Files will be securely copied using scp, and it assumes that you have a key on the server ( for passwordless access). You can set the user, port etc for the server in your .ssh/config file
If a location for a file starts with `ssh:` it is assumed the next part
of the file is the hostname, followed by a colon, and then the path.
Files will be securely copied using scp, and it assumes that you have a
key on the server (for passwordless access). You can set the user,
port etc for the server in your `.ssh/config` file.
If an ACL starts with ftp: or sftp: it as assumed that the line is in the format "ftp:UserID:Password:servername:/path/to/acme-challenge". sftp requires sshpass.
Note: FTP can be used for copying tokens only and can **not** be used for uploading private key or certificates as it's not a secure method of transfer.
If an ACL starts with `ftp:` or `sftp:` it as assumed that the line is
in the format "ftp:UserID:Password:servername:/path/to/acme-challenge".
sftp requires sshpass.
Note: FTP can be used for copying tokens only
and can **not** be used for uploading private key or certificates as
it's not a secure method of transfer.
ssh can also be used for the reload command if using on remote servers. ssh can also be used for the reload command if using on remote servers.
Multiple locations can be defined for a file by separating the locations with a semi-colon. Multiple locations can be defined for a file by separating the locations with a semi-colon.
A typical config file for `example.com` and `www.example.com` on the
same server would be:
A typical config file for example.com and www.example.com on the same server would be
```
```getssl
# uncomment and modify any variables you need # uncomment and modify any variables you need
# The staging server is best for testing # The staging server is best for testing
CA="https://acme-staging.api.letsencrypt.org"
CA="https://acme-staging-v02.api.letsencrypt.org"
# This server issues full certificates, however has rate limits # This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
#CA="https://acme-v02.api.letsencrypt.org"
# additional domains - this could be multiple domains / subdomains in a comma separated list # additional domains - this could be multiple domains / subdomains in a comma separated list
SANS="www.example.com" SANS="www.example.com"
@ -231,6 +304,7 @@ RELOAD_CMD="service apache2 reload"
``` ```
## Server-Types ## Server-Types
OpenSSL has built-in support for getting the certificate from a number of SSL services OpenSSL has built-in support for getting the certificate from a number of SSL services
these are available in getssl to check if the certificate is installed correctly these are available in getssl to check if the certificate is installed correctly
@ -252,23 +326,32 @@ these are available in getssl to check if the certificate is installed correctly
| ldaps | 636 | | | ldaps | 636 | |
| port number | | | | port number | | |
## Revoke a certificate ## Revoke a certificate
In general revoking a certificate is not required. In general revoking a certificate is not required.
Usage: `getssl -r path/to/cert path/to/key [CA_server]` Usage: `getssl -r path/to/cert path/to/key [CA_server]`
You need to specify both the certificate you want to revoke, and the account or private domain key which was used to sign / obtain the original certificate. The CA_server is an optional parameter and defaults to Let's Encrypt ( "https://acme-v01.api.letsencrypt.org" ) as that is currently the only Certificate Authority using the ACME protocol.
You need to specify both the certificate you want to revoke, and the
account or private domain key which was used to sign / obtain the
original certificate. The `CA_server` is an optional parameter and
defaults to Let's Encrypt ("<https://acme-v01.api.letsencrypt.org>") as
that is currently the only Certificate Authority using the ACME
protocol.
## Elliptic curve keys ## Elliptic curve keys
You can use Elliptic curve keys for both the account key and the domain key (different of course, don't use the same key for both). prime256v1 (NIST P-256) and secp384r1 (NIST P-384) are both fully supported. secp521r1 (NIST P-521) is included in the code, but not currently supported by Let's Encrypt).
You can use Elliptic curve keys for both the account key and the domain
key (different of course, don't use the same key for both). prime256v1
(NIST P-256) and secp384r1 (NIST P-384) are both fully supported.
secp521r1 (NIST P-521) is included in the code, but not currently
supported by Let's Encrypt).
## Issues / problems / help ## Issues / problems / help
If you have any issues, please log them at https://github.com/srvrco/getssl/issues
If you have any issues, please log them at <https://github.com/srvrco/getssl/issues>
There are additional help pages on the [wiki](https://github.com/srvrco/getssl/wiki) There are additional help pages on the [wiki](https://github.com/srvrco/getssl/wiki)
If you have any suggestions for improvements then pull requests are welcomed, or raise an issue.
If you have any suggestions for improvements then pull requests are
welcomed, or raise an issue.

+ 1
- 1
dns_scripts/dns_add_challtestsrv View File

@ -4,4 +4,4 @@
fulldomain="${1}" fulldomain="${1}"
token="${2}" token="${2}"
curl -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt
curl --silent -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt

+ 103
- 0
dns_scripts/dns_add_clouddns View File

@ -0,0 +1,103 @@
#!/usr/bin/env bash
# Need to add your email address and API key to clouddns below or set as env variables
email=${CLOUDDNS_EMAIL:-''}
password=${CLOUDDNS_PASSWORD:-''}
client=${CLOUDDNS_CLIENT:-''}
# This script adds a token to clouddns DNS for the ACME challenge
# usage dns_add_clouddns "domain name" "token"
# return codes are;
# 0 - success
# 1 - error in input
# 2 - error within internal processing
# 3 - error in result ( domain not found in clouddns etc)
fulldomain="${1}"
token="${2}"
API='https://admin.vshosting.cloud/clouddns'
LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
# Check initial parameters
if [[ -z "$fulldomain" ]]; then
echo "DNS script requires full domain name as first parameter"
exit 1
fi
if [[ -z "$token" ]]; then
echo "DNS script requires challenge token as second parameter"
exit 1
fi
if [[ -z "$email" ]]; then
echo "CLOUDDNS_EMAIL (email) parameter not set"
exit 1
fi
if [[ -z "$password" ]]; then
echo "CLOUDDNS_PASSWORD (password) parameter not set"
exit 1
fi
if [[ -z "$client" ]]; then
echo "CLOUDDNS_CLIENT (id) parameter not set"
exit 1
fi
# Login to clouddns to get accessToken
resp=$(curl --silent -X POST -H 'Content-Type: application/json' "$LOGIN_API" \
--data "{\"email\": \"$email\", \"password\": \"$password\"}")
re='"accessToken":"([^,]*)",' # Match access token
if [[ "${resp// }" =~ $re ]]; then
access_token="${BASH_REMATCH[1]}"
fi
if [[ -z "$access_token" ]]; then
echo 'Could not get access token; check your credentials'
exit 3
fi
curl_params=( -H "Authorization: Bearer $access_token" -H 'Content-Type: application/json' )
# Get main domain
resp=$(curl --silent "${curl_params[@]}" -X POST "$API/domain/search" \
--data "{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$client\"}]}")
domain_slice="$fulldomain"
while [[ -z "$domain_root" ]]; do
if [[ "${resp// }" =~ domainName\":\"$domain_slice ]]; then
domain_root="$domain_slice"
_debug domain_root "$domain_root"
fi
domain_slice="${domain_slice#[^\.]*.}"
done
# Get domain id
resp=$(curl --silent "${curl_params[@]}" -X POST "$API/domain/search" \
--data "{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$client\"}, {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}")
re='domainType":"[^"]*","id":"([^,]*)",' # Match domain id
if [[ "${resp//[$'\t\r\n ']}" =~ $re ]]; then
domain_id="${BASH_REMATCH[1]}"
fi
if [[ -z "$domain_id" ]]; then
echo 'Domain name not found on your CloudDNS account'
exit 3
fi
# Add challenge record
txt_record="_acme-challenge.$fulldomain."
resp=$(curl --silent "${curl_params[@]}" -X POST "$API/record-txt" \
--data "{\"type\":\"TXT\",\"name\":\"$txt_record\",\"value\":\"$token\",\"domainId\":\"$domain_id\"}")
# If adding record failed (error:) then print error message
if [[ "${resp// }" == *'"error"'* ]]; then
if [[ "${resp// }" == *'"code":4136'* ]]; then
echo "DNS challenge token already exists"
exit
fi
re='"message":"([^"]+)"'
if [[ "$resp" =~ $re ]]; then
echo "Error: DNS challenge not added: ${BASH_REMATCH[1]}"
exit 3
else
echo "Error: DNS challenge not added: unknown error - ${resp}"
exit 3
fi
fi
# Publish challenge record
resp=$(curl --silent "${curl_params[@]}" -X PUT "$API/domain/$domain_id/publish" \
--data "{\"soaTtl\":300}")

+ 19
- 0
dns_scripts/dns_add_duckdns View File

@ -0,0 +1,19 @@
#!/bin/bash
# need to add your Token for duckdns below
token=${DUCKDNS_TOKEN:-}
if [ -z "$token" ]; then
echo "DUCKDNS_TOKEN not set"
exit 1
fi
domain="$1"
txtvalue="$2"
response=$(curl --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}")
if [ "$response" != "OK" ]; then
echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)"
echo "Response: $response"
exit 1
fi

+ 13
- 11
dns_scripts/dns_add_nsupdate View File

@ -14,26 +14,28 @@ token="$2"
if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'open' "${fulldomain}" ; then
exit $(( $? + 128 ))
fi
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'open' "${fulldomain}" ; then
exit $(( $? + 128 ))
fi
options="-k ${DNS_NSUPDATE_KEYFILE}"
options="-k ${DNS_NSUPDATE_KEYFILE}"
fi fi
# Note that blank line is a "send" command to nsupdate
if [ -n "${DNS_SERVER}" ]; then
cmd+="server ${DNS_SERVER}\n"
fi
nsupdate "${options}" -v <<EOF
update add _acme-challenge.${fulldomain}. 300 in TXT "${token}"
cmd+="update add ${DNS_ZONE:-"_acme-challenge.${fulldomain}."} 300 in TXT \"${token}\"\n"
cmd+="\n" # blank line is a "send" command to nsupdate
EOF
printf "$cmd" | nsupdate ${options} -v
sts=$? sts=$?
if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'close' "${fulldomain}"; then
exit $(( sts + ( $? * 10 ) ))
fi
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! ${DNS_NSUPDATE_KEY_HOOK} 'add' 'close' "${fulldomain}"; then
exit $(( sts + ( $? * 10 ) ))
fi
fi fi
exit ${sts} exit ${sts}

+ 0
- 0
dns_scripts/dns_del_challtestsrv View File


+ 110
- 0
dns_scripts/dns_del_clouddns View File

@ -0,0 +1,110 @@
#!/usr/bin/env bash
# Need to add your email address and API key to clouddns below or set as env variables
email=${CLOUDDNS_EMAIL:-''}
password=${CLOUDDNS_PASSWORD:-''}
client=${CLOUDDNS_CLIENT:-''}
# This script adds a token to clouddns DNS for the ACME challenge
# usage dns_add_clouddns "domain name" "token"
# return codes are;
# 0 - success
# 1 - error in input
# 2 - error within internal processing
# 3 - error in result ( domain not found in clouddns etc)
fulldomain="${1}"
token="${2}"
API='https://admin.vshosting.cloud/clouddns'
LOGIN_API='https://admin.vshosting.cloud/api/public/auth/login'
# Check initial parameters
if [[ -z "$fulldomain" ]]; then
echo "DNS script requires full domain name as first parameter"
exit 1
fi
if [[ -z "$token" ]]; then
echo "DNS script requires challenge token as second parameter"
exit 1
fi
if [[ -z "$email" ]]; then
echo "CLOUDDNS_EMAIL (email) parameter not set"
exit 1
fi
if [[ -z "$password" ]]; then
echo "CLOUDDNS_PASSWORD (password) parameter not set"
exit 1
fi
if [[ -z "$client" ]]; then
echo "CLOUDDNS_CLIENT (id) parameter not set"
exit 1
fi
# Login to clouddns to get accessToken
resp=$(curl --silent -X POST -H 'Content-Type: application/json' "$LOGIN_API" \
--data "{\"email\": \"$email\", \"password\": \"$password\"}")
re='"accessToken":"([^,]*)",' # Match access token
if [[ "${resp// }" =~ $re ]]; then
access_token="${BASH_REMATCH[1]}"
fi
if [[ -z "$access_token" ]]; then
echo 'Could not get access token; check your credentials'
exit 3
fi
curl_params=( -H "Authorization: Bearer $access_token" -H 'Content-Type: application/json' )
# Get main domain and challenge record
resp=$(curl --silent "${curl_params[@]}" -X POST "$API/domain/search" \
--data "{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$client\"}]}")
domain_slice="$fulldomain"
while [[ -z "$domain_root" ]]; do
if [[ "${resp// }" =~ domainName\":\"$domain_slice ]]; then
domain_root="$domain_slice"
_debug domain_root "$domain_root"
fi
domain_slice="${domain_slice#[^\.]*.}"
done
txt_record="_acme-challenge.$fulldomain."
# Get domain id
curl_domainid_body="{\"search\": [{\"name\": \"clientId\", \"operator\": \"eq\", \"value\": \"$client\"}, {\"name\": \"domainName\", \"operator\": \"eq\", \"value\": \"$domain_root.\"}]}"
resp=$(curl --silent "${curl_params[@]}" -X POST -d "$curl_domainid_body" "$API/domain/search")
re='domainType":"[^"]*","id":"([^,]*)",' # Find result section
if [[ "${resp//[$'\t\r\n ']}" =~ $re ]]; then
domain_id="${BASH_REMATCH[1]}"
fi
if [[ -z "$domain_id" ]]; then
echo 'Domain name not found on your CloudDNS account'
exit 3
fi
# Get challenge record ID
resp=$(curl --silent "${curl_params[@]}" -X GET "$API/domain/$domain_id" )
re="\"lastDomainRecordList\".*\"id\":\"([^,]*)\"[^}]*\"name\":\"$txt_record\"," # Match domain id
if [[ "${resp//[$'\t\r\n ']}" =~ $re ]]; then
record_id="${BASH_REMATCH[1]}"
fi
if [[ -z "$record_id" ]]; then
echo 'Challenge record does not exist'
exit 3
fi
# Remove challenge record
resp=$(curl --silent "${curl_params[@]}" -X DELETE "$API/record/$record_id")
# If removing record failed (error:) then print error message
if [[ "${resp// }" == *'"error"'* ]]; then
re='"message":"([^"]+)"'
if [[ "$resp" =~ $re ]]; then
echo "Error: DNS challenge not removed: ${BASH_REMATCH[1]}"
exit 3
else
echo "Error: DNS challenge not removed: unknown error - ${resp}"
exit 3
fi
fi
# Publish challenge record deletion
resp=$(curl --silent "${curl_params[@]}" -X PUT "$API/domain/$domain_id/publish" \
--data "{\"soaTtl\":300}")

+ 12
- 0
dns_scripts/dns_del_duckdns View File

@ -0,0 +1,12 @@
#!/bin/bash
# need to add your Token for duckdns below
token=${DUCKDNS_TOKEN:-}
domain="$1"
response=$(curl --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true")
if [ "$response" != "OK" ]; then
echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)"
echo "$response"
exit 1
fi

+ 13
- 11
dns_scripts/dns_del_nsupdate View File

@ -14,26 +14,28 @@ token="$2"
# 'open" / 'close' # 'open" / 'close'
if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! "${DNS_NSUPDATE_KEY_HOOK}" 'del' 'open' "${fulldomain}" ; then
exit $(( $? + 128 ))
fi
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! "${DNS_NSUPDATE_KEY_HOOK}" 'del' 'open' "${fulldomain}" ; then
exit $(( $? + 128 ))
fi
options="-k ${DNS_NSUPDATE_KEYFILE}"
options="-k ${DNS_NSUPDATE_KEYFILE}"
fi fi
# Note that blank line is a "send" command to nsupdate
if [ -n "${DNS_SERVER}" ]; then
cmd+="server ${DNS_SERVER}\n"
fi
nsupdate "${options}" -v <<EOF
update delete "_acme-challenge.${fulldomain}." 300 in TXT "${token}"
cmd+="update delete ${DNS_ZONE:-"_acme-challenge.${fulldomain}."} 300 in TXT \"${token}\"\n"
cmd+="\n" # blank line is a "send" command to nsupdate
EOF
printf "$cmd" | nsupdate ${options} -v
sts=$? sts=$?
if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then if [ -n "${DNS_NSUPDATE_KEYFILE}" ]; then
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! "${DNS_NSUPDATE_KEY_HOOK}" 'del' 'close' "${fulldomain}" ; then
exit $(( sts + ( $? * 10 ) ))
fi
if [ -n "${DNS_NSUPDATE_KEY_HOOK}" ] && ! "${DNS_NSUPDATE_KEY_HOOK}" 'del' 'close' "${fulldomain}" ; then
exit $(( sts + ( $? * 10 ) ))
fi
fi fi
exit ${sts} exit ${sts}

+ 702
- 0
dns_scripts/dns_freedns.sh View File

@ -0,0 +1,702 @@
#!/usr/bin/env sh
#This file name is "dns_freedns.sh"
#So, here must be a method dns_freedns_add()
#Which will be called by acme.sh to add the txt record to your api system.
#returns 0 means success, otherwise error.
#
#Author: David Kerr
#Report Bugs here: https://github.com/dkerr64/acme.sh
#or here... https://github.com/Neilpang/acme.sh/issues/2305
#
######## Public functions #####################
# Export FreeDNS userid and password in following variables...
# FREEDNS_User=username
# FREEDNS_Password=password
# login cookie is saved in acme account config file so userid / pw
# need to be set only when changed.
#Usage: dns_freedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_freedns_add() {
fulldomain="_acme-challenge.$1"
txtvalue="$2"
FREEDNS_COOKIE="$(cat $(dirname "$(readlink -f "$0")")/freednscookie.dat)"
echo "Info: Add TXT record using FreeDNS"
#echo "Debug: fulldomain: $fulldomain"
#echo "Debug: txtvalue: $txtvalue"
if [ -z "$FREEDNS_User" ] || [ -z "$FREEDNS_Password" ]; then
FREEDNS_User=""
FREEDNS_Password=""
if [ -z "$FREEDNS_COOKIE" ]; then
echo "ERROR: You did not specify the FreeDNS username and password yet."
echo "ERROR: Please export as FREEDNS_User / FREEDNS_Password and try again."
return 1
fi
using_cached_cookies="true"
else
FREEDNS_COOKIE="$(_freedns_login "$FREEDNS_User" "$FREEDNS_Password")"
if [ -z "$FREEDNS_COOKIE" ]; then
return 1
fi
using_cached_cookies="false"
fi
#echo "Debug: FreeDNS login cookies: $FREEDNS_COOKIE (cached = $using_cached_cookies)"
echo "$FREEDNS_COOKIE">$(dirname "$(readlink -f "$0")")/freednscookie.dat
# We may have to cycle through the domain name to find the
# TLD that we own...
i=1
wmax="$(echo "$fulldomain" | tr '.' ' ' | wc -w)"
while [ "$i" -lt "$wmax" ]; do
# split our full domain name into two parts...
sub_domain="$(echo "$fulldomain" | cut -d. -f -"$i")"
i="$(_math "$i" + 1)"
top_domain="$(echo "$fulldomain" | cut -d. -f "$i"-100)"
#echo "Debug: sub_domain: $sub_domain"
#echo "Debug: top_domain: $top_domain"
DNSdomainid="$(_freedns_domain_id "$top_domain")"
if [ "$?" = "0" ]; then
echo "Info:Domain $top_domain found at FreeDNS, domain_id $DNSdomainid"
break
else
echo "Info:Domain $top_domain not found at FreeDNS, try with next level of TLD"
fi
done
if [ -z "$DNSdomainid" ]; then
# If domain ID is empty then something went wrong (top level
# domain not found at FreeDNS).
echo "ERROR: Domain $top_domain not found at FreeDNS"
return 1
fi
# Add in new TXT record with the value provided
#echo "Debug: Adding TXT record for $fulldomain, $txtvalue"
_freedns_add_txt_record "$FREEDNS_COOKIE" "$DNSdomainid" "$sub_domain" "$txtvalue"
return $?
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_freedns_rm() {
fulldomain="_acme-challenge.$1"
txtvalue="$2"
echo "Info:Delete TXT record using FreeDNS"
#echo "Debug: fulldomain: $fulldomain"
#echo "Debug: txtvalue: $txtvalue"
# Need to read cookie from conf file again in case new value set
# during login to FreeDNS when TXT record was created.
FREEDNS_COOKIE="$(cat $(dirname "$(readlink -f "$0")")/freednscookie.dat)"
#echo "Debug: FreeDNS login cookies: $FREEDNS_COOKIE"
TXTdataid="$(_freedns_data_id "$fulldomain" "TXT")"
if [ "$?" != "0" ]; then
echo "Info:Cannot delete TXT record for $fulldomain, record does not exist at FreeDNS"
return 1
fi
#echo "Debug: Data ID's found, $TXTdataid"
# now we have one (or more) TXT record data ID's. Load the page
# for that record and search for the record txt value. If match
# then we can delete it.
lines="$(echo "$TXTdataid" | wc -l)"
#echo "Debug: Found $lines TXT data records for $fulldomain"
i=0
while [ "$i" -lt "$lines" ]; do
i="$(_math "$i" + 1)"
dataid="$(echo "$TXTdataid" | sed -n "${i}p")"
#echo "Debug: $dataid"
htmlpage="$(_freedns_retrieve_data_page "$FREEDNS_COOKIE" "$dataid")"
if [ "$?" != "0" ]; then
if [ "$using_cached_cookies" = "true" ]; then
echo "ERROR: Has your FreeDNS username and password changed? If so..."
echo "ERROR: Please export as FREEDNS_User / FREEDNS_Password and try again."
fi
return 1
fi
echo "$htmlpage" | grep "value=\"&quot;$txtvalue&quot;\"" >/dev/null
if [ "$?" = "0" ]; then
# Found a match... delete the record and return
echo "Info:Deleting TXT record for $fulldomain, $txtvalue"
_freedns_delete_txt_record "$FREEDNS_COOKIE" "$dataid"
return $?
fi
done
# If we get this far we did not find a match
# Not necessarily an error, but log anyway.
echo "Info:Cannot delete TXT record for $fulldomain, $txtvalue. Does not exist at FreeDNS"
return 0
}
#################### Private functions below ##################################
# usage: _freedns_login username password
# print string "cookie=value" etc.
# returns 0 success
_freedns_login() {
export _H1="Accept-Language:en-US"
username="$1"
password="$2"
url="https://freedns.afraid.org/zc.php?step=2"
#echo "Debug: Login to FreeDNS as user $username"
data="username=$(printf '%s' "$username" | _url_encode)&password=$(printf '%s' "$password" | _url_encode)&submit=Login&action=auth"
#echo "$data"
if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
HTTP_HEADER="$(_mktemp)"
fi
htmlpage="$(curl -L --silent --dump-header $HTTP_HEADER -X POST -H "$_H1" -H "$_H2" --data "$data" "$url")"
if [ "$?" != "0" ]; then
echo "ERROR: FreeDNS login failed for user $username bad RC from _post"
return 1
fi
cookies="$(grep -i '^Set-Cookie.*dns_cookie.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
# if cookies is not empty then logon successful
if [ -z "$cookies" ]; then
#echo "Debug3: htmlpage: $htmlpage"
echo "ERROR: FreeDNS login failed for user $username. Check $HTTP_HEADER file"
return 1
fi
printf "%s" "$cookies"
return 0
}
# usage _freedns_retrieve_subdomain_page login_cookies
# echo page retrieved (html)
# returns 0 success
_freedns_retrieve_subdomain_page() {
export _H1="Cookie:$1"
export _H2="Accept-Language:en-US"
url="https://freedns.afraid.org/subdomain/"
#echo "Debug: Retrieve subdomain page from FreeDNS"
htmlpage="$(curl -L --silent -H "$_H1" -H "$_H2" "$url")"
if [ "$?" != "0" ]; then
echo "ERROR: FreeDNS retrieve subdomains failed bad RC from _get"
return 1
elif [ -z "$htmlpage" ]; then
echo "ERROR: FreeDNS returned empty subdomain page"
return 1
fi
#echo "Debug3: htmlpage: $htmlpage"
printf "%s" "$htmlpage"
return 0
}
# usage _freedns_retrieve_data_page login_cookies data_id
# echo page retrieved (html)
# returns 0 success
_freedns_retrieve_data_page() {
export _H1="Cookie:$1"
export _H2="Accept-Language:en-US"
data_id="$2"
url="https://freedns.afraid.org/subdomain/edit.php?data_id=$2"
#echo "Debug: Retrieve data page for ID $data_id from FreeDNS"
htmlpage="$(curl -L --silent -H "$_H1" -H "$_H2" "$url")"
if [ "$?" != "0" ]; then
echo "ERROR: FreeDNS retrieve data page failed bad RC from _get"
return 1
elif [ -z "$htmlpage" ]; then
echo "ERROR: FreeDNS returned empty data page"
return 1
fi
#echo "Debug3: htmlpage: $htmlpage"
printf "%s" "$htmlpage"
return 0
}
# usage _freedns_add_txt_record login_cookies domain_id subdomain value
# returns 0 success
_freedns_add_txt_record() {
export _H1="Cookie:$1"
export _H2="Accept-Language:en-US"
domain_id="$2"
subdomain="$3"
value="$(printf '%s' "$4" | _url_encode)"
url="https://freedns.afraid.org/subdomain/save.php?step=2"
if [ -z "$HTTP_HEADER" ] || ! touch "$HTTP_HEADER"; then
HTTP_HEADER="$(_mktemp)"
fi
htmlpage="$(curl -L --silent --dump-header $HTTP_HEADER -X POST -H "$_H1" -H "$_H2" --data "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")"
if [ "$?" != "0" ]; then
echo "ERROR: FreeDNS failed to add TXT record for $subdomain bad RC from _post"
return 1
elif ! grep "200 OK" "$HTTP_HEADER" >/dev/null; then
#echo "Debug3: htmlpage: $(cat $HTTP_HEADER)"
echo "ERROR: FreeDNS failed to add TXT record for $subdomain. Check $HTTP_HEADER file"
return 1
elif _contains "$htmlpage" "security code was incorrect"; then
#echo "Debug3: htmlpage: $htmlpage"
echo "ERROR: FreeDNS failed to add TXT record for $subdomain as FreeDNS requested security code"
echo "ERROR: Note that you cannot use automatic DNS validation for FreeDNS public domains"
return 1
fi
#echo "Debug3: htmlpage: $htmlpage"
echo "Info:Added acme challenge TXT record for $fulldomain at FreeDNS"
return 0
}
# usage _freedns_delete_txt_record login_cookies data_id
# returns 0 success
_freedns_delete_txt_record() {
export _H1="Cookie:$1"
export _H2="Accept-Language:en-US"
data_id="$2"
url="https://freedns.afraid.org/subdomain/delete2.php"
htmlheader="$(curl -L --silent -I -H "$_H1" -H "$_H2" "$url?data_id%5B%5D=$data_id&submit=delete+selected")"
if [ "$?" != "0" ]; then
echo "ERROR: FreeDNS failed to delete TXT record for $data_id bad RC from _get"
return 1
elif ! _contains "$htmlheader" "200 OK"; then
#echo "Debug2: htmlheader: $htmlheader"
echo "ERROR: FreeDNS failed to delete TXT record $data_id"
return 1
fi
echo "Info:Deleted acme challenge TXT record for $fulldomain at FreeDNS"
return 0
}
# usage _freedns_domain_id domain_name
# echo the domain_id if found
# return 0 success
_freedns_domain_id() {
# Start by escaping the dots in the domain name
search_domain="$(echo "$1" | sed 's/\./\\./g')"
# Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again
# returns the correct subdomain page. So, we will try twice to
# load the page and obtain our domain ID
attempts=2
while [ "$attempts" -gt "0" ]; do
attempts="$(_math "$attempts" - 1)"
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
if [ "$?" != "0" ]; then
if [ "$using_cached_cookies" = "true" ]; then
echo "ERROR: Has your FreeDNS username and password changed? If so..."
echo "ERROR: Please export as FREEDNS_User / FREEDNS_Password and try again."
fi
return 1
fi
domain_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' \
| grep "<td>$search_domain</td>\|<td>$search_domain(.*)</td>" \
| sed -n 's/.*\(edit\.php?edit_domain_id=[0-9a-zA-Z]*\).*/\1/p' \
| cut -d = -f 2)"
# The above beauty extracts domain ID from the html page...
# strip out all blank space and new lines. Then insert newlines
# before each table row <tr>
# search for the domain within each row (which may or may not have
# a text string in brackets (.*) after it.
# And finally extract the domain ID.
if [ -n "$domain_id" ]; then
printf "%s" "$domain_id"
return 0
fi
#echo "Debug:Domain $search_domain not found. Retry loading subdomain page ($attempts attempts remaining)"
done
#echo "Debug:Domain $search_domain not found after retry"
return 1
}
# usage _freedns_data_id domain_name record_type
# echo the data_id(s) if found
# return 0 success
_freedns_data_id() {
# Start by escaping the dots in the domain name
search_domain="$(echo "$1" | sed 's/\./\\./g')"
record_type="$2"
# Sometimes FreeDNS does not return the subdomain page but rather
# returns a page regarding becoming a premium member. This usually
# happens after a period of inactivity. Immediately trying again
# returns the correct subdomain page. So, we will try twice to
# load the page and obtain our domain ID
attempts=2
while [ "$attempts" -gt "0" ]; do
attempts="$(_math "$attempts" - 1)"
htmlpage="$(_freedns_retrieve_subdomain_page "$FREEDNS_COOKIE")"
if [ "$?" != "0" ]; then
if [ "$using_cached_cookies" = "true" ]; then
echo "ERROR: Has your FreeDNS username and password changed? If so..."
echo "ERROR: Please export as FREEDNS_User / FREEDNS_Password and try again."
fi
return 1
fi
data_id="$(echo "$htmlpage" | tr -d " \t\r\n\v\f" | sed 's/<tr>/@<tr>/g' | tr '@' '\n' \
| grep "<td[a-zA-Z=#]*>$record_type</td>" \
| grep "<ahref.*>$search_domain</a>" \
| sed -n 's/.*\(edit\.php?data_id=[0-9a-zA-Z]*\).*/\1/p' \
| cut -d = -f 2)"
# The above beauty extracts data ID from the html page...
# strip out all blank space and new lines. Then insert newlines
# before each table row <tr>
# search for the record type withing each row (e.g. TXT)
# search for the domain within each row (which is within a <a..>
# </a> anchor. And finally extract the domain ID.
if [ -n "$data_id" ]; then
printf "%s" "$data_id"
return 0
fi
#echo "Debug:Domain $search_domain not found. Retry loading subdomain page ($attempts attempts remaining)"
done
#echo "Debug:Domain $search_domain not found after retry"
return 1
}
#### BEGIN things shamefully ripped from https://github.com/Neilpang/acme.sh/blob/master/acme.sh
#_ascii_hex str
#this can only process ascii chars, should only be used when od command is missing as a backup way.
_ascii_hex() {
_debug2 "Using _ascii_hex"
_str="$1"
_str_len=${#_str}
_h_i=1
while [ "$_h_i" -le "$_str_len" ]; do
_str_c="$(printf "%s" "$_str" | cut -c "$_h_i")"
printf " %02x" "'$_str_c"
_h_i="$(_math "$_h_i" + 1)"
done
}
#stdin output hexstr splited by one space
#input:"abc"
#output: " 61 62 63"
_hex_dump() {
if _exists od; then
od -A n -v -t x1 | tr -s " " | sed 's/ $//' | tr -d "\r\t\n"
elif _exists hexdump; then
hexdump -v -e '/1 ""' -e '/1 " %02x" ""'
elif _exists xxd; then
xxd -ps -c 20 -i | sed "s/ 0x/ /g" | tr -d ",\n" | tr -s " "
else
str=$(cat)
_ascii_hex "$str"
fi
}
#url encode, no-preserved chars
#A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
#41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a
#a b c d e f g h i j k l m n o p q r s t u v w x y z
#61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a
#0 1 2 3 4 5 6 7 8 9 - _ . ~
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
#stdin stdout
_url_encode() {
_hex_str=$(_hex_dump)
for _hex_code in $_hex_str; do
#upper case
case "${_hex_code}" in
"41")
printf "%s" "A"
;;
"42")
printf "%s" "B"
;;
"43")
printf "%s" "C"
;;
"44")
printf "%s" "D"
;;
"45")
printf "%s" "E"
;;
"46")
printf "%s" "F"
;;
"47")
printf "%s" "G"
;;
"48")
printf "%s" "H"
;;
"49")
printf "%s" "I"
;;
"4a")
printf "%s" "J"
;;
"4b")
printf "%s" "K"
;;
"4c")
printf "%s" "L"
;;
"4d")
printf "%s" "M"
;;
"4e")
printf "%s" "N"
;;
"4f")
printf "%s" "O"
;;
"50")
printf "%s" "P"
;;
"51")
printf "%s" "Q"
;;
"52")
printf "%s" "R"
;;
"53")
printf "%s" "S"
;;
"54")
printf "%s" "T"
;;
"55")
printf "%s" "U"
;;
"56")
printf "%s" "V"
;;
"57")
printf "%s" "W"
;;
"58")
printf "%s" "X"
;;
"59")
printf "%s" "Y"
;;
"5a")
printf "%s" "Z"
;;
#lower case
"61")
printf "%s" "a"
;;
"62")
printf "%s" "b"
;;
"63")
printf "%s" "c"
;;
"64")
printf "%s" "d"
;;
"65")
printf "%s" "e"
;;
"66")
printf "%s" "f"
;;
"67")
printf "%s" "g"
;;
"68")
printf "%s" "h"
;;
"69")
printf "%s" "i"
;;
"6a")
printf "%s" "j"
;;
"6b")
printf "%s" "k"
;;
"6c")
printf "%s" "l"
;;
"6d")
printf "%s" "m"
;;
"6e")
printf "%s" "n"
;;
"6f")
printf "%s" "o"
;;
"70")
printf "%s" "p"
;;
"71")
printf "%s" "q"
;;
"72")
printf "%s" "r"
;;
"73")
printf "%s" "s"
;;
"74")
printf "%s" "t"
;;
"75")
printf "%s" "u"
;;
"76")
printf "%s" "v"
;;
"77")
printf "%s" "w"
;;
"78")
printf "%s" "x"
;;
"79")
printf "%s" "y"
;;
"7a")
printf "%s" "z"
;;
#numbers
"30")
printf "%s" "0"
;;
"31")
printf "%s" "1"
;;
"32")
printf "%s" "2"
;;
"33")
printf "%s" "3"
;;
"34")
printf "%s" "4"
;;
"35")
printf "%s" "5"
;;
"36")
printf "%s" "6"
;;
"37")
printf "%s" "7"
;;
"38")
printf "%s" "8"
;;
"39")
printf "%s" "9"
;;
"2d")
printf "%s" "-"
;;
"5f")
printf "%s" "_"
;;
"2e")
printf "%s" "."
;;
"7e")
printf "%s" "~"
;;
#other hex
*)
printf '%%%s' "$_hex_code"
;;
esac
done
}
_exists() {
cmd="$1"
if [ -z "$cmd" ]; then
_usage "Usage: _exists cmd"
return 1
fi
if eval type type >/dev/null 2>&1; then
eval type "$cmd" >/dev/null 2>&1
elif command >/dev/null 2>&1; then
command -v "$cmd" >/dev/null 2>&1
else
which "$cmd" >/dev/null 2>&1
fi
ret="$?"
#echo "Debug3: $cmd exists=$ret"
return $ret
}
_head_n() {
head -n "$1"
}
_mktemp() {
if _exists mktemp; then
if mktemp 2>/dev/null; then
return 0
elif _contains "$(mktemp 2>&1)" "-t prefix" && mktemp -t "$PROJECT_NAME" 2>/dev/null; then
#for Mac osx
return 0
fi
fi
if [ -d "/tmp" ]; then
echo "/tmp/${PROJECT_NAME}wefADf24sf.$(_time).tmp"
return 0
elif [ "$LE_TEMP_DIR" ] && mkdir -p "$LE_TEMP_DIR"; then
echo "/$LE_TEMP_DIR/wefADf24sf.$(_time).tmp"
return 0
fi
_err "Can not create temp file."
}
#a + b
_math() {
_m_opts="$@"
printf "%s" "$(($_m_opts))"
}
_contains() {
_str="$1"
_sub="$2"
echo "$_str" | grep -- "$_sub" >/dev/null 2>&1
}
##Now actually do something with that function
case "$1" in
add)
dns_freedns_add $2 $3
;;
rm)
dns_freedns_rm $2 $3
;;
esac

+ 1
- 1
dns_scripts/dns_route53.py View File

@ -31,7 +31,7 @@ for zone in response['HostedZones']:
if not zone['Config']['PrivateZone']: if not zone['Config']['PrivateZone']:
zone_list[zone['Name']] = zone['Id'] zone_list[zone['Name']] = zone['Id']
for key in sorted(zone_list.iterkeys(), key=len, reverse=True):
for key in sorted(zone_list.keys(), key=len, reverse=True):
if ".{z}".format(z=key) in ".{z}.".format(z=fqdn): if ".{z}".format(z=key) in ".{z}.".format(z=fqdn):
zone_id = zone_list[key] zone_id = zone_list[key]


+ 3
- 14
docker-compose.yml View File

@ -3,12 +3,10 @@ services:
pebble: pebble:
image: letsencrypt/pebble:latest image: letsencrypt/pebble:latest
# TODO enable -strict # TODO enable -strict
command: pebble -config /test/config/pebble-config.json -dnsserver 10.30.50.3:8053
command: pebble -config /test/config/pebble-config.json -dnsserver 10.30.50.3:53
environment: environment:
# with Go 1.13.x which defaults TLS 1.3 to on # with Go 1.13.x which defaults TLS 1.3 to on
GODEBUG: "tls13=1" GODEBUG: "tls13=1"
# don't reuse authorizations (breaks testing force renew)
PEBBLE_AUTHZREUSE: 0
ports: ports:
- 14000:14000 # HTTPS ACME API - 14000:14000 # HTTPS ACME API
- 15000:15000 # HTTPS Management API - 15000:15000 # HTTPS Management API
@ -17,22 +15,13 @@ services:
ipv4_address: 10.30.50.2 ipv4_address: 10.30.50.2
challtestsrv: challtestsrv:
image: letsencrypt/pebble-challtestsrv:latest image: letsencrypt/pebble-challtestsrv:latest
command: pebble-challtestsrv -defaultIPv6 "" -defaultIPv4 10.30.50.3
command: pebble-challtestsrv -defaultIPv6 "" -defaultIPv4 10.30.50.3 -dns01 ":53"
ports: ports:
- 8055:8055 # HTTP Management API - 8055:8055 # HTTP Management API
networks: networks:
acmenet: acmenet:
ipv4_address: 10.30.50.3 ipv4_address: 10.30.50.3
getssl:
build:
context: .
dockerfile: test/Dockerfile-ubuntu
container_name: getssl
volumes:
- .:/getssl
networks:
acmenet:
ipv4_address: 10.30.50.4
networks: networks:
acmenet: acmenet:


+ 1328
- 1099
getssl
File diff suppressed because it is too large
View File


+ 40
- 0
test/1-simple-http01-dig.bats View File

@ -0,0 +1,40 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
if [ -f /usr/bin/host ]; then
mv /usr/bin/host /usr/bin/host.getssl.bak
fi
if [ -f /usr/bin/nslookup ]; then
mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak
fi
}
teardown() {
if [ -f /usr/bin/host.getssl.bak ]; then
mv /usr/bin/host.getssl.bak /usr/bin/host
fi
if [ -f /usr/bin/nslookup.getssl.bak ]; then
mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup
fi
}
@test "Create new certificate using HTTP-01 verification (dig)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}

+ 40
- 0
test/1-simple-http01-nslookup.bats View File

@ -0,0 +1,40 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
if [ -f /usr/bin/dig ]; then
mv /usr/bin/dig /usr/bin/dig.getssl.bak
fi
if [ -f /usr/bin/host ]; then
mv /usr/bin/host /usr/bin/host.getssl.bak
fi
}
teardown() {
if [ -f /usr/bin/dig.getssl.bak ]; then
mv /usr/bin/dig.getssl.bak /usr/bin/dig
fi
if [ -f /usr/bin/host.getssl.bak ]; then
mv /usr/bin/host.getssl.bak /usr/bin/host
fi
}
@test "Create new certificate using HTTP-01 verification (nslookup)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}

+ 35
- 0
test/1-simple-http01.bats View File

@ -0,0 +1,35 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Create new certificate using HTTP-01 verification (any dns tool)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of certificate using HTTP-01 (any dns tool)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
cleanup_environment
}

+ 22
- 0
test/10-mixed-case-staging.bats View File

@ -0,0 +1,22 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
@test "Check can create certificate if domain is not lowercase using staging server and DuckDNS" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
CONFIG_FILE="getssl-staging-dns01.cfg"
GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z)
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}

+ 41
- 0
test/10-mixed-case.bats View File

@ -0,0 +1,41 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Check that HTTP-01 verification works if the domain is not lowercase" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z)
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Check that DNS-01 verification works if the domain is not lowercase" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-dns01.cfg"
GETSSL_CMD_HOST=$(echo $GETSSL_HOST | tr a-z A-Z)
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}

+ 63
- 0
test/11-test--install.bats View File

@ -0,0 +1,63 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Check that config files in /etc/getssl works" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
setup_environment
# Fail if not running in docker and /etc/getssl already exists
refute [ -d /etc/getssl ]
# Create /etc/getssl/$DOMAIN
mkdir -p /etc/getssl/${GETSSL_CMD_HOST}
# Copy the config file to /etc/getssl
cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "/etc/getssl/${GETSSL_CMD_HOST}/getssl.cfg"
cp "${CODE_DIR}/test/test-config/getssl-etc-template.cfg" "/etc/getssl/getssl.cfg"
# Run getssl
run ${CODE_DIR}/getssl "$GETSSL_CMD_HOST"
assert_success
check_output_for_errors
assert_line 'Verification completed, obtaining certificate.'
assert_line 'Requesting certificate'
refute [ -d '$HOME/.getssl' ]
}
@test "Check that --install doesn't call the ACME server" {
# NOTE that this test depends on the previous test!
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01.cfg"
# Run getssl
run ${CODE_DIR}/getssl --install "$GETSSL_CMD_HOST"
assert_success
check_output_for_errors
refute_line 'Verification completed, obtaining certificate.'
refute_line 'Requesting certificate'
assert_line --partial 'copying domain certificate to'
assert_line --partial 'copying private key to'
assert_line --partial 'copying CA certificate to'
# Cleanup previous test
rm -rf /etc/getssl
}

+ 20
- 0
test/11-test-no-domain-storage.bats View File

@ -0,0 +1,20 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
@test "Check that if domain storage isn't set getssl doesn't try to delete /tmp" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-no-domain-storage.cfg"
setup_environment
mkdir ${INSTALL_DIR}/.getssl
cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg"
run ${CODE_DIR}/getssl -a
assert_success
check_output_for_errors
assert_line 'Not going to delete TEMP_DIR ///tmp as it appears to be /tmp'
}

+ 53
- 0
test/2-simple-dns01-dig.bats View File

@ -0,0 +1,53 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
if [ -f /usr/bin/host ]; then
mv /usr/bin/host /usr/bin/host.getssl.bak
fi
if [ -f /usr/bin/nslookup ]; then
mv /usr/bin/nslookup /usr/bin/nslookup.getssl.bak
fi
}
teardown() {
if [ -f /usr/bin/host.getssl.bak ]; then
mv /usr/bin/host.getssl.bak /usr/bin/host
fi
if [ -f /usr/bin/nslookup.getssl.bak ]; then
mv /usr/bin/nslookup.getssl.bak /usr/bin/nslookup
fi
}
@test "Create new certificate using DNS-01 verification (dig)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-dns01.cfg"
setup_environment
init_getssl
create_certificate -d
assert_success
assert_output --partial "dig"
check_output_for_errors "debug"
}
@test "Force renewal of certificate using DNS-01 (dig)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -d -f $GETSSL_HOST
assert_success
assert_output --partial "dig"
check_output_for_errors "debug"
cleanup_environment
}

+ 42
- 0
test/2-simple-dns01-nslookup.bats View File

@ -0,0 +1,42 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
if [ -f /usr/bin/dig ]; then
mv /usr/bin/dig /usr/bin/dig.getssl.bak
fi
if [ -f /usr/bin/host ]; then
mv /usr/bin/host /usr/bin/host.getssl.bak
fi
}
teardown() {
if [ -f /usr/bin/dig.getssl.bak ]; then
mv /usr/bin/dig.getssl.bak /usr/bin/dig
fi
if [ -f /usr/bin/host.getssl.bak ]; then
mv /usr/bin/host.getssl.bak /usr/bin/host
fi
}
@test "Create new certificate using DNS-01 verification (nslookup)" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-dns01.cfg"
setup_environment
init_getssl
create_certificate -d
assert_success
assert_output --partial "nslookup"
check_output_for_errors "debug"
}

+ 65
- 0
test/3-dual-rsa-ecdsa.bats View File

@ -0,0 +1,65 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Create dual certificates using HTTP-01 verification" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-dual-rsa-ecdsa.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
check_certificates
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ]
}
@test "Force renewal of dual certificates using HTTP-01" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
}
@test "Create dual certificates using DNS-01 verification" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
check_certificates
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.ec.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" ]
}
@test "Force renewal of dual certificates using DNS-01" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
cleanup_environment
}

+ 45
- 0
test/4-more-than-10-hosts.bats View File

@ -0,0 +1,45 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Create certificates for more than 10 hosts using HTTP-01 verification" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-10-hosts.cfg"
setup_environment
# Add 11 hosts to DNS (also need to be added as aliases in docker-compose.yml)
for prefix in a b c d e f g h i j k; do
curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a
done
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of more than 10 certificates using HTTP-01" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
# Remove all the dns aliases
cleanup_environment
for prefix in a b c d e f g h i j k; do
curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a
done
}

+ 57
- 0
test/5-secp384-http01.bats View File

@ -0,0 +1,57 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Create new secp384r1 certificate using HTTP-01 verification" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-secp384.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of secp384r1 certificate using HTTP-01" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
}
@test "Create new secp521r1 certificate using HTTP-01 verification" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-secp521.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of secp521r1 certificate using HTTP-01" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
}

+ 48
- 0
test/6-dual-rsa-ecdsa-copy-2-locations.bats View File

@ -0,0 +1,48 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# These are run for every test, not once per file
setup() {
if [ -z "$STAGING" ]; then
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a
fi
}
teardown() {
if [ -z "$STAGING" ]; then
curl --silent -X POST -d '{"host":"'a.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a
fi
}
@test "Create dual certificates and copy RSA and ECDSA chain and key to two locations" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations.cfg"
setup_environment
mkdir -p /root/a.${GETSSL_HOST}
init_getssl
create_certificate
assert_success
check_output_for_errors
# Check that the RSA chain and key have been copied to both locations
assert [ -e "/etc/nginx/pki/domain-chain.crt" ]
assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.crt" ]
assert [ -e "/etc/nginx/pki/private/server.key" ]
assert [ -e "/root/a.${GETSSL_HOST}/server.key" ]
# Check that the ECDSA chain and key have been copied to both locations
assert [ -e "/etc/nginx/pki/domain-chain.ec.crt" ]
assert [ -e "/root/a.${GETSSL_HOST}/domain-chain.ec.crt" ]
assert [ -e "/etc/nginx/pki/private/server.ec.key" ]
assert [ -e "/root/a.${GETSSL_HOST}/server.ec.key" ]
}

+ 30
- 0
test/7-staging-dns01-dig.bats View File

@ -0,0 +1,30 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
@test "Create new certificate using staging server, dig and DuckDNS" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
CONFIG_FILE="getssl-staging-dns01.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of certificate using staging server, dig and DuckDNS" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
cleanup_environment
}

+ 45
- 0
test/7-staging-dns01-nslookup.bats View File

@ -0,0 +1,45 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
if [ -f /usr/bin/dig ]; then
mv /usr/bin/dig /usr/bin/dig.getssl.bak
fi
}
teardown() {
if [ -f /usr/bin/dig.getssl.bak ]; then
mv /usr/bin/dig.getssl.bak /usr/bin/dig
fi
}
@test "Create new certificate using staging server, nslookup and DuckDNS" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
CONFIG_FILE="getssl-staging-dns01.cfg"
setup_environment
init_getssl
create_certificate
assert_success
check_output_for_errors "debug"
}
@test "Force renewal of certificate using staging server, nslookup and DuckDNS" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors "debug"
cleanup_environment
}

+ 62
- 0
test/8-staging-ecdsa.bats View File

@ -0,0 +1,62 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
@test "Create new certificate using staging server and prime256v1" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
CONFIG_FILE="getssl-staging-dns01.cfg"
setup_environment
init_getssl
sed -e 's/rsa/prime256v1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
run ${CODE_DIR}/getssl -d "$GETSSL_HOST"
assert_success
check_output_for_errors "debug"
}
@test "Force renewal of certificate using staging server and prime256v1" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
run ${CODE_DIR}/getssl -d -f $GETSSL_HOST
assert_success
check_output_for_errors "debug"
cleanup_environment
}
@test "Create new certificate using staging server and secp384r1" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
CONFIG_FILE="getssl-staging-dns01.cfg"
setup_environment
init_getssl
sed -e 's/rsa/secp384r1/g' < "${CODE_DIR}/test/test-config/${CONFIG_FILE}" > "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
run ${CODE_DIR}/getssl -d "$GETSSL_HOST"
assert_success
check_output_for_errors "debug"
}
@test "Force renewal of certificate using staging server and secp384r1" {
if [ -z "$STAGING" ]; then
skip "Running internal tests, skipping external test"
fi
run ${CODE_DIR}/getssl -d -f $GETSSL_HOST
assert_success
check_output_for_errors "debug"
cleanup_environment
}
# Note letsencrypt doesn't support ECDSA curve P-521 as it's being deprecated

+ 60
- 0
test/9-multiple-domains-dns01.bats View File

@ -0,0 +1,60 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
}
@test "Create certificates for multi-level domains using DNS-01 verification" {
# This tests we can create a certificate for <os>.getssl.test and getssl.test (in SANS)
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-multiple-domains-dns01.cfg"
setup_environment
# Add top level domain from SANS to DNS
curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a
init_getssl
create_certificate
assert_success
check_output_for_errors
}
@test "Force renewal of multi-level domains using DNS-01" {
# This tests we can renew a certificate for <os>.getssl.test and getssl.test (in SANS)
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
run ${CODE_DIR}/getssl -f $GETSSL_HOST
assert_success
check_output_for_errors
# Remove all the dns aliases
cleanup_environment
curl --silent -X POST -d '{"host":"getssl.tst"}' http://10.30.50.3:8055/clear-a
}
@test "Test IGNORE_DIRECTORY_DOMAIN using DNS-01 verification" {
# This tests we can create a certificate for getssl.test and <os>.getssl.test (*both* in SANS)
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
CONFIG_FILE="getssl-ignore-directory-domain.cfg"
setup_environment
# Add top level domain from SANS to DNS
curl --silent -X POST -d '{"host":"getssl.test", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/add-a
init_getssl
create_certificate
assert_success
check_output_for_errors
}

+ 32
- 0
test/9-test--all.bats View File

@ -0,0 +1,32 @@
#! /usr/bin/env bats
load '/bats-support/load.bash'
load '/bats-assert/load.bash'
load '/getssl/test/test_helper.bash'
# This is run for every test
setup() {
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
export PATH=$PATH:/getssl
}
@test "Create new certificate using --all" {
if [ -n "$STAGING" ]; then
skip "Using staging server, skipping internal test"
fi
# Setup
CONFIG_FILE="getssl-http01.cfg"
setup_environment
init_getssl
cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
# Run test
run ${CODE_DIR}/getssl --all
# Check success conditions
assert_success
check_output_for_errors
}

+ 22
- 0
test/Dockerfile-alpine View File

@ -0,0 +1,22 @@
FROM alpine:latest
# Note this image uses busybox awk instead of gawk
RUN apk --no-cache add supervisor openssl git curl bind-tools wget nginx bash
WORKDIR /root
# Create nginx directories in standard places
RUN mkdir /run/nginx
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
# Use supervisord to run nginx in the background
COPY ./test/test-config/alpine-supervisord.conf /etc/supervisord.conf
CMD tail -f /dev/null

+ 24
- 0
test/Dockerfile-centos6 View File

@ -0,0 +1,24 @@
FROM centos:centos6
# Note this image uses gawk
# Update and install required software
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y install git curl dnsutils wget nginx
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
EXPOSE 80 443
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 20
- 0
test/Dockerfile-centos7 View File

@ -0,0 +1,20 @@
FROM centos:centos7
# Note this image uses drill, does not have dig or nslookup installed
# Update and install required software
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y install git curl ldns wget which nginx
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf
COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local

+ 28
- 0
test/Dockerfile-centos7-staging View File

@ -0,0 +1,28 @@
FROM centos:centos7
# Note this image uses gawk
# Update and install required software
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y install git curl bind-utils wget which nginx
ENV staging "true"
ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/conf.d/default.conf
COPY ./test/test-config/nginx-centos7.conf /etc/nginx/nginx.conf
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
EXPOSE 80 443
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 20
- 0
test/Dockerfile-debian View File

@ -0,0 +1,20 @@
FROM debian:latest
# Note this image uses mawk 1.3
# Update and install required software
RUN apt-get update --fix-missing
RUN apt-get install -y git curl dnsutils wget nginx-light
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 0
- 22
test/Dockerfile-rhel6 View File

@ -1,22 +0,0 @@
FROM roboxes/rhel6
# FROM centos:centos6
# bionic = latest 18 version
# Update and install required software
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y install git curl dnsutils wget # nginx-light
WORKDIR /root
#RUN mkdir /etc/nginx/pki
#RUN mkdir /etc/nginx/pki/private
#COPY ./test/test-config/nginx-ubuntu-sites-enabled-default /etc/nginx/sites-enabled/default
# BATS (Bash Automated Testings)
# RUN git clone https://github.com/bats-core/bats-core.git
# RUN bats-core/install.sh /usr/local
EXPOSE 80 443
# Run eternal loop - for testing
CMD ["/bin/bash", "-c", "while :; do sleep 10; done"]

+ 16
- 13
test/Dockerfile-ubuntu View File

@ -1,23 +1,26 @@
FROM ubuntu:xenial
# bionic = latest 18 version
FROM ubuntu:latest
# Note this image uses mawk1.3
# Set noninteractive otherwise tzdata hangs
ENV DEBIAN_FRONTEND noninteractive
# Update and install required software # Update and install required software
RUN apt-get update
# TODO work out why default version of awk fails
RUN apt-get install -y git curl dnsutils wget gawk nginx-light # linux-libc-dev make gcc binutils
RUN apt-get update --fix-missing
RUN apt-get install -y git curl dnsutils wget nginx-light
RUN apt-get install -y vim dos2unix # for debugging RUN apt-get install -y vim dos2unix # for debugging
# TODO test with drill, dig, host # TODO test with drill, dig, host
WORKDIR /root WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default
# BATS (Bash Automated Testings)
# RUN git clone https://github.com/bats-core/bats-core.git
# RUN bats-core/install.sh /usr/local
# Prevent "Can't load /root/.rnd into RNG" error from openssl
RUN touch /root/.rnd
EXPOSE 80 443
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
# Run eternal loop - for testing # Run eternal loop - for testing
CMD ["/bin/bash", "-c", "while :; do sleep 10; done"]
CMD tail -f /dev/null

+ 30
- 0
test/Dockerfile-ubuntu-staging View File

@ -0,0 +1,30 @@
FROM ubuntu:latest
# Note this image uses mawk1.3
# Set noninteractive otherwise tzdata hangs
ENV DEBIAN_FRONTEND noninteractive
# Ensure tests in this image use the staging server
ENV staging "true"
ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb
# Update and install required software
RUN apt-get update --fix-missing
RUN apt-get install -y git curl dnsutils wget nginx-light
RUN apt-get install -y vim dos2unix # for debugging
# TODO test with drill, dig, host
WORKDIR /root
# Prevent "Can't load /root/.rnd into RNG" error from openssl
RUN touch /root/.rnd
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 25
- 0
test/Dockerfile-ubuntu16 View File

@ -0,0 +1,25 @@
FROM ubuntu:xenial
# xenial = 16
# Note this image uses mawk
# Update and install required software
RUN apt-get update --fix-missing
RUN apt-get install -y git curl dnsutils wget nginx-light
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default
# Prevent "Can't load /root/.rnd into RNG" error from openssl
# RUN touch /root/.rnd
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 27
- 0
test/Dockerfile-ubuntu18 View File

@ -0,0 +1,27 @@
FROM ubuntu:bionic
# bionic = 18 LTS (long term support)
# Note this image uses gawk
# Update and install required software
RUN apt-get update --fix-missing
RUN apt-get install -y git curl dnsutils wget gawk nginx-light
WORKDIR /root
RUN mkdir /etc/nginx/pki
RUN mkdir /etc/nginx/pki/private
COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default
# Prevent "Can't load /root/.rnd into RNG" error from openssl
RUN touch /root/.rnd
# BATS (Bash Automated Testings)
RUN git clone https://github.com/bats-core/bats-core.git /bats-core
RUN git clone https://github.com/bats-core/bats-support /bats-support
RUN git clone https://github.com/bats-core/bats-assert /bats-assert
RUN /bats-core/install.sh /usr/local
EXPOSE 80 443
# Run eternal loop - for testing
CMD tail -f /dev/null

+ 35
- 0
test/README-Testing.md View File

@ -0,0 +1,35 @@
# Testing
## Continuous Integration
For continuous integration testing we have the following:
`gitactions` script which runs whenever a PR is pushed:
1. Uses `docker-compose` to start `pebble` (letsencrypt test server) and `challtestsrv` (minimal dns client for pebble)
2. Then runs the `bats` test scripts (all the files with a ".bats" extension) for each OS (alpine, centos6, debian, ubuntu)
3. Runs the `bats` test script against the staging server (using nn ubuntu docker image and duckdns.org)
## To run all the tests on a single OS
1. Start `pebble` and `challtestsrv` using ```docker-compose up -d --build```
2. Run the test suite ```run-test.sh [<os>]```
3. eg. `run-test.sh ubuntu16`
## To run a single bats test on a single OS
1. Start `pebble` and `challtestsrv` using ```docker-compose up -d --build```
2. ```run-test.sh <os> bats <bats test script>```
3. e.g. `run-test.sh ubuntu bats /getssl/test/1-simple-http01.bats`
## To debug a test
1. Start `pebble` and `challtestsrv` using ```docker-compose up -d --build```
2. ```run-test.sh <os> /getssl/test/debug-test.sh <getssl config file>```
3. e.g. `run-test.sh ubuntu /getssl/test/debug-test.sh -d /getssl/test/test-config/getssl-http01-cfg`
## TODO
1. Test wildcards
2. Test SSH, SFTP, SCP
3. Test change of key algorithm (should automatically delete and re-create account.key)

+ 0
- 20
test/README.md View File

@ -1,20 +0,0 @@
# Testing
This directory contains a simple test script which tests creating certificates with Pebble (testing version of the LetsEncrypt server)
Start up pebble, the challdnstest server for DNS challenges
`docker-compose -f "docker-compose.yml" up -d --build`
Run the tests
`docker exec -it getssl /getssl/test/run-test.sh`
Debug (need to set CURL_CA_BUNDLE as pebble uses a local certificate, otherwise you get a "unknown API version" error)
`docker exec -it getssl /bin/bash`
`export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt`
`/getssl/getssl -d getssl`
# TODO
1. Move to BATS (bash automated testing) instead of run-test.sh
2. Test RHEL6, Debian as well
3. Test SSH, SFTP
4. Test wildcards

+ 30
- 0
test/debug-test.sh View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# This runs getssl outside of the BATS framework for debugging, etc, against pebble
# Usage: /getssl/test/debug-test.sh getssl-http01.cfg
DEBUG=""
if [ $# -eq 2 ]; then
DEBUG=$1
shift
fi
#shellcheck disable=SC1091
source /getssl/test/test_helper.bash 3>&1
CONFIG_FILE=$1
if [ ! -e "$CONFIG_FILE" ]; then
CONFIG_FILE=${CODE_DIR}/test/test-config/${CONFIG_FILE}
fi
setup_environment 3>&1
# Only add the pebble CA to the cert bundle if using pebble
if grep -q pebble "${CONFIG_FILE}"; then
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
fi
"${CODE_DIR}/getssl" -c "$GETSSL_HOST" 3>&1
cp "${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_HOST}/getssl.cfg"
# shellcheck disable=SC2086
"${CODE_DIR}/getssl" ${DEBUG} -f "$GETSSL_HOST" 3>&1

+ 11
- 0
test/restart-nginx View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
if [ "$GETSSL_OS" = "alpine" ]; then
killall -HUP nginx >&3-
sleep 5
elif [ "$GETSSL_OS" == "centos7" ]; then
pgrep nginx | head -1 | xargs kill -HUP
sleep 5
else
service nginx restart >/dev/null >&3-
fi

+ 54
- 0
test/run-test.cmd View File

@ -0,0 +1,54 @@
@echo off
IF %1.==. GOTO NoOS
set OS=%1
:CheckCommand
IF %2.==. GOTO NoCmd
set COMMAND=%2 %3
:CheckAlias
REM check if OS *contains* staging
IF NOT x%OS:staging=%==x%OS% GOTO staging
set ALIAS=%OS%.getssl.test
set STAGING=
GOTO Run
:NoOS
set OS=ubuntu
GOTO CheckCommand
:NoCmd
REM set COMMAND=/getssl/test/run-bats.sh
set COMMAND=bats /getssl/test
GOTO CheckAlias
:staging
set ALIAS=%OS:-staging=%-getssl.duckdns.org
set STAGING=--env STAGING=true
:Run
for %%I in (.) do set CurrDirName=%%~nxI
docker build --rm -f "test\Dockerfile-%OS%" -t getssl-%OS% .
@echo on
docker run -it ^
--env GETSSL_HOST=%ALIAS% %STAGING% ^
--env GETSSL_OS=%OS:-staging=% ^
-v %cd%:/getssl ^
--rm ^
--network %CurrDirName%_acmenet ^
--network-alias %ALIAS% ^
--network-alias a.%OS%.getssl.test ^
--network-alias b.%OS%.getssl.test ^
--network-alias c.%OS%.getssl.test ^
--network-alias d.%OS%.getssl.test ^
--network-alias e.%OS%.getssl.test ^
--network-alias f.%OS%.getssl.test ^
--network-alias g.%OS%.getssl.test ^
--network-alias h.%OS%.getssl.test ^
--network-alias i.%OS%.getssl.test ^
--network-alias j.%OS%.getssl.test ^
--network-alias k.%OS%.getssl.test ^
--name getssl-%OS% ^
getssl-%OS% ^
%COMMAND%

+ 42
- 38
test/run-test.sh View File

@ -1,43 +1,47 @@
#! /bin/bash
#! /usr/bin/env bash
set -e
# Test setup
if [[ -d /root/.getssl ]]; then
rm -r /root/.getssl
if [ $# -eq 0 ]; then
echo "Usage: $(basename "$0") <os> [<command>]"
echo "e.g. $(basename "$0") alpine bats /getssl/test"
exit 1
fi fi
OS=$1
wget --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem
# cat /etc/pki/tls/certs/ca-bundle.crt /root/pebble.minica.pem > /root/pebble-ca-bundle.crt
cat /etc/ssl/certs/ca-certificates.crt /root/pebble.minica.pem > /root/pebble-ca-bundle.crt
export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt
curl -X POST -d '{"host":"getssl", "addresses":["10.30.50.4"]}' http://10.30.50.3:8055/add-a
# Test #1 - http-01 verification
echo Test \#1 - http-01 verification
cp /getssl/test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default
service nginx restart
/getssl/getssl -c getssl
cp /getssl/test/test-config/getssl-http01.cfg /root/.getssl/getssl/getssl.cfg
/getssl/getssl -f getssl
# Test #2 - http-01 forced renewal
echo Test \#2 - http-01 forced renewal
/getssl/getssl getssl -f
# Test cleanup
rm -r /root/.getssl
if [ $# -gt 1 ]; then
shift
COMMAND=$*
else
COMMAND="bats /getssl/test"
fi
# Test #3 - dns-01 verification
echo Test \#3 - dns-01 verification
cp /getssl/test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default
service nginx restart
/getssl/getssl -c getssl
cp /getssl/test/test-config/getssl-dns01.cfg /root/.getssl/getssl/getssl.cfg
/getssl/getssl getssl
if [[ "$OS" == *"staging"* ]]; then
ALIAS="${OS%-staging}-getssl.duckdns.org"
STAGING="--env STAGING=true"
else
ALIAS="$OS.getssl.test"
STAGING=""
fi
# Test #4 - dns-01 forced renewal
echo Test \#4 - dns-01 forced renewal
/getssl/getssl getssl -f
docker build --rm -f "test/Dockerfile-$OS" -t "getssl-$OS" .
# shellcheck disable=SC2086
docker run \
--env GETSSL_HOST=$ALIAS $STAGING \
--env GETSSL_OS=${OS%-staging} \
-v "$(pwd)":/getssl \
--rm \
--network ${PWD##*/}_acmenet \
--network-alias $ALIAS \
--network-alias "a.$OS.getssl.test" \
--network-alias "b.$OS.getssl.test" \
--network-alias "c.$OS.getssl.test" \
--network-alias "d.$OS.getssl.test" \
--network-alias "e.$OS.getssl.test" \
--network-alias "f.$OS.getssl.test" \
--network-alias "g.$OS.getssl.test" \
--network-alias "h.$OS.getssl.test" \
--network-alias "i.$OS.getssl.test" \
--network-alias "j.$OS.getssl.test" \
--network-alias "k.$OS.getssl.test" \
--name "getssl-$OS" \
"getssl-$OS" \
$COMMAND

+ 14
- 0
test/test-config/alpine-supervisord.conf View File

@ -0,0 +1,14 @@
[supervisord]
nodaemon=false
logfile=/tmp/supervisord.log
childlogdir=/tmp
pidfile = /tmp/supervisord.pid
[program:nginx]
command=nginx
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=false
startretries=0

+ 39
- 0
test/test-config/getssl-dns01-dual-rsa-ecdsa.cfg View File

@ -0,0 +1,39 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
VALIDATE_VIA_DNS=true
DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv"
DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv"
PUBLIC_DNS_SERVER=10.30.50.3
DNS_EXTRA_WAIT=""
DUAL_RSA_ECDSA="true"
ACCOUNT_KEY_TYPE="prime256v1"
PRIVATE_KEY_ALG="prime256v1"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 6
- 25
test/test-config/getssl-dns01.cfg View File

@ -2,35 +2,19 @@
# see https://github.com/srvrco/getssl/wiki/Config-variables for details # see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs # see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
# #
# The staging server is best for testing
#CA="https://acme-staging.api.letsencrypt.org"
# This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
CA="https://pebble:14000/dir" CA="https://pebble:14000/dir"
VALIDATE_VIA_DNS=true VALIDATE_VIA_DNS=true
DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv" DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv"
DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv" DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv"
# AUTH_DNS_SERVER=10.30.50.3
#PRIVATE_KEY_ALG="rsa"
PUBLIC_DNS_SERVER=10.30.50.3
DNS_EXTRA_WAIT=""
# Additional domains - this could be multiple domains / subdomains in a comma separated list # Additional domains - this could be multiple domains / subdomains in a comma separated list
# Note: this is Additional domains - so should not include the primary domain.
SANS="" SANS=""
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain. # Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
# If these start with ssh: then the next variable is assumed to be the hostname and the rest the location.
# An ssh key will be needed to provide you with access to the remote server.
# Optionally, you can specify a different userid for ssh/scp to use on the remote server before the @ sign.
# If left blank, the username on the local server will be used to authenticate against the remote server.
# If these start with ftp: then the next variables are ftpuserid:ftppassword:servername:ACL_location
# These should be of the form "/path/to/your/website/folder/.well-known/acme-challenge"
# where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain.
ACL=('/var/www/html/.well-known/acme-challenge') ACL=('/var/www/html/.well-known/acme-challenge')
# 'ssh:server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge'
# 'ssh:sshuserid@server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge'
# 'ftp:ftpuserid:ftppassword:getssltest.hopto.org:/web/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks #Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false" USE_SINGLE_ACL="false"
@ -44,11 +28,8 @@ DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use # The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl /etc/nginx/sites-enabled/default && service nginx restart"
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp,
# smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which
# will be checked for certificate expiry and also will be checked after
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
#SERVER_TYPE="https"
#CHECK_REMOTE="true"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 45
- 0
test/test-config/getssl-etc-template.cfg View File

@ -0,0 +1,45 @@
# vim: filetype=sh
#
# This file is read first and is common to all domains
#
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
#
# The staging server is best for testing (hence set as default)
CA="https://acme-staging-v02.api.letsencrypt.org"
# This server issues full certificates, however has rate limits
#CA="https://acme-v02.api.letsencrypt.org"
# The agreement that must be signed with the CA, if not defined the default agreement will be used
#AGREEMENT=""
# Set an email address associated with your account - generally set at account level rather than domain.
#ACCOUNT_EMAIL="me@example.com"
ACCOUNT_KEY_LENGTH=4096
ACCOUNT_KEY="/etc/getssl/account.key"
# Account key and private key types - can be rsa, prime256v1, secp384r1 or secp521r1
#ACCOUNT_KEY_TYPE="rsa"
PRIVATE_KEY_ALG="rsa"
#REUSE_PRIVATE_KEY="true"
# The command needed to reload apache / nginx or whatever you use
#RELOAD_CMD=""
# The time period within which you want to allow renewal of a certificate
# this prevents hitting some of the rate limits.
# Creating a file called FORCE_RENEWAL in the domain directory allows one-off overrides
# of this setting
RENEW_ALLOW="30"
# Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp,
# smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which
# will be checked for certificate expiry and also will be checked after
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
SERVER_TYPE="https"
CHECK_REMOTE="true"
# Use the following 3 variables if you want to validate via DNS
#VALIDATE_VIA_DNS="true"
#DNS_ADD_COMMAND=
#DNS_DEL_COMMAND=

+ 28
- 0
test/test-config/getssl-http01-10-hosts.cfg View File

@ -0,0 +1,28 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
CA="https://pebble:14000/dir"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS="a.${GETSSL_HOST},b.${GETSSL_HOST},c.${GETSSL_HOST},d.${GETSSL_HOST},e.${GETSSL_HOST},f.${GETSSL_HOST},g.${GETSSL_HOST},h.${GETSSL_HOST},i.${GETSSL_HOST},j.${GETSSL_HOST},k.${GETSSL_HOST}"
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
# Use a single ACL for all checks
USE_SINGLE_ACL="true"
# Location for all your certs, these can either be on the server (full path name)
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 32
- 0
test/test-config/getssl-http01-dual-rsa-ecdsa-2-locations.cfg View File

@ -0,0 +1,32 @@
# Test that more than one location can be specified for CERT and KEY locations and that the
# files are copied to both locations when both RSA and ECDSA certificates are created
#
CA="https://pebble:14000/dir"
DUAL_RSA_ECDSA="true"
ACCOUNT_KEY_TYPE="prime256v1"
PRIVATE_KEY_ALG="prime256v1"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS="a.${GETSSL_HOST}"
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="true"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key;/root/a.${GETSSL_HOST}/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 33
- 0
test/test-config/getssl-http01-dual-rsa-ecdsa.cfg View File

@ -0,0 +1,33 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
DUAL_RSA_ECDSA="true"
ACCOUNT_KEY_TYPE="prime256v1"
PRIVATE_KEY_ALG="prime256v1"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 31
- 0
test/test-config/getssl-http01-no-domain-storage.cfg View File

@ -0,0 +1,31 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"
DOMAIN_STORAGE="/"

+ 32
- 0
test/test-config/getssl-http01-secp384.cfg View File

@ -0,0 +1,32 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
ACCOUNT_KEY_TYPE="secp384r1"
PRIVATE_KEY_ALG="secp384r1"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 32
- 0
test/test-config/getssl-http01-secp521.cfg View File

@ -0,0 +1,32 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
ACCOUNT_KEY_TYPE="secp521r1"
PRIVATE_KEY_ALG="secp521r1"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 5
- 29
test/test-config/getssl-http01.cfg View File

@ -2,34 +2,13 @@
# see https://github.com/srvrco/getssl/wiki/Config-variables for details # see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs # see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
# #
# The staging server is best for testing
#CA="https://acme-staging.api.letsencrypt.org"
# This server issues full certificates, however has rate limits
#CA="https://acme-v01.api.letsencrypt.org"
CA="https://pebble:14000/dir" CA="https://pebble:14000/dir"
#VALIDATE_VIA_DNS=true
#DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv"
#DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv"
#PRIVATE_KEY_ALG="rsa"
# Additional domains - this could be multiple domains / subdomains in a comma separated list # Additional domains - this could be multiple domains / subdomains in a comma separated list
# Note: this is Additional domains - so should not include the primary domain.
SANS="" SANS=""
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
# If these start with ssh: then the next variable is assumed to be the hostname and the rest the location.
# An ssh key will be needed to provide you with access to the remote server.
# Optionally, you can specify a different userid for ssh/scp to use on the remote server before the @ sign.
# If left blank, the username on the local server will be used to authenticate against the remote server.
# If these start with ftp: then the next variables are ftpuserid:ftppassword:servername:ACL_location
# These should be of the form "/path/to/your/website/folder/.well-known/acme-challenge"
# where "/path/to/your/website/folder/" is the path, on your web server, to the web root for your domain.
# Acme Challenge Location.
ACL=('/var/www/html/.well-known/acme-challenge') ACL=('/var/www/html/.well-known/acme-challenge')
# 'ssh:server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge'
# 'ssh:sshuserid@server5:/var/www/getssltest.hopto.org/web/.well-known/acme-challenge'
# 'ftp:ftpuserid:ftppassword:getssltest.hopto.org:/web/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks #Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false" USE_SINGLE_ACL="false"
@ -43,11 +22,8 @@ DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use # The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl /etc/nginx/sites-enabled/default && service nginx restart"
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type. This can be https, ftp, ftpi, imap, imaps, pop3, pop3s, smtp,
# smtps_deprecated, smtps, smtp_submission, xmpp, xmpps, ldaps or a port number which
# will be checked for certificate expiry and also will be checked after
# an update to confirm correct certificate is running (if CHECK_REMOTE) is set to true
#SERVER_TYPE="https"
#CHECK_REMOTE="true"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 39
- 0
test/test-config/getssl-ignore-directory-domain.cfg View File

@ -0,0 +1,39 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
VALIDATE_VIA_DNS=true
DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv"
DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv"
PUBLIC_DNS_SERVER=10.30.50.3
DNS_EXTRA_WAIT=""
# Ignore directory domain (i.e. the domain passed on the command line), and just use the domains in the SANS list
IGNORE_DIRECTORY_DOMAIN="true"
SANS="getssl.test,$GETSSL_HOST"
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
ACL=(
'/var/www/html/.well-known/acme-challenge'
'/var/www/html/.well-known/acme-challenge'
)
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 38
- 0
test/test-config/getssl-multiple-domains-dns01.cfg View File

@ -0,0 +1,38 @@
# Uncomment and modify any variables you need
# see https://github.com/srvrco/getssl/wiki/Config-variables for details
# see https://github.com/srvrco/getssl/wiki/Example-config-files for example configs
#
CA="https://pebble:14000/dir"
VALIDATE_VIA_DNS=true
DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_challtestsrv"
DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_challtestsrv"
PUBLIC_DNS_SERVER=10.30.50.3
DNS_EXTRA_WAIT=""
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS="getssl.test"
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
ACL=(
'/var/www/html/.well-known/acme-challenge'
'/var/www/html/.well-known/acme-challenge'
)
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 37
- 0
test/test-config/getssl-staging-dns01.cfg View File

@ -0,0 +1,37 @@
# Test that the script works with external dns provider and staging server
#
CA="https://acme-staging-v02.api.letsencrypt.org/directory"
VALIDATE_VIA_DNS=true
DNS_ADD_COMMAND="/getssl/dns_scripts/dns_add_duckdns"
DNS_DEL_COMMAND="/getssl/dns_scripts/dns_del_duckdns"
PUBLIC_DNS_SERVER=ns2.duckdns.org
CHECK_ALL_AUTH_DNS=true
DNS_EXTRA_WAIT=60
ACCOUNT_KEY_TYPE="rsa"
PRIVATE_KEY_ALG="rsa"
# Additional domains - this could be multiple domains / subdomains in a comma separated list
SANS=""
# Acme Challenge Location. The first line for the domain, the following ones for each additional domain.
ACL=('/var/www/html/.well-known/acme-challenge')
#Set USE_SINGLE_ACL="true" to use a single ACL for all checks
USE_SINGLE_ACL="false"
# Location for all your certs, these can either be on the server (full path name)
# or using ssh /sftp as for the ACL
DOMAIN_CERT_LOCATION="/etc/nginx/pki/server.crt"
DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key"
CA_CERT_LOCATION="/etc/nginx/pki/chain.crt"
DOMAIN_CHAIN_LOCATION="" # this is the domain cert and CA cert
DOMAIN_PEM_LOCATION="" # this is the domain_key, domain cert and CA cert
# The command needed to reload apache / nginx or whatever you use
RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-ssl ${NGINX_CONFIG} && /getssl/test/restart-nginx"
# Define the server type and confirm correct certificate is installed (using a custom port)
SERVER_TYPE="https"
CHECK_REMOTE="true"

+ 37
- 0
test/test-config/nginx-centos7.conf View File

@ -0,0 +1,37 @@
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
}

+ 0
- 63
test/test-config/nginx-ubuntu-no-ssl View File

@ -1,16 +1,3 @@
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration # Default server configuration
# #
server { server {
@ -26,18 +13,6 @@ server {
listen 5001 default_server; listen 5001 default_server;
listen [::]:5001 default_server; listen [::]:5001 default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html; root /var/www/html;
# Add index.php to the list if you are using PHP # Add index.php to the list if you are using PHP
@ -52,42 +27,4 @@ server {
# as directory, then fall back to displaying a 404. # as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
} }
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php7.0-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php7.0-fpm:
# fastcgi_pass unix:/run/php/php7.0-fpm.sock;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
} }
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}

+ 99
- 0
test/test_helper.bash View File

@ -0,0 +1,99 @@
INSTALL_DIR=/root
CODE_DIR=/getssl
check_certificates()
{
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/chain.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" ]
assert [ -e "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" ]
}
check_output_for_errors() {
refute_output --regexp '[Ff][Aa][Ii][Ll][Ee][Dd]'
# less strict tests if running with debug output
if [ -n "$1" ]; then
# don't fail for :error:badNonce
refute_output --regexp '[^:][Ee][Rr][Rr][Oo][Rr][^:]'
# don't check for "Warnings:" as there might be a warning message if nslookup doesn't support -debug (alpine/ubuntu)
refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg][^:]'
else
refute_output --regexp '[Ee][Rr][Rr][Oo][Rr]'
refute_output --regexp '[Ww][Aa][Rr][Nn][Ii][Nn][Gg]'
fi
refute_line --partial 'command not found'
}
cleanup_environment() {
curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'"}' http://10.30.50.3:8055/clear-a
}
create_certificate() {
# Create certificate
cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg"
# shellcheck disable=SC2086
run ${CODE_DIR}/getssl $1 "$GETSSL_CMD_HOST"
}
init_getssl() {
# Run initialisation (create account key, etc)
run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST"
assert_success
[ -d "$INSTALL_DIR/.getssl" ]
}
setup_environment() {
# One-off test setup
if [[ -d ${INSTALL_DIR}/.getssl ]]; then
rm -r ${INSTALL_DIR}/.getssl
fi
curl --silent -X POST -d '{"host":"'"$GETSSL_HOST"'", "addresses":["'"$GETSSL_IP"'"]}' http://10.30.50.3:8055/add-a
cp ${CODE_DIR}/test/test-config/nginx-ubuntu-no-ssl "${NGINX_CONFIG}"
/getssl/test/restart-nginx
}
# start nginx in background on alpine via supervisord
# shellcheck disable=SC2153 # Ignore GETSSL_OS looks like typo of GETSSL_IP
if [[ -f /usr/bin/supervisord && -f /etc/supervisord.conf ]]; then
if [[ ! $(pgrep supervisord) ]]; then
/usr/bin/supervisord -c /etc/supervisord.conf >&3-
fi
elif [ "$GETSSL_OS" == "centos7" ]; then
if [ -z "$(pgrep nginx)" ]; then
nginx >&3-
fi
fi
# Find NGINX configuration directory for HTTP-01 testing (need to add SSL to config)
if [[ -f /etc/nginx/conf.d/default.conf ]]; then
export NGINX_CONFIG=/etc/nginx/conf.d/default.conf
elif [[ -f /etc/nginx/sites-enabled/default ]]; then
export NGINX_CONFIG=/etc/nginx/sites-enabled/default
else
echo "Can't find NGINX directory"
exit 1
fi
# Find IP address
if [[ -n "$(command -v ip)" ]]; then
GETSSL_IP=$(ip address | awk '/10.30.50/ { print $2 }' | awk -F/ '{ print $1 }')
elif [[ -n "$(command -v hostname)" ]]; then
GETSSL_IP=$(hostname -I | sed -e 's/[[:space:]]*$//')
else
echo "Cannot find IP address"
exit 1
fi
export GETSSL_IP
GETSSL_CMD_HOST=$GETSSL_HOST
export GETSSL_CMD_HOST
if [ ! -f ${INSTALL_DIR}/pebble.minica.pem ]; then
wget --quiet --no-clobber https://raw.githubusercontent.com/letsencrypt/pebble/master/test/certs/pebble.minica.pem 2>&1
CERT_FILE=/etc/ssl/certs/ca-certificates.crt
if [ ! -f $CERT_FILE ]; then
CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
fi
cat $CERT_FILE ${INSTALL_DIR}/pebble.minica.pem > ${INSTALL_DIR}/pebble-ca-bundle.crt
fi

Loading…
Cancel
Save