Local changes (to be pushed upstream):
add standard -v and --version options
dns_godaddy - correct fix for a godaddy API change
export AUTH_DNS_SERVER, PUBLIC_DNS_SERVER, LANG for hooks
apply $DNS_CHECK_OPTIONS to all dns lookups (for binding to an IP or
applying a TSIG file)
When making combined cert/key files, force 077 permissions
In Makefile, handle *_scripts directories with install to get proper permissions.
Update template with advice on split views.
In dns_*_nsupdate, fix indent, prevent malformed commands
pull/660/head
| @ -1,3 +1,11 @@ | |||||
| # Files not to include in .zip/.tar.gz archives | # Files not to include in .zip/.tar.gz archives | ||||
| # | # | ||||
| .git* export-ignore | .git* export-ignore | ||||
| # Handle line endings automatically for files detected as text | |||||
| # and leave all files detected as binary untouched. | |||||
| * text=auto | |||||
| # Make all text files lf formatted | |||||
| * text eol=lf | |||||
| @ -0,0 +1,30 @@ | |||||
| --- | |||||
| name: Bug report | |||||
| about: Create a report to help us improve | |||||
| title: '' | |||||
| labels: '' | |||||
| assignees: '' | |||||
| --- | |||||
| **Describe the bug** | |||||
| A clear and concise description of what the bug is. | |||||
| **To Reproduce** | |||||
| Steps to reproduce the behavior: | |||||
| 1. Go to '...' | |||||
| 2. Click on '....' | |||||
| 3. Scroll down to '....' | |||||
| 4. See error | |||||
| **Expected behavior** | |||||
| A clear and concise description of what you expected to happen. | |||||
| **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)] | |||||
| **Additional context** | |||||
| Add any other context about the problem here. | |||||
| @ -0,0 +1,20 @@ | |||||
| --- | |||||
| name: Feature request | |||||
| about: Suggest an idea for this project | |||||
| title: '' | |||||
| labels: '' | |||||
| assignees: '' | |||||
| --- | |||||
| **Is your feature request related to a problem? Please describe.** | |||||
| A clear and concise description of what the problem is. [...] | |||||
| **Describe the solution you'd like** | |||||
| A clear and concise description of what you want to happen. | |||||
| **Describe alternatives you've considered** | |||||
| A clear and concise description of any alternative solutions or features you've considered. | |||||
| **Additional context** | |||||
| Add any other context or screenshots about the feature request here. | |||||
| @ -0,0 +1,97 @@ | |||||
| name: Run all tests on pebble | |||||
| 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-bash-4-0: | |||||
| 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 using Bash 4.0 | |||||
| run: test/run-test.sh bash4-0 | |||||
| test-bash-4-2: | |||||
| 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 using Bash 4.2 | |||||
| run: test/run-test.sh bash4-2 | |||||
| test-bash-5-0: | |||||
| 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 using Bash 5 | |||||
| run: test/run-test.sh bash5-0 | |||||
| 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-centos8: | |||||
| 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 CentOS8 | |||||
| run: test/run-test.sh centos8 | |||||
| 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 | |||||
| @ -0,0 +1,25 @@ | |||||
| name: Run all tests using DuckDNS | |||||
| on: | |||||
| push: | |||||
| branches: | |||||
| - master | |||||
| pull_request: | |||||
| branches: | |||||
| - master | |||||
| jobs: | |||||
| test-centos7-duckdns: | |||||
| 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-duckdns | |||||
| test-ubuntu-duckdns: | |||||
| 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-duckdns | |||||
| @ -0,0 +1,25 @@ | |||||
| name: Run all tests using Dynu | |||||
| on: | |||||
| push: | |||||
| branches: | |||||
| - master | |||||
| pull_request: | |||||
| branches: | |||||
| - master | |||||
| jobs: | |||||
| test-centos7-dynu: | |||||
| 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 Dynu | |||||
| run: test/run-test.sh centos7-dynu | |||||
| test-ubuntu-dynu: | |||||
| 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 Dynu | |||||
| run: test/run-test.sh ubuntu-dynu | |||||
| @ -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" | |||||
| @ -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 | |||||
| @ -1,17 +0,0 @@ | |||||
| language: bash | |||||
| # Use container-based infrastructure for quicker build start-up | |||||
| sudo: false | |||||
| addons: | |||||
| apt: | |||||
| sources: | |||||
| - debian-sid # Grab shellcheck from the Debian repo (o_O) | |||||
| packages: | |||||
| - shellcheck | |||||
| script: | |||||
| - bash -c 'shopt -s globstar; shellcheck getssl' | |||||
| matrix: | |||||
| fast_finish: true | |||||
| @ -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 :) | |||||
| @ -0,0 +1,52 @@ | |||||
| ## Using Cloudflare DNS for LetsEncrypt domain validation | |||||
| ### Enabling the scripts | |||||
| Set the following options in `getssl.cfg` (either global or domain-specific): | |||||
| ``` | |||||
| VALIDATE_VIA_DNS="true" | |||||
| DNS_ADD_COMMAND="/usr/share/getssl/dns_scripts/dns_add_cloudflare" | |||||
| DNS_DEL_COMMAND="/usr/share/getssl/dns_scripts/dns_del_cloudflare" | |||||
| ``` | |||||
| ### Authentication | |||||
| There are 2 methods of authenticating with Cloudflare: | |||||
| 1. API Keys - Account level, all-purpose tokens | |||||
| 2. API Tokens - Scoped and permissioned access to resources | |||||
| Both are configured from your profile in the [Cloudflare dashboard][1] | |||||
| [1]: https://dash.cloudflare.com/profile/api-tokens | |||||
| #### API Keys | |||||
| The **Zone ID** for the domain will be searched for programmatically. | |||||
| Set the following options in `getssl.cfg`: | |||||
| ``` | |||||
| export CF_EMAIL="..." # Cloudflare account email address | |||||
| export CF_KEY="..." # Global API Key | |||||
| ``` | |||||
| #### API Tokens | |||||
| Cloudflare provides a template for creating an API Token with access to edit | |||||
| zone records. Tokens must be created with at least '**DNS:Edit** permissions | |||||
| for the domain to add/delete records. | |||||
| The API requires higher privileges to be able to list zones, therefore this | |||||
| method also requires the **Zone ID** from the Overview tab in the Cloudflare | |||||
| Dashboard. | |||||
| Set the following options in the domain-specific `getssl.cfg` | |||||
| ``` | |||||
| export CF_API_TOKEN="..." | |||||
| export CF_ZONE_ID="..." | |||||
| ``` | |||||
| __Note__: API Keys will be used instead if also configured | |||||
| @ -0,0 +1,10 @@ | |||||
| # Do DNS-01 verification using Route53 | |||||
| I was not about to implement this in BASH, sorry guys. I'd like you to have it, however. | |||||
| It's pretty simple to use. | |||||
| 1. pip install boto3 dnspython | |||||
| 2. ln -s dns_route53.py dns_add_route53 | |||||
| 3. ln -s dns_route53.py dns_del_route53 | |||||
| 4. Use it just like the other scripts | |||||
| @ -0,0 +1,60 @@ | |||||
| Using GoDaddy DNS for LetsEncrypt domain validation. | |||||
| Quick guide to setting up getssl for domain validation of | |||||
| GoDaddy DNS domains. | |||||
| There are two prerequisites to using getssl with GoDaddy DNS: | |||||
| 1) Obtain an API access key from developer.godaddy.com | |||||
| At first sign-up, you will be required to take a "test" key. | |||||
| This is NOT what you need. Accept it, then get a "Production" | |||||
| key. At this writing, there is no charge - but you must have | |||||
| a GoDaddy customer account. | |||||
| You must get the API key for the account which owns the domain | |||||
| that you want to get certificates for. If the domains that you | |||||
| manage are owned by more than one account, get a key for each. | |||||
| The access key consists of a "Key" and a "Secret". You need | |||||
| both. | |||||
| 2) Obtain JSON.sh - https://github.com/dominictarr/JSON.sh | |||||
| With those in hand, the installation procedure is: | |||||
| 1) Put JSON.sh in the getssl DNS scripts directory | |||||
| Default: /usr/share/getssl/dns_scripts | |||||
| 2) Open your config file (the global file in ~/.getssl/getssl.cfg | |||||
| or the per-account file in ~/.getssl/example.net/getssl.cfg | |||||
| 3) Set the following options: | |||||
| VALIDATE_VIA_DNS="true" | |||||
| DNS_ADD_COMMAND="/usr/share/getssl/dns_scripts/dns_add_godaddy" | |||||
| DNS_DEL_COMMAND="/usr/share/getssl/dns_scripts/dns_del_godaddy" | |||||
| # The API key for your account/this domain | |||||
| export GODADDY_KEY="..." GODADDY_SECRET="..." | |||||
| 4) Set any other options that you wish (per the standard | |||||
| directions.) Use the test CA to make sure that | |||||
| everything is setup correctly. | |||||
| That's it. getssl example.net will now validate with DNS. | |||||
| To trace record additions and removals, run getssl as | |||||
| GODADDY_TRACE=Y getssl example.net | |||||
| There are additional options, which are documented in the | |||||
| *godaddy" files and dns_godaddy -h. | |||||
| Copyright (2017) Timothe Litt litt at acm _dot org | |||||
| This sofware may be freely used providing this notice is included with | |||||
| all copies. The name of the author may not be used to endorse | |||||
| any other product or derivative work. No warranty is provided | |||||
| and the user assumes all responsibility for use of this software. | |||||
| Report any issues to https://github.com/tlhackque/getssl/issues. | |||||
| Enjoy. | |||||
| @ -0,0 +1,7 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Simple script to update the challtestserv mock DNS server when testing DNS responses | |||||
| fulldomain="${1}" | |||||
| token="${2}" | |||||
| curl --silent -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\", \"value\": \"${token}\"}" http://10.30.50.3:8055/set-txt | |||||
| @ -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}") | |||||
| @ -0,0 +1,76 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Need to add your email address and API key to cpanel below or set as env variables | |||||
| user=${CPANEL_USERNAME:-''} | |||||
| password=${CPANEL_PASSWORD:-''} | |||||
| url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083 | |||||
| apitoken=${CPANEL_APITOKEN:-''} | |||||
| fulldomain="${1}" | |||||
| token="${2}" | |||||
| # 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 "$user" ]]; then | |||||
| echo "CPANEL_USERNAME (username) parameter not set" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then | |||||
| echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$url" ]]; then | |||||
| echo "CPANEL_URL (url) parameter not set" | |||||
| exit 1 | |||||
| fi | |||||
| # Setup | |||||
| request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit" | |||||
| if [[ -n $apitoken ]]; then | |||||
| curl_params=( -H "Authorization: cpanel $user:$apitoken" ) | |||||
| else | |||||
| auth_string=$(echo -ne "$user:$password" | base64 --wrap 0) | |||||
| curl_params=( -H "Authorization: Basic $auth_string" ) | |||||
| fi | |||||
| # Check if domain is a CNAME | |||||
| res=$(dig CNAME "$fulldomain") | |||||
| domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') | |||||
| if [[ -n "$domain" ]]; then | |||||
| name=".${fulldomain%.$domain}" | |||||
| else | |||||
| domain=$fulldomain | |||||
| name="" | |||||
| fi | |||||
| # Check to see if challenge dns entry already exists (update or delete?) | |||||
| request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}." | |||||
| resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") | |||||
| if [[ "$resp" = *\"error\":* ]]; then | |||||
| echo -n "cpanel fetchzone records failed: " | |||||
| echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }' | |||||
| exit 1 | |||||
| fi | |||||
| # If no existing record, create a new TXT record, otherwise edit the existing record | |||||
| if [[ "$resp" == *\"data\":[]* ]]; then | |||||
| request_params="&cpanel_jsonapi_func=add_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=$token" | |||||
| else | |||||
| # shellcheck disable=SC2001 | |||||
| line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/') | |||||
| request_params="&cpanel_jsonapi_func=edit_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&txtdata=${token}&line=${line}" | |||||
| fi | |||||
| resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") | |||||
| if [[ "$resp" = *\"status\":0* ]]; then | |||||
| echo -n "cpanel edit zone record failed: " | |||||
| echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }' | |||||
| exit 1 | |||||
| fi | |||||
| @ -0,0 +1,185 @@ | |||||
| #!/bin/bash | |||||
| #https://blog.aymar.cn | |||||
| #https://protocol.aymar.cn | |||||
| PROGNAME=${0##*/} | |||||
| VERSION="2021年3月22日 16:07:05" | |||||
| Ali_API="https://dns.aliyuncs.com/" | |||||
| _timestamp=$(date -u +"%Y-%m-%dT%H%%3A%M%%3A%SZ") | |||||
| __debug="0" | |||||
| __delete="0" | |||||
| #Wildcard certificates | |||||
| #A partial example getssl.cfg file is: | |||||
| #VALIDATE_VIA_DNS=true | |||||
| #DNS_ADD_COMMAND=/root/.getssl/dns_add_del_aliyun.sh | |||||
| #DNS_DEL_COMMAND=/root/.getssl/dns_add_del_aliyun.sh | |||||
| # either configure KeyId & KeySecret here or export environment variables in getssl.cfg | |||||
| AccessKeyId=${ALI_KeyId:-''} | |||||
| AccessKeySecret=${ALI_KeySecret:-''} | |||||
| usage() { # print out the program usage | |||||
| echo "Usage: $PROGNAME [-a|--add <Domain Name> <RecordValue>] [-d|--delete <Full.DomainName.com>] [-s|--search <Full.DomainName.com> ] [-h|--help] [-t|--type] "\ | |||||
| "[-q|--quiet] [-c|--check] [-S|--status] [-l|--lock #] [-T|--ttl] [-u|--update] [-w|--weight] [-L|--Line]" | |||||
| } | |||||
| help_message() { # print out the help message | |||||
| cat <<- _EOF_ | |||||
| $PROGNAME Version. $VERSION | |||||
| $(usage) | |||||
| Options: | |||||
| -a, --add Add Domain Record 域名 ip (默认类型TXT) | |||||
| -d, --delete Delete Domain Record 域名 (默认类型TXT) | |||||
| -s, --search Search Domain Record 域名 | |||||
| -t, --type Record Type 类型(A、MX、CNAME、TXT、REDIRECT_URL、FORWORD_URL、NS、AAAA、SRV) | |||||
| _EOF_ | |||||
| } | |||||
| _arg_check(){ | |||||
| [ -z "$1" ] || _arg_count=$1 | |||||
| shift | |||||
| [ ${#} -lt $_arg_count ] && help_message && exit 1 || (echo $2 | grep "^-") && help_message && exit 1 | |||||
| #If the number of arguments <$_ARG_COUNT print help and exit, and if the second argument begins with “-” print help and exit | |||||
| return 0 | |||||
| } | |||||
| #[ ${#} -lt 2 ] && help_message && exit 1 #Same as below | |||||
| #[ -z "$2" ] && help_message && exit 1 #Same as below | |||||
| _arg_check 2 $@ | |||||
| _debug (){ | |||||
| if [ "$__debug" -eq 1 ]; then | |||||
| echo -e "\033[1;31m # debug: $(date "+%m %d %T") | Func: ${FUNCNAME[@]} | Line:${BASH_LINENO[@]} \033[0m" "\n $@ " #"Current FUNCNAME ${FUNCNAME} #$LINENO " #"$(($RANDOM%10))" | |||||
| fi | |||||
| return 0 | |||||
| } | |||||
| _requires() { | |||||
| _cmds='' # Check if the commands exists | |||||
| if [[ "$#" -gt 0 ]]; then | |||||
| for i in "$@"; do | |||||
| if eval type type >/dev/null 2>&1; then | |||||
| eval type "$i" >/dev/null 2>&1 | |||||
| elif command >/dev/null 2>&1; then | |||||
| command -v "$i" >/dev/null 2>&1 | |||||
| else | |||||
| which "$i" >/dev/null 2>&1 | |||||
| fi | |||||
| #[ "$?" -eq 0 ] && _debug "checking for $i exists = ok" || _cmds=$_cmds"$i: " | |||||
| #shellcheck disable=SC2181 | |||||
| if [ "$?" -eq 0 ]; then | |||||
| #_debug "checking for $i exists = ok" | |||||
| continue | |||||
| else | |||||
| _cmds=$_cmds"$i: " | |||||
| fi | |||||
| done | |||||
| else | |||||
| echo "Usage: _requires [command] " | |||||
| return 1 | |||||
| fi | |||||
| [ -n "$_cmds" ] && { echo -e "\033[1;31m $_cmds command not found \033[0m" && return 1 ;} || return 0 | |||||
| } | |||||
| _requires openssl | |||||
| #shellcheck disable=SC2120 | |||||
| _hex_dump() { #ascii hex | |||||
| local _str='' | |||||
| [ $# -gt 0 ] && _str=$@ || read _str | |||||
| local _str_len=${#_str} | |||||
| local i=1 | |||||
| while [ "$i" -le "$_str_len" ]; do | |||||
| local _str_c="$(printf "%s" "$_str" | cut -c "$i")" | |||||
| printf " %02x" "'$_str_c" | |||||
| i=$(($i + 1)) | |||||
| done | |||||
| #printf "%s" " 0a" | |||||
| } | |||||
| _urlencode() { | |||||
| local length="${#1}" | |||||
| local i='' | |||||
| for i in $(awk "BEGIN { for ( i=0; i<$length; i++ ) print i }") | |||||
| do | |||||
| #local _strc="$(printf "%s" "$1" | cut -c "$i")" #i=1; i<=$length; i++ | |||||
| local _strc="${1:$i:1}" | |||||
| case $_strc in [a-zA-Z0-9.~_-]) printf "%s" "$_strc" ;; *) printf "%%%02X" "'$_strc" ;; | |||||
| esac | |||||
| done | |||||
| } | |||||
| _signature(){ | |||||
| signature='' | |||||
| _hexkey=$(printf "%s" "$AccessKeySecret&" | _hex_dump |sed 's/ //g') | |||||
| #signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -hmac $(printf "%s" "$AccessKeySecret&" | _hex_dump |sed 's/ //g'| xxd -r -p ) -binary | openssl base64 -e) | |||||
| signature=$(printf "%s" "GET&%2F&$(_urlencode "$query")" | openssl dgst -sha1 -mac HMAC -macopt "hexkey:$_hexkey" -binary | openssl base64 -e) | |||||
| signature=$(_urlencode "$signature") | |||||
| } | |||||
| _query() { | |||||
| [ -n "$__type" ] && { [[ "$_Action" = "AddDomainRecord" ]] && _Type="$__type" || { [ "$_Action" = "DescribeDomainRecords" ] && _TypeKeyWord="$__type"; } ; } | |||||
| query='' | |||||
| [ -n $AccessKeyId ] && query=$query'AccessKeyId='$AccessKeyId | |||||
| query=$query'&Action='"$1" | |||||
| [ -z $_DomainNames ] || query=$query'&DomainName='$_DomainNames | |||||
| query=$query'&Format=json' | |||||
| [ -z $_RR ] || query=$query'&RR='$_RR | |||||
| [ -z $_RRKeyWord ] || query=$query'&RRKeyWord='$_RRKeyWord | |||||
| [ -z $_RecordId ] || query=$query'&RecordId='$_RecordId | |||||
| query=$query'&SignatureMethod=HMAC-SHA1' | |||||
| query=$query"&SignatureNonce=$(date +"%s%N")" | |||||
| query=$query'&SignatureVersion=1.0' | |||||
| query=$query'&Timestamp='$_timestamp | |||||
| [ -z $_Type ] || query=$query'&Type='$_Type | |||||
| [ -z $_TypeKeyWord ] || query=$query'&TypeKeyWord='$_TypeKeyWord | |||||
| [ -z $_Value ] || query=$query'&Value='$_Value | |||||
| [ -z $_ValueKeyWord ] || query=$query'&ValueKeyWord='$_ValueKeyWord | |||||
| query=$query'&Version=2015-01-09' | |||||
| #_debug "$query" | |||||
| _signature | |||||
| return 0 | |||||
| } | |||||
| _Get_RecordIds(){ | |||||
| _Action="DescribeDomainRecords" | |||||
| _query $_Action $_DomainNames | |||||
| url="${Ali_API}?${query}&Signature=${signature}" | |||||
| _debug $url | |||||
| _RecordIds=$(curl -k -s $url | grep -Po 'RecordId[": "]+\K[^"]+') && __delete="1" #RecordId requisite | |||||
| _debug $_RecordIds | |||||
| return 0 | |||||
| } | |||||
| __type='TXT' | |||||
| _DomainNames=$(printf "%s" $1| awk -F"." '{if(NF>=2){print $(NF-1)"."$NF}}') #awk -F\. '{print $(NF-1) FS $NF}') #requisite | |||||
| _RRKeyWord="_acme-challenge" | |||||
| _Get_RecordIds | |||||
| _RRKeyWord='' | |||||
| _TypeKeyWord='' | |||||
| _ValueKeyWord='' | |||||
| if [ "$__delete" = "1" ];then | |||||
| _Action="DeleteDomainRecord" #Action requisite | |||||
| _DomainNames='' | |||||
| for _RecordId in ${_RecordIds[@]} #Delete multiple txt domain record | |||||
| do | |||||
| _debug "_RecordId" $_RecordId | |||||
| _query $_Action $_RecordId | |||||
| url="${Ali_API}?${query}&Signature=${signature}" | |||||
| _debug $url | |||||
| curl -k -s $url && ( echo -e "\n\033[1;32m Aliyun DNS record _acme-challenge.$1 has been deleted \033[0m") | |||||
| done | |||||
| else | |||||
| _Action="AddDomainRecord" #requisite | |||||
| _RR=$(printf "_acme-challenge.%s" $1| awk -F'.' '{if(NF>2){gsub("."$(NF-1)"."$NF,"");print}}') #requisite | |||||
| _Value=$2 #requisite | |||||
| _query $_Action $_DomainNames | |||||
| url="${Ali_API}?${query}&Signature=${signature}" | |||||
| _debug $url | |||||
| curl -k -s $url && (echo -e "\n\033[1;32m Start Checking aliyun DNS record _acme-challenge.$1 \033[0m") | |||||
| exit 0 | |||||
| fi | |||||
| @ -0,0 +1,28 @@ | |||||
| #!/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" | |||||
| i=1 | |||||
| response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") | |||||
| while [[ "${response}" == *"502 Bad Gateway"* ]] && [ $i -le 5 ]; do | |||||
| echo "Retrying Bad Gateway response (attempt $i of 5)" | |||||
| sleep 5 | |||||
| i=$((i+1)) | |||||
| response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=${txtvalue}") | |||||
| done | |||||
| 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 | |||||
| @ -0,0 +1,72 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Need to add your API key below or set as env variable | |||||
| apikey=${DYNU_API_KEY:-''} | |||||
| # This script adds a token to dynu.com DNS for the ACME challenge | |||||
| # usage dns_add_dynu "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 dynu.com etc) | |||||
| fulldomain="${1}" | |||||
| token="${2}" | |||||
| API='https://api.dynu.com/v2/dns' | |||||
| # 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 | |||||
| curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) | |||||
| # Get domain id | |||||
| # curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org | |||||
| resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") | |||||
| # Match domain id | |||||
| re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" | |||||
| if [[ "$resp" =~ $re ]]; then | |||||
| domain_id="${BASH_REMATCH[1]}" | |||||
| fi | |||||
| if [[ -z "$domain_id" ]]; then | |||||
| echo 'Domain name not found on your Dynu account' | |||||
| exit 3 | |||||
| fi | |||||
| # Check for existing _acme-challenge TXT record | |||||
| # curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" | |||||
| resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") | |||||
| re="\"id\":([^,]*)" | |||||
| if [[ "$resp" =~ $re ]]; then | |||||
| record_id="${BASH_REMATCH[1]}" | |||||
| fi | |||||
| if [[ -z "$record_id" ]]; then | |||||
| # Add new TXT challenge record | |||||
| resp=$(curl --silent \ | |||||
| "${curl_params[@]}" \ | |||||
| -X POST "${API}/${domain_id}/record" \ | |||||
| --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") | |||||
| else | |||||
| # Update existing record | |||||
| # curl -X POST https://api.dynu.com/v2/dns/9329328/record/7082063 -d "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"Test2\"}" | |||||
| resp=$(curl --silent \ | |||||
| "${curl_params[@]}" \ | |||||
| -X POST "${API}/${domain_id}/record/${record_id}" \ | |||||
| --data "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"state\":\"true\",\"textData\":\"$token\"}") | |||||
| fi | |||||
| # If adding record failed (exception:) then print error message | |||||
| if [[ "$resp" != *"\"statusCode\":200"* ]]; then | |||||
| echo "Error: DNS challenge not added: unknown error - ${resp}" | |||||
| exit 3 | |||||
| fi | |||||
| @ -0,0 +1,44 @@ | |||||
| #!/bin/bash | |||||
| FULLDOMAIN=$1 | |||||
| TOKEN=$2 | |||||
| TMPFILE=$(mktemp /tmp/dns_add_joker.XXXXXXX) | |||||
| USERNAME="youruser" | |||||
| PASSWORD="yourpassword" | |||||
| # Verify that required parameters are set | |||||
| 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 | |||||
| DOMAIN_ROOT=$(echo "${FULLDOMAIN}" | awk -F\. '{print $(NF-1) FS $NF}') | |||||
| SID=$(curl --silent -X POST https://dmapi.joker.com/request/login \ | |||||
| -H "Accept: application/json" -H "User-Agent: getssl/0.1" \ | |||||
| -H "application/x-www-form-urlencoded" -d "username=${USERNAME}&password=${PASSWORD}" \ | |||||
| -i -k 2>/dev/null | grep Auth-Sid | awk '{ print $2 }') | |||||
| ## put zone data in tempfile | |||||
| curl --silent -X POST https://dmapi.joker.com/request/dns-zone-get \ | |||||
| -H "Accept: application/json" -H "User-Agent: getssl/0.1" \ | |||||
| -H "application/x-www-form-urlencoded" -d "domain=${DOMAIN_ROOT}&auth-sid=${SID}" | \ | |||||
| tail -n +7 >"${TMPFILE}" | |||||
| ## add txt record | |||||
| printf "_acme-challenge.%s. TXT 0 \"%s \" 300\n\n" "${FULLDOMAIN}" "${TOKEN}" >>"${TMPFILE}" | |||||
| ## generate encoded url data | |||||
| URLDATA=$(cat "${TMPFILE}" | sed 's/ /%20/g' | sed 's/"/%22/g' | sed ':a;N;$!ba;s/\n/%0A/g') | |||||
| ## write new zonefile to joker | |||||
| curl --silent --output /dev/null "https://dmapi.joker.com/request/dns-zone-put?domain=${DOMAIN_ROOT}&zone=${URLDATA}&auth-sid=${SID}" 2>&1 | |||||
| ## remove tempfile | |||||
| rm -f "${TMPFILE}" | |||||
| @ -1,33 +1,33 @@ | |||||
| #!/bin/bash | |||||
| domains=($(echo "$1"|sed -e 's/^\(\([a-zA-Z0-9.-]*\?\)\.\)*\([a-zA-Z0-9-]\+\.[a-zA-Z-]\+\)$/"\1" _acme-challenge.\2 \3/g')) | |||||
| challenge="$2" | |||||
| # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ | |||||
| # permissions needed are /domain/zone/* in GET,POST,DELETE | |||||
| applicationKey="YourAK" | |||||
| applicationSecret="YourAS" | |||||
| consumerKey="YourCK" | |||||
| topDomain=${domains[2]} | |||||
| subDomain=${domains[1]%%.} | |||||
| function send | |||||
| { | |||||
| method=$1 | |||||
| url=$2 | |||||
| body=$3 | |||||
| ts=$(date +%s) | |||||
| sign=\$1\$$(echo -n "${applicationSecret}+${consumerKey}+${method}+https://eu.api.ovh.com/1.0${url}+${body}+${ts}"|sha1sum|cut -d" " -f1) | |||||
| curl -X ${method} -H "Content-Type: application/json" -H "X-Ovh-Application: ${applicationKey}" -H "X-Ovh-Timestamp: ${ts}" -H "X-Ovh-Signature: ${sign}" -H "X-Ovh-Consumer: ${consumerKey}" -d "${body}" https://eu.api.ovh.com/1.0${url} | |||||
| } | |||||
| # Creation request | |||||
| send POST /domain/zone/${topDomain}/record "{\"fieldType\":\"TXT\",\"subDomain\":\"$subDomain\",\"ttl\":60,\"target\":\"$challenge\"}" | |||||
| # Refresh request | |||||
| send POST /domain/zone/${topDomain}/refresh "" | |||||
| # Pause for 10 seconds, for DNS propagation | |||||
| sleep 10 | |||||
| #!/bin/bash | |||||
| domains=($(echo "$1"|sed -e 's/^\(\([a-zA-Z0-9.-]*\?\)\.\)*\([a-zA-Z0-9-]\+\.[a-zA-Z-]\+\)$/"\1" _acme-challenge.\2 \3/g')) | |||||
| challenge="$2" | |||||
| # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ | |||||
| # permissions needed are /domain/zone/* in GET,POST,DELETE | |||||
| applicationKey="YourAK" | |||||
| applicationSecret="YourAS" | |||||
| consumerKey="YourCK" | |||||
| topDomain=${domains[2]} | |||||
| subDomain=${domains[1]%%.} | |||||
| function send | |||||
| { | |||||
| method=$1 | |||||
| url=$2 | |||||
| body=$3 | |||||
| ts=$(date +%s) | |||||
| sign=\$1\$$(echo -n "${applicationSecret}+${consumerKey}+${method}+https://eu.api.ovh.com/1.0${url}+${body}+${ts}"|sha1sum|cut -d" " -f1) | |||||
| curl -X "${method}" -H "Content-Type: application/json" -H "X-Ovh-Application: ${applicationKey}" -H "X-Ovh-Timestamp: ${ts}" -H "X-Ovh-Signature: ${sign}" -H "X-Ovh-Consumer: ${consumerKey}" -d "${body}" "https://eu.api.ovh.com/1.0${url}" | |||||
| } | |||||
| # Creation request | |||||
| send POST "/domain/zone/${topDomain}/record" "{\"fieldType\":\"TXT\",\"subDomain\":\"$subDomain\",\"ttl\":60,\"target\":\"$challenge\"}" | |||||
| # Refresh request | |||||
| send POST "/domain/zone/${topDomain}/refresh" "" | |||||
| # Pause for 10 seconds, for DNS propagation | |||||
| sleep 10 | |||||
| @ -0,0 +1,6 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Simple script to update the challtestserv mock DNS server when testing DNS responses | |||||
| fulldomain="${1}" | |||||
| curl -X POST -d "{\"host\":\"_acme-challenge.${fulldomain}.\"}" http://10.30.50.3:8055/clear-txt | |||||
| @ -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}") | |||||
| @ -0,0 +1,69 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Need to add your email address and API key to cpanel below or set as env variables | |||||
| user=${CPANEL_USERNAME:-''} | |||||
| password=${CPANEL_PASSWORD:-''} | |||||
| url=${CPANEL_URL:-''} # e.g. https://www.cpanel-host.test:2083 | |||||
| apitoken=${CPANEL_APITOKEN:-''} | |||||
| fulldomain="${1}" | |||||
| # Check initial parameters | |||||
| if [[ -z "$fulldomain" ]]; then | |||||
| echo "DNS script requires full domain name as first parameter" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$user" ]]; then | |||||
| echo "CPANEL_USERNAME (username) parameter not set" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$apitoken" ]] && [[ -z "$password" ]]; then | |||||
| echo "Must set either CPANEL_APITOKEN or CPANEL_PASSWORD in dns script, environment variable or getssl.cfg" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$url" ]]; then | |||||
| echo "CPANEL_URL (url) parameter not set" | |||||
| exit 1 | |||||
| fi | |||||
| # Setup | |||||
| request_func="${url}/json-api/cpanel?cpanel_jsonapi_apiversion=2&cpanel_jsonapi_module=ZoneEdit" | |||||
| if [[ -n $apitoken ]]; then | |||||
| curl_params=( -H "Authorization: cpanel $user:$apitoken" ) | |||||
| else | |||||
| auth_string=$(echo -ne "$user:$password" | base64 --wrap 0) | |||||
| curl_params=( -H "Authorization: Basic $auth_string" ) | |||||
| fi | |||||
| # Check if domain is a CNAME | |||||
| res=$(dig CNAME "$fulldomain") | |||||
| domain=$(echo "$res"| awk '$4 ~ "CNAME" {print $5}' |sed 's/\.$//g') | |||||
| if [[ -n "$domain" ]]; then | |||||
| name=".${fulldomain%.$domain}" | |||||
| else | |||||
| domain=$fulldomain | |||||
| name="" | |||||
| fi | |||||
| # Find line number of existing record | |||||
| request_params="&cpanel_jsonapi_func=fetchzone_records&domain=${domain}&type=TXT&name=_acme-challenge.${fulldomain}." | |||||
| resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") | |||||
| if [[ "$resp" = *\"error\":* ]]; then | |||||
| echo -n "cpanel fetchzone records failed: " | |||||
| echo "$resp" | awk -F"error" '{ print $2 }' | awk -F\" '{ print $3 }' | |||||
| exit 1 | |||||
| fi | |||||
| # shellcheck disable=SC2001 | |||||
| line=$(echo "$resp" | sed -e 's/.*line":\([0-9]*\),.*/\1/') | |||||
| if [[ "$line" != "" ]]; then | |||||
| # Delete the challenge token | |||||
| request_params="&cpanel_jsonapi_func=remove_zone_record&domain=$domain&type=TXT&name=_acme-challenge$name&line=$line" | |||||
| resp=$(curl --silent "${curl_params[@]}" "$request_func$request_params") | |||||
| fi | |||||
| if [[ "$resp" = *\"status\":0* ]]; then | |||||
| echo -n "cpanel remove zone record failed: " | |||||
| echo "$resp" | awk -F"statusmsg" '{ print $2 }' | awk -F\" '{ print $3 }' | |||||
| exit 1 | |||||
| fi | |||||
| @ -0,0 +1,21 @@ | |||||
| #!/bin/bash | |||||
| # need to add your Token for duckdns below | |||||
| token=${DUCKDNS_TOKEN:-} | |||||
| domain="$1" | |||||
| i=1 | |||||
| response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") | |||||
| while [[ "${response}" == *"502 Bad Gateway"* ]] && [ $i -le 5 ]; do | |||||
| echo "Retrying Bad Gateway response (attempt $i of 5)" | |||||
| sleep 5 | |||||
| i=$((i+1)) | |||||
| response=$(curl --retry 5 --silent "https://www.duckdns.org/update?domains=${domain}&token=${token}&txt=&clear=true") | |||||
| done | |||||
| if [ "$response" != "OK" ]; then | |||||
| echo "Failed to update TXT record for ${domain} at duckdns.org (is the TOKEN valid?)" | |||||
| echo "$response" | |||||
| exit 1 | |||||
| fi | |||||
| @ -0,0 +1,71 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Need to add your API key below or set as env variable | |||||
| apikey=${DYNU_API_KEY:-''} | |||||
| # This script deletes the _acme-challenge TXT record from the dynu.com DNS entry for the domain | |||||
| # usage dns_del_dynu "domain name" | |||||
| # return codes are; | |||||
| # 0 - success | |||||
| # 1 - error in input | |||||
| # 2 - error within internal processing | |||||
| # 3 - error in result ( domain not found in dynu.com etc) | |||||
| # After deleting the TXT record from Dynu.com it takes over 30 minutes to add a new TXT record! | |||||
| # This doesn't happen when updating the TXT record, just for delete then add | |||||
| # As this is used for testing, changed the delete to a no-op. | |||||
| exit 0 | |||||
| fulldomain="${1}" | |||||
| API='https://api.dynu.com/v2/dns' | |||||
| # Check initial parameters | |||||
| if [[ -z "$fulldomain" ]]; then | |||||
| echo "DNS script requires full domain name as first parameter" | |||||
| exit 1 | |||||
| fi | |||||
| if [[ -z "$apikey" ]]; then | |||||
| echo "DNS script requires apikey environment variable to be set" | |||||
| exit 1 | |||||
| fi | |||||
| curl_params=( -H "accept: application/json" -H "API-Key: $apikey" -H 'Content-Type: application/json' ) | |||||
| # Get domain id | |||||
| # curl -X GET https://api.dynu.com/v2/dns/getroot/ubuntu-getssl.freeddns.org | |||||
| resp=$(curl --silent "${curl_params[@]}" -X GET "$API/getroot/${fulldomain}") | |||||
| # Match domain id | |||||
| re="\"id\":([^,]*),\"domainName\":\"${fulldomain}\"" | |||||
| if [[ "$resp" =~ $re ]]; then | |||||
| domain_id="${BASH_REMATCH[1]}" | |||||
| fi | |||||
| if [[ -z "$domain_id" ]]; then | |||||
| echo 'Domain name not found on your Dynu account' | |||||
| exit 3 | |||||
| fi | |||||
| # Check for existing _acme-challenge TXT record | |||||
| # curl -X GET "https://api.dynu.com/v2/dns/record/_acme-challenge.ubuntu-getssl.freeddns.org?recordType=TXT" | |||||
| resp=$(curl --silent "${curl_params[@]}" -X GET "${API}/record/_acme-challenge.${fulldomain}?recordType=TXT") | |||||
| re="\"id\":([^,]*)" | |||||
| if [[ "$resp" =~ $re ]]; then | |||||
| record_id="${BASH_REMATCH[1]}" | |||||
| fi | |||||
| if [[ -z "$record_id" ]]; then | |||||
| echo "No _acme-challenge.${fulldomain} TXT record found" | |||||
| exit 0 | |||||
| fi | |||||
| resp=$(curl --silent \ | |||||
| "${curl_params[@]}" \ | |||||
| -X DELETE "${API}/${domain_id}/record/${record_id}") | |||||
| # If adding record failed (exception:) then print error message | |||||
| if [[ "$resp" != *"\"statusCode\":200"* ]]; then | |||||
| echo "Error: DNS challenge not added: unknown error - ${resp}" | |||||
| exit 3 | |||||
| fi | |||||
| @ -0,0 +1,44 @@ | |||||
| #!/bin/bash | |||||
| FULLDOMAIN=$1 | |||||
| TOKEN=$2 | |||||
| TMPFILE=$(mktemp /tmp/dns_add_joker.XXXXXXX) | |||||
| USERNAME="youruser" | |||||
| PASSWORD="yourpassword" | |||||
| # Verify that required parameters are set | |||||
| 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 | |||||
| DOMAIN_ROOT=$(echo "${FULLDOMAIN}" | awk -F\. '{print $(NF-1) FS $NF}') | |||||
| SID=$(curl --silent -X POST https://dmapi.joker.com/request/login \ | |||||
| -H "Accept: application/json" -H "User-Agent: getssl/0.1" \ | |||||
| -H "application/x-www-form-urlencoded" -d "username=${USERNAME}&password=${PASSWORD}" \ | |||||
| -i -k 2>/dev/null | grep Auth-Sid | awk '{ print $2 }') | |||||
| ## put zone data in tempfile | |||||
| curl --silent -X POST https://dmapi.joker.com/request/dns-zone-get \ | |||||
| -H "Accept: application/json" -H "User-Agent: getssl/0.1" \ | |||||
| -H "application/x-www-form-urlencoded" -d "domain=${DOMAIN_ROOT}&auth-sid=${SID}" | \ | |||||
| tail -n +7 >"${TMPFILE}" | |||||
| ## remove txt record | |||||
| sed -i "/_acme-challenge.${FULLDOMAIN}.*${TOKEN}.*/d" "${TMPFILE}" | |||||
| ## generate encoded url data | |||||
| URLDATA=$(cat "${TMPFILE}" | sed 's/ /%20/g' | sed 's/"/%22/g' | sed ':a;N;$!ba;s/\n/%0A/g') | |||||
| ## write new zonefile to joker | |||||
| curl --silent --output /dev/null "https://dmapi.joker.com/request/dns-zone-put?domain=${DOMAIN_ROOT}&zone=${URLDATA}&auth-sid=${SID}" 2>&1 | |||||
| ## remove tempfile | |||||
| rm -f "${TMPFILE}" | |||||
| @ -1,35 +1,35 @@ | |||||
| #!/bin/bash | |||||
| domains=($(echo "$1"|sed -e 's/^\(\([a-zA-Z0-9.-]*\?\)\.\)*\([a-zA-Z0-9-]\+\.[a-zA-Z-]\+\)$/"\1" _acme-challenge.\2 \3/g')) | |||||
| challenge="$2" | |||||
| # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ | |||||
| # permissions needed are /domain/zone/* in GET,POST,DELETE | |||||
| applicationKey="YourAK" | |||||
| applicationSecret="YourAS" | |||||
| consumerKey="YourCK" | |||||
| topDomain=${domains[2]} | |||||
| subDomain=${domains[1]%%.} | |||||
| function send | |||||
| { | |||||
| method=$1 | |||||
| url=$2 | |||||
| body=$3 | |||||
| ts=$(date +%s) | |||||
| sign=\$1\$$(echo -n "${applicationSecret}+${consumerKey}+${method}+https://eu.api.ovh.com/1.0${url}+${body}+${ts}"|sha1sum|cut -d" " -f1) | |||||
| curl -X ${method} -H "Content-Type: application/json" -H "X-Ovh-Application: ${applicationKey}" -H "X-Ovh-Timestamp: ${ts}" -H "X-Ovh-Signature: ${sign}" -H "X-Ovh-Consumer: ${consumerKey}" -d "${body}" https://eu.api.ovh.com/1.0${url} | |||||
| } | |||||
| # Creation request | |||||
| oldResult=$(send GET "/domain/zone/${topDomain}/record?fieldType=TXT&subDomain=${subDomain}" ""|sed -e 's/\[//' -e 's/\]//') | |||||
| for num in ${oldResult//,/ } | |||||
| do | |||||
| send DELETE "/domain/zone/${topDomain}/record/${num}" "" | |||||
| done | |||||
| # Refresh request | |||||
| send POST /domain/zone/${topDomain}/refresh "" | |||||
| #!/bin/bash | |||||
| domains=($(echo "$1"|sed -e 's/^\(\([a-zA-Z0-9.-]*\?\)\.\)*\([a-zA-Z0-9-]\+\.[a-zA-Z-]\+\)$/"\1" _acme-challenge.\2 \3/g')) | |||||
| #challenge="$2" | |||||
| # Please, do not forget to ask for your credentials at https://eu.api.ovh.com/createToken/ | |||||
| # permissions needed are /domain/zone/* in GET,POST,DELETE | |||||
| applicationKey="YourAK" | |||||
| applicationSecret="YourAS" | |||||
| consumerKey="YourCK" | |||||
| topDomain=${domains[2]} | |||||
| subDomain=${domains[1]%%.} | |||||
| function send | |||||
| { | |||||
| method=$1 | |||||
| url=$2 | |||||
| body=$3 | |||||
| ts=$(date +%s) | |||||
| sign=\$1\$$(echo -n "${applicationSecret}+${consumerKey}+${method}+https://eu.api.ovh.com/1.0${url}+${body}+${ts}"|sha1sum|cut -d" " -f1) | |||||
| curl -X "${method}" -H "Content-Type: application/json" -H "X-Ovh-Application: ${applicationKey}" -H "X-Ovh-Timestamp: ${ts}" -H "X-Ovh-Signature: ${sign}" -H "X-Ovh-Consumer: ${consumerKey}" -d "${body}" "https://eu.api.ovh.com/1.0${url}" | |||||
| } | |||||
| # Creation request | |||||
| oldResult=$(send GET "/domain/zone/${topDomain}/record?fieldType=TXT&subDomain=${subDomain}" ""|sed -e 's/\[//' -e 's/\]//') | |||||
| for num in ${oldResult//,/ } | |||||
| do | |||||
| send DELETE "/domain/zone/${topDomain}/record/${num}" "" | |||||
| done | |||||
| # Refresh request | |||||
| send POST "/domain/zone/${topDomain}/refresh" "" | |||||
| @ -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=\""$txtvalue"\"" >/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 | |||||
| @ -0,0 +1,87 @@ | |||||
| #!/usr/bin/env python | |||||
| import boto3, sys, time | |||||
| from os.path import basename | |||||
| import dns.resolver | |||||
| client = boto3.client('route53') | |||||
| name = sys.argv[0] | |||||
| fqdn = sys.argv[1] | |||||
| challenge = sys.argv[2] | |||||
| bname = basename(name) | |||||
| if bname == 'dns_add_route53': | |||||
| action = 'UPSERT' | |||||
| elif bname == 'dns_del_route53': | |||||
| action = 'DELETE' | |||||
| else: | |||||
| print("No such action: {a}".format(a=bname)) | |||||
| sys.exit(1) | |||||
| try: | |||||
| response = client.list_hosted_zones() | |||||
| except Exception as e: | |||||
| print("Oops: {e!r}".format(e=e)) | |||||
| sys.exit(1) | |||||
| zone_id = "" | |||||
| zone_list = dict() | |||||
| for zone in response['HostedZones']: | |||||
| if not zone['Config']['PrivateZone']: | |||||
| zone_list[zone['Name']] = zone['Id'] | |||||
| for key in sorted(zone_list.keys(), key=len, reverse=True): | |||||
| if ".{z}".format(z=key) in ".{z}.".format(z=fqdn): | |||||
| zone_id = zone_list[key] | |||||
| if zone_id == "": | |||||
| print("We didn't find the zone") | |||||
| sys.exit(1) | |||||
| challenge_fqdn = "_acme-challenge.{f}".format(f=fqdn) | |||||
| try: | |||||
| response = client.change_resource_record_sets( | |||||
| HostedZoneId=zone_id, | |||||
| ChangeBatch={ | |||||
| 'Comment': 'getssl/Letsencrypt verification', | |||||
| 'Changes': [ | |||||
| { | |||||
| 'Action': action, | |||||
| 'ResourceRecordSet': { | |||||
| 'Name': challenge_fqdn, | |||||
| 'Type': 'TXT', | |||||
| 'TTL': 300, | |||||
| 'ResourceRecords': [{'Value': "\"{c}\"".format(c=challenge)}] | |||||
| } | |||||
| }, | |||||
| ] | |||||
| } | |||||
| ) | |||||
| except Exception as e: | |||||
| print("Oops: {e!r}".format(e=e)) | |||||
| sys.exit(1) | |||||
| waiting = 0 | |||||
| if action == 'UPSERT': | |||||
| # Wait until we see the record before returning. The ACME server's timeout is too short. | |||||
| # But only if we're adding the record. Don't care how long it takes to delete. | |||||
| while (True): | |||||
| try: | |||||
| my_resolver = dns.resolver.Resolver(configure=False) | |||||
| my_resolver.nameservers = ['8.8.8.8', '8.8.4.4'] | |||||
| results = my_resolver.resolve(challenge_fqdn, 'TXT') | |||||
| data = str(results.response.answer[0][0]).strip('\"') | |||||
| if data == challenge: | |||||
| print("found {f} entry".format(f=challenge_fqdn)) | |||||
| else: | |||||
| print("found {f} entry but it has bad data: {d}".format(f=challenge_fqdn, | |||||
| d=data)) | |||||
| break | |||||
| except dns.resolver.NXDOMAIN: | |||||
| waiting += 10 | |||||
| print("Didn't find {f} entry yet, sleeping... ({w}s)".format(f=challenge_fqdn, | |||||
| w=waiting)) | |||||
| time.sleep(10) | |||||
| pass | |||||
| @ -0,0 +1,33 @@ | |||||
| version: '3' | |||||
| services: | |||||
| pebble: | |||||
| image: letsencrypt/pebble:latest | |||||
| # TODO enable -strict | |||||
| command: pebble -config /test/config/pebble-config.json -dnsserver 10.30.50.3:53 | |||||
| environment: | |||||
| # with Go 1.13.x which defaults TLS 1.3 to on | |||||
| GODEBUG: "tls13=1" | |||||
| PEBBLE_ALTERNATE_ROOTS: 2 | |||||
| ports: | |||||
| - 14000:14000 # HTTPS ACME API | |||||
| - 15000:15000 # HTTPS Management API | |||||
| networks: | |||||
| acmenet: | |||||
| ipv4_address: 10.30.50.2 | |||||
| challtestsrv: | |||||
| image: letsencrypt/pebble-challtestsrv:latest | |||||
| command: pebble-challtestsrv -defaultIPv6 "" -defaultIPv4 10.30.50.3 -dns01 ":53" | |||||
| ports: | |||||
| - 8055:8055 # HTTP Management API | |||||
| networks: | |||||
| acmenet: | |||||
| ipv4_address: 10.30.50.3 | |||||
| networks: | |||||
| acmenet: | |||||
| driver: bridge | |||||
| ipam: | |||||
| driver: default | |||||
| config: | |||||
| - subnet: 10.30.50.0/24 | |||||
| @ -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 | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -0,0 +1,26 @@ | |||||
| #! /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 can install challenge token to multiple locations when using HTTP-01 verification" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01-two-acl.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate -d | |||||
| assert_success | |||||
| assert_output --partial "to /var/www/html/.well-known/acme-challenge" | |||||
| assert_output --partial "to /var/webroot/html/.well-known/acme-challenge" | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @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" { | |||||
| 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 | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -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' | |||||
| } | |||||
| @ -0,0 +1,75 @@ | |||||
| #! /usr/bin/env bats | |||||
| load '/bats-support/load.bash' | |||||
| load '/bats-assert/load.bash' | |||||
| load '/getssl/test/test_helper.bash' | |||||
| @test "Check that auto upgrade to v2 doesn't change pebble url" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-upgrade-test-pebble.cfg" | |||||
| setup_environment | |||||
| mkdir ${INSTALL_DIR}/.getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" | |||||
| assert_success | |||||
| assert_line 'Using certificate issuer: https://pebble:14000/dir' | |||||
| } | |||||
| @test "Check that auto upgrade to v2 doesn't change v2 staging url" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-upgrade-test-v2-staging.cfg" | |||||
| setup_environment | |||||
| mkdir ${INSTALL_DIR}/.getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" | |||||
| assert_success | |||||
| assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' | |||||
| } | |||||
| @test "Check that auto upgrade to v2 doesn't change v2 prod url" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-upgrade-test-v2-prod.cfg" | |||||
| setup_environment | |||||
| mkdir ${INSTALL_DIR}/.getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" | |||||
| assert_success | |||||
| assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' | |||||
| } | |||||
| @test "Check that auto upgrade to v2 changes v1 staging to v2 staging url" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-upgrade-test-v1-staging.cfg" | |||||
| setup_environment | |||||
| mkdir ${INSTALL_DIR}/.getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" | |||||
| assert_success | |||||
| assert_line 'Using certificate issuer: https://acme-staging-v02.api.letsencrypt.org/directory' | |||||
| } | |||||
| @test "Check that auto upgrade to v2 changes v1 prod to v2 prod url" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-upgrade-test-v1-prod.cfg" | |||||
| setup_environment | |||||
| mkdir ${INSTALL_DIR}/.getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl -d --check-config "$GETSSL_CMD_HOST" | |||||
| assert_success | |||||
| assert_line 'Using certificate issuer: https://acme-v02.api.letsencrypt.org/directory' | |||||
| } | |||||
| @ -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 certificate to check valid exit code" { | |||||
| 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 "Check no-renewal needed exits with normal exit code" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| run ${CODE_DIR}/getssl $GETSSL_HOST | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check no-renewal needed returns 2 if requested" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| run ${CODE_DIR}/getssl --notify-valid $GETSSL_HOST | |||||
| assert [ $status == 2 ] | |||||
| check_output_for_errors | |||||
| cleanup_environment | |||||
| } | |||||
| @ -0,0 +1,44 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Create certificate to check revoke" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check we can revoke a certificate" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt | |||||
| KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | |||||
| run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA | |||||
| assert_success | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -0,0 +1,50 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Create certificate to check revoke (no suffix)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01-no-suffix.cfg" | |||||
| fi | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check we can revoke a certificate (no suffix)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| echo 'CA="https://acme-staging-v02.api.letsencrypt.org"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt | |||||
| KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | |||||
| run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA | |||||
| assert_success | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -0,0 +1,23 @@ | |||||
| #! /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 "Test behaviour if ACL= line has a space" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01-bad-acl.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_failure | |||||
| } | |||||
| @ -0,0 +1,87 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Test behaviour if SANS line is space separated instead of comma separated (dns01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01-spaces-sans.cfg" | |||||
| setup_environment | |||||
| # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) | |||||
| for prefix in a b c; 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 "Test renewal if SANS line is space separated instead of comma separated (dns01)" { | |||||
| 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 | |||||
| } | |||||
| @test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (dns01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01-spaces-sans-and-ignore-dir-domain.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (dns01)" { | |||||
| 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 | |||||
| } | |||||
| @test "Test behaviour if SANS line is comma and space separated (dns01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01-spaces-and-commas-sans.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| cleanup_environment | |||||
| for prefix in a b c; do | |||||
| curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a | |||||
| done | |||||
| } | |||||
| @ -0,0 +1,87 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Test behaviour if SANS line is space separated instead of comma separated (http01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01-spaces-sans.cfg" | |||||
| setup_environment | |||||
| # Add hosts to DNS (also need to be added as aliases in docker-compose.yml) | |||||
| for prefix in a b c; 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 "Test renewal if SANS line is space separated instead of comma separated (http01)" { | |||||
| 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 | |||||
| } | |||||
| @test "Test behaviour if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (http01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01-spaces-sans-and-ignore-dir-domain.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Test renewal if SANS line is space separated and IGNORE_DIRECTORY_DOMAIN (http01)" { | |||||
| 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 | |||||
| } | |||||
| @test "Test behaviour if SANS line is comma and space separated (http01)" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01-spaces-and-commas-sans.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| cleanup_environment | |||||
| for prefix in a b c; do | |||||
| curl --silent -X POST -d '{"host":"'$prefix.$GETSSL_HOST'"}' http://10.30.50.3:8055/clear-a | |||||
| done | |||||
| } | |||||
| @ -0,0 +1,38 @@ | |||||
| #! /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 retry add dns command if dns isn't updated" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Running internal tests, skipping external test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| DNS_ADD_COMMAND="/getssl/test/dns_add_fail" | |||||
| # Speed up the test by reducing the number or retries and the wait between retries. | |||||
| DNS_WAIT=2 | |||||
| DNS_WAIT_COUNT=11 | |||||
| DNS_EXTRA_WAIT=0 | |||||
| CHECK_ALL_AUTH_DNS="false" | |||||
| CHECK_PUBLIC_DNS_SERVER="false" | |||||
| DNS_WAIT_RETRY_ADD="true" | |||||
| _RUNNING_TEST=1 | |||||
| EOF | |||||
| create_certificate | |||||
| assert_failure | |||||
| assert_line --partial "Retrying adding DNS via command" | |||||
| } | |||||
| @ -0,0 +1,64 @@ | |||||
| #! /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() { | |||||
| 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 | |||||
| curl --silent -X POST -d '{"host":"b.'$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'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a | |||||
| curl --silent -X POST -d '{"host":"b.'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a | |||||
| fi | |||||
| } | |||||
| @test "Create certificate to check can add to SANS" { | |||||
| skip "FIXME: Certificate is not recreated when SANS is updated" | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Not trying on staging server yet" | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01-add-to-sans-1.cfg" | |||||
| fi | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check we can add a new domain to SANS" { | |||||
| skip "FIXME: Certificate is not recreated when SANS is updated" | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Not trying on staging server yet" | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01-add-to-sans-2.cfg" | |||||
| fi | |||||
| # . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| # CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt | |||||
| # KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | |||||
| # cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| # As the SANS list changed, a new certificate is needed | |||||
| assert_line --partial "certificate installed OK on server" | |||||
| refute_line --partial 'certificate is valid for more than' | |||||
| } | |||||
| @ -0,0 +1,49 @@ | |||||
| #! /usr/bin/env bats | |||||
| load '/bats-support/load.bash' | |||||
| load '/bats-assert/load.bash' | |||||
| load '/getssl/test/test_helper.bash' | |||||
| setup() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| 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)" { | |||||
| 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)" { | |||||
| run ${CODE_DIR}/getssl -d -f $GETSSL_HOST | |||||
| assert_success | |||||
| assert_output --partial "dig" | |||||
| check_output_for_errors "debug" | |||||
| cleanup_environment | |||||
| } | |||||
| @ -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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| 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)" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate -d | |||||
| assert_success | |||||
| assert_output --partial "nslookup" | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -0,0 +1,64 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Create wildcard certificate" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check CHECK_REMOTE works for wildcard certificates" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| run ${CODE_DIR}/getssl "*.$GETSSL_HOST" | |||||
| assert_success | |||||
| assert_line --partial "certificate is valid for more than" | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Force renewal of wildcard certificate" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" | |||||
| assert_success | |||||
| refute_line --partial "certificate is valid for more than" | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check renewal of near-expiration wildcard certificate" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| echo "RENEW_ALLOW=2000" >> "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" | |||||
| run ${CODE_DIR}/getssl "*.$GETSSL_HOST" | |||||
| assert_success | |||||
| refute_line --partial "certificate is valid for more than" | |||||
| check_output_for_errors | |||||
| cleanup_environment | |||||
| } | |||||
| @ -0,0 +1,74 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Create secp384r1 wildcard certificate" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| ACCOUNT_KEY_TYPE="secp384r1" | |||||
| PRIVATE_KEY_ALG="secp384r1" | |||||
| EOF | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | |||||
| assert_line --partial "Public Key Algorithm: id-ecPublicKey" | |||||
| cleanup_environment | |||||
| } | |||||
| @test "Create dual certificates using DNS-01 verification" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| DUAL_RSA_ECDSA="true" | |||||
| ACCOUNT_KEY_TYPE="prime256v1" | |||||
| PRIVATE_KEY_ALG="prime256v1" | |||||
| EOF | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| echo 'RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| else | |||||
| echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| fi | |||||
| 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" ] | |||||
| run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | |||||
| assert_line --partial "Public Key Algorithm: rsaEncryption" | |||||
| run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.ec.crt" | |||||
| assert_line --partial "Public Key Algorithm: id-ecPublicKey" | |||||
| cleanup_environment | |||||
| } | |||||
| @ -0,0 +1,61 @@ | |||||
| #! /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 | |||||
| fi | |||||
| } | |||||
| @test "Create dual certificates (one wildcard) and copy RSA and ECDSA chain and key to two locations" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- 'EOF' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| DUAL_RSA_ECDSA="true" | |||||
| ACCOUNT_KEY_TYPE="prime256v1" | |||||
| PRIVATE_KEY_ALG="prime256v1" | |||||
| DOMAIN_KEY_LOCATION="/etc/nginx/pki/private/server.key;/root/a.${GETSSL_HOST}/server.key" | |||||
| DOMAIN_CHAIN_LOCATION="/etc/nginx/pki/domain-chain.crt;/root/a.${GETSSL_HOST}/domain-chain.crt" # this is the domain cert and CA cert | |||||
| EOF | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| echo 'RELOAD_CMD="cp /getssl/test/test-config/nginx-ubuntu-dual-certs ${NGINX_CONFIG} && /getssl/test/restart-nginx"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| else | |||||
| echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| fi | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| assert_line --partial "rsa certificate installed OK on server" | |||||
| assert_line --partial "prime256v1 certificate installed OK on server" | |||||
| fi | |||||
| # 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" ] | |||||
| cleanup_environment | |||||
| } | |||||
| @ -0,0 +1,46 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Check for globbing for wildcard domains" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| fi | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| # Create a directory in /root which looks like a domain so that if glob expansion is performed a certificate for the wrong domain will be created | |||||
| mkdir -p "${INSTALL_DIR}/a.${GETSSL_HOST}" | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Force renewal of wildcard certificate" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Not trying on staging server yet" | |||||
| fi | |||||
| run ${CODE_DIR}/getssl -f "*.$GETSSL_HOST" | |||||
| assert_success | |||||
| refute_line --partial "certificate is valid for more than" | |||||
| check_output_for_errors | |||||
| } | |||||
| @ -0,0 +1,64 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| curl --silent -X POST -d '{"host":"wild-'$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":"wild-'$GETSSL_HOST'", "addresses":["'$GETSSL_IP'"]}' http://10.30.50.3:8055/clear-a | |||||
| fi | |||||
| } | |||||
| @test "Check can create certificate for wildcard domain as arg and non-wildcard in SANS" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| # Staging server generates an error if try to create a certificate for *.domain and a.domain | |||||
| # so create for *.wild-domain and a.domain instead | |||||
| GETSSL_CMD_HOST="*.wild-${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| echo 'SANS="${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| if [ -n "$STAGING" ]; then | |||||
| echo 'CHECK_REMOTE="false"' >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| fi | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | |||||
| # verify certificate is for wildcard domain with non-wildcard domain in the Subject Alternative Name list | |||||
| assert_output --regexp "Subject: CN[ ]?=[ ]?\*.wild-${GETSSL_HOST}" | |||||
| assert_output --partial "DNS:${GETSSL_HOST}" | |||||
| } | |||||
| @test "Check can create certificate for non-wildcard domain as arg and wildcard in SANS" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| echo 'SANS="*.wild-${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| run openssl x509 -noout -text -in "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | |||||
| # verify certificate is for non-wildcard domain with wildcard domain in the Subject Alternative Name list | |||||
| assert_output --regexp "Subject: CN[ ]?=[ ]?${GETSSL_HOST}" | |||||
| assert_output --partial "DNS:*.wild-${GETSSL_HOST}" | |||||
| } | |||||
| @ -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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Check can create certificate for wildcard domain using --all" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| fi | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| # Create .getssl directory and .getssl/*.{host} directory | |||||
| init_getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/*.${GETSSL_HOST}/getssl.cfg" | |||||
| # create another domain in the .getssl directory | |||||
| run ${CODE_DIR}/getssl -c "a.${GETSSL_HOST}" | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/a.${GETSSL_HOST}/getssl.cfg" | |||||
| # Create a directory in /root which looks like a domain so that if glob expansion is performed the wildcard certificate won't be created | |||||
| mkdir -p "${INSTALL_DIR}/a.${GETSSL_HOST}" | |||||
| run ${CODE_DIR}/getssl --all | |||||
| assert_success | |||||
| assert_line --partial "Certificate saved in /root/.getssl/*.${GETSSL_HOST}/*.${GETSSL_HOST}" | |||||
| assert_line --partial "Certificate saved in /root/.getssl/a.${GETSSL_HOST}/a.${GETSSL_HOST}" | |||||
| check_output_for_errors | |||||
| } | |||||
| @ -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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Create certificate to check wildcard revoke" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Check we can revoke a wildcard certificate" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| . "${CODE_DIR}/test/test-config/${CONFIG_FILE}" | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| CERT=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt | |||||
| KEY=${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.key | |||||
| run ${CODE_DIR}/getssl -d --revoke $CERT $KEY $CA | |||||
| assert_line "certificate revoked" | |||||
| assert_success | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Check that new creating a new configuration files uses details from existing certificate" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| fi | |||||
| # Create and install certificate for wildcard + another domain | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| echo 'SANS="a.${GETSSL_HOST}"' > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| # Delete configuration | |||||
| rm -r ${INSTALL_DIR}/.getssl | |||||
| # Create configuration | |||||
| run ${CODE_DIR}/getssl -c "${GETSSL_CMD_HOST}" | |||||
| # Assert that the newly created configuration contains the additional domain in SANS | |||||
| # if this fails then error in tests will be "grep failed" - this means SANS did not hold the expected value | |||||
| # eg SANS="a.centos7.getssl.test" | |||||
| grep -q "SANS=\"a.${GETSSL_HOST}\"" ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg | |||||
| assert_success | |||||
| } | |||||
| @ -0,0 +1,31 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Check that trying to create a wildcard certificate using http-01 validation shows an error message" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Internal test, no need to test on staging server" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| # Try and create a wildcard certificate using http-01 validation | |||||
| GETSSL_CMD_HOST="*.${GETSSL_HOST}" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_failure | |||||
| assert_line --partial "cannot use http-01 validation for wildcard domains" | |||||
| } | |||||
| @ -0,0 +1,47 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Check that getssl -c fails with an error message if mktemp fails" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Internal test, no need to test on staging server" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| # set TMPDIR to an invalid directory and check for failure | |||||
| export TMPDIR=/getssl.invalid.directory | |||||
| setup_environment | |||||
| run ${CODE_DIR}/getssl -c "$GETSSL_CMD_HOST" | |||||
| assert_failure | |||||
| assert_line --partial "mktemp failed" | |||||
| } | |||||
| @test "Check that getssl fails with an error message if mktemp fails" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Internal test, no need to test on staging server" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| fi | |||||
| setup_environment | |||||
| init_getssl | |||||
| # set TMPDIR to an invalid directory and check for failure | |||||
| export TMPDIR=/getssl.invalid.directory | |||||
| create_certificate | |||||
| assert_failure | |||||
| assert_line --partial "mktemp failed" | |||||
| } | |||||
| @ -0,0 +1,96 @@ | |||||
| #! /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 | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| CONFIG_FILE="getssl-http01-dual-rsa-ecdsa.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-old-nginx.cfg" | |||||
| fi | |||||
| 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 "Check renewal test works for dual certificates using HTTP-01" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| check_nginx | |||||
| run ${CODE_DIR}/getssl -d $GETSSL_HOST | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| assert_line "certificate on server is same as the local cert" | |||||
| else | |||||
| assert_line --partial "certificate is valid for more than 30 days" | |||||
| fi | |||||
| assert_success | |||||
| } | |||||
| @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 | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-dns01-dual-rsa-ecdsa-old-nginx.cfg" | |||||
| fi | |||||
| 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 | |||||
| } | |||||
| @ -0,0 +1,44 @@ | |||||
| #! /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/drill ]; then | |||||
| mv /usr/bin/drill /usr/bin/drill.getssl.bak | |||||
| fi | |||||
| if [ -f /usr/bin/dig ]; then | |||||
| chmod -x /usr/bin/dig | |||||
| fi | |||||
| } | |||||
| teardown() { | |||||
| if [ -f /usr/bin/drill.getssl.bak ]; then | |||||
| mv /usr/bin/drill.getssl.bak /usr/bin/drill | |||||
| fi | |||||
| if [ -f /usr/bin/dig ]; then | |||||
| chmod +x /usr/bin/dig | |||||
| fi | |||||
| } | |||||
| @test "Test that if dig exists but errors HAS_DIG is not set" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| if [ ! -f /usr/bin/dig ]; then | |||||
| skip "dig not installed, skipping dig test" | |||||
| fi | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| create_certificate -d | |||||
| assert_success | |||||
| refute_line --partial "HAS DIG_OR_DRILL=dig" | |||||
| check_output_for_errors "debug" | |||||
| } | |||||
| @ -0,0 +1,25 @@ | |||||
| #! /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 "Test that running in POSIX mode shows an error" { | |||||
| # v2.31 uses read to create an array in the get_auth_dns function which causes a parse error in posix mode | |||||
| # Could be re-written to not use this functionality if it causes for required. | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| run bash --posix "${CODE_DIR}/getssl" | |||||
| assert_failure | |||||
| assert_line "getssl: Running with POSIX mode enabled is not supported" | |||||
| check_output_for_errors | |||||
| } | |||||
| @ -0,0 +1,111 @@ | |||||
| #! /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 | |||||
| # Turn off warning about detached head | |||||
| git config --global advice.detachedHead false | |||||
| run git clone https://github.com/srvrco/getssl.git "$INSTALL_DIR/upgrade-getssl" | |||||
| # Don't do version arithmetics any longer, look what was the previous version by getting the last | |||||
| # line (starting with v) and the one before that from the list of tags. | |||||
| cd "$INSTALL_DIR/upgrade-getssl" | |||||
| # This sets CURRENT_TAG and PREVIOUS_TAG bash variables | |||||
| eval $(git tag -l | awk 'BEGIN {cur="?.??"};/^v/{prv=cur;cur=substr($1,2)};END{ printf("CURRENT_TAG=\"%s\";PREVIOUS_TAG=\"%s\"\n",cur,prv)}') | |||||
| # The version in the file, which we will overwrite | |||||
| FILE_VERSION=$(awk -F'"' '/^VERSION=/{print $2}' "$CODE_DIR/getssl") | |||||
| # If FILE_VERSION > CURRENT_TAG then either we are testing a push to master or the last version wasn't released | |||||
| } | |||||
| teardown() { | |||||
| rm -r "$INSTALL_DIR/upgrade-getssl" | |||||
| } | |||||
| @test "Test that we are told that a newer version is available" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| cd "$INSTALL_DIR/upgrade-getssl" | |||||
| git checkout tags/v${PREVIOUS_TAG} | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" | |||||
| # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy | |||||
| # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development | |||||
| cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" | |||||
| sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" | |||||
| run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config ${GETSSL_CMD_HOST} | |||||
| assert_success | |||||
| # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) | |||||
| assert_line --regexp "A more recent version \(v(${CURRENT_TAG}|${FILE_VERSION})\) of getssl is available, please update" | |||||
| check_output_for_errors | |||||
| } | |||||
| @test "Test that we can upgrade to the newer version" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| cd "$INSTALL_DIR/upgrade-getssl" | |||||
| git checkout tags/v${CURRENT_TAG} | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" | |||||
| # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy | |||||
| # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development | |||||
| cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" | |||||
| sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" | |||||
| run "$INSTALL_DIR/upgrade-getssl/getssl" --check-config --upgrade ${GETSSL_CMD_HOST} | |||||
| assert_success | |||||
| # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) | |||||
| assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" | |||||
| } | |||||
| @test "Test that we can upgrade to the newer version when invoking as \"bash ./getssl\"" { | |||||
| # Note that `bash getssl` will fail if the CWD isn't in the PATH and an upgrade occurs | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| cd "$INSTALL_DIR/upgrade-getssl" | |||||
| git checkout tags/v${PREVIOUS_TAG} | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cp "${CODE_DIR}/test/test-config/${CONFIG_FILE}" "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl.cfg" | |||||
| # Overwrite checked out getssl-script with copy of new one, but write the previous version into the copy | |||||
| # Note that this way we mock downgrading getssl and are testing the upgrading of the version in development | |||||
| cp "$CODE_DIR/getssl" "$INSTALL_DIR/upgrade-getssl/" | |||||
| sed -i -e "s/VERSION=\"${FILE_VERSION}\"/VERSION=\"${PREVIOUS_TAG}\"/" "$INSTALL_DIR/upgrade-getssl/getssl" | |||||
| run bash ./getssl --check-config --upgrade ${GETSSL_CMD_HOST} | |||||
| assert_success | |||||
| # Check for current tag or file version otherwise push to master fails on a new version (or if the tag hasn't been updated) | |||||
| assert_line --regexp "Updated getssl from v${PREVIOUS_TAG} to v(${CURRENT_TAG}|${FILE_VERSION})" | |||||
| } | |||||
| @ -0,0 +1,71 @@ | |||||
| #! /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 [ -n "${VSFTPD_CONF}" ]; then | |||||
| cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl | |||||
| # enable passive and disable active mode | |||||
| # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode | |||||
| cat <<- _FTP >> $VSFTPD_CONF | |||||
| pasv_enable=NO | |||||
| _FTP | |||||
| ${CODE_DIR}/test/restart-ftpd | |||||
| fi | |||||
| } | |||||
| teardown() { | |||||
| if [ -n "${VSFTPD_CONF}" ]; then | |||||
| cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF | |||||
| ${CODE_DIR}/test/restart-ftpd | |||||
| fi | |||||
| } | |||||
| @test "Use FTP to create challenge file" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| if [[ ! -d /var/www/html/.well-known/acme-challenge ]]; then | |||||
| mkdir -p /var/www/html/.well-known/acme-challenge | |||||
| fi | |||||
| # Always change ownership and permissions in case previous tests created the directories as root | |||||
| chgrp -R www-data /var/www/html/.well-known | |||||
| chmod -R g+w /var/www/html/.well-known | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" | |||||
| EOF | |||||
| if [[ "$GETSSL_OS" = "alpine" ]]; then | |||||
| cat <<- EOF2 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| FTP_OPTIONS="set ftp:passive-mode off" | |||||
| EOF2 | |||||
| elif [[ "$FTP_PASSIVE_DEFAULT" == "true" ]]; then | |||||
| cat <<- EOF3 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| FTP_OPTIONS="passive" | |||||
| EOF3 | |||||
| fi | |||||
| create_certificate | |||||
| assert_success | |||||
| assert_line --partial "ftp:ftpuser:ftpuser:" | |||||
| if [[ "$GETSSL_OS" != "alpine" ]] && [[ "$FTP_PASSIVE_DEFAULT" == "true" ]]; then | |||||
| assert_line --partial "Passive mode off" | |||||
| fi | |||||
| check_output_for_errors | |||||
| } | |||||
| @ -0,0 +1,71 @@ | |||||
| #! /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 [ -n "${VSFTPD_CONF}" ]; then | |||||
| cp $VSFTPD_CONF ${VSFTPD_CONF}.getssl | |||||
| # enable passive and disable active mode | |||||
| # https://www.pixelstech.net/article/1364817664-FTP-active-mode-and-passive-mode | |||||
| cat <<- _FTP >> $VSFTPD_CONF | |||||
| pasv_enable=YES | |||||
| pasv_max_port=10100 | |||||
| pasv_min_port=10090 | |||||
| connect_from_port_20=NO | |||||
| _FTP | |||||
| ${CODE_DIR}/test/restart-ftpd | |||||
| fi | |||||
| } | |||||
| teardown() { | |||||
| if [ -n "${VSFTPD_CONF}" ]; then | |||||
| cp ${VSFTPD_CONF}.getssl $VSFTPD_CONF | |||||
| ${CODE_DIR}/test/restart-ftpd | |||||
| fi | |||||
| } | |||||
| @test "Use Passive FTP to create challenge file" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| if [[ ! -d /var/www/html/.well-known/acme-challenge ]]; then | |||||
| mkdir -p /var/www/html/.well-known/acme-challenge | |||||
| fi | |||||
| # Always change ownership and permissions in case previous tests created the directories as root | |||||
| chgrp -R www-data /var/www/html/.well-known | |||||
| chmod -R g+w /var/www/html/.well-known | |||||
| CONFIG_FILE="getssl-http01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| ACL="ftp:ftpuser:ftpuser:${GETSSL_CMD_HOST}:/var/www/html/.well-known/acme-challenge" | |||||
| EOF | |||||
| if [[ "$FTP_PASSIVE_DEFAULT" == "false" ]]; then | |||||
| cat <<- EOF3 >> ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| FTP_OPTIONS="passive" | |||||
| EOF3 | |||||
| fi | |||||
| create_certificate | |||||
| assert_success | |||||
| assert_line --partial "ftp:ftpuser:ftpuser:" | |||||
| if [[ "$FTP_PASSIVE_DEFAULT" == "false" ]]; then | |||||
| assert_line --partial "Passive mode on" | |||||
| else | |||||
| refute_line --partial "Passive mode off" | |||||
| fi | |||||
| check_output_for_errors | |||||
| } | |||||
| @ -0,0 +1,111 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Use PREFERRED_CHAIN to select an alternate root" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| PREFERRED_CHAIN="\(STAGING\) Pretend Pear X1" | |||||
| CHECK_CHAIN="(STAGING) Pretend Pear X1" | |||||
| else | |||||
| PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN *= *" '{ print $2 }') | |||||
| PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace | |||||
| CHECK_CHAIN=$PREFERRED_CHAIN | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| PREFERRED_CHAIN="${PREFERRED_CHAIN}" | |||||
| EOF | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| # verify certificate is issued by preferred chain root | |||||
| if [[ "${CHECK_CHAIN}" != "$issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# issuer=$issuer" | |||||
| fi | |||||
| [ "${CHECK_CHAIN}" = "$issuer" ] | |||||
| } | |||||
| @test "Use PREFERRED_CHAIN to select the default root" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| PREFERRED_CHAIN="\(STAGING\) Doctored Durian Root CA X3" | |||||
| CHECK_CHAIN="(STAGING) Doctored Durian Root CA X3" | |||||
| else | |||||
| PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/0 | openssl x509 -text -noout | grep Issuer: | awk -F"CN *= *" '{ print $2 }') | |||||
| PREFERRED_CHAIN="${PREFERRED_CHAIN# }" # remove leading whitespace | |||||
| CHECK_CHAIN=$PREFERRED_CHAIN | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| PREFERRED_CHAIN="${PREFERRED_CHAIN}" | |||||
| EOF | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| # verify certificate is issued by preferred chain root | |||||
| if [[ "${CHECK_CHAIN}" != "$issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# issuer=$issuer" | |||||
| fi | |||||
| [ "${CHECK_CHAIN}" = "$issuer" ] | |||||
| } | |||||
| @test "Use PREFERRED_CHAIN to select an alternate root by suffix" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| FULL_PREFERRED_CHAIN="(STAGING) Pretend Pear X1" | |||||
| else | |||||
| FULL_PREFERRED_CHAIN=$(curl --silent https://pebble:15000/roots/2 | openssl x509 -text -noout | grep "Issuer:" | awk -F"CN *= *" '{ print $2 }') | |||||
| FULL_PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN# }" # remove leading whitespace | |||||
| fi | |||||
| # Take the last word from FULL_PREFERRED_CHAIN as the chain to use | |||||
| PREFERRED_CHAIN="${FULL_PREFERRED_CHAIN##* }" | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| PREFERRED_CHAIN="${PREFERRED_CHAIN}" | |||||
| EOF | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Issuer: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| # verify certificate is issued by preferred chain root | |||||
| if [[ "${FULL_PREFERRED_CHAIN}" != "$issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# FULL_PREFERRED_CHAIN=$FULL_PREFERRED_CHAIN" | |||||
| echo "# issuer=$issuer" | |||||
| fi | |||||
| [ "${FULL_PREFERRED_CHAIN}" = "$issuer" ] | |||||
| } | |||||
| @ -0,0 +1,94 @@ | |||||
| #! /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() { | |||||
| if [ -z "$STAGING" ]; then | |||||
| export CURL_CA_BUNDLE=/root/pebble-ca-bundle.crt | |||||
| fi | |||||
| } | |||||
| @test "Use FULL_CHAIN_INCLUDE_ROOT to include the root certificate in the fullchain" { | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| FULL_CHAIN_INCLUDE_ROOT="true" | |||||
| EOF | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| if [ -n "$STAGING" ]; then | |||||
| PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" | |||||
| else | |||||
| # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) | |||||
| # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate | |||||
| PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| fi | |||||
| final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| # verify certificate includes the chain root | |||||
| if [[ "${PREFERRED_CHAIN}" != "$final_issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# final_issuer=$final_issuer" | |||||
| fi | |||||
| [ "${PREFERRED_CHAIN}" = "$final_issuer" ] | |||||
| } | |||||
| @test "Use FULL_CHAIN_INCLUDE_ROOT with dual certificates" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" | |||||
| fi | |||||
| CONFIG_FILE="getssl-dns01.cfg" | |||||
| setup_environment | |||||
| init_getssl | |||||
| cat <<- EOF > ${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/getssl_test_specific.cfg | |||||
| FULL_CHAIN_INCLUDE_ROOT="true" | |||||
| DUAL_RSA_ECDSA="true" | |||||
| ACCOUNT_KEY_TYPE="prime256v1" | |||||
| PRIVATE_KEY_ALG="prime256v1" | |||||
| CHECK_REMOTE="false" | |||||
| EOF | |||||
| 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" ] | |||||
| if [ -n "$STAGING" ]; then | |||||
| PREFERRED_CHAIN="(STAGING) Doctored Durian Root CA X3" | |||||
| else | |||||
| # pebble doesn't support CA Issuers so the fullchain.crt will just contain the certificate (code path means it won't contain the intermediate cert in this case) | |||||
| # This is testing that requesting FULL_CHAIN_INCLUDE_ROOT doesn't fail if there is no CA Issuers in the certificate | |||||
| PREFERRED_CHAIN=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/${GETSSL_CMD_HOST}.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| fi | |||||
| # verify both rsa and ecdsa certificates include the chain root | |||||
| final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| if [[ "${PREFERRED_CHAIN}" != "$final_issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# final_issuer=$final_issuer" | |||||
| fi | |||||
| [ "${PREFERRED_CHAIN}" = "$final_issuer" ] | |||||
| ecdsa_final_issuer=$(openssl crl2pkcs7 -nocrl -certfile "${INSTALL_DIR}/.getssl/${GETSSL_CMD_HOST}/fullchain.ec.crt" | openssl pkcs7 -print_certs -text -noout | grep Subject: | tail -1 | awk -F"CN=" '{ print $2 }') | |||||
| if [[ "$PREFERRED_CHAIN" != "$ecdsa_final_issuer" ]]; then | |||||
| echo "# PREFERRED_CHAIN=$PREFERRED_CHAIN" | |||||
| echo "# ecdsa_final_issuer=$ecdsa_final_issuer" | |||||
| fi | |||||
| [ "${PREFERRED_CHAIN}" = "$ecdsa_final_issuer" ] | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -0,0 +1,81 @@ | |||||
| #! /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 | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations.cfg" | |||||
| else | |||||
| CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations-old-nginx.cfg" | |||||
| fi | |||||
| setup_environment | |||||
| mkdir -p /root/a.${GETSSL_HOST} | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_success | |||||
| check_output_for_errors | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| assert_line --partial "rsa certificate installed OK on server" | |||||
| assert_line --partial "prime256v1 certificate installed OK on server" | |||||
| fi | |||||
| # 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" ] | |||||
| } | |||||
| @test "Create dual certificates and copy to two locations but not returned by server" { | |||||
| if [ -n "$STAGING" ]; then | |||||
| skip "Using staging server, skipping internal test" | |||||
| fi | |||||
| check_nginx | |||||
| if [ "$OLD_NGINX" = "false" ]; then | |||||
| CONFIG_FILE="getssl-http01-dual-rsa-ecdsa-2-locations-wrong-nginx.cfg" | |||||
| else | |||||
| skip "Skipping as old nginx servers cannot return both certificates" | |||||
| fi | |||||
| setup_environment | |||||
| mkdir -p /root/a.${GETSSL_HOST} | |||||
| init_getssl | |||||
| create_certificate | |||||
| assert_failure | |||||
| assert_line --partial "prime256v1 certificate obtained but not installed on server" | |||||
| } | |||||
| @ -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 external tests, skipping internal testing" | |||||
| fi | |||||
| CONFIG_FILE="getssl-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 external tests, skipping internal testing" | |||||
| fi | |||||
| CONFIG_FILE="getssl-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 | |||||
| @ -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-dns01-multiple-domains.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-dns01-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 | |||||
| } | |||||
| @ -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 | |||||
| } | |||||
| @ -0,0 +1,33 @@ | |||||
| FROM alpine:latest | |||||
| # Note this image uses busybox awk instead of gawk | |||||
| RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx bash lftp vsftpd openssh-server | |||||
| WORKDIR /root | |||||
| # Create nginx directories in standard places | |||||
| RUN mkdir /run/nginx | |||||
| RUN mkdir -p /etc/nginx/pki/private | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf | |||||
| RUN adduser -D ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R ftpuser.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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" ] | |||||
| @ -0,0 +1,34 @@ | |||||
| FROM bash:4.0 | |||||
| # https://hub.docker.com/_/bash | |||||
| RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server | |||||
| WORKDIR /root | |||||
| # Create nginx directories in standard places | |||||
| RUN mkdir /run/nginx | |||||
| RUN mkdir /etc/nginx/pki | |||||
| RUN mkdir /etc/nginx/pki/private | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf | |||||
| RUN adduser -D ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R ftpuser.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| 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 | |||||
| @ -0,0 +1,34 @@ | |||||
| FROM bash:4.2 | |||||
| # https://hub.docker.com/_/bash | |||||
| RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server | |||||
| WORKDIR /root | |||||
| # Create nginx directories in standard places | |||||
| RUN mkdir /run/nginx | |||||
| RUN mkdir /etc/nginx/pki | |||||
| RUN mkdir /etc/nginx/pki/private | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf | |||||
| RUN adduser -D ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R ftpuser.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| 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 | |||||
| @ -0,0 +1,34 @@ | |||||
| FROM bash:5.0 | |||||
| # https://hub.docker.com/_/bash | |||||
| RUN apk --no-cache add supervisor openssl git curl bind-tools drill wget nginx lftp vsftpd openssh-server | |||||
| WORKDIR /root | |||||
| # Create nginx directories in standard places | |||||
| RUN mkdir /run/nginx | |||||
| RUN mkdir /etc/nginx/pki | |||||
| RUN mkdir /etc/nginx/pki/private | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY ./test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN echo "seccomp_sandbox=NO" >> /etc/vsftpd.conf | |||||
| RUN adduser -D ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R ftpuser.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| 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 | |||||
| @ -0,0 +1,47 @@ | |||||
| FROM centos:centos6 | |||||
| # Note this image uses gawk | |||||
| # Note if you are running this using WSL2 you need to put the following lines in %userprofile%\.wslconfig | |||||
| # [wsl2] | |||||
| # kernelCommandLine = vsyscall=emulate | |||||
| # Centos 6 is EOL and is no longer available from the usual mirrors, so switch to https://vault.centos.org | |||||
| RUN sed -i 's/enabled=1/enabled=0/g' /etc/yum/pluginconf.d/fastestmirror.conf && \ | |||||
| sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/*.repo && \ | |||||
| sed -i 's;^#baseurl=http://mirror;baseurl=https://vault;g' /etc/yum.repos.d/*.repo | |||||
| # Update and install required software | |||||
| RUN yum -y install epel-release | |||||
| RUN yum -y install git curl dnsutils ldns wget nginx | |||||
| RUN yum -y install ftp vsftpd | |||||
| RUN yum -y install openssh-server | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser www-data | |||||
| RUN usermod -G www-data ftpuser | |||||
| RUN usermod -G www-data root | |||||
| RUN mkdir -p /var/www/.well-known/acme-challenge | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /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 # --branch v1.2.1 | |||||
| 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 | |||||
| # Hack to disable BATS pretty formatter which stopped working on centos6 | |||||
| ENV CI=yes | |||||
| EXPOSE 80 443 | |||||
| # Run eternal loop - for testing | |||||
| CMD [ "tail", "-f", "/dev/null" ] | |||||
| @ -0,0 +1,32 @@ | |||||
| FROM centos:centos7 | |||||
| # Update and install required software | |||||
| RUN yum -y update | |||||
| RUN yum -y install epel-release | |||||
| RUN yum -y install git curl ldns bind-utils wget which nginx | |||||
| RUN yum -y install ftp vsftpd | |||||
| RUN yum -y install openssh-server | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /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 | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser www-data | |||||
| RUN usermod -G www-data ftpuser | |||||
| RUN usermod -G www-data root | |||||
| RUN mkdir -p /var/www/.well-known/acme-challenge | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert | |||||
| RUN /bats-core/install.sh /usr/local | |||||
| @ -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 ldns wget which nginx | |||||
| ENV staging "true" | |||||
| ENV dynamic_dns "dynu" | |||||
| ENV DUCKDNS_TOKEN 1d616aa9-b8e4-4bb4-b312-3289de82badb | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /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 --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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" ] | |||||
| @ -0,0 +1,29 @@ | |||||
| 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 ldns wget which nginx | |||||
| ENV staging "true" | |||||
| ENV dynamic_dns "duckdns" | |||||
| ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 | |||||
| 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 --branch v1.2.1 | |||||
| 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 | |||||
| @ -0,0 +1,34 @@ | |||||
| FROM centos:centos8 | |||||
| # 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 bind-utils wget which nginx | |||||
| RUN yum -y install ftp vsftpd | |||||
| RUN yum -y install openssh-server | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /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 | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=true | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd/vsftpd.conf | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser www-data | |||||
| RUN usermod -G www-data ftpuser | |||||
| RUN usermod -G www-data root | |||||
| RUN mkdir -p /var/www/.well-known/acme-challenge | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-assert /bats-assert | |||||
| RUN /bats-core/install.sh /usr/local | |||||
| @ -0,0 +1,32 @@ | |||||
| 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 ldnsutils wget nginx-light | |||||
| RUN apt-get install -y ftp vsftpd | |||||
| RUN apt-get install -y openssh-server | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /etc/nginx/pki/private | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=false | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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,0 +1,38 @@ | |||||
| FROM ubuntu:latest | |||||
| # Note this image uses mawk1.3 | |||||
| # Set noninteractive otherwise tzdata hangs | |||||
| ENV DEBIAN_FRONTEND noninteractive | |||||
| # Update and install required software | |||||
| RUN apt-get update --fix-missing | |||||
| RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light | |||||
| RUN apt-get install -y vim dos2unix # for debugging | |||||
| RUN apt-get install -y ftp vsftpd | |||||
| RUN apt-get install -y openssh-server | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=false | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| WORKDIR /root | |||||
| # Prevent "Can't load /root/.rnd into RNG" error from openssl | |||||
| RUN touch /root/.rnd | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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,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 dynamic_dns "duckdns" | |||||
| 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 ldnsutils wget nginx-light | |||||
| RUN apt-get install -y vim dos2unix # for debugging | |||||
| WORKDIR /root | |||||
| # Prevent "Can't load /root/.rnd into RNG" error from openssl | |||||
| RUN touch /root/.rnd | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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,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 dynamic_dns "dynu" | |||||
| ENV DYNU_API_KEY 65cXefd35XbYf36546eg5dYcZT6X52Y2 | |||||
| # Update and install required software | |||||
| RUN apt-get update --fix-missing | |||||
| RUN apt-get install -y git curl dnsutils ldnsutils wget nginx-light | |||||
| RUN apt-get install -y vim dos2unix # for debugging | |||||
| 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 --branch v1.2.1 | |||||
| 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,0 +1,36 @@ | |||||
| 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 ldnsutils wget nginx-light | |||||
| RUN apt-get install -y ftp vsftpd | |||||
| RUN apt-get install -y openssh-server | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /etc/nginx/pki/private | |||||
| COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=false | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| # The default init.d script seems to have an incorrect check that vsftpd has started | |||||
| COPY test/test-config/vsftpd.initd /etc/init.d/vsftpd | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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,0 +1,41 @@ | |||||
| 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 ldnsutils wget gawk nginx-light | |||||
| RUN apt-get install -y ftp vsftpd | |||||
| RUN apt-get install -y openssh-server | |||||
| WORKDIR /root | |||||
| RUN mkdir -p /etc/nginx/pki/private | |||||
| COPY ./test/test-config/nginx-ubuntu-no-ssl /etc/nginx/sites-enabled/default | |||||
| # Setup ftp | |||||
| ENV VSFTPD_CONF=/etc/vsftpd.conf | |||||
| ENV FTP_PASSIVE_DEFAULT=false | |||||
| COPY test/test-config/vsftpd.conf /etc/vsftpd.conf | |||||
| # The default init.d script seems to have an incorrect check that vsftpd has started | |||||
| COPY test/test-config/vsftpd.initd /etc/init.d/vsftpd | |||||
| RUN adduser ftpuser | |||||
| RUN echo 'ftpuser:ftpuser' | chpasswd | |||||
| RUN adduser ftpuser www-data | |||||
| RUN adduser root www-data | |||||
| RUN chown -R www-data.www-data /var/www | |||||
| RUN chmod g+w -R /var/www | |||||
| # Prevent "Can't load /root/.rnd into RNG" error from openssl | |||||
| RUN touch /root/.rnd | |||||
| # BATS (Bash Automated Testings) | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-core.git /bats-core --branch v1.2.1 | |||||
| RUN git clone --depth 1 https://github.com/bats-core/bats-support /bats-support | |||||
| RUN git clone --depth 1 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" ] | |||||
| @ -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 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,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 | |||||
| @ -0,0 +1,6 @@ | |||||
| #!/usr/bin/env bash | |||||
| # Special test script which will always fail to update dns | |||||
| echo "This is a test script to check retry works if DNS isn't updated" | |||||
| exit 0 | |||||
| @ -0,0 +1,9 @@ | |||||
| #!/usr/bin/env bash | |||||
| if [ "$GETSSL_OS" = "alpine" ]; then | |||||
| killall -HUP vsftpd >&3- | |||||
| elif [[ "$GETSSL_OS" == "centos"[78] ]]; then | |||||
| pgrep vsftpd | head -1 | xargs kill -HUP | |||||
| else | |||||
| service vsftpd restart >/dev/null >&3- | |||||
| fi | |||||