summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/xenolf/lego
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/xenolf/lego')
-rw-r--r--vendor/github.com/xenolf/lego/.gitcookies.encbin480 -> 0 bytes
-rw-r--r--vendor/github.com/xenolf/lego/.gitignore4
-rw-r--r--vendor/github.com/xenolf/lego/.travis.yml16
-rw-r--r--vendor/github.com/xenolf/lego/CHANGELOG.md154
-rw-r--r--vendor/github.com/xenolf/lego/CONTRIBUTING.md32
-rw-r--r--vendor/github.com/xenolf/lego/Dockerfile15
-rw-r--r--vendor/github.com/xenolf/lego/LICENSE21
-rw-r--r--vendor/github.com/xenolf/lego/README.md273
-rw-r--r--vendor/github.com/xenolf/lego/account.go109
-rw-r--r--vendor/github.com/xenolf/lego/acme/challenges.go16
-rw-r--r--vendor/github.com/xenolf/lego/acme/client.go825
-rw-r--r--vendor/github.com/xenolf/lego/acme/client_test.go269
-rw-r--r--vendor/github.com/xenolf/lego/acme/crypto.go347
-rw-r--r--vendor/github.com/xenolf/lego/acme/crypto_test.go93
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge.go309
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go53
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge_test.go200
-rw-r--r--vendor/github.com/xenolf/lego/acme/error.go94
-rw-r--r--vendor/github.com/xenolf/lego/acme/http.go160
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_challenge.go41
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_challenge_server.go79
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_challenge_test.go57
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_test.go100
-rw-r--r--vendor/github.com/xenolf/lego/acme/jws.go131
-rw-r--r--vendor/github.com/xenolf/lego/acme/messages.go115
-rw-r--r--vendor/github.com/xenolf/lego/acme/pop_challenge.go1
-rw-r--r--vendor/github.com/xenolf/lego/acme/provider.go28
-rw-r--r--vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.15
-rw-r--r--vendor/github.com/xenolf/lego/acme/tls_sni_challenge.go67
-rw-r--r--vendor/github.com/xenolf/lego/acme/tls_sni_challenge_server.go62
-rw-r--r--vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go65
-rw-r--r--vendor/github.com/xenolf/lego/acme/utils.go29
-rw-r--r--vendor/github.com/xenolf/lego/acme/utils_test.go26
-rw-r--r--vendor/github.com/xenolf/lego/cli.go232
-rw-r--r--vendor/github.com/xenolf/lego/cli_handlers.go423
-rw-r--r--vendor/github.com/xenolf/lego/configuration.go76
-rw-r--r--vendor/github.com/xenolf/lego/crypto.go56
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go141
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns_test.go148
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/azure/azure.go151
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/azure/azure_test.go89
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go223
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare_test.go80
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go166
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean_test.go117
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dns_providers.go86
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dns_providers_test.go50
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go180
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple_test.go140
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go248
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy_test.go37
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go146
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod_test.go72
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go274
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/dyn/dyn_test.go53
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go128
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale_test.go103
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go472
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/gandi/gandi_test.go939
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go155
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy_test.go60
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud.go205
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud_test.go99
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/linode/linode.go131
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/linode/linode_test.go317
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go416
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap_test.go402
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go97
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/ns1/ns1_test.go67
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/otc/mock.go152
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/otc/otc.go388
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/otc/otc_test.go112
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go159
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/ovh/ovh_test.go103
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/pdns/README.md7
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go343
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/pdns/pdns_test.go80
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go284
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace_test.go220
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go152
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136_test.go244
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/route53/fixtures_test.go39
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/route53/route53.go185
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/route53/route53_integration_test.go70
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/route53/route53_test.go105
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/route53/testutil_test.go38
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go127
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/vultr/vultr_test.go65
-rw-r--r--vendor/github.com/xenolf/lego/providers/http/memcached/README.md15
-rw-r--r--vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go60
-rw-r--r--vendor/github.com/xenolf/lego/providers/http/memcached/memcached_test.go111
-rw-r--r--vendor/github.com/xenolf/lego/providers/http/webroot/webroot.go58
-rw-r--r--vendor/github.com/xenolf/lego/providers/http/webroot/webroot_test.go46
93 files changed, 0 insertions, 13738 deletions
diff --git a/vendor/github.com/xenolf/lego/.gitcookies.enc b/vendor/github.com/xenolf/lego/.gitcookies.enc
deleted file mode 100644
index 09c303c94..000000000
--- a/vendor/github.com/xenolf/lego/.gitcookies.enc
+++ /dev/null
Binary files differ
diff --git a/vendor/github.com/xenolf/lego/.gitignore b/vendor/github.com/xenolf/lego/.gitignore
deleted file mode 100644
index 74d32f0ab..000000000
--- a/vendor/github.com/xenolf/lego/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-lego.exe
-lego
-.lego
-.idea
diff --git a/vendor/github.com/xenolf/lego/.travis.yml b/vendor/github.com/xenolf/lego/.travis.yml
deleted file mode 100644
index d7a626e23..000000000
--- a/vendor/github.com/xenolf/lego/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: go
-go:
-- 1.8.x
-- 1.9.x
-- tip
-services:
- - memcached
-env:
- - MEMCACHED_HOSTS=localhost:11211
-install:
-- go get -t ./...
-script:
-- go vet ./...
-- go test -v ./...
-before_install:
-- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && openssl aes-256-cbc -K $encrypted_26c593b079d9_key -iv $encrypted_26c593b079d9_iv -in .gitcookies.enc -out .gitcookies -d || true'
diff --git a/vendor/github.com/xenolf/lego/CHANGELOG.md b/vendor/github.com/xenolf/lego/CHANGELOG.md
deleted file mode 100644
index d71cc23dc..000000000
--- a/vendor/github.com/xenolf/lego/CHANGELOG.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# Changelog
-
-## [0.4.1] - 2017-09-26
-
-### Added:
-- lib: A new DNS provider for OTC.
-- lib: The `AWS_HOSTED_ZONE_ID` environment variable for the Route53 DNS provider to directly specify the zone.
-- lib: The `RFC2136_TIMEOUT` enviroment variable to make the timeout for the RFC2136 provider configurable.
-- lib: The `GCE_SERVICE_ACCOUNT_FILE` environment variable to specify a service account file for the Google Cloud DNS provider.
-
-### Fixed:
-- lib: Fixed an authentication issue with the latest Azure SDK.
-
-## [0.4.0] - 2017-07-13
-
-### Added:
-- CLI: The `--http-timeout` switch. This allows for an override of the default client HTTP timeout.
-- lib: The `HTTPClient` field. This allows for an override of the default HTTP timeout for library HTTP requests.
-- CLI: The `--dns-timeout` switch. This allows for an override of the default DNS timeout for library DNS requests.
-- lib: The `DNSTimeout` switch. This allows for an override of the default client DNS timeout.
-- lib: The `QueryRegistration` function on `acme.Client`. This performs a POST on the client registration's URI and gets the updated registration info.
-- lib: The `DeleteRegistration` function on `acme.Client`. This deletes the registration as currently configured in the client.
-- lib: The `ObtainCertificateForCSR` function on `acme.Client`. The function allows to request a certificate for an already existing CSR.
-- CLI: The `--csr` switch. Allows to use already existing CSRs for certificate requests on the command line.
-- CLI: The `--pem` flag. This will change the certificate output so it outputs a .pem file concatanating the .key and .crt files together.
-- CLI: The `--dns-resolvers` flag. Allows for users to override the default DNS servers used for recursive lookup.
-- lib: Added a memcached provider for the HTTP challenge.
-- CLI: The `--memcached-host` flag. This allows to use memcached for challenge storage.
-- CLI: The `--must-staple` flag. This enables OCSP must staple in the generated CSR.
-- lib: The library will now honor entries in your resolv.conf.
-- lib: Added a field `IssuerCertificate` to the `CertificateResource` struct.
-- lib: A new DNS provider for OVH.
-- lib: A new DNS provider for DNSMadeEasy.
-- lib: A new DNS provider for Linode.
-- lib: A new DNS provider for AuroraDNS.
-- lib: A new DNS provider for NS1.
-- lib: A new DNS provider for Azure DNS.
-- lib: A new DNS provider for Rackspace DNS.
-- lib: A new DNS provider for Exoscale DNS.
-- lib: A new DNS provider for DNSPod.
-
-### Changed:
-- lib: Exported the `PreCheckDNS` field so library users can manage the DNS check in tests.
-- lib: The library will now skip challenge solving if a valid Authz already exists.
-
-### Removed:
-- lib: The library will no longer check for auto renewed certificates. This has been removed from the spec and is not supported in Boulder.
-
-### Fixed:
-- lib: Fix a problem with the Route53 provider where it was possible the verification was published to a private zone.
-- lib: Loading an account from file should fail if a integral part is nil
-- lib: Fix a potential issue where the Dyn provider could resolve to an incorrect zone.
-- lib: If a registration encounteres a conflict, the old registration is now recovered.
-- CLI: The account.json file no longer has the executable flag set.
-- lib: Made the client registration more robust in case of a 403 HTTP response.
-- lib: Fixed an issue with zone lookups when they have a CNAME in another zone.
-- lib: Fixed the lookup for the authoritative zone for Google Cloud.
-- lib: Fixed a race condition in the nonce store.
-- lib: The Google Cloud provider now removes old entries before trying to add new ones.
-- lib: Fixed a condition where we could stall due to an early error condition.
-- lib: Fixed an issue where Authz object could end up in an active state after an error condition.
-
-## [0.3.1] - 2016-04-19
-
-### Added:
-- lib: A new DNS provider for Vultr.
-
-### Fixed:
-- lib: DNS Provider for DigitalOcean could not handle subdomains properly.
-- lib: handleHTTPError should only try to JSON decode error messages with the right content type.
-- lib: The propagation checker for the DNS challenge would not retry on send errors.
-
-
-## [0.3.0] - 2016-03-19
-
-### Added:
-- CLI: The `--dns` switch. To include the DNS challenge for consideration. When using this switch, all other solvers are disabled. Supported are the following solvers: cloudflare, digitalocean, dnsimple, dyn, gandi, googlecloud, namecheap, route53, rfc2136 and manual.
-- CLI: The `--accept-tos` switch. Indicates your acceptance of the Let's Encrypt terms of service without prompting you.
-- CLI: The `--webroot` switch. The HTTP-01 challenge may now be completed by dropping a file into a webroot. When using this switch, all other solvers are disabled.
-- CLI: The `--key-type` switch. This replaces the `--rsa-key-size` switch and supports the following key types: EC256, EC384, RSA2048, RSA4096 and RSA8192.
-- CLI: The `--dnshelp` switch. This displays a more in-depth help topic for DNS solvers.
-- CLI: The `--no-bundle` sub switch for the `run` and `renew` commands. When this switch is set, the CLI will not bundle the issuer certificate with your certificate.
-- lib: A new type for challenge identifiers `Challenge`
-- lib: A new interface for custom challenge providers `acme.ChallengeProvider`
-- lib: A new interface for DNS-01 providers to allow for custom timeouts for the validation function `acme.ChallengeProviderTimeout`
-- lib: SetChallengeProvider function. Pass a challenge identifier and a Provider to replace the default behaviour of a challenge.
-- lib: The DNS-01 challenge has been implemented with modular solvers using the `ChallengeProvider` interface. Included solvers are: cloudflare, digitalocean, dnsimple, gandi, namecheap, route53, rfc2136 and manual.
-- lib: The `acme.KeyType` type was added and is used for the configuration of crypto parameters for RSA and EC keys. Valid KeyTypes are: EC256, EC384, RSA2048, RSA4096 and RSA8192.
-
-### Changed
-- lib: ExcludeChallenges now expects to be passed an array of `Challenge` types.
-- lib: HTTP-01 now supports custom solvers using the `ChallengeProvider` interface.
-- lib: TLS-SNI-01 now supports custom solvers using the `ChallengeProvider` interface.
-- lib: The `GetPrivateKey` function in the `acme.User` interface is now expected to return a `crypto.PrivateKey` instead of an `rsa.PrivateKey` for EC compat.
-- lib: The `acme.NewClient` function now expects an `acme.KeyType` instead of the keyBits parameter.
-
-### Removed
-- CLI: The `rsa-key-size` switch was removed in favor of `key-type` to support EC keys.
-
-### Fixed
-- lib: Fixed a race condition in HTTP-01
-- lib: Fixed an issue where status codes on ACME challenge responses could lead to no action being taken.
-- lib: Fixed a regression when calling the Renew function with a SAN certificate.
-
-## [0.2.0] - 2016-01-09
-
-### Added:
-- CLI: The `--exclude` or `-x` switch. To exclude a challenge from being solved.
-- CLI: The `--http` switch. To set the listen address and port of HTTP based challenges. Supports `host:port` and `:port` for any interface.
-- CLI: The `--tls` switch. To set the listen address and port of TLS based challenges. Supports `host:port` and `:port` for any interface.
-- CLI: The `--reuse-key` switch for the `renew` operation. This lets you reuse an existing private key for renewals.
-- lib: ExcludeChallenges function. Pass an array of challenge identifiers to exclude them from solving.
-- lib: SetHTTPAddress function. Pass a port to set the listen port for HTTP based challenges.
-- lib: SetTLSAddress function. Pass a port to set the listen port of TLS based challenges.
-- lib: acme.UserAgent variable. Use this to customize the user agent on all requests sent by lego.
-
-### Changed:
-- lib: NewClient does no longer accept the optPort parameter
-- lib: ObtainCertificate now returns a SAN certificate if you pass more then one domain.
-- lib: GetOCSPForCert now returns the parsed OCSP response instead of just the status.
-- lib: ObtainCertificate has a new parameter `privKey crypto.PrivateKey` which lets you reuse an existing private key for new certificates.
-- lib: RenewCertificate now expects the PrivateKey property of the CertificateResource to be set only if you want to reuse the key.
-
-### Removed:
-- CLI: The `--port` switch was removed.
-- lib: RenewCertificate does no longer offer to also revoke your old certificate.
-
-### Fixed:
-- CLI: Fix logic using the `--days` parameter for renew
-
-## [0.1.1] - 2015-12-18
-
-### Added:
-- CLI: Added a way to automate renewal through a cronjob using the --days parameter to renew
-
-### Changed:
-- lib: Improved log output on challenge failures.
-
-### Fixed:
-- CLI: The short parameter for domains would not get accepted
-- CLI: The cli did not return proper exit codes on error library errors.
-- lib: RenewCertificate did not properly renew SAN certificates.
-
-### Security
-- lib: Fix possible DOS on GetOCSPForCert
-
-## [0.1.0] - 2015-12-03
-- Initial release
-
-[0.3.1]: https://github.com/xenolf/lego/compare/v0.3.0...v0.3.1
-[0.3.0]: https://github.com/xenolf/lego/compare/v0.2.0...v0.3.0
-[0.2.0]: https://github.com/xenolf/lego/compare/v0.1.1...v0.2.0
-[0.1.1]: https://github.com/xenolf/lego/compare/v0.1.0...v0.1.1
-[0.1.0]: https://github.com/xenolf/lego/tree/v0.1.0
diff --git a/vendor/github.com/xenolf/lego/CONTRIBUTING.md b/vendor/github.com/xenolf/lego/CONTRIBUTING.md
deleted file mode 100644
index 9939a5ab3..000000000
--- a/vendor/github.com/xenolf/lego/CONTRIBUTING.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# How to contribute to lego
-
-Contributions in the form of patches and proposals are essential to keep lego great and to make it even better.
-To ensure a great and easy experience for everyone, please review the few guidelines in this document.
-
-## Bug reports
-
-- Use the issue search to see if the issue has already been reported.
-- Also look for closed issues to see if your issue has already been fixed.
-- If both of the above do not apply create a new issue and include as much information as possible.
-
-Bug reports should include all information a person could need to reproduce your problem without the need to
-follow up for more information. If possible, provide detailed steps for us to reproduce it, the expected behaviour and the actual behaviour.
-
-## Feature proposals and requests
-
-Feature requests are welcome and should be discussed in an issue.
-Please keep proposals focused on one thing at a time and be as detailed as possible.
-It is up to you to make a strong point about your proposal and convince us of the merits and the added complexity of this feature.
-
-## Pull requests
-
-Patches, new features and improvements are a great way to help the project.
-Please keep them focused on one thing and do not include unrelated commits.
-
-All pull requests which alter the behaviour of the program, add new behaviour or somehow alter code in a non-trivial way should **always** include tests.
-
-If you want to contribute a significant pull request (with a non-trivial workload for you) please **ask first**. We do not want you to spend
-a lot of time on something the project's developers might not want to merge into the project.
-
-**IMPORTANT**: By submitting a patch, you agree to allow the project
-owners to license your work under the terms of the [MIT License](LICENSE).
diff --git a/vendor/github.com/xenolf/lego/Dockerfile b/vendor/github.com/xenolf/lego/Dockerfile
deleted file mode 100644
index 511e403ce..000000000
--- a/vendor/github.com/xenolf/lego/Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM alpine:3.6
-
-ENV GOPATH /go
-ENV LEGO_VERSION tags/v0.4.1
-
-RUN apk update && apk add --no-cache --virtual run-dependencies ca-certificates && \
- apk add --no-cache --virtual build-dependencies go git musl-dev && \
- go get -u github.com/xenolf/lego && \
- cd ${GOPATH}/src/github.com/xenolf/lego && \
- git checkout ${LEGO_VERSION} && \
- go build -o /usr/bin/lego . && \
- apk del build-dependencies && \
- rm -rf ${GOPATH}
-
-ENTRYPOINT [ "/usr/bin/lego" ]
diff --git a/vendor/github.com/xenolf/lego/LICENSE b/vendor/github.com/xenolf/lego/LICENSE
deleted file mode 100644
index 270cba089..000000000
--- a/vendor/github.com/xenolf/lego/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015-2017 Sebastian Erhart
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/xenolf/lego/README.md b/vendor/github.com/xenolf/lego/README.md
deleted file mode 100644
index 9ec7e1f38..000000000
--- a/vendor/github.com/xenolf/lego/README.md
+++ /dev/null
@@ -1,273 +0,0 @@
-# lego
-Let's Encrypt client and ACME library written in Go
-
-[![GoDoc](https://godoc.org/github.com/xenolf/lego/acme?status.svg)](https://godoc.org/github.com/xenolf/lego/acme)
-[![Build Status](https://travis-ci.org/xenolf/lego.svg?branch=master)](https://travis-ci.org/xenolf/lego)
-[![Dev Chat](https://img.shields.io/badge/dev%20chat-gitter-blue.svg?label=dev+chat)](https://gitter.im/xenolf/lego)
-[![Beerpay](https://beerpay.io/xenolf/lego/badge.svg)](https://beerpay.io/xenolf/lego)
-
-#### General
-This is a work in progress. Please do *NOT* run this on a production server and please report any bugs you find!
-
-#### Installation
-lego supports both binary installs and install from source.
-
-To get the binary just download the latest release for your OS/Arch from [the release page](https://github.com/xenolf/lego/releases)
-and put the binary somewhere convenient. lego does not assume anything about the location you run it from.
-
-To install from source, just run
-```
-go get -u github.com/xenolf/lego
-```
-
-To build lego inside a Docker container, just run
-```
-docker build -t lego .
-```
-##### From the package manager
-- [ArchLinux (AUR)](https://aur.archlinux.org/packages/lego-git):
-```
-yaourt -S lego-git
-```
-#### Features
-
-- Register with CA
-- Obtain certificates, both from scratch or with an existing CSR
-- Renew certificates
-- Revoke certificates
-- Robust implementation of all ACME challenges
- - HTTP (http-01)
- - TLS with Server Name Indication (tls-sni-01)
- - DNS (dns-01)
-- SAN certificate support
-- Comes with multiple optional [DNS providers](https://github.com/xenolf/lego/tree/master/providers/dns)
-- [Custom challenge solvers](https://github.com/xenolf/lego/wiki/Writing-a-Challenge-Solver)
-- Certificate bundling
-- OCSP helper function
-
-Please keep in mind that CLI switches and APIs are still subject to change.
-
-When using the standard `--path` option, all certificates and account configurations are saved to a folder *.lego* in the current working directory.
-
-#### Sudo
-The CLI does not require root permissions but needs to bind to port 80 and 443 for certain challenges.
-To run the CLI without sudo, you have four options:
-
-- Use setcap 'cap_net_bind_service=+ep' /path/to/program
-- Pass the `--http` or/and the `--tls` option and specify a custom port to bind to. In this case you have to forward port 80/443 to these custom ports (see [Port Usage](#port-usage)).
-- Pass the `--webroot` option and specify the path to your webroot folder. In this case the challenge will be written in a file in `.well-known/acme-challenge/` inside your webroot.
-- Pass the `--dns` option and specify a DNS provider.
-
-#### Port Usage
-By default lego assumes it is able to bind to ports 80 and 443 to solve challenges.
-If this is not possible in your environment, you can use the `--http` and `--tls` options to instruct
-lego to listen on that interface:port for any incoming challenges.
-
-If you are using this option, make sure you proxy all of the following traffic to these ports.
-
-HTTP Port:
-- All plaintext HTTP requests to port 80 which begin with a request path of `/.well-known/acme-challenge/` for the HTTP challenge.
-
-TLS Port:
-- All TLS handshakes on port 443 for the TLS-SNI challenge.
-
-This traffic redirection is only needed as long as lego solves challenges. As soon as you have received your certificates you can deactivate the forwarding.
-
-#### Usage
-
-```
-NAME:
- lego - Let's Encrypt client written in Go
-
-USAGE:
- lego [global options] command [command options] [arguments...]
-
-VERSION:
- 0.4.1
-
-COMMANDS:
- run Register an account, then create and install a certificate
- revoke Revoke a certificate
- renew Renew a certificate
- dnshelp Shows additional help for the --dns global option
- help, h Shows a list of commands or help for one command
-
-GLOBAL OPTIONS:
- --domains value, -d value Add a domain to the process. Can be specified multiple times.
- --csr value, -c value Certificate signing request filename, if an external CSR is to be used
- --server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v01.api.letsencrypt.org/directory")
- --email value, -m value Email used for registration and recovery contact.
- --accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
- --key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384 (default: "rsa2048")
- --path value Directory to use for storing the data (default: "/.lego")
- --exclude value, -x value Explicitly disallow solvers by name from being used. Solvers: "http-01", "tls-sni-01".
- --webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge
- --memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
- --http value Set the port and interface to use for HTTP based challenges to listen on. Supported: interface:port or :port
- --tls value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port
- --dns value Solve a DNS challenge using the specified provider. Disables all other challenges. Run 'lego dnshelp' for help on usage.
- --http-timeout value Set the HTTP timeout value to a specific value in seconds. The default is 10 seconds. (default: 0)
- --dns-timeout value Set the DNS timeout value to a specific value in seconds. The default is 10 seconds. (default: 0)
- --dns-resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use Google's DNS resolvers.
- --pem Generate a .pem file by concatanating the .key and .crt files together.
- --help, -h show help
- --version, -v print the version
-```
-
-##### CLI Example
-
-Assumes the `lego` binary has permission to bind to ports 80 and 443. You can get a pre-built binary from the [releases](https://github.com/xenolf/lego/releases) page.
-If your environment does not allow you to bind to these ports, please read [Port Usage](#port-usage).
-
-Obtain a certificate:
-
-```bash
-$ lego --email="foo@bar.com" --domains="example.com" run
-```
-
-(Find your certificate in the `.lego` folder of current working directory.)
-
-To renew the certificate:
-
-```bash
-$ lego --email="foo@bar.com" --domains="example.com" renew
-```
-
-To renew the certificate only if it's older than 30 days
-
-```bash
-$ lego --email="foo@bar.com" --domains="example.com" renew --days 30
-```
-
-Obtain a certificate using the DNS challenge and AWS Route 53:
-
-```bash
-$ AWS_REGION=us-east-1 AWS_ACCESS_KEY_ID=my_id AWS_SECRET_ACCESS_KEY=my_key lego --email="foo@bar.com" --domains="example.com" --dns="route53" run
-```
-
-Note that `--dns=foo` implies `--exclude=http-01` and `--exclude=tls-sni-01`. lego will not attempt other challenges if you've told it to use DNS instead.
-
-Obtain a certificate given a certificate signing request (CSR) generated by something else:
-
-```bash
-$ lego --email="foo@bar.com" --csr=/path/to/csr.pem run
-```
-
-(lego will infer the domains to be validated based on the contents of the CSR, so make sure the CSR's Common Name and optional SubjectAltNames are set correctly.)
-
-lego defaults to communicating with the production Let's Encrypt ACME server. If you'd like to test something without issuing real certificates, consider using the staging endpoint instead:
-
-```bash
-$ lego --server=https://acme-staging.api.letsencrypt.org/directory …
-```
-
-#### DNS Challenge API Details
-
-##### AWS Route 53
-
-The following AWS IAM policy document describes the permissions required for lego to complete the DNS challenge.
-Replace `<INSERT_YOUR_HOSTED_ZONE_ID_HERE>` with the Route 53 zone ID of the domain you are authorizing.
-
-```json
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "route53:GetChange",
- "route53:ListHostedZonesByName"
- ],
- "Resource": [
- "*"
- ]
- },
- {
- "Effect": "Allow",
- "Action": [
- "route53:ChangeResourceRecordSets"
- ],
- "Resource": [
- "arn:aws:route53:::hostedzone/<INSERT_YOUR_HOSTED_ZONE_ID_HERE>"
- ]
- }
- ]
-}
-```
-
-#### ACME Library Usage
-
-A valid, but bare-bones example use of the acme package:
-
-```go
-// You'll need a user or account type that implements acme.User
-type MyUser struct {
- Email string
- Registration *acme.RegistrationResource
- key crypto.PrivateKey
-}
-func (u MyUser) GetEmail() string {
- return u.Email
-}
-func (u MyUser) GetRegistration() *acme.RegistrationResource {
- return u.Registration
-}
-func (u MyUser) GetPrivateKey() crypto.PrivateKey {
- return u.key
-}
-
-// Create a user. New accounts need an email and private key to start.
-const rsaKeySize = 2048
-privateKey, err := rsa.GenerateKey(rand.Reader, rsaKeySize)
-if err != nil {
- log.Fatal(err)
-}
-myUser := MyUser{
- Email: "you@yours.com",
- key: privateKey,
-}
-
-// A client facilitates communication with the CA server. This CA URL is
-// configured for a local dev instance of Boulder running in Docker in a VM.
-client, err := acme.NewClient("http://192.168.99.100:4000/directory", &myUser, acme.RSA2048)
-if err != nil {
- log.Fatal(err)
-}
-
-// We specify an http port of 5002 and an tls port of 5001 on all interfaces
-// because we aren't running as root and can't bind a listener to port 80 and 443
-// (used later when we attempt to pass challenges). Keep in mind that we still
-// need to proxy challenge traffic to port 5002 and 5001.
-client.SetHTTPAddress(":5002")
-client.SetTLSAddress(":5001")
-
-// New users will need to register
-reg, err := client.Register()
-if err != nil {
- log.Fatal(err)
-}
-myUser.Registration = reg
-
-// SAVE THE USER.
-
-// The client has a URL to the current Let's Encrypt Subscriber
-// Agreement. The user will need to agree to it.
-err = client.AgreeToTOS()
-if err != nil {
- log.Fatal(err)
-}
-
-// The acme library takes care of completing the challenges to obtain the certificate(s).
-// The domains must resolve to this machine or you have to use the DNS challenge.
-bundle := false
-certificates, failures := client.ObtainCertificate([]string{"mydomain.com"}, bundle, nil, false)
-if len(failures) > 0 {
- log.Fatal(failures)
-}
-
-// Each certificate comes back with the cert bytes, the bytes of the client's
-// private key, and a certificate URL. SAVE THESE TO DISK.
-fmt.Printf("%#v\n", certificates)
-
-// ... all done.
-```
diff --git a/vendor/github.com/xenolf/lego/account.go b/vendor/github.com/xenolf/lego/account.go
deleted file mode 100644
index 34856e16f..000000000
--- a/vendor/github.com/xenolf/lego/account.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package main
-
-import (
- "crypto"
- "encoding/json"
- "io/ioutil"
- "os"
- "path"
-
- "github.com/xenolf/lego/acme"
-)
-
-// Account represents a users local saved credentials
-type Account struct {
- Email string `json:"email"`
- key crypto.PrivateKey
- Registration *acme.RegistrationResource `json:"registration"`
-
- conf *Configuration
-}
-
-// NewAccount creates a new account for an email address
-func NewAccount(email string, conf *Configuration) *Account {
- accKeysPath := conf.AccountKeysPath(email)
- // TODO: move to function in configuration?
- accKeyPath := accKeysPath + string(os.PathSeparator) + email + ".key"
- if err := checkFolder(accKeysPath); err != nil {
- logger().Fatalf("Could not check/create directory for account %s: %v", email, err)
- }
-
- var privKey crypto.PrivateKey
- if _, err := os.Stat(accKeyPath); os.IsNotExist(err) {
-
- logger().Printf("No key found for account %s. Generating a curve P384 EC key.", email)
- privKey, err = generatePrivateKey(accKeyPath)
- if err != nil {
- logger().Fatalf("Could not generate RSA private account key for account %s: %v", email, err)
- }
-
- logger().Printf("Saved key to %s", accKeyPath)
- } else {
- privKey, err = loadPrivateKey(accKeyPath)
- if err != nil {
- logger().Fatalf("Could not load RSA private key from file %s: %v", accKeyPath, err)
- }
- }
-
- accountFile := path.Join(conf.AccountPath(email), "account.json")
- if _, err := os.Stat(accountFile); os.IsNotExist(err) {
- return &Account{Email: email, key: privKey, conf: conf}
- }
-
- fileBytes, err := ioutil.ReadFile(accountFile)
- if err != nil {
- logger().Fatalf("Could not load file for account %s -> %v", email, err)
- }
-
- var acc Account
- err = json.Unmarshal(fileBytes, &acc)
- if err != nil {
- logger().Fatalf("Could not parse file for account %s -> %v", email, err)
- }
-
- acc.key = privKey
- acc.conf = conf
-
- if acc.Registration == nil {
- logger().Fatalf("Could not load account for %s. Registration is nil.", email)
- }
-
- if acc.conf == nil {
- logger().Fatalf("Could not load account for %s. Configuration is nil.", email)
- }
-
- return &acc
-}
-
-/** Implementation of the acme.User interface **/
-
-// GetEmail returns the email address for the account
-func (a *Account) GetEmail() string {
- return a.Email
-}
-
-// GetPrivateKey returns the private RSA account key.
-func (a *Account) GetPrivateKey() crypto.PrivateKey {
- return a.key
-}
-
-// GetRegistration returns the server registration
-func (a *Account) GetRegistration() *acme.RegistrationResource {
- return a.Registration
-}
-
-/** End **/
-
-// Save the account to disk
-func (a *Account) Save() error {
- jsonBytes, err := json.MarshalIndent(a, "", "\t")
- if err != nil {
- return err
- }
-
- return ioutil.WriteFile(
- path.Join(a.conf.AccountPath(a.Email), "account.json"),
- jsonBytes,
- 0600,
- )
-}
diff --git a/vendor/github.com/xenolf/lego/acme/challenges.go b/vendor/github.com/xenolf/lego/acme/challenges.go
deleted file mode 100644
index 857900507..000000000
--- a/vendor/github.com/xenolf/lego/acme/challenges.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package acme
-
-// Challenge is a string that identifies a particular type and version of ACME challenge.
-type Challenge string
-
-const (
- // HTTP01 is the "http-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http
- // Note: HTTP01ChallengePath returns the URL path to fulfill this challenge
- HTTP01 = Challenge("http-01")
- // TLSSNI01 is the "tls-sni-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni
- // Note: TLSSNI01ChallengeCert returns a certificate to fulfill this challenge
- TLSSNI01 = Challenge("tls-sni-01")
- // DNS01 is the "dns-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#dns
- // Note: DNS01Record returns a DNS record which will fulfill this challenge
- DNS01 = Challenge("dns-01")
-)
diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go
deleted file mode 100644
index bcb844371..000000000
--- a/vendor/github.com/xenolf/lego/acme/client.go
+++ /dev/null
@@ -1,825 +0,0 @@
-// Package acme implements the ACME protocol for Let's Encrypt and other conforming providers.
-package acme
-
-import (
- "crypto"
- "crypto/x509"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "log"
- "net"
- "net/http"
- "regexp"
- "strconv"
- "strings"
- "time"
-)
-
-var (
- // Logger is an optional custom logger.
- Logger *log.Logger
-)
-
-const (
- // maxBodySize is the maximum size of body that we will read.
- maxBodySize = 1024 * 1024
-
- // overallRequestLimit is the overall number of request per second limited on the
- // “new-reg”, “new-authz” and “new-cert” endpoints. From the documentation the
- // limitation is 20 requests per second, but using 20 as value doesn't work but 18 do
- overallRequestLimit = 18
-)
-
-// logf writes a log entry. It uses Logger if not
-// nil, otherwise it uses the default log.Logger.
-func logf(format string, args ...interface{}) {
- if Logger != nil {
- Logger.Printf(format, args...)
- } else {
- log.Printf(format, args...)
- }
-}
-
-// User interface is to be implemented by users of this library.
-// It is used by the client type to get user specific information.
-type User interface {
- GetEmail() string
- GetRegistration() *RegistrationResource
- GetPrivateKey() crypto.PrivateKey
-}
-
-// Interface for all challenge solvers to implement.
-type solver interface {
- Solve(challenge challenge, domain string) error
-}
-
-type validateFunc func(j *jws, domain, uri string, chlng challenge) error
-
-// Client is the user-friendy way to ACME
-type Client struct {
- directory directory
- user User
- jws *jws
- keyType KeyType
- solvers map[Challenge]solver
-}
-
-// NewClient creates a new ACME client on behalf of the user. The client will depend on
-// the ACME directory located at caDirURL for the rest of its actions. A private
-// key of type keyType (see KeyType contants) will be generated when requesting a new
-// certificate if one isn't provided.
-func NewClient(caDirURL string, user User, keyType KeyType) (*Client, error) {
- privKey := user.GetPrivateKey()
- if privKey == nil {
- return nil, errors.New("private key was nil")
- }
-
- var dir directory
- if _, err := getJSON(caDirURL, &dir); err != nil {
- return nil, fmt.Errorf("get directory at '%s': %v", caDirURL, err)
- }
-
- if dir.NewRegURL == "" {
- return nil, errors.New("directory missing new registration URL")
- }
- if dir.NewAuthzURL == "" {
- return nil, errors.New("directory missing new authz URL")
- }
- if dir.NewCertURL == "" {
- return nil, errors.New("directory missing new certificate URL")
- }
- if dir.RevokeCertURL == "" {
- return nil, errors.New("directory missing revoke certificate URL")
- }
-
- jws := &jws{privKey: privKey, directoryURL: caDirURL}
-
- // REVIEW: best possibility?
- // Add all available solvers with the right index as per ACME
- // spec to this map. Otherwise they won`t be found.
- solvers := make(map[Challenge]solver)
- solvers[HTTP01] = &httpChallenge{jws: jws, validate: validate, provider: &HTTPProviderServer{}}
- solvers[TLSSNI01] = &tlsSNIChallenge{jws: jws, validate: validate, provider: &TLSProviderServer{}}
-
- return &Client{directory: dir, user: user, jws: jws, keyType: keyType, solvers: solvers}, nil
-}
-
-// SetChallengeProvider specifies a custom provider p that can solve the given challenge type.
-func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider) error {
- switch challenge {
- case HTTP01:
- c.solvers[challenge] = &httpChallenge{jws: c.jws, validate: validate, provider: p}
- case TLSSNI01:
- c.solvers[challenge] = &tlsSNIChallenge{jws: c.jws, validate: validate, provider: p}
- case DNS01:
- c.solvers[challenge] = &dnsChallenge{jws: c.jws, validate: validate, provider: p}
- default:
- return fmt.Errorf("Unknown challenge %v", challenge)
- }
- return nil
-}
-
-// SetHTTPAddress specifies a custom interface:port to be used for HTTP based challenges.
-// If this option is not used, the default port 80 and all interfaces will be used.
-// To only specify a port and no interface use the ":port" notation.
-//
-// NOTE: This REPLACES any custom HTTP provider previously set by calling
-// c.SetChallengeProvider with the default HTTP challenge provider.
-func (c *Client) SetHTTPAddress(iface string) error {
- host, port, err := net.SplitHostPort(iface)
- if err != nil {
- return err
- }
-
- if chlng, ok := c.solvers[HTTP01]; ok {
- chlng.(*httpChallenge).provider = NewHTTPProviderServer(host, port)
- }
-
- return nil
-}
-
-// SetTLSAddress specifies a custom interface:port to be used for TLS based challenges.
-// If this option is not used, the default port 443 and all interfaces will be used.
-// To only specify a port and no interface use the ":port" notation.
-//
-// NOTE: This REPLACES any custom TLS-SNI provider previously set by calling
-// c.SetChallengeProvider with the default TLS-SNI challenge provider.
-func (c *Client) SetTLSAddress(iface string) error {
- host, port, err := net.SplitHostPort(iface)
- if err != nil {
- return err
- }
-
- if chlng, ok := c.solvers[TLSSNI01]; ok {
- chlng.(*tlsSNIChallenge).provider = NewTLSProviderServer(host, port)
- }
- return nil
-}
-
-// ExcludeChallenges explicitly removes challenges from the pool for solving.
-func (c *Client) ExcludeChallenges(challenges []Challenge) {
- // Loop through all challenges and delete the requested one if found.
- for _, challenge := range challenges {
- delete(c.solvers, challenge)
- }
-}
-
-// Register the current account to the ACME server.
-func (c *Client) Register() (*RegistrationResource, error) {
- if c == nil || c.user == nil {
- return nil, errors.New("acme: cannot register a nil client or user")
- }
- logf("[INFO] acme: Registering account for %s", c.user.GetEmail())
-
- regMsg := registrationMessage{
- Resource: "new-reg",
- }
- if c.user.GetEmail() != "" {
- regMsg.Contact = []string{"mailto:" + c.user.GetEmail()}
- } else {
- regMsg.Contact = []string{}
- }
-
- var serverReg Registration
- var regURI string
- hdr, err := postJSON(c.jws, c.directory.NewRegURL, regMsg, &serverReg)
- if err != nil {
- remoteErr, ok := err.(RemoteError)
- if ok && remoteErr.StatusCode == 409 {
- regURI = hdr.Get("Location")
- regMsg = registrationMessage{
- Resource: "reg",
- }
- if hdr, err = postJSON(c.jws, regURI, regMsg, &serverReg); err != nil {
- return nil, err
- }
- } else {
- return nil, err
- }
- }
-
- reg := &RegistrationResource{Body: serverReg}
-
- links := parseLinks(hdr["Link"])
-
- if regURI == "" {
- regURI = hdr.Get("Location")
- }
- reg.URI = regURI
- if links["terms-of-service"] != "" {
- reg.TosURL = links["terms-of-service"]
- }
-
- if links["next"] != "" {
- reg.NewAuthzURL = links["next"]
- } else {
- return nil, errors.New("acme: The server did not return 'next' link to proceed")
- }
-
- return reg, nil
-}
-
-// DeleteRegistration deletes the client's user registration from the ACME
-// server.
-func (c *Client) DeleteRegistration() error {
- if c == nil || c.user == nil {
- return errors.New("acme: cannot unregister a nil client or user")
- }
- logf("[INFO] acme: Deleting account for %s", c.user.GetEmail())
-
- regMsg := registrationMessage{
- Resource: "reg",
- Delete: true,
- }
-
- _, err := postJSON(c.jws, c.user.GetRegistration().URI, regMsg, nil)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// QueryRegistration runs a POST request on the client's registration and
-// returns the result.
-//
-// This is similar to the Register function, but acting on an existing
-// registration link and resource.
-func (c *Client) QueryRegistration() (*RegistrationResource, error) {
- if c == nil || c.user == nil {
- return nil, errors.New("acme: cannot query the registration of a nil client or user")
- }
- // Log the URL here instead of the email as the email may not be set
- logf("[INFO] acme: Querying account for %s", c.user.GetRegistration().URI)
-
- regMsg := registrationMessage{
- Resource: "reg",
- }
-
- var serverReg Registration
- hdr, err := postJSON(c.jws, c.user.GetRegistration().URI, regMsg, &serverReg)
- if err != nil {
- return nil, err
- }
-
- reg := &RegistrationResource{Body: serverReg}
-
- links := parseLinks(hdr["Link"])
- // Location: header is not returned so this needs to be populated off of
- // existing URI
- reg.URI = c.user.GetRegistration().URI
- if links["terms-of-service"] != "" {
- reg.TosURL = links["terms-of-service"]
- }
-
- if links["next"] != "" {
- reg.NewAuthzURL = links["next"]
- } else {
- return nil, errors.New("acme: No new-authz link in response to registration query")
- }
-
- return reg, nil
-}
-
-// AgreeToTOS updates the Client registration and sends the agreement to
-// the server.
-func (c *Client) AgreeToTOS() error {
- reg := c.user.GetRegistration()
-
- reg.Body.Agreement = c.user.GetRegistration().TosURL
- reg.Body.Resource = "reg"
- _, err := postJSON(c.jws, c.user.GetRegistration().URI, c.user.GetRegistration().Body, nil)
- return err
-}
-
-// ObtainCertificateForCSR tries to obtain a certificate matching the CSR passed into it.
-// The domains are inferred from the CommonName and SubjectAltNames, if any. The private key
-// for this CSR is not required.
-// If bundle is true, the []byte contains both the issuer certificate and
-// your issued certificate as a bundle.
-// This function will never return a partial certificate. If one domain in the list fails,
-// the whole certificate will fail.
-func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, map[string]error) {
- // figure out what domains it concerns
- // start with the common name
- domains := []string{csr.Subject.CommonName}
-
- // loop over the SubjectAltName DNS names
-DNSNames:
- for _, sanName := range csr.DNSNames {
- for _, existingName := range domains {
- if existingName == sanName {
- // duplicate; skip this name
- continue DNSNames
- }
- }
-
- // name is unique
- domains = append(domains, sanName)
- }
-
- if bundle {
- logf("[INFO][%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
- } else {
- logf("[INFO][%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
- }
-
- challenges, failures := c.getChallenges(domains)
- // If any challenge fails - return. Do not generate partial SAN certificates.
- if len(failures) > 0 {
- for _, auth := range challenges {
- c.disableAuthz(auth)
- }
-
- return CertificateResource{}, failures
- }
-
- errs := c.solveChallenges(challenges)
- // If any challenge fails - return. Do not generate partial SAN certificates.
- if len(errs) > 0 {
- return CertificateResource{}, errs
- }
-
- logf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
-
- cert, err := c.requestCertificateForCsr(challenges, bundle, csr.Raw, nil)
- if err != nil {
- for _, chln := range challenges {
- failures[chln.Domain] = err
- }
- }
-
- // Add the CSR to the certificate so that it can be used for renewals.
- cert.CSR = pemEncode(&csr)
-
- return cert, failures
-}
-
-// ObtainCertificate tries to obtain a single certificate using all domains passed into it.
-// The first domain in domains is used for the CommonName field of the certificate, all other
-// domains are added using the Subject Alternate Names extension. A new private key is generated
-// for every invocation of this function. If you do not want that you can supply your own private key
-// in the privKey parameter. If this parameter is non-nil it will be used instead of generating a new one.
-// If bundle is true, the []byte contains both the issuer certificate and
-// your issued certificate as a bundle.
-// This function will never return a partial certificate. If one domain in the list fails,
-// the whole certificate will fail.
-func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, map[string]error) {
- if bundle {
- logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
- } else {
- logf("[INFO][%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
- }
-
- challenges, failures := c.getChallenges(domains)
- // If any challenge fails - return. Do not generate partial SAN certificates.
- if len(failures) > 0 {
- for _, auth := range challenges {
- c.disableAuthz(auth)
- }
-
- return CertificateResource{}, failures
- }
-
- errs := c.solveChallenges(challenges)
- // If any challenge fails - return. Do not generate partial SAN certificates.
- if len(errs) > 0 {
- return CertificateResource{}, errs
- }
-
- logf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
-
- cert, err := c.requestCertificate(challenges, bundle, privKey, mustStaple)
- if err != nil {
- for _, chln := range challenges {
- failures[chln.Domain] = err
- }
- }
-
- return cert, failures
-}
-
-// RevokeCertificate takes a PEM encoded certificate or bundle and tries to revoke it at the CA.
-func (c *Client) RevokeCertificate(certificate []byte) error {
- certificates, err := parsePEMBundle(certificate)
- if err != nil {
- return err
- }
-
- x509Cert := certificates[0]
- if x509Cert.IsCA {
- return fmt.Errorf("Certificate bundle starts with a CA certificate")
- }
-
- encodedCert := base64.URLEncoding.EncodeToString(x509Cert.Raw)
-
- _, err = postJSON(c.jws, c.directory.RevokeCertURL, revokeCertMessage{Resource: "revoke-cert", Certificate: encodedCert}, nil)
- return err
-}
-
-// RenewCertificate takes a CertificateResource and tries to renew the certificate.
-// If the renewal process succeeds, the new certificate will ge returned in a new CertResource.
-// Please be aware that this function will return a new certificate in ANY case that is not an error.
-// If the server does not provide us with a new cert on a GET request to the CertURL
-// this function will start a new-cert flow where a new certificate gets generated.
-// If bundle is true, the []byte contains both the issuer certificate and
-// your issued certificate as a bundle.
-// For private key reuse the PrivateKey property of the passed in CertificateResource should be non-nil.
-func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple bool) (CertificateResource, error) {
- // Input certificate is PEM encoded. Decode it here as we may need the decoded
- // cert later on in the renewal process. The input may be a bundle or a single certificate.
- certificates, err := parsePEMBundle(cert.Certificate)
- if err != nil {
- return CertificateResource{}, err
- }
-
- x509Cert := certificates[0]
- if x509Cert.IsCA {
- return CertificateResource{}, fmt.Errorf("[%s] Certificate bundle starts with a CA certificate", cert.Domain)
- }
-
- // This is just meant to be informal for the user.
- timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
- logf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
-
- // We always need to request a new certificate to renew.
- // Start by checking to see if the certificate was based off a CSR, and
- // use that if it's defined.
- if len(cert.CSR) > 0 {
- csr, err := pemDecodeTox509CSR(cert.CSR)
- if err != nil {
- return CertificateResource{}, err
- }
- newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
- return newCert, failures[cert.Domain]
- }
-
- var privKey crypto.PrivateKey
- if cert.PrivateKey != nil {
- privKey, err = parsePEMPrivateKey(cert.PrivateKey)
- if err != nil {
- return CertificateResource{}, err
- }
- }
-
- var domains []string
- var failures map[string]error
- // check for SAN certificate
- if len(x509Cert.DNSNames) > 1 {
- domains = append(domains, x509Cert.Subject.CommonName)
- for _, sanDomain := range x509Cert.DNSNames {
- if sanDomain == x509Cert.Subject.CommonName {
- continue
- }
- domains = append(domains, sanDomain)
- }
- } else {
- domains = append(domains, x509Cert.Subject.CommonName)
- }
-
- newCert, failures := c.ObtainCertificate(domains, bundle, privKey, mustStaple)
- return newCert, failures[cert.Domain]
-}
-
-// Looks through the challenge combinations to find a solvable match.
-// Then solves the challenges in series and returns.
-func (c *Client) solveChallenges(challenges []authorizationResource) map[string]error {
- // loop through the resources, basically through the domains.
- failures := make(map[string]error)
- for _, authz := range challenges {
- if authz.Body.Status == "valid" {
- // Boulder might recycle recent validated authz (see issue #267)
- logf("[INFO][%s] acme: Authorization already valid; skipping challenge", authz.Domain)
- continue
- }
- // no solvers - no solving
- if solvers := c.chooseSolvers(authz.Body, authz.Domain); solvers != nil {
- for i, solver := range solvers {
- // TODO: do not immediately fail if one domain fails to validate.
- err := solver.Solve(authz.Body.Challenges[i], authz.Domain)
- if err != nil {
- c.disableAuthz(authz)
- failures[authz.Domain] = err
- }
- }
- } else {
- c.disableAuthz(authz)
- failures[authz.Domain] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Domain)
- }
- }
-
- return failures
-}
-
-// Checks all combinations from the server and returns an array of
-// solvers which should get executed in series.
-func (c *Client) chooseSolvers(auth authorization, domain string) map[int]solver {
- for _, combination := range auth.Combinations {
- solvers := make(map[int]solver)
- for _, idx := range combination {
- if solver, ok := c.solvers[auth.Challenges[idx].Type]; ok {
- solvers[idx] = solver
- } else {
- logf("[INFO][%s] acme: Could not find solver for: %s", domain, auth.Challenges[idx].Type)
- }
- }
-
- // If we can solve the whole combination, return the solvers
- if len(solvers) == len(combination) {
- return solvers
- }
- }
- return nil
-}
-
-// Get the challenges needed to proof our identifier to the ACME server.
-func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[string]error) {
- resc, errc := make(chan authorizationResource), make(chan domainError)
-
- delay := time.Second / overallRequestLimit
-
- for _, domain := range domains {
- time.Sleep(delay)
-
- go func(domain string) {
- authMsg := authorization{Resource: "new-authz", Identifier: identifier{Type: "dns", Value: domain}}
- var authz authorization
- hdr, err := postJSON(c.jws, c.user.GetRegistration().NewAuthzURL, authMsg, &authz)
- if err != nil {
- errc <- domainError{Domain: domain, Error: err}
- return
- }
-
- links := parseLinks(hdr["Link"])
- if links["next"] == "" {
- logf("[ERROR][%s] acme: Server did not provide next link to proceed", domain)
- errc <- domainError{Domain: domain, Error: errors.New("Server did not provide next link to proceed")}
- return
- }
-
- resc <- authorizationResource{Body: authz, NewCertURL: links["next"], AuthURL: hdr.Get("Location"), Domain: domain}
- }(domain)
- }
-
- responses := make(map[string]authorizationResource)
- failures := make(map[string]error)
- for i := 0; i < len(domains); i++ {
- select {
- case res := <-resc:
- responses[res.Domain] = res
- case err := <-errc:
- failures[err.Domain] = err.Error
- }
- }
-
- challenges := make([]authorizationResource, 0, len(responses))
- for _, domain := range domains {
- if challenge, ok := responses[domain]; ok {
- challenges = append(challenges, challenge)
- }
- }
-
- logAuthz(challenges)
-
- close(resc)
- close(errc)
-
- return challenges, failures
-}
-
-func logAuthz(authz []authorizationResource) {
- for _, auth := range authz {
- logf("[INFO][%s] AuthURL: %s", auth.Domain, auth.AuthURL)
- }
-}
-
-// cleanAuthz loops through the passed in slice and disables any auths which are not "valid"
-func (c *Client) disableAuthz(auth authorizationResource) error {
- var disabledAuth authorization
- _, err := postJSON(c.jws, auth.AuthURL, deactivateAuthMessage{Resource: "authz", Status: "deactivated"}, &disabledAuth)
- return err
-}
-
-func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) {
- if len(authz) == 0 {
- return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!")
- }
-
- var err error
- if privKey == nil {
- privKey, err = generatePrivateKey(c.keyType)
- if err != nil {
- return CertificateResource{}, err
- }
- }
-
- // determine certificate name(s) based on the authorization resources
- commonName := authz[0]
- var san []string
- for _, auth := range authz[1:] {
- san = append(san, auth.Domain)
- }
-
- // TODO: should the CSR be customizable?
- csr, err := generateCsr(privKey, commonName.Domain, san, mustStaple)
- if err != nil {
- return CertificateResource{}, err
- }
-
- return c.requestCertificateForCsr(authz, bundle, csr, pemEncode(privKey))
-}
-
-func (c *Client) requestCertificateForCsr(authz []authorizationResource, bundle bool, csr []byte, privateKeyPem []byte) (CertificateResource, error) {
- commonName := authz[0]
-
- var authURLs []string
- for _, auth := range authz[1:] {
- authURLs = append(authURLs, auth.AuthURL)
- }
-
- csrString := base64.URLEncoding.EncodeToString(csr)
- jsonBytes, err := json.Marshal(csrMessage{Resource: "new-cert", Csr: csrString, Authorizations: authURLs})
- if err != nil {
- return CertificateResource{}, err
- }
-
- resp, err := c.jws.post(commonName.NewCertURL, jsonBytes)
- if err != nil {
- return CertificateResource{}, err
- }
-
- certRes := CertificateResource{
- Domain: commonName.Domain,
- CertURL: resp.Header.Get("Location"),
- PrivateKey: privateKeyPem,
- }
-
- maxChecks := 1000
- for i := 0; i < maxChecks; i++ {
- done, err := c.checkCertResponse(resp, &certRes, bundle)
- resp.Body.Close()
- if err != nil {
- return CertificateResource{}, err
- }
- if done {
- break
- }
- if i == maxChecks-1 {
- return CertificateResource{}, fmt.Errorf("polled for certificate %d times; giving up", i)
- }
- resp, err = httpGet(certRes.CertURL)
- if err != nil {
- return CertificateResource{}, err
- }
- }
-
- return certRes, nil
-}
-
-// checkCertResponse checks resp to see if a certificate is contained in the
-// response, and if so, loads it into certRes and returns true. If the cert
-// is not yet ready, it returns false. This function honors the waiting period
-// required by the Retry-After header of the response, if specified. This
-// function may read from resp.Body but does NOT close it. The certRes input
-// should already have the Domain (common name) field populated. If bundle is
-// true, the certificate will be bundled with the issuer's cert.
-func (c *Client) checkCertResponse(resp *http.Response, certRes *CertificateResource, bundle bool) (bool, error) {
- switch resp.StatusCode {
- case 201, 202:
- cert, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize))
- if err != nil {
- return false, err
- }
-
- // The server returns a body with a length of zero if the
- // certificate was not ready at the time this request completed.
- // Otherwise the body is the certificate.
- if len(cert) > 0 {
- certRes.CertStableURL = resp.Header.Get("Content-Location")
- certRes.AccountRef = c.user.GetRegistration().URI
-
- issuedCert := pemEncode(derCertificateBytes(cert))
-
- // The issuer certificate link is always supplied via an "up" link
- // in the response headers of a new certificate.
- links := parseLinks(resp.Header["Link"])
- issuerCert, err := c.getIssuerCertificate(links["up"])
- if err != nil {
- // If we fail to acquire the issuer cert, return the issued certificate - do not fail.
- logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
- } else {
- issuerCert = pemEncode(derCertificateBytes(issuerCert))
-
- // If bundle is true, we want to return a certificate bundle.
- // To do this, we append the issuer cert to the issued cert.
- if bundle {
- issuedCert = append(issuedCert, issuerCert...)
- }
- }
-
- certRes.Certificate = issuedCert
- certRes.IssuerCertificate = issuerCert
- logf("[INFO][%s] Server responded with a certificate.", certRes.Domain)
- return true, nil
- }
-
- // The certificate was granted but is not yet issued.
- // Check retry-after and loop.
- ra := resp.Header.Get("Retry-After")
- retryAfter, err := strconv.Atoi(ra)
- if err != nil {
- return false, err
- }
-
- logf("[INFO][%s] acme: Server responded with status 202; retrying after %ds", certRes.Domain, retryAfter)
- time.Sleep(time.Duration(retryAfter) * time.Second)
-
- return false, nil
- default:
- return false, handleHTTPError(resp)
- }
-}
-
-// getIssuerCertificate requests the issuer certificate
-func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
- logf("[INFO] acme: Requesting issuer cert from %s", url)
- resp, err := httpGet(url)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize))
- if err != nil {
- return nil, err
- }
-
- _, err = x509.ParseCertificate(issuerBytes)
- if err != nil {
- return nil, err
- }
-
- return issuerBytes, err
-}
-
-func parseLinks(links []string) map[string]string {
- aBrkt := regexp.MustCompile("[<>]")
- slver := regexp.MustCompile("(.+) *= *\"(.+)\"")
- linkMap := make(map[string]string)
-
- for _, link := range links {
-
- link = aBrkt.ReplaceAllString(link, "")
- parts := strings.Split(link, ";")
-
- matches := slver.FindStringSubmatch(parts[1])
- if len(matches) > 0 {
- linkMap[matches[2]] = parts[0]
- }
- }
-
- return linkMap
-}
-
-// validate makes the ACME server start validating a
-// challenge response, only returning once it is done.
-func validate(j *jws, domain, uri string, chlng challenge) error {
- var challengeResponse challenge
-
- hdr, err := postJSON(j, uri, chlng, &challengeResponse)
- if err != nil {
- return err
- }
-
- // After the path is sent, the ACME server will access our server.
- // Repeatedly check the server for an updated status on our request.
- for {
- switch challengeResponse.Status {
- case "valid":
- logf("[INFO][%s] The server validated our request", domain)
- return nil
- case "pending":
- break
- case "invalid":
- return handleChallengeError(challengeResponse)
- default:
- return errors.New("The server returned an unexpected state.")
- }
-
- ra, err := strconv.Atoi(hdr.Get("Retry-After"))
- if err != nil {
- // The ACME server MUST return a Retry-After.
- // If it doesn't, we'll just poll hard.
- ra = 1
- }
- time.Sleep(time.Duration(ra) * time.Second)
-
- hdr, err = getJSON(uri, &challengeResponse)
- if err != nil {
- return err
- }
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/client_test.go b/vendor/github.com/xenolf/lego/acme/client_test.go
deleted file mode 100644
index b18334c8a..000000000
--- a/vendor/github.com/xenolf/lego/acme/client_test.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package acme
-
-import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "encoding/json"
- "net"
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
- "time"
-)
-
-func TestNewClient(t *testing.T) {
- keyBits := 32 // small value keeps test fast
- keyType := RSA2048
- key, err := rsa.GenerateKey(rand.Reader, keyBits)
- if err != nil {
- t.Fatal("Could not generate test key:", err)
- }
- user := mockUser{
- email: "test@test.com",
- regres: new(RegistrationResource),
- privatekey: key,
- }
-
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- data, _ := json.Marshal(directory{NewAuthzURL: "http://test", NewCertURL: "http://test", NewRegURL: "http://test", RevokeCertURL: "http://test"})
- w.Write(data)
- }))
-
- client, err := NewClient(ts.URL, user, keyType)
- if err != nil {
- t.Fatalf("Could not create client: %v", err)
- }
-
- if client.jws == nil {
- t.Fatalf("Expected client.jws to not be nil")
- }
- if expected, actual := key, client.jws.privKey; actual != expected {
- t.Errorf("Expected jws.privKey to be %p but was %p", expected, actual)
- }
-
- if client.keyType != keyType {
- t.Errorf("Expected keyType to be %s but was %s", keyType, client.keyType)
- }
-
- if expected, actual := 2, len(client.solvers); actual != expected {
- t.Fatalf("Expected %d solver(s), got %d", expected, actual)
- }
-}
-
-func TestClientOptPort(t *testing.T) {
- keyBits := 32 // small value keeps test fast
- key, err := rsa.GenerateKey(rand.Reader, keyBits)
- if err != nil {
- t.Fatal("Could not generate test key:", err)
- }
- user := mockUser{
- email: "test@test.com",
- regres: new(RegistrationResource),
- privatekey: key,
- }
-
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- data, _ := json.Marshal(directory{NewAuthzURL: "http://test", NewCertURL: "http://test", NewRegURL: "http://test", RevokeCertURL: "http://test"})
- w.Write(data)
- }))
-
- optPort := "1234"
- optHost := ""
- client, err := NewClient(ts.URL, user, RSA2048)
- if err != nil {
- t.Fatalf("Could not create client: %v", err)
- }
- client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
- client.SetTLSAddress(net.JoinHostPort(optHost, optPort))
-
- httpSolver, ok := client.solvers[HTTP01].(*httpChallenge)
- if !ok {
- t.Fatal("Expected http-01 solver to be httpChallenge type")
- }
- if httpSolver.jws != client.jws {
- t.Error("Expected http-01 to have same jws as client")
- }
- if got := httpSolver.provider.(*HTTPProviderServer).port; got != optPort {
- t.Errorf("Expected http-01 to have port %s but was %s", optPort, got)
- }
- if got := httpSolver.provider.(*HTTPProviderServer).iface; got != optHost {
- t.Errorf("Expected http-01 to have iface %s but was %s", optHost, got)
- }
-
- httpsSolver, ok := client.solvers[TLSSNI01].(*tlsSNIChallenge)
- if !ok {
- t.Fatal("Expected tls-sni-01 solver to be httpChallenge type")
- }
- if httpsSolver.jws != client.jws {
- t.Error("Expected tls-sni-01 to have same jws as client")
- }
- if got := httpsSolver.provider.(*TLSProviderServer).port; got != optPort {
- t.Errorf("Expected tls-sni-01 to have port %s but was %s", optPort, got)
- }
- if got := httpsSolver.provider.(*TLSProviderServer).iface; got != optHost {
- t.Errorf("Expected tls-sni-01 to have port %s but was %s", optHost, got)
- }
-
- // test setting different host
- optHost = "127.0.0.1"
- client.SetHTTPAddress(net.JoinHostPort(optHost, optPort))
- client.SetTLSAddress(net.JoinHostPort(optHost, optPort))
-
- if got := httpSolver.provider.(*HTTPProviderServer).iface; got != optHost {
- t.Errorf("Expected http-01 to have iface %s but was %s", optHost, got)
- }
- if got := httpsSolver.provider.(*TLSProviderServer).port; got != optPort {
- t.Errorf("Expected tls-sni-01 to have port %s but was %s", optPort, got)
- }
-}
-
-func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) {
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- time.Sleep(250 * time.Millisecond)
- w.Header().Add("Replay-Nonce", "12345")
- w.Header().Add("Retry-After", "0")
- writeJSONResponse(w, &challenge{Type: "http-01", Status: "Valid", URI: "http://example.com/", Token: "token"})
- }))
- defer ts.Close()
-
- privKey, _ := rsa.GenerateKey(rand.Reader, 512)
- j := &jws{privKey: privKey, directoryURL: ts.URL}
- ch := make(chan bool)
- resultCh := make(chan bool)
- go func() {
- j.Nonce()
- ch <- true
- }()
- go func() {
- j.Nonce()
- ch <- true
- }()
- go func() {
- <-ch
- <-ch
- resultCh <- true
- }()
- select {
- case <-resultCh:
- case <-time.After(400 * time.Millisecond):
- t.Fatal("JWS is probably holding a lock while making HTTP request")
- }
-}
-
-func TestValidate(t *testing.T) {
- var statuses []string
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // Minimal stub ACME server for validation.
- w.Header().Add("Replay-Nonce", "12345")
- w.Header().Add("Retry-After", "0")
- switch r.Method {
- case "HEAD":
- case "POST":
- st := statuses[0]
- statuses = statuses[1:]
- writeJSONResponse(w, &challenge{Type: "http-01", Status: st, URI: "http://example.com/", Token: "token"})
-
- case "GET":
- st := statuses[0]
- statuses = statuses[1:]
- writeJSONResponse(w, &challenge{Type: "http-01", Status: st, URI: "http://example.com/", Token: "token"})
-
- default:
- http.Error(w, r.Method, http.StatusMethodNotAllowed)
- }
- }))
- defer ts.Close()
-
- privKey, _ := rsa.GenerateKey(rand.Reader, 512)
- j := &jws{privKey: privKey, directoryURL: ts.URL}
-
- tsts := []struct {
- name string
- statuses []string
- want string
- }{
- {"POST-unexpected", []string{"weird"}, "unexpected"},
- {"POST-valid", []string{"valid"}, ""},
- {"POST-invalid", []string{"invalid"}, "Error Detail"},
- {"GET-unexpected", []string{"pending", "weird"}, "unexpected"},
- {"GET-valid", []string{"pending", "valid"}, ""},
- {"GET-invalid", []string{"pending", "invalid"}, "Error Detail"},
- }
-
- for _, tst := range tsts {
- statuses = tst.statuses
- if err := validate(j, "example.com", ts.URL, challenge{Type: "http-01", Token: "token"}); err == nil && tst.want != "" {
- t.Errorf("[%s] validate: got error %v, want something with %q", tst.name, err, tst.want)
- } else if err != nil && !strings.Contains(err.Error(), tst.want) {
- t.Errorf("[%s] validate: got error %v, want something with %q", tst.name, err, tst.want)
- }
- }
-}
-
-func TestGetChallenges(t *testing.T) {
- var ts *httptest.Server
- ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- switch r.Method {
- case "GET", "HEAD":
- w.Header().Add("Replay-Nonce", "12345")
- w.Header().Add("Retry-After", "0")
- writeJSONResponse(w, directory{NewAuthzURL: ts.URL, NewCertURL: ts.URL, NewRegURL: ts.URL, RevokeCertURL: ts.URL})
- case "POST":
- writeJSONResponse(w, authorization{})
- }
- }))
- defer ts.Close()
-
- keyBits := 512 // small value keeps test fast
- keyType := RSA2048
- key, err := rsa.GenerateKey(rand.Reader, keyBits)
- if err != nil {
- t.Fatal("Could not generate test key:", err)
- }
- user := mockUser{
- email: "test@test.com",
- regres: &RegistrationResource{NewAuthzURL: ts.URL},
- privatekey: key,
- }
-
- client, err := NewClient(ts.URL, user, keyType)
- if err != nil {
- t.Fatalf("Could not create client: %v", err)
- }
-
- _, failures := client.getChallenges([]string{"example.com"})
- if failures["example.com"] == nil {
- t.Fatal("Expecting \"Server did not provide next link to proceed\" error, got nil")
- }
-}
-
-// writeJSONResponse marshals the body as JSON and writes it to the response.
-func writeJSONResponse(w http.ResponseWriter, body interface{}) {
- bs, err := json.Marshal(body)
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- if _, err := w.Write(bs); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
-}
-
-// stubValidate is like validate, except it does nothing.
-func stubValidate(j *jws, domain, uri string, chlng challenge) error {
- return nil
-}
-
-type mockUser struct {
- email string
- regres *RegistrationResource
- privatekey *rsa.PrivateKey
-}
-
-func (u mockUser) GetEmail() string { return u.email }
-func (u mockUser) GetRegistration() *RegistrationResource { return u.regres }
-func (u mockUser) GetPrivateKey() crypto.PrivateKey { return u.privatekey }
diff --git a/vendor/github.com/xenolf/lego/acme/crypto.go b/vendor/github.com/xenolf/lego/acme/crypto.go
deleted file mode 100644
index fa868a90d..000000000
--- a/vendor/github.com/xenolf/lego/acme/crypto.go
+++ /dev/null
@@ -1,347 +0,0 @@
-package acme
-
-import (
- "bytes"
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/rsa"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/base64"
- "encoding/pem"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "math/big"
- "net/http"
- "strings"
- "time"
-
- "encoding/asn1"
-
- "golang.org/x/crypto/ocsp"
-)
-
-// KeyType represents the key algo as well as the key size or curve to use.
-type KeyType string
-type derCertificateBytes []byte
-
-// Constants for all key types we support.
-const (
- EC256 = KeyType("P256")
- EC384 = KeyType("P384")
- RSA2048 = KeyType("2048")
- RSA4096 = KeyType("4096")
- RSA8192 = KeyType("8192")
-)
-
-const (
- // OCSPGood means that the certificate is valid.
- OCSPGood = ocsp.Good
- // OCSPRevoked means that the certificate has been deliberately revoked.
- OCSPRevoked = ocsp.Revoked
- // OCSPUnknown means that the OCSP responder doesn't know about the certificate.
- OCSPUnknown = ocsp.Unknown
- // OCSPServerFailed means that the OCSP responder failed to process the request.
- OCSPServerFailed = ocsp.ServerFailed
-)
-
-// Constants for OCSP must staple
-var (
- tlsFeatureExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
- ocspMustStapleFeature = []byte{0x30, 0x03, 0x02, 0x01, 0x05}
-)
-
-// GetOCSPForCert takes a PEM encoded cert or cert bundle returning the raw OCSP response,
-// the parsed response, and an error, if any. The returned []byte can be passed directly
-// into the OCSPStaple property of a tls.Certificate. If the bundle only contains the
-// issued certificate, this function will try to get the issuer certificate from the
-// IssuingCertificateURL in the certificate. If the []byte and/or ocsp.Response return
-// values are nil, the OCSP status may be assumed OCSPUnknown.
-func GetOCSPForCert(bundle []byte) ([]byte, *ocsp.Response, error) {
- certificates, err := parsePEMBundle(bundle)
- if err != nil {
- return nil, nil, err
- }
-
- // We expect the certificate slice to be ordered downwards the chain.
- // SRV CRT -> CA. We need to pull the leaf and issuer certs out of it,
- // which should always be the first two certificates. If there's no
- // OCSP server listed in the leaf cert, there's nothing to do. And if
- // we have only one certificate so far, we need to get the issuer cert.
- issuedCert := certificates[0]
- if len(issuedCert.OCSPServer) == 0 {
- return nil, nil, errors.New("no OCSP server specified in cert")
- }
- if len(certificates) == 1 {
- // TODO: build fallback. If this fails, check the remaining array entries.
- if len(issuedCert.IssuingCertificateURL) == 0 {
- return nil, nil, errors.New("no issuing certificate URL")
- }
-
- resp, err := httpGet(issuedCert.IssuingCertificateURL[0])
- if err != nil {
- return nil, nil, err
- }
- defer resp.Body.Close()
-
- issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024))
- if err != nil {
- return nil, nil, err
- }
-
- issuerCert, err := x509.ParseCertificate(issuerBytes)
- if err != nil {
- return nil, nil, err
- }
-
- // Insert it into the slice on position 0
- // We want it ordered right SRV CRT -> CA
- certificates = append(certificates, issuerCert)
- }
- issuerCert := certificates[1]
-
- // Finally kick off the OCSP request.
- ocspReq, err := ocsp.CreateRequest(issuedCert, issuerCert, nil)
- if err != nil {
- return nil, nil, err
- }
-
- reader := bytes.NewReader(ocspReq)
- req, err := httpPost(issuedCert.OCSPServer[0], "application/ocsp-request", reader)
- if err != nil {
- return nil, nil, err
- }
- defer req.Body.Close()
-
- ocspResBytes, err := ioutil.ReadAll(limitReader(req.Body, 1024*1024))
- ocspRes, err := ocsp.ParseResponse(ocspResBytes, issuerCert)
- if err != nil {
- return nil, nil, err
- }
-
- return ocspResBytes, ocspRes, nil
-}
-
-func getKeyAuthorization(token string, key interface{}) (string, error) {
- var publicKey crypto.PublicKey
- switch k := key.(type) {
- case *ecdsa.PrivateKey:
- publicKey = k.Public()
- case *rsa.PrivateKey:
- publicKey = k.Public()
- }
-
- // Generate the Key Authorization for the challenge
- jwk := keyAsJWK(publicKey)
- if jwk == nil {
- return "", errors.New("Could not generate JWK from key.")
- }
- thumbBytes, err := jwk.Thumbprint(crypto.SHA256)
- if err != nil {
- return "", err
- }
-
- // unpad the base64URL
- keyThumb := base64.URLEncoding.EncodeToString(thumbBytes)
- index := strings.Index(keyThumb, "=")
- if index != -1 {
- keyThumb = keyThumb[:index]
- }
-
- return token + "." + keyThumb, nil
-}
-
-// parsePEMBundle parses a certificate bundle from top to bottom and returns
-// a slice of x509 certificates. This function will error if no certificates are found.
-func parsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
- var certificates []*x509.Certificate
- var certDERBlock *pem.Block
-
- for {
- certDERBlock, bundle = pem.Decode(bundle)
- if certDERBlock == nil {
- break
- }
-
- if certDERBlock.Type == "CERTIFICATE" {
- cert, err := x509.ParseCertificate(certDERBlock.Bytes)
- if err != nil {
- return nil, err
- }
- certificates = append(certificates, cert)
- }
- }
-
- if len(certificates) == 0 {
- return nil, errors.New("No certificates were found while parsing the bundle.")
- }
-
- return certificates, nil
-}
-
-func parsePEMPrivateKey(key []byte) (crypto.PrivateKey, error) {
- keyBlock, _ := pem.Decode(key)
-
- switch keyBlock.Type {
- case "RSA PRIVATE KEY":
- return x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
- case "EC PRIVATE KEY":
- return x509.ParseECPrivateKey(keyBlock.Bytes)
- default:
- return nil, errors.New("Unknown PEM header value")
- }
-}
-
-func generatePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
-
- switch keyType {
- case EC256:
- return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- case EC384:
- return ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
- case RSA2048:
- return rsa.GenerateKey(rand.Reader, 2048)
- case RSA4096:
- return rsa.GenerateKey(rand.Reader, 4096)
- case RSA8192:
- return rsa.GenerateKey(rand.Reader, 8192)
- }
-
- return nil, fmt.Errorf("Invalid KeyType: %s", keyType)
-}
-
-func generateCsr(privateKey crypto.PrivateKey, domain string, san []string, mustStaple bool) ([]byte, error) {
- template := x509.CertificateRequest{
- Subject: pkix.Name{
- CommonName: domain,
- },
- }
-
- if len(san) > 0 {
- template.DNSNames = san
- }
-
- if mustStaple {
- template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{
- Id: tlsFeatureExtensionOID,
- Value: ocspMustStapleFeature,
- })
- }
-
- return x509.CreateCertificateRequest(rand.Reader, &template, privateKey)
-}
-
-func pemEncode(data interface{}) []byte {
- var pemBlock *pem.Block
- switch key := data.(type) {
- case *ecdsa.PrivateKey:
- keyBytes, _ := x509.MarshalECPrivateKey(key)
- pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
- case *rsa.PrivateKey:
- pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}
- break
- case *x509.CertificateRequest:
- pemBlock = &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: key.Raw}
- break
- case derCertificateBytes:
- pemBlock = &pem.Block{Type: "CERTIFICATE", Bytes: []byte(data.(derCertificateBytes))}
- }
-
- return pem.EncodeToMemory(pemBlock)
-}
-
-func pemDecode(data []byte) (*pem.Block, error) {
- pemBlock, _ := pem.Decode(data)
- if pemBlock == nil {
- return nil, fmt.Errorf("Pem decode did not yield a valid block. Is the certificate in the right format?")
- }
-
- return pemBlock, nil
-}
-
-func pemDecodeTox509(pem []byte) (*x509.Certificate, error) {
- pemBlock, err := pemDecode(pem)
- if pemBlock == nil {
- return nil, err
- }
-
- return x509.ParseCertificate(pemBlock.Bytes)
-}
-
-func pemDecodeTox509CSR(pem []byte) (*x509.CertificateRequest, error) {
- pemBlock, err := pemDecode(pem)
- if pemBlock == nil {
- return nil, err
- }
-
- if pemBlock.Type != "CERTIFICATE REQUEST" {
- return nil, fmt.Errorf("PEM block is not a certificate request")
- }
-
- return x509.ParseCertificateRequest(pemBlock.Bytes)
-}
-
-// GetPEMCertExpiration returns the "NotAfter" date of a PEM encoded certificate.
-// The certificate has to be PEM encoded. Any other encodings like DER will fail.
-func GetPEMCertExpiration(cert []byte) (time.Time, error) {
- pemBlock, err := pemDecode(cert)
- if pemBlock == nil {
- return time.Time{}, err
- }
-
- return getCertExpiration(pemBlock.Bytes)
-}
-
-// getCertExpiration returns the "NotAfter" date of a DER encoded certificate.
-func getCertExpiration(cert []byte) (time.Time, error) {
- pCert, err := x509.ParseCertificate(cert)
- if err != nil {
- return time.Time{}, err
- }
-
- return pCert.NotAfter, nil
-}
-
-func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
- derBytes, err := generateDerCert(privKey, time.Time{}, domain)
- if err != nil {
- return nil, err
- }
-
- return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
-}
-
-func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) {
- serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
- serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
- if err != nil {
- return nil, err
- }
-
- if expiration.IsZero() {
- expiration = time.Now().Add(365)
- }
-
- template := x509.Certificate{
- SerialNumber: serialNumber,
- Subject: pkix.Name{
- CommonName: "ACME Challenge TEMP",
- },
- NotBefore: time.Now(),
- NotAfter: expiration,
-
- KeyUsage: x509.KeyUsageKeyEncipherment,
- BasicConstraintsValid: true,
- DNSNames: []string{domain},
- }
-
- return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
-}
-
-func limitReader(rd io.ReadCloser, numBytes int64) io.ReadCloser {
- return http.MaxBytesReader(nil, rd, numBytes)
-}
diff --git a/vendor/github.com/xenolf/lego/acme/crypto_test.go b/vendor/github.com/xenolf/lego/acme/crypto_test.go
deleted file mode 100644
index 6f43835fb..000000000
--- a/vendor/github.com/xenolf/lego/acme/crypto_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package acme
-
-import (
- "bytes"
- "crypto/rand"
- "crypto/rsa"
- "testing"
- "time"
-)
-
-func TestGeneratePrivateKey(t *testing.T) {
- key, err := generatePrivateKey(RSA2048)
- if err != nil {
- t.Error("Error generating private key:", err)
- }
- if key == nil {
- t.Error("Expected key to not be nil, but it was")
- }
-}
-
-func TestGenerateCSR(t *testing.T) {
- key, err := rsa.GenerateKey(rand.Reader, 512)
- if err != nil {
- t.Fatal("Error generating private key:", err)
- }
-
- csr, err := generateCsr(key, "fizz.buzz", nil, true)
- if err != nil {
- t.Error("Error generating CSR:", err)
- }
- if csr == nil || len(csr) == 0 {
- t.Error("Expected CSR with data, but it was nil or length 0")
- }
-}
-
-func TestPEMEncode(t *testing.T) {
- buf := bytes.NewBufferString("TestingRSAIsSoMuchFun")
-
- reader := MockRandReader{b: buf}
- key, err := rsa.GenerateKey(reader, 32)
- if err != nil {
- t.Fatal("Error generating private key:", err)
- }
-
- data := pemEncode(key)
-
- if data == nil {
- t.Fatal("Expected result to not be nil, but it was")
- }
- if len(data) != 127 {
- t.Errorf("Expected PEM encoding to be length 127, but it was %d", len(data))
- }
-}
-
-func TestPEMCertExpiration(t *testing.T) {
- privKey, err := generatePrivateKey(RSA2048)
- if err != nil {
- t.Fatal("Error generating private key:", err)
- }
-
- expiration := time.Now().Add(365)
- expiration = expiration.Round(time.Second)
- certBytes, err := generateDerCert(privKey.(*rsa.PrivateKey), expiration, "test.com")
- if err != nil {
- t.Fatal("Error generating cert:", err)
- }
-
- buf := bytes.NewBufferString("TestingRSAIsSoMuchFun")
-
- // Some random string should return an error.
- if ctime, err := GetPEMCertExpiration(buf.Bytes()); err == nil {
- t.Errorf("Expected getCertExpiration to return an error for garbage string but returned %v", ctime)
- }
-
- // A DER encoded certificate should return an error.
- if _, err := GetPEMCertExpiration(certBytes); err == nil {
- t.Errorf("Expected getCertExpiration to return an error for DER certificates but returned none.")
- }
-
- // A PEM encoded certificate should work ok.
- pemCert := pemEncode(derCertificateBytes(certBytes))
- if ctime, err := GetPEMCertExpiration(pemCert); err != nil || !ctime.Equal(expiration.UTC()) {
- t.Errorf("Expected getCertExpiration to return %v but returned %v. Error: %v", expiration, ctime, err)
- }
-}
-
-type MockRandReader struct {
- b *bytes.Buffer
-}
-
-func (r MockRandReader) Read(p []byte) (int, error) {
- return r.b.Read(p)
-}
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge.go b/vendor/github.com/xenolf/lego/acme/dns_challenge.go
deleted file mode 100644
index d6844dcd4..000000000
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge.go
+++ /dev/null
@@ -1,309 +0,0 @@
-package acme
-
-import (
- "crypto/sha256"
- "encoding/base64"
- "errors"
- "fmt"
- "log"
- "net"
- "strings"
- "time"
-
- "github.com/miekg/dns"
-)
-
-type preCheckDNSFunc func(fqdn, value string) (bool, error)
-
-var (
- // PreCheckDNS checks DNS propagation before notifying ACME that
- // the DNS challenge is ready.
- PreCheckDNS preCheckDNSFunc = checkDNSPropagation
- fqdnToZone = map[string]string{}
-)
-
-const defaultResolvConf = "/etc/resolv.conf"
-
-var defaultNameservers = []string{
- "google-public-dns-a.google.com:53",
- "google-public-dns-b.google.com:53",
-}
-
-var RecursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers)
-
-// DNSTimeout is used to override the default DNS timeout of 10 seconds.
-var DNSTimeout = 10 * time.Second
-
-// getNameservers attempts to get systems nameservers before falling back to the defaults
-func getNameservers(path string, defaults []string) []string {
- config, err := dns.ClientConfigFromFile(path)
- if err != nil || len(config.Servers) == 0 {
- return defaults
- }
-
- systemNameservers := []string{}
- for _, server := range config.Servers {
- // ensure all servers have a port number
- if _, _, err := net.SplitHostPort(server); err != nil {
- systemNameservers = append(systemNameservers, net.JoinHostPort(server, "53"))
- } else {
- systemNameservers = append(systemNameservers, server)
- }
- }
- return systemNameservers
-}
-
-// DNS01Record returns a DNS record which will fulfill the `dns-01` challenge
-func DNS01Record(domain, keyAuth string) (fqdn string, value string, ttl int) {
- keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
- // base64URL encoding without padding
- keyAuthSha := base64.URLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
- value = strings.TrimRight(keyAuthSha, "=")
- ttl = 120
- fqdn = fmt.Sprintf("_acme-challenge.%s.", domain)
- return
-}
-
-// dnsChallenge implements the dns-01 challenge according to ACME 7.5
-type dnsChallenge struct {
- jws *jws
- validate validateFunc
- provider ChallengeProvider
-}
-
-func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
- logf("[INFO][%s] acme: Trying to solve DNS-01", domain)
-
- if s.provider == nil {
- return errors.New("No DNS Provider configured")
- }
-
- // Generate the Key Authorization for the challenge
- keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
- if err != nil {
- return err
- }
-
- err = s.provider.Present(domain, chlng.Token, keyAuth)
- if err != nil {
- return fmt.Errorf("Error presenting token: %s", err)
- }
- defer func() {
- err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
- if err != nil {
- log.Printf("Error cleaning up %s: %v ", domain, err)
- }
- }()
-
- fqdn, value, _ := DNS01Record(domain, keyAuth)
-
- logf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
-
- var timeout, interval time.Duration
- switch provider := s.provider.(type) {
- case ChallengeProviderTimeout:
- timeout, interval = provider.Timeout()
- default:
- timeout, interval = 60*time.Second, 2*time.Second
- }
-
- err = WaitFor(timeout, interval, func() (bool, error) {
- return PreCheckDNS(fqdn, value)
- })
- if err != nil {
- return err
- }
-
- return s.validate(s.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
-}
-
-// checkDNSPropagation checks if the expected TXT record has been propagated to all authoritative nameservers.
-func checkDNSPropagation(fqdn, value string) (bool, error) {
- // Initial attempt to resolve at the recursive NS
- r, err := dnsQuery(fqdn, dns.TypeTXT, RecursiveNameservers, true)
- if err != nil {
- return false, err
- }
- if r.Rcode == dns.RcodeSuccess {
- // If we see a CNAME here then use the alias
- for _, rr := range r.Answer {
- if cn, ok := rr.(*dns.CNAME); ok {
- if cn.Hdr.Name == fqdn {
- fqdn = cn.Target
- break
- }
- }
- }
- }
-
- authoritativeNss, err := lookupNameservers(fqdn)
- if err != nil {
- return false, err
- }
-
- return checkAuthoritativeNss(fqdn, value, authoritativeNss)
-}
-
-// checkAuthoritativeNss queries each of the given nameservers for the expected TXT record.
-func checkAuthoritativeNss(fqdn, value string, nameservers []string) (bool, error) {
- for _, ns := range nameservers {
- r, err := dnsQuery(fqdn, dns.TypeTXT, []string{net.JoinHostPort(ns, "53")}, false)
- if err != nil {
- return false, err
- }
-
- if r.Rcode != dns.RcodeSuccess {
- return false, fmt.Errorf("NS %s returned %s for %s", ns, dns.RcodeToString[r.Rcode], fqdn)
- }
-
- var found bool
- for _, rr := range r.Answer {
- if txt, ok := rr.(*dns.TXT); ok {
- if strings.Join(txt.Txt, "") == value {
- found = true
- break
- }
- }
- }
-
- if !found {
- return false, fmt.Errorf("NS %s did not return the expected TXT record", ns)
- }
- }
-
- return true, nil
-}
-
-// dnsQuery will query a nameserver, iterating through the supplied servers as it retries
-// The nameserver should include a port, to facilitate testing where we talk to a mock dns server.
-func dnsQuery(fqdn string, rtype uint16, nameservers []string, recursive bool) (in *dns.Msg, err error) {
- m := new(dns.Msg)
- m.SetQuestion(fqdn, rtype)
- m.SetEdns0(4096, false)
-
- if !recursive {
- m.RecursionDesired = false
- }
-
- // Will retry the request based on the number of servers (n+1)
- for i := 1; i <= len(nameservers)+1; i++ {
- ns := nameservers[i%len(nameservers)]
- udp := &dns.Client{Net: "udp", Timeout: DNSTimeout}
- in, _, err = udp.Exchange(m, ns)
-
- if err == dns.ErrTruncated {
- tcp := &dns.Client{Net: "tcp", Timeout: DNSTimeout}
- // If the TCP request succeeds, the err will reset to nil
- in, _, err = tcp.Exchange(m, ns)
- }
-
- if err == nil {
- break
- }
- }
- return
-}
-
-// lookupNameservers returns the authoritative nameservers for the given fqdn.
-func lookupNameservers(fqdn string) ([]string, error) {
- var authoritativeNss []string
-
- zone, err := FindZoneByFqdn(fqdn, RecursiveNameservers)
- if err != nil {
- return nil, fmt.Errorf("Could not determine the zone: %v", err)
- }
-
- r, err := dnsQuery(zone, dns.TypeNS, RecursiveNameservers, true)
- if err != nil {
- return nil, err
- }
-
- for _, rr := range r.Answer {
- if ns, ok := rr.(*dns.NS); ok {
- authoritativeNss = append(authoritativeNss, strings.ToLower(ns.Ns))
- }
- }
-
- if len(authoritativeNss) > 0 {
- return authoritativeNss, nil
- }
- return nil, fmt.Errorf("Could not determine authoritative nameservers")
-}
-
-// FindZoneByFqdn determines the zone apex for the given fqdn by recursing up the
-// domain labels until the nameserver returns a SOA record in the answer section.
-func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
- // Do we have it cached?
- if zone, ok := fqdnToZone[fqdn]; ok {
- return zone, nil
- }
-
- labelIndexes := dns.Split(fqdn)
- for _, index := range labelIndexes {
- domain := fqdn[index:]
-
- in, err := dnsQuery(domain, dns.TypeSOA, nameservers, true)
- if err != nil {
- return "", err
- }
-
- // Any response code other than NOERROR and NXDOMAIN is treated as error
- if in.Rcode != dns.RcodeNameError && in.Rcode != dns.RcodeSuccess {
- return "", fmt.Errorf("Unexpected response code '%s' for %s",
- dns.RcodeToString[in.Rcode], domain)
- }
-
- // Check if we got a SOA RR in the answer section
- if in.Rcode == dns.RcodeSuccess {
-
- // CNAME records cannot/should not exist at the root of a zone.
- // So we skip a domain when a CNAME is found.
- if dnsMsgContainsCNAME(in) {
- continue
- }
-
- for _, ans := range in.Answer {
- if soa, ok := ans.(*dns.SOA); ok {
- zone := soa.Hdr.Name
- fqdnToZone[fqdn] = zone
- return zone, nil
- }
- }
- }
- }
-
- return "", fmt.Errorf("Could not find the start of authority")
-}
-
-// dnsMsgContainsCNAME checks for a CNAME answer in msg
-func dnsMsgContainsCNAME(msg *dns.Msg) bool {
- for _, ans := range msg.Answer {
- if _, ok := ans.(*dns.CNAME); ok {
- return true
- }
- }
- return false
-}
-
-// ClearFqdnCache clears the cache of fqdn to zone mappings. Primarily used in testing.
-func ClearFqdnCache() {
- fqdnToZone = map[string]string{}
-}
-
-// ToFqdn converts the name into a fqdn appending a trailing dot.
-func ToFqdn(name string) string {
- n := len(name)
- if n == 0 || name[n-1] == '.' {
- return name
- }
- return name + "."
-}
-
-// UnFqdn converts the fqdn into a name removing the trailing dot.
-func UnFqdn(name string) string {
- n := len(name)
- if n != 0 && name[n-1] == '.' {
- return name[:n-1]
- }
- return name
-}
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go b/vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go
deleted file mode 100644
index 240384e60..000000000
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package acme
-
-import (
- "bufio"
- "fmt"
- "os"
-)
-
-const (
- dnsTemplate = "%s %d IN TXT \"%s\""
-)
-
-// DNSProviderManual is an implementation of the ChallengeProvider interface
-type DNSProviderManual struct{}
-
-// NewDNSProviderManual returns a DNSProviderManual instance.
-func NewDNSProviderManual() (*DNSProviderManual, error) {
- return &DNSProviderManual{}, nil
-}
-
-// Present prints instructions for manually creating the TXT record
-func (*DNSProviderManual) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := DNS01Record(domain, keyAuth)
- dnsRecord := fmt.Sprintf(dnsTemplate, fqdn, ttl, value)
-
- authZone, err := FindZoneByFqdn(fqdn, RecursiveNameservers)
- if err != nil {
- return err
- }
-
- logf("[INFO] acme: Please create the following TXT record in your %s zone:", authZone)
- logf("[INFO] acme: %s", dnsRecord)
- logf("[INFO] acme: Press 'Enter' when you are done")
-
- reader := bufio.NewReader(os.Stdin)
- _, _ = reader.ReadString('\n')
- return nil
-}
-
-// CleanUp prints instructions for manually removing the TXT record
-func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, ttl := DNS01Record(domain, keyAuth)
- dnsRecord := fmt.Sprintf(dnsTemplate, fqdn, ttl, "...")
-
- authZone, err := FindZoneByFqdn(fqdn, RecursiveNameservers)
- if err != nil {
- return err
- }
-
- logf("[INFO] acme: You can now remove this TXT record from your %s zone:", authZone)
- logf("[INFO] acme: %s", dnsRecord)
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go b/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
deleted file mode 100644
index 117ac3038..000000000
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
+++ /dev/null
@@ -1,200 +0,0 @@
-package acme
-
-import (
- "bufio"
- "crypto/rand"
- "crypto/rsa"
- "net/http"
- "net/http/httptest"
- "os"
- "reflect"
- "sort"
- "strings"
- "testing"
- "time"
-)
-
-var lookupNameserversTestsOK = []struct {
- fqdn string
- nss []string
-}{
- {"books.google.com.ng.",
- []string{"ns1.google.com.", "ns2.google.com.", "ns3.google.com.", "ns4.google.com."},
- },
- {"www.google.com.",
- []string{"ns1.google.com.", "ns2.google.com.", "ns3.google.com.", "ns4.google.com."},
- },
- {"physics.georgetown.edu.",
- []string{"ns1.georgetown.edu.", "ns2.georgetown.edu.", "ns3.georgetown.edu."},
- },
-}
-
-var lookupNameserversTestsErr = []struct {
- fqdn string
- error string
-}{
- // invalid tld
- {"_null.n0n0.",
- "Could not determine the zone",
- },
-}
-
-var findZoneByFqdnTests = []struct {
- fqdn string
- zone string
-}{
- {"mail.google.com.", "google.com."}, // domain is a CNAME
- {"foo.google.com.", "google.com."}, // domain is a non-existent subdomain
- {"example.com.ac.", "ac."}, // domain is a eTLD
- {"cross-zone-example.assets.sh.", "assets.sh."}, // domain is a cross-zone CNAME
-}
-
-var checkAuthoritativeNssTests = []struct {
- fqdn, value string
- ns []string
- ok bool
-}{
- // TXT RR w/ expected value
- {"8.8.8.8.asn.routeviews.org.", "151698.8.8.024", []string{"asnums.routeviews.org."},
- true,
- },
- // No TXT RR
- {"ns1.google.com.", "", []string{"ns2.google.com."},
- false,
- },
-}
-
-var checkAuthoritativeNssTestsErr = []struct {
- fqdn, value string
- ns []string
- error string
-}{
- // TXT RR /w unexpected value
- {"8.8.8.8.asn.routeviews.org.", "fe01=", []string{"asnums.routeviews.org."},
- "did not return the expected TXT record",
- },
- // No TXT RR
- {"ns1.google.com.", "fe01=", []string{"ns2.google.com."},
- "did not return the expected TXT record",
- },
-}
-
-var checkResolvConfServersTests = []struct {
- fixture string
- expected []string
- defaults []string
-}{
- {"testdata/resolv.conf.1", []string{"10.200.3.249:53", "10.200.3.250:5353", "[2001:4860:4860::8844]:53", "[10.0.0.1]:5353"}, []string{"127.0.0.1:53"}},
- {"testdata/resolv.conf.nonexistant", []string{"127.0.0.1:53"}, []string{"127.0.0.1:53"}},
-}
-
-func TestDNSValidServerResponse(t *testing.T) {
- PreCheckDNS = func(fqdn, value string) (bool, error) {
- return true, nil
- }
- privKey, _ := rsa.GenerateKey(rand.Reader, 512)
-
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Add("Replay-Nonce", "12345")
- w.Write([]byte("{\"type\":\"dns01\",\"status\":\"valid\",\"uri\":\"http://some.url\",\"token\":\"http8\"}"))
- }))
-
- manualProvider, _ := NewDNSProviderManual()
- jws := &jws{privKey: privKey, directoryURL: ts.URL}
- solver := &dnsChallenge{jws: jws, validate: validate, provider: manualProvider}
- clientChallenge := challenge{Type: "dns01", Status: "pending", URI: ts.URL, Token: "http8"}
-
- go func() {
- time.Sleep(time.Second * 2)
- f := bufio.NewWriter(os.Stdout)
- defer f.Flush()
- f.WriteString("\n")
- }()
-
- if err := solver.Solve(clientChallenge, "example.com"); err != nil {
- t.Errorf("VALID: Expected Solve to return no error but the error was -> %v", err)
- }
-}
-
-func TestPreCheckDNS(t *testing.T) {
- ok, err := PreCheckDNS("acme-staging.api.letsencrypt.org", "fe01=")
- if err != nil || !ok {
- t.Errorf("preCheckDNS failed for acme-staging.api.letsencrypt.org")
- }
-}
-
-func TestLookupNameserversOK(t *testing.T) {
- for _, tt := range lookupNameserversTestsOK {
- nss, err := lookupNameservers(tt.fqdn)
- if err != nil {
- t.Fatalf("#%s: got %q; want nil", tt.fqdn, err)
- }
-
- sort.Strings(nss)
- sort.Strings(tt.nss)
-
- if !reflect.DeepEqual(nss, tt.nss) {
- t.Errorf("#%s: got %v; want %v", tt.fqdn, nss, tt.nss)
- }
- }
-}
-
-func TestLookupNameserversErr(t *testing.T) {
- for _, tt := range lookupNameserversTestsErr {
- _, err := lookupNameservers(tt.fqdn)
- if err == nil {
- t.Fatalf("#%s: expected %q (error); got <nil>", tt.fqdn, tt.error)
- }
-
- if !strings.Contains(err.Error(), tt.error) {
- t.Errorf("#%s: expected %q (error); got %q", tt.fqdn, tt.error, err)
- continue
- }
- }
-}
-
-func TestFindZoneByFqdn(t *testing.T) {
- for _, tt := range findZoneByFqdnTests {
- res, err := FindZoneByFqdn(tt.fqdn, RecursiveNameservers)
- if err != nil {
- t.Errorf("FindZoneByFqdn failed for %s: %v", tt.fqdn, err)
- }
- if res != tt.zone {
- t.Errorf("%s: got %s; want %s", tt.fqdn, res, tt.zone)
- }
- }
-}
-
-func TestCheckAuthoritativeNss(t *testing.T) {
- for _, tt := range checkAuthoritativeNssTests {
- ok, _ := checkAuthoritativeNss(tt.fqdn, tt.value, tt.ns)
- if ok != tt.ok {
- t.Errorf("%s: got %t; want %t", tt.fqdn, ok, tt.ok)
- }
- }
-}
-
-func TestCheckAuthoritativeNssErr(t *testing.T) {
- for _, tt := range checkAuthoritativeNssTestsErr {
- _, err := checkAuthoritativeNss(tt.fqdn, tt.value, tt.ns)
- if err == nil {
- t.Fatalf("#%s: expected %q (error); got <nil>", tt.fqdn, tt.error)
- }
- if !strings.Contains(err.Error(), tt.error) {
- t.Errorf("#%s: expected %q (error); got %q", tt.fqdn, tt.error, err)
- continue
- }
- }
-}
-
-func TestResolveConfServers(t *testing.T) {
- for _, tt := range checkResolvConfServersTests {
- result := getNameservers(tt.fixture, tt.defaults)
-
- sort.Strings(result)
- sort.Strings(tt.expected)
- if !reflect.DeepEqual(result, tt.expected) {
- t.Errorf("#%s: expected %q; got %q", tt.fixture, tt.expected, result)
- }
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/error.go b/vendor/github.com/xenolf/lego/acme/error.go
deleted file mode 100644
index e4bc934c2..000000000
--- a/vendor/github.com/xenolf/lego/acme/error.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package acme
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "strings"
-)
-
-const (
- tosAgreementError = "Must agree to subscriber agreement before any further actions"
- invalidNonceError = "JWS has invalid anti-replay nonce"
-)
-
-// RemoteError is the base type for all errors specific to the ACME protocol.
-type RemoteError struct {
- StatusCode int `json:"status,omitempty"`
- Type string `json:"type"`
- Detail string `json:"detail"`
-}
-
-func (e RemoteError) Error() string {
- return fmt.Sprintf("acme: Error %d - %s - %s", e.StatusCode, e.Type, e.Detail)
-}
-
-// TOSError represents the error which is returned if the user needs to
-// accept the TOS.
-// TODO: include the new TOS url if we can somehow obtain it.
-type TOSError struct {
- RemoteError
-}
-
-// NonceError represents the error which is returned if the
-// nonce sent by the client was not accepted by the server.
-type NonceError struct {
- RemoteError
-}
-
-type domainError struct {
- Domain string
- Error error
-}
-
-type challengeError struct {
- RemoteError
- records []validationRecord
-}
-
-func (c challengeError) Error() string {
-
- var errStr string
- for _, validation := range c.records {
- errStr = errStr + fmt.Sprintf("\tValidation for %s:%s\n\tResolved to:\n\t\t%s\n\tUsed: %s\n\n",
- validation.Hostname, validation.Port, strings.Join(validation.ResolvedAddresses, "\n\t\t"), validation.UsedAddress)
- }
-
- return fmt.Sprintf("%s\nError Detail:\n%s", c.RemoteError.Error(), errStr)
-}
-
-func handleHTTPError(resp *http.Response) error {
- var errorDetail RemoteError
-
- contentType := resp.Header.Get("Content-Type")
- if contentType == "application/json" || contentType == "application/problem+json" {
- err := json.NewDecoder(resp.Body).Decode(&errorDetail)
- if err != nil {
- return err
- }
- } else {
- detailBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize))
- if err != nil {
- return err
- }
- errorDetail.Detail = string(detailBytes)
- }
-
- errorDetail.StatusCode = resp.StatusCode
-
- // Check for errors we handle specifically
- if errorDetail.StatusCode == http.StatusForbidden && errorDetail.Detail == tosAgreementError {
- return TOSError{errorDetail}
- }
-
- if errorDetail.StatusCode == http.StatusBadRequest && strings.HasPrefix(errorDetail.Detail, invalidNonceError) {
- return NonceError{errorDetail}
- }
-
- return errorDetail
-}
-
-func handleChallengeError(chlng challenge) error {
- return challengeError{chlng.Error, chlng.ValidationRecords}
-}
diff --git a/vendor/github.com/xenolf/lego/acme/http.go b/vendor/github.com/xenolf/lego/acme/http.go
deleted file mode 100644
index e469e0de2..000000000
--- a/vendor/github.com/xenolf/lego/acme/http.go
+++ /dev/null
@@ -1,160 +0,0 @@
-package acme
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "runtime"
- "strings"
- "time"
-)
-
-// UserAgent (if non-empty) will be tacked onto the User-Agent string in requests.
-var UserAgent string
-
-// HTTPClient is an HTTP client with a reasonable timeout value.
-var HTTPClient = http.Client{
- Transport: &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- Dial: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- }).Dial,
- TLSHandshakeTimeout: 15 * time.Second,
- ResponseHeaderTimeout: 15 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- },
-}
-
-const (
- // defaultGoUserAgent is the Go HTTP package user agent string. Too
- // bad it isn't exported. If it changes, we should update it here, too.
- defaultGoUserAgent = "Go-http-client/1.1"
-
- // ourUserAgent is the User-Agent of this underlying library package.
- ourUserAgent = "xenolf-acme"
-)
-
-// httpHead performs a HEAD request with a proper User-Agent string.
-// The response body (resp.Body) is already closed when this function returns.
-func httpHead(url string) (resp *http.Response, err error) {
- req, err := http.NewRequest("HEAD", url, nil)
- if err != nil {
- return nil, fmt.Errorf("failed to head %q: %v", url, err)
- }
-
- req.Header.Set("User-Agent", userAgent())
-
- resp, err = HTTPClient.Do(req)
- if err != nil {
- return resp, fmt.Errorf("failed to do head %q: %v", url, err)
- }
- resp.Body.Close()
- return resp, err
-}
-
-// httpPost performs a POST request with a proper User-Agent string.
-// Callers should close resp.Body when done reading from it.
-func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) {
- req, err := http.NewRequest("POST", url, body)
- if err != nil {
- return nil, fmt.Errorf("failed to post %q: %v", url, err)
- }
- req.Header.Set("Content-Type", bodyType)
- req.Header.Set("User-Agent", userAgent())
-
- return HTTPClient.Do(req)
-}
-
-// httpGet performs a GET request with a proper User-Agent string.
-// Callers should close resp.Body when done reading from it.
-func httpGet(url string) (resp *http.Response, err error) {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return nil, fmt.Errorf("failed to get %q: %v", url, err)
- }
- req.Header.Set("User-Agent", userAgent())
-
- return HTTPClient.Do(req)
-}
-
-// getJSON performs an HTTP GET request and parses the response body
-// as JSON, into the provided respBody object.
-func getJSON(uri string, respBody interface{}) (http.Header, error) {
- resp, err := httpGet(uri)
- if err != nil {
- return nil, fmt.Errorf("failed to get json %q: %v", uri, err)
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= http.StatusBadRequest {
- return resp.Header, handleHTTPError(resp)
- }
-
- return resp.Header, json.NewDecoder(resp.Body).Decode(respBody)
-}
-
-// postJSON performs an HTTP POST request and parses the response body
-// as JSON, into the provided respBody object.
-func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) {
- jsonBytes, err := json.Marshal(reqBody)
- if err != nil {
- return nil, errors.New("Failed to marshal network message...")
- }
-
- resp, err := j.post(uri, jsonBytes)
- if err != nil {
- return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode >= http.StatusBadRequest {
-
- err := handleHTTPError(resp)
-
- switch err.(type) {
-
- case NonceError:
-
- // Retry once if the nonce was invalidated
-
- retryResp, err := j.post(uri, jsonBytes)
- if err != nil {
- return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
- }
-
- defer retryResp.Body.Close()
-
- if retryResp.StatusCode >= http.StatusBadRequest {
- return retryResp.Header, handleHTTPError(retryResp)
- }
-
- if respBody == nil {
- return retryResp.Header, nil
- }
-
- return retryResp.Header, json.NewDecoder(retryResp.Body).Decode(respBody)
-
- default:
- return resp.Header, err
-
- }
-
- }
-
- if respBody == nil {
- return resp.Header, nil
- }
-
- return resp.Header, json.NewDecoder(resp.Body).Decode(respBody)
-}
-
-// userAgent builds and returns the User-Agent string to use in requests.
-func userAgent() string {
- ua := fmt.Sprintf("%s (%s; %s) %s %s", defaultGoUserAgent, runtime.GOOS, runtime.GOARCH, ourUserAgent, UserAgent)
- return strings.TrimSpace(ua)
-}
diff --git a/vendor/github.com/xenolf/lego/acme/http_challenge.go b/vendor/github.com/xenolf/lego/acme/http_challenge.go
deleted file mode 100644
index 95cb1fd81..000000000
--- a/vendor/github.com/xenolf/lego/acme/http_challenge.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package acme
-
-import (
- "fmt"
- "log"
-)
-
-type httpChallenge struct {
- jws *jws
- validate validateFunc
- provider ChallengeProvider
-}
-
-// HTTP01ChallengePath returns the URL path for the `http-01` challenge
-func HTTP01ChallengePath(token string) string {
- return "/.well-known/acme-challenge/" + token
-}
-
-func (s *httpChallenge) Solve(chlng challenge, domain string) error {
-
- logf("[INFO][%s] acme: Trying to solve HTTP-01", domain)
-
- // Generate the Key Authorization for the challenge
- keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
- if err != nil {
- return err
- }
-
- err = s.provider.Present(domain, chlng.Token, keyAuth)
- if err != nil {
- return fmt.Errorf("[%s] error presenting token: %v", domain, err)
- }
- defer func() {
- err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
- if err != nil {
- log.Printf("[%s] error cleaning up: %v", domain, err)
- }
- }()
-
- return s.validate(s.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
-}
diff --git a/vendor/github.com/xenolf/lego/acme/http_challenge_server.go b/vendor/github.com/xenolf/lego/acme/http_challenge_server.go
deleted file mode 100644
index 64c6a8280..000000000
--- a/vendor/github.com/xenolf/lego/acme/http_challenge_server.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package acme
-
-import (
- "fmt"
- "net"
- "net/http"
- "strings"
-)
-
-// HTTPProviderServer implements ChallengeProvider for `http-01` challenge
-// It may be instantiated without using the NewHTTPProviderServer function if
-// you want only to use the default values.
-type HTTPProviderServer struct {
- iface string
- port string
- done chan bool
- listener net.Listener
-}
-
-// NewHTTPProviderServer creates a new HTTPProviderServer on the selected interface and port.
-// Setting iface and / or port to an empty string will make the server fall back to
-// the "any" interface and port 80 respectively.
-func NewHTTPProviderServer(iface, port string) *HTTPProviderServer {
- return &HTTPProviderServer{iface: iface, port: port}
-}
-
-// Present starts a web server and makes the token available at `HTTP01ChallengePath(token)` for web requests.
-func (s *HTTPProviderServer) Present(domain, token, keyAuth string) error {
- if s.port == "" {
- s.port = "80"
- }
-
- var err error
- s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port))
- if err != nil {
- return fmt.Errorf("Could not start HTTP server for challenge -> %v", err)
- }
-
- s.done = make(chan bool)
- go s.serve(domain, token, keyAuth)
- return nil
-}
-
-// CleanUp closes the HTTP server and removes the token from `HTTP01ChallengePath(token)`
-func (s *HTTPProviderServer) CleanUp(domain, token, keyAuth string) error {
- if s.listener == nil {
- return nil
- }
- s.listener.Close()
- <-s.done
- return nil
-}
-
-func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
- path := HTTP01ChallengePath(token)
-
- // The handler validates the HOST header and request type.
- // For validation it then writes the token the server returned with the challenge
- mux := http.NewServeMux()
- mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
- if strings.HasPrefix(r.Host, domain) && r.Method == "GET" {
- w.Header().Add("Content-Type", "text/plain")
- w.Write([]byte(keyAuth))
- logf("[INFO][%s] Served key authentication", domain)
- } else {
- logf("[WARN] Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
- w.Write([]byte("TEST"))
- }
- })
-
- httpServer := &http.Server{
- Handler: mux,
- }
- // Once httpServer is shut down we don't want any lingering
- // connections, so disable KeepAlives.
- httpServer.SetKeepAlivesEnabled(false)
- httpServer.Serve(s.listener)
- s.done <- true
-}
diff --git a/vendor/github.com/xenolf/lego/acme/http_challenge_test.go b/vendor/github.com/xenolf/lego/acme/http_challenge_test.go
deleted file mode 100644
index 7400f56d4..000000000
--- a/vendor/github.com/xenolf/lego/acme/http_challenge_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package acme
-
-import (
- "crypto/rand"
- "crypto/rsa"
- "io/ioutil"
- "strings"
- "testing"
-)
-
-func TestHTTPChallenge(t *testing.T) {
- privKey, _ := rsa.GenerateKey(rand.Reader, 512)
- j := &jws{privKey: privKey}
- clientChallenge := challenge{Type: HTTP01, Token: "http1"}
- mockValidate := func(_ *jws, _, _ string, chlng challenge) error {
- uri := "http://localhost:23457/.well-known/acme-challenge/" + chlng.Token
- resp, err := httpGet(uri)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- if want := "text/plain"; resp.Header.Get("Content-Type") != want {
- t.Errorf("Get(%q) Content-Type: got %q, want %q", uri, resp.Header.Get("Content-Type"), want)
- }
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return err
- }
- bodyStr := string(body)
-
- if bodyStr != chlng.KeyAuthorization {
- t.Errorf("Get(%q) Body: got %q, want %q", uri, bodyStr, chlng.KeyAuthorization)
- }
-
- return nil
- }
- solver := &httpChallenge{jws: j, validate: mockValidate, provider: &HTTPProviderServer{port: "23457"}}
-
- if err := solver.Solve(clientChallenge, "localhost:23457"); err != nil {
- t.Errorf("Solve error: got %v, want nil", err)
- }
-}
-
-func TestHTTPChallengeInvalidPort(t *testing.T) {
- privKey, _ := rsa.GenerateKey(rand.Reader, 128)
- j := &jws{privKey: privKey}
- clientChallenge := challenge{Type: HTTP01, Token: "http2"}
- solver := &httpChallenge{jws: j, validate: stubValidate, provider: &HTTPProviderServer{port: "123456"}}
-
- if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil {
- t.Errorf("Solve error: got %v, want error", err)
- } else if want, want18 := "invalid port 123456", "123456: invalid port"; !strings.HasSuffix(err.Error(), want) && !strings.HasSuffix(err.Error(), want18) {
- t.Errorf("Solve error: got %q, want suffix %q", err.Error(), want)
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/http_test.go b/vendor/github.com/xenolf/lego/acme/http_test.go
deleted file mode 100644
index 33a48a331..000000000
--- a/vendor/github.com/xenolf/lego/acme/http_test.go
+++ /dev/null
@@ -1,100 +0,0 @@
-package acme
-
-import (
- "net/http"
- "net/http/httptest"
- "strings"
- "testing"
-)
-
-func TestHTTPHeadUserAgent(t *testing.T) {
- var ua, method string
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ua = r.Header.Get("User-Agent")
- method = r.Method
- }))
- defer ts.Close()
-
- _, err := httpHead(ts.URL)
- if err != nil {
- t.Fatal(err)
- }
-
- if method != "HEAD" {
- t.Errorf("Expected method to be HEAD, got %s", method)
- }
- if !strings.Contains(ua, ourUserAgent) {
- t.Errorf("Expected User-Agent to contain '%s', got: '%s'", ourUserAgent, ua)
- }
-}
-
-func TestHTTPGetUserAgent(t *testing.T) {
- var ua, method string
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ua = r.Header.Get("User-Agent")
- method = r.Method
- }))
- defer ts.Close()
-
- res, err := httpGet(ts.URL)
- if err != nil {
- t.Fatal(err)
- }
- res.Body.Close()
-
- if method != "GET" {
- t.Errorf("Expected method to be GET, got %s", method)
- }
- if !strings.Contains(ua, ourUserAgent) {
- t.Errorf("Expected User-Agent to contain '%s', got: '%s'", ourUserAgent, ua)
- }
-}
-
-func TestHTTPPostUserAgent(t *testing.T) {
- var ua, method string
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ua = r.Header.Get("User-Agent")
- method = r.Method
- }))
- defer ts.Close()
-
- res, err := httpPost(ts.URL, "text/plain", strings.NewReader("falalalala"))
- if err != nil {
- t.Fatal(err)
- }
- res.Body.Close()
-
- if method != "POST" {
- t.Errorf("Expected method to be POST, got %s", method)
- }
- if !strings.Contains(ua, ourUserAgent) {
- t.Errorf("Expected User-Agent to contain '%s', got: '%s'", ourUserAgent, ua)
- }
-}
-
-func TestUserAgent(t *testing.T) {
- ua := userAgent()
-
- if !strings.Contains(ua, defaultGoUserAgent) {
- t.Errorf("Expected UA to contain %s, got '%s'", defaultGoUserAgent, ua)
- }
- if !strings.Contains(ua, ourUserAgent) {
- t.Errorf("Expected UA to contain %s, got '%s'", ourUserAgent, ua)
- }
- if strings.HasSuffix(ua, " ") {
- t.Errorf("UA should not have trailing spaces; got '%s'", ua)
- }
-
- // customize the UA by appending a value
- UserAgent = "MyApp/1.2.3"
- ua = userAgent()
- if !strings.Contains(ua, defaultGoUserAgent) {
- t.Errorf("Expected UA to contain %s, got '%s'", defaultGoUserAgent, ua)
- }
- if !strings.Contains(ua, ourUserAgent) {
- t.Errorf("Expected UA to contain %s, got '%s'", ourUserAgent, ua)
- }
- if !strings.Contains(ua, UserAgent) {
- t.Errorf("Expected custom UA to contain %s, got '%s'", UserAgent, ua)
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go
deleted file mode 100644
index a39434342..000000000
--- a/vendor/github.com/xenolf/lego/acme/jws.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package acme
-
-import (
- "bytes"
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rsa"
- "fmt"
- "net/http"
- "sync"
-
- "gopkg.in/square/go-jose.v1"
-)
-
-type jws struct {
- directoryURL string
- privKey crypto.PrivateKey
- nonces nonceManager
-}
-
-func keyAsJWK(key interface{}) *jose.JsonWebKey {
- switch k := key.(type) {
- case *ecdsa.PublicKey:
- return &jose.JsonWebKey{Key: k, Algorithm: "EC"}
- case *rsa.PublicKey:
- return &jose.JsonWebKey{Key: k, Algorithm: "RSA"}
-
- default:
- return nil
- }
-}
-
-// Posts a JWS signed message to the specified URL.
-// It does NOT close the response body, so the caller must
-// do that if no error was returned.
-func (j *jws) post(url string, content []byte) (*http.Response, error) {
- signedContent, err := j.signContent(content)
- if err != nil {
- return nil, fmt.Errorf("Failed to sign content -> %s", err.Error())
- }
-
- resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize())))
- if err != nil {
- return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error())
- }
-
- nonce, nonceErr := getNonceFromResponse(resp)
- if nonceErr == nil {
- j.nonces.Push(nonce)
- }
-
- return resp, nil
-}
-
-func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) {
-
- var alg jose.SignatureAlgorithm
- switch k := j.privKey.(type) {
- case *rsa.PrivateKey:
- alg = jose.RS256
- case *ecdsa.PrivateKey:
- if k.Curve == elliptic.P256() {
- alg = jose.ES256
- } else if k.Curve == elliptic.P384() {
- alg = jose.ES384
- }
- }
-
- signer, err := jose.NewSigner(alg, j.privKey)
- if err != nil {
- return nil, fmt.Errorf("Failed to create jose signer -> %s", err.Error())
- }
- signer.SetNonceSource(j)
-
- signed, err := signer.Sign(content)
- if err != nil {
- return nil, fmt.Errorf("Failed to sign content -> %s", err.Error())
- }
- return signed, nil
-}
-
-func (j *jws) Nonce() (string, error) {
- if nonce, ok := j.nonces.Pop(); ok {
- return nonce, nil
- }
-
- return getNonce(j.directoryURL)
-}
-
-type nonceManager struct {
- nonces []string
- sync.Mutex
-}
-
-func (n *nonceManager) Pop() (string, bool) {
- n.Lock()
- defer n.Unlock()
-
- if len(n.nonces) == 0 {
- return "", false
- }
-
- nonce := n.nonces[len(n.nonces)-1]
- n.nonces = n.nonces[:len(n.nonces)-1]
- return nonce, true
-}
-
-func (n *nonceManager) Push(nonce string) {
- n.Lock()
- defer n.Unlock()
- n.nonces = append(n.nonces, nonce)
-}
-
-func getNonce(url string) (string, error) {
- resp, err := httpHead(url)
- if err != nil {
- return "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error())
- }
-
- return getNonceFromResponse(resp)
-}
-
-func getNonceFromResponse(resp *http.Response) (string, error) {
- nonce := resp.Header.Get("Replay-Nonce")
- if nonce == "" {
- return "", fmt.Errorf("Server did not respond with a proper nonce header.")
- }
-
- return nonce, nil
-}
diff --git a/vendor/github.com/xenolf/lego/acme/messages.go b/vendor/github.com/xenolf/lego/acme/messages.go
deleted file mode 100644
index 79ccf154e..000000000
--- a/vendor/github.com/xenolf/lego/acme/messages.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package acme
-
-import (
- "time"
-
- "gopkg.in/square/go-jose.v1"
-)
-
-type directory struct {
- NewAuthzURL string `json:"new-authz"`
- NewCertURL string `json:"new-cert"`
- NewRegURL string `json:"new-reg"`
- RevokeCertURL string `json:"revoke-cert"`
-}
-
-type registrationMessage struct {
- Resource string `json:"resource"`
- Contact []string `json:"contact"`
- Delete bool `json:"delete,omitempty"`
-}
-
-// Registration is returned by the ACME server after the registration
-// The client implementation should save this registration somewhere.
-type Registration struct {
- Resource string `json:"resource,omitempty"`
- ID int `json:"id"`
- Key jose.JsonWebKey `json:"key"`
- Contact []string `json:"contact"`
- Agreement string `json:"agreement,omitempty"`
- Authorizations string `json:"authorizations,omitempty"`
- Certificates string `json:"certificates,omitempty"`
-}
-
-// RegistrationResource represents all important informations about a registration
-// of which the client needs to keep track itself.
-type RegistrationResource struct {
- Body Registration `json:"body,omitempty"`
- URI string `json:"uri,omitempty"`
- NewAuthzURL string `json:"new_authzr_uri,omitempty"`
- TosURL string `json:"terms_of_service,omitempty"`
-}
-
-type authorizationResource struct {
- Body authorization
- Domain string
- NewCertURL string
- AuthURL string
-}
-
-type authorization struct {
- Resource string `json:"resource,omitempty"`
- Identifier identifier `json:"identifier"`
- Status string `json:"status,omitempty"`
- Expires time.Time `json:"expires,omitempty"`
- Challenges []challenge `json:"challenges,omitempty"`
- Combinations [][]int `json:"combinations,omitempty"`
-}
-
-type identifier struct {
- Type string `json:"type"`
- Value string `json:"value"`
-}
-
-type validationRecord struct {
- URI string `json:"url,omitempty"`
- Hostname string `json:"hostname,omitempty"`
- Port string `json:"port,omitempty"`
- ResolvedAddresses []string `json:"addressesResolved,omitempty"`
- UsedAddress string `json:"addressUsed,omitempty"`
-}
-
-type challenge struct {
- Resource string `json:"resource,omitempty"`
- Type Challenge `json:"type,omitempty"`
- Status string `json:"status,omitempty"`
- URI string `json:"uri,omitempty"`
- Token string `json:"token,omitempty"`
- KeyAuthorization string `json:"keyAuthorization,omitempty"`
- TLS bool `json:"tls,omitempty"`
- Iterations int `json:"n,omitempty"`
- Error RemoteError `json:"error,omitempty"`
- ValidationRecords []validationRecord `json:"validationRecord,omitempty"`
-}
-
-type csrMessage struct {
- Resource string `json:"resource,omitempty"`
- Csr string `json:"csr"`
- Authorizations []string `json:"authorizations"`
-}
-
-type revokeCertMessage struct {
- Resource string `json:"resource"`
- Certificate string `json:"certificate"`
-}
-
-type deactivateAuthMessage struct {
- Resource string `json:"resource,omitempty"`
- Status string `jsom:"status"`
-}
-
-// CertificateResource represents a CA issued certificate.
-// PrivateKey, Certificate and IssuerCertificate are all
-// already PEM encoded and can be directly written to disk.
-// Certificate may be a certificate bundle, depending on the
-// options supplied to create it.
-type CertificateResource struct {
- Domain string `json:"domain"`
- CertURL string `json:"certUrl"`
- CertStableURL string `json:"certStableUrl"`
- AccountRef string `json:"accountRef,omitempty"`
- PrivateKey []byte `json:"-"`
- Certificate []byte `json:"-"`
- IssuerCertificate []byte `json:"-"`
- CSR []byte `json:"-"`
-}
diff --git a/vendor/github.com/xenolf/lego/acme/pop_challenge.go b/vendor/github.com/xenolf/lego/acme/pop_challenge.go
deleted file mode 100644
index 8d2a213b0..000000000
--- a/vendor/github.com/xenolf/lego/acme/pop_challenge.go
+++ /dev/null
@@ -1 +0,0 @@
-package acme
diff --git a/vendor/github.com/xenolf/lego/acme/provider.go b/vendor/github.com/xenolf/lego/acme/provider.go
deleted file mode 100644
index d177ff07a..000000000
--- a/vendor/github.com/xenolf/lego/acme/provider.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package acme
-
-import "time"
-
-// ChallengeProvider enables implementing a custom challenge
-// provider. Present presents the solution to a challenge available to
-// be solved. CleanUp will be called by the challenge if Present ends
-// in a non-error state.
-type ChallengeProvider interface {
- Present(domain, token, keyAuth string) error
- CleanUp(domain, token, keyAuth string) error
-}
-
-// ChallengeProviderTimeout allows for implementing a
-// ChallengeProvider where an unusually long timeout is required when
-// waiting for an ACME challenge to be satisfied, such as when
-// checking for DNS record progagation. If an implementor of a
-// ChallengeProvider provides a Timeout method, then the return values
-// of the Timeout method will be used when appropriate by the acme
-// package. The interval value is the time between checks.
-//
-// The default values used for timeout and interval are 60 seconds and
-// 2 seconds respectively. These are used when no Timeout method is
-// defined for the ChallengeProvider.
-type ChallengeProviderTimeout interface {
- ChallengeProvider
- Timeout() (timeout, interval time.Duration)
-}
diff --git a/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1 b/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1
deleted file mode 100644
index 3098f99b5..000000000
--- a/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1
+++ /dev/null
@@ -1,5 +0,0 @@
-domain company.com
-nameserver 10.200.3.249
-nameserver 10.200.3.250:5353
-nameserver 2001:4860:4860::8844
-nameserver [10.0.0.1]:5353
diff --git a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge.go b/vendor/github.com/xenolf/lego/acme/tls_sni_challenge.go
deleted file mode 100644
index 34383cbfa..000000000
--- a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package acme
-
-import (
- "crypto/rsa"
- "crypto/sha256"
- "crypto/tls"
- "encoding/hex"
- "fmt"
- "log"
-)
-
-type tlsSNIChallenge struct {
- jws *jws
- validate validateFunc
- provider ChallengeProvider
-}
-
-func (t *tlsSNIChallenge) Solve(chlng challenge, domain string) error {
- // FIXME: https://github.com/ietf-wg-acme/acme/pull/22
- // Currently we implement this challenge to track boulder, not the current spec!
-
- logf("[INFO][%s] acme: Trying to solve TLS-SNI-01", domain)
-
- // Generate the Key Authorization for the challenge
- keyAuth, err := getKeyAuthorization(chlng.Token, t.jws.privKey)
- if err != nil {
- return err
- }
-
- err = t.provider.Present(domain, chlng.Token, keyAuth)
- if err != nil {
- return fmt.Errorf("[%s] error presenting token: %v", domain, err)
- }
- defer func() {
- err := t.provider.CleanUp(domain, chlng.Token, keyAuth)
- if err != nil {
- log.Printf("[%s] error cleaning up: %v", domain, err)
- }
- }()
- return t.validate(t.jws, domain, chlng.URI, challenge{Resource: "challenge", Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
-}
-
-// TLSSNI01ChallengeCert returns a certificate and target domain for the `tls-sni-01` challenge
-func TLSSNI01ChallengeCert(keyAuth string) (tls.Certificate, string, error) {
- // generate a new RSA key for the certificates
- tempPrivKey, err := generatePrivateKey(RSA2048)
- if err != nil {
- return tls.Certificate{}, "", err
- }
- rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
- rsaPrivPEM := pemEncode(rsaPrivKey)
-
- zBytes := sha256.Sum256([]byte(keyAuth))
- z := hex.EncodeToString(zBytes[:sha256.Size])
- domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:])
- tempCertPEM, err := generatePemCert(rsaPrivKey, domain)
- if err != nil {
- return tls.Certificate{}, "", err
- }
-
- certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
- if err != nil {
- return tls.Certificate{}, "", err
- }
-
- return certificate, domain, nil
-}
diff --git a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_server.go b/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_server.go
deleted file mode 100644
index df00fbb5a..000000000
--- a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_server.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package acme
-
-import (
- "crypto/tls"
- "fmt"
- "net"
- "net/http"
-)
-
-// TLSProviderServer implements ChallengeProvider for `TLS-SNI-01` challenge
-// It may be instantiated without using the NewTLSProviderServer function if
-// you want only to use the default values.
-type TLSProviderServer struct {
- iface string
- port string
- done chan bool
- listener net.Listener
-}
-
-// NewTLSProviderServer creates a new TLSProviderServer on the selected interface and port.
-// Setting iface and / or port to an empty string will make the server fall back to
-// the "any" interface and port 443 respectively.
-func NewTLSProviderServer(iface, port string) *TLSProviderServer {
- return &TLSProviderServer{iface: iface, port: port}
-}
-
-// Present makes the keyAuth available as a cert
-func (s *TLSProviderServer) Present(domain, token, keyAuth string) error {
- if s.port == "" {
- s.port = "443"
- }
-
- cert, _, err := TLSSNI01ChallengeCert(keyAuth)
- if err != nil {
- return err
- }
-
- tlsConf := new(tls.Config)
- tlsConf.Certificates = []tls.Certificate{cert}
-
- s.listener, err = tls.Listen("tcp", net.JoinHostPort(s.iface, s.port), tlsConf)
- if err != nil {
- return fmt.Errorf("Could not start HTTPS server for challenge -> %v", err)
- }
-
- s.done = make(chan bool)
- go func() {
- http.Serve(s.listener, nil)
- s.done <- true
- }()
- return nil
-}
-
-// CleanUp closes the HTTP server.
-func (s *TLSProviderServer) CleanUp(domain, token, keyAuth string) error {
- if s.listener == nil {
- return nil
- }
- s.listener.Close()
- <-s.done
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go b/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go
deleted file mode 100644
index 83b2833a9..000000000
--- a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package acme
-
-import (
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/tls"
- "encoding/hex"
- "fmt"
- "strings"
- "testing"
-)
-
-func TestTLSSNIChallenge(t *testing.T) {
- privKey, _ := rsa.GenerateKey(rand.Reader, 512)
- j := &jws{privKey: privKey}
- clientChallenge := challenge{Type: TLSSNI01, Token: "tlssni1"}
- mockValidate := func(_ *jws, _, _ string, chlng challenge) error {
- conn, err := tls.Dial("tcp", "localhost:23457", &tls.Config{
- InsecureSkipVerify: true,
- })
- if err != nil {
- t.Errorf("Expected to connect to challenge server without an error. %s", err.Error())
- }
-
- // Expect the server to only return one certificate
- connState := conn.ConnectionState()
- if count := len(connState.PeerCertificates); count != 1 {
- t.Errorf("Expected the challenge server to return exactly one certificate but got %d", count)
- }
-
- remoteCert := connState.PeerCertificates[0]
- if count := len(remoteCert.DNSNames); count != 1 {
- t.Errorf("Expected the challenge certificate to have exactly one DNSNames entry but had %d", count)
- }
-
- zBytes := sha256.Sum256([]byte(chlng.KeyAuthorization))
- z := hex.EncodeToString(zBytes[:sha256.Size])
- domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:])
-
- if remoteCert.DNSNames[0] != domain {
- t.Errorf("Expected the challenge certificate DNSName to match %s but was %s", domain, remoteCert.DNSNames[0])
- }
-
- return nil
- }
- solver := &tlsSNIChallenge{jws: j, validate: mockValidate, provider: &TLSProviderServer{port: "23457"}}
-
- if err := solver.Solve(clientChallenge, "localhost:23457"); err != nil {
- t.Errorf("Solve error: got %v, want nil", err)
- }
-}
-
-func TestTLSSNIChallengeInvalidPort(t *testing.T) {
- privKey, _ := rsa.GenerateKey(rand.Reader, 128)
- j := &jws{privKey: privKey}
- clientChallenge := challenge{Type: TLSSNI01, Token: "tlssni2"}
- solver := &tlsSNIChallenge{jws: j, validate: stubValidate, provider: &TLSProviderServer{port: "123456"}}
-
- if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil {
- t.Errorf("Solve error: got %v, want error", err)
- } else if want, want18 := "invalid port 123456", "123456: invalid port"; !strings.HasSuffix(err.Error(), want) && !strings.HasSuffix(err.Error(), want18) {
- t.Errorf("Solve error: got %q, want suffix %q", err.Error(), want)
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/utils.go b/vendor/github.com/xenolf/lego/acme/utils.go
deleted file mode 100644
index 2fa0db304..000000000
--- a/vendor/github.com/xenolf/lego/acme/utils.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package acme
-
-import (
- "fmt"
- "time"
-)
-
-// WaitFor polls the given function 'f', once every 'interval', up to 'timeout'.
-func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error {
- var lastErr string
- timeup := time.After(timeout)
- for {
- select {
- case <-timeup:
- return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr)
- default:
- }
-
- stop, err := f()
- if stop {
- return nil
- }
- if err != nil {
- lastErr = err.Error()
- }
-
- time.Sleep(interval)
- }
-}
diff --git a/vendor/github.com/xenolf/lego/acme/utils_test.go b/vendor/github.com/xenolf/lego/acme/utils_test.go
deleted file mode 100644
index 158af4116..000000000
--- a/vendor/github.com/xenolf/lego/acme/utils_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package acme
-
-import (
- "testing"
- "time"
-)
-
-func TestWaitForTimeout(t *testing.T) {
- c := make(chan error)
- go func() {
- err := WaitFor(3*time.Second, 1*time.Second, func() (bool, error) {
- return false, nil
- })
- c <- err
- }()
-
- timeout := time.After(4 * time.Second)
- select {
- case <-timeout:
- t.Fatal("timeout exceeded")
- case err := <-c:
- if err == nil {
- t.Errorf("expected timeout error; got %v", err)
- }
- }
-}
diff --git a/vendor/github.com/xenolf/lego/cli.go b/vendor/github.com/xenolf/lego/cli.go
deleted file mode 100644
index 58567be9f..000000000
--- a/vendor/github.com/xenolf/lego/cli.go
+++ /dev/null
@@ -1,232 +0,0 @@
-// Let's Encrypt client to go!
-// CLI application for generating Let's Encrypt certificates using the ACME package.
-package main
-
-import (
- "fmt"
- "log"
- "os"
- "path"
- "strings"
- "text/tabwriter"
-
- "github.com/urfave/cli"
- "github.com/xenolf/lego/acme"
-)
-
-// Logger is used to log errors; if nil, the default log.Logger is used.
-var Logger *log.Logger
-
-// logger is an helper function to retrieve the available logger
-func logger() *log.Logger {
- if Logger == nil {
- Logger = log.New(os.Stderr, "", log.LstdFlags)
- }
- return Logger
-}
-
-var gittag string
-
-func main() {
- app := cli.NewApp()
- app.Name = "lego"
- app.Usage = "Let's Encrypt client written in Go"
-
- version := "0.4.1"
- if strings.HasPrefix(gittag, "v") {
- version = gittag
- }
-
- app.Version = version
-
- acme.UserAgent = "lego/" + app.Version
-
- defaultPath := ""
- cwd, err := os.Getwd()
- if err == nil {
- defaultPath = path.Join(cwd, ".lego")
- }
-
- app.Before = func(c *cli.Context) error {
- if c.GlobalString("path") == "" {
- logger().Fatal("Could not determine current working directory. Please pass --path.")
- }
- return nil
- }
-
- app.Commands = []cli.Command{
- {
- Name: "run",
- Usage: "Register an account, then create and install a certificate",
- Action: run,
- Flags: []cli.Flag{
- cli.BoolFlag{
- Name: "no-bundle",
- Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
- },
- cli.BoolFlag{
- Name: "must-staple",
- Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
- },
- },
- },
- {
- Name: "revoke",
- Usage: "Revoke a certificate",
- Action: revoke,
- },
- {
- Name: "renew",
- Usage: "Renew a certificate",
- Action: renew,
- Flags: []cli.Flag{
- cli.IntFlag{
- Name: "days",
- Value: 0,
- Usage: "The number of days left on a certificate to renew it.",
- },
- cli.BoolFlag{
- Name: "reuse-key",
- Usage: "Used to indicate you want to reuse your current private key for the new certificate.",
- },
- cli.BoolFlag{
- Name: "no-bundle",
- Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
- },
- cli.BoolFlag{
- Name: "must-staple",
- Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
- },
- },
- },
- {
- Name: "dnshelp",
- Usage: "Shows additional help for the --dns global option",
- Action: dnshelp,
- },
- }
-
- app.Flags = []cli.Flag{
- cli.StringSliceFlag{
- Name: "domains, d",
- Usage: "Add a domain to the process. Can be specified multiple times.",
- },
- cli.StringFlag{
- Name: "csr, c",
- Usage: "Certificate signing request filename, if an external CSR is to be used",
- },
- cli.StringFlag{
- Name: "server, s",
- Value: "https://acme-v01.api.letsencrypt.org/directory",
- Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.",
- },
- cli.StringFlag{
- Name: "email, m",
- Usage: "Email used for registration and recovery contact.",
- },
- cli.BoolFlag{
- Name: "accept-tos, a",
- Usage: "By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.",
- },
- cli.StringFlag{
- Name: "key-type, k",
- Value: "rsa2048",
- Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384",
- },
- cli.StringFlag{
- Name: "path",
- Usage: "Directory to use for storing the data",
- Value: defaultPath,
- },
- cli.StringSliceFlag{
- Name: "exclude, x",
- Usage: "Explicitly disallow solvers by name from being used. Solvers: \"http-01\", \"tls-sni-01\".",
- },
- cli.StringFlag{
- Name: "webroot",
- Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge",
- },
- cli.StringSliceFlag{
- Name: "memcached-host",
- Usage: "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.",
- },
- cli.StringFlag{
- Name: "http",
- Usage: "Set the port and interface to use for HTTP based challenges to listen on. Supported: interface:port or :port",
- },
- cli.StringFlag{
- Name: "tls",
- Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port",
- },
- cli.StringFlag{
- Name: "dns",
- Usage: "Solve a DNS challenge using the specified provider. Disables all other challenges. Run 'lego dnshelp' for help on usage.",
- },
- cli.IntFlag{
- Name: "http-timeout",
- Usage: "Set the HTTP timeout value to a specific value in seconds. The default is 10 seconds.",
- },
- cli.IntFlag{
- Name: "dns-timeout",
- Usage: "Set the DNS timeout value to a specific value in seconds. The default is 10 seconds.",
- },
- cli.StringSliceFlag{
- Name: "dns-resolvers",
- Usage: "Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.",
- },
- cli.BoolFlag{
- Name: "pem",
- Usage: "Generate a .pem file by concatanating the .key and .crt files together.",
- },
- }
-
- err = app.Run(os.Args)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func dnshelp(c *cli.Context) error {
- fmt.Printf(
- `Credentials for DNS providers must be passed through environment variables.
-
-Here is an example bash command using the CloudFlare DNS provider:
-
- $ CLOUDFLARE_EMAIL=foo@bar.com \
- CLOUDFLARE_API_KEY=b9841238feb177a84330febba8a83208921177bffe733 \
- lego --dns cloudflare --domains www.example.com --email me@bar.com run
-
-`)
-
- w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
- fmt.Fprintln(w, "Valid providers and their associated credential environment variables:")
- fmt.Fprintln(w)
- fmt.Fprintln(w, "\tazure:\tAZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP")
- fmt.Fprintln(w, "\tauroradns:\tAURORA_USER_ID, AURORA_KEY, AURORA_ENDPOINT")
- fmt.Fprintln(w, "\tcloudflare:\tCLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY")
- fmt.Fprintln(w, "\tdigitalocean:\tDO_AUTH_TOKEN")
- fmt.Fprintln(w, "\tdnsimple:\tDNSIMPLE_EMAIL, DNSIMPLE_OAUTH_TOKEN")
- fmt.Fprintln(w, "\tdnsmadeeasy:\tDNSMADEEASY_API_KEY, DNSMADEEASY_API_SECRET")
- fmt.Fprintln(w, "\texoscale:\tEXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT")
- fmt.Fprintln(w, "\tgandi:\tGANDI_API_KEY")
- fmt.Fprintln(w, "\tgcloud:\tGCE_PROJECT, GCE_SERVICE_ACCOUNT_FILE")
- fmt.Fprintln(w, "\tlinode:\tLINODE_API_KEY")
- fmt.Fprintln(w, "\tmanual:\tnone")
- fmt.Fprintln(w, "\tnamecheap:\tNAMECHEAP_API_USER, NAMECHEAP_API_KEY")
- fmt.Fprintln(w, "\trackspace:\tRACKSPACE_USER, RACKSPACE_API_KEY")
- fmt.Fprintln(w, "\trfc2136:\tRFC2136_TSIG_KEY, RFC2136_TSIG_SECRET,\n\t\tRFC2136_TSIG_ALGORITHM, RFC2136_NAMESERVER")
- fmt.Fprintln(w, "\troute53:\tAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_HOSTED_ZONE_ID")
- fmt.Fprintln(w, "\tdyn:\tDYN_CUSTOMER_NAME, DYN_USER_NAME, DYN_PASSWORD")
- fmt.Fprintln(w, "\tvultr:\tVULTR_API_KEY")
- fmt.Fprintln(w, "\tovh:\tOVH_ENDPOINT, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY")
- fmt.Fprintln(w, "\tpdns:\tPDNS_API_KEY, PDNS_API_URL")
- fmt.Fprintln(w, "\tdnspod:\tDNSPOD_API_KEY")
- fmt.Fprintln(w, "\totc:\tOTC_USER_NAME, OTC_PASSWORD, OTC_PROJECT_NAME, OTC_DOMAIN_NAME, OTC_IDENTITY_ENDPOINT")
- w.Flush()
-
- fmt.Println(`
-For a more detailed explanation of a DNS provider's credential variables,
-please consult their online documentation.`)
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/cli_handlers.go b/vendor/github.com/xenolf/lego/cli_handlers.go
deleted file mode 100644
index b8790c4b2..000000000
--- a/vendor/github.com/xenolf/lego/cli_handlers.go
+++ /dev/null
@@ -1,423 +0,0 @@
-package main
-
-import (
- "bufio"
- "bytes"
- "crypto/x509"
- "encoding/json"
- "encoding/pem"
- "io/ioutil"
- "net/http"
- "os"
- "path"
- "strings"
- "time"
-
- "github.com/urfave/cli"
- "github.com/xenolf/lego/acme"
- "github.com/xenolf/lego/providers/dns"
- "github.com/xenolf/lego/providers/http/memcached"
- "github.com/xenolf/lego/providers/http/webroot"
-)
-
-func checkFolder(path string) error {
- if _, err := os.Stat(path); os.IsNotExist(err) {
- return os.MkdirAll(path, 0700)
- }
- return nil
-}
-
-func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
-
- if c.GlobalIsSet("http-timeout") {
- acme.HTTPClient = http.Client{Timeout: time.Duration(c.GlobalInt("http-timeout")) * time.Second}
- }
-
- if c.GlobalIsSet("dns-timeout") {
- acme.DNSTimeout = time.Duration(c.GlobalInt("dns-timeout")) * time.Second
- }
-
- if len(c.GlobalStringSlice("dns-resolvers")) > 0 {
- resolvers := []string{}
- for _, resolver := range c.GlobalStringSlice("dns-resolvers") {
- if !strings.Contains(resolver, ":") {
- resolver += ":53"
- }
- resolvers = append(resolvers, resolver)
- }
- acme.RecursiveNameservers = resolvers
- }
-
- err := checkFolder(c.GlobalString("path"))
- if err != nil {
- logger().Fatalf("Could not check/create path: %s", err.Error())
- }
-
- conf := NewConfiguration(c)
- if len(c.GlobalString("email")) == 0 {
- logger().Fatal("You have to pass an account (email address) to the program using --email or -m")
- }
-
- //TODO: move to account struct? Currently MUST pass email.
- acc := NewAccount(c.GlobalString("email"), conf)
-
- keyType, err := conf.KeyType()
- if err != nil {
- logger().Fatal(err.Error())
- }
-
- client, err := acme.NewClient(c.GlobalString("server"), acc, keyType)
- if err != nil {
- logger().Fatalf("Could not create client: %s", err.Error())
- }
-
- if len(c.GlobalStringSlice("exclude")) > 0 {
- client.ExcludeChallenges(conf.ExcludedSolvers())
- }
-
- if c.GlobalIsSet("webroot") {
- provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot"))
- if err != nil {
- logger().Fatal(err)
- }
-
- client.SetChallengeProvider(acme.HTTP01, provider)
-
- // --webroot=foo indicates that the user specifically want to do a HTTP challenge
- // infer that the user also wants to exclude all other challenges
- client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01})
- }
- if c.GlobalIsSet("memcached-host") {
- provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host"))
- if err != nil {
- logger().Fatal(err)
- }
-
- client.SetChallengeProvider(acme.HTTP01, provider)
-
- // --memcached-host=foo:11211 indicates that the user specifically want to do a HTTP challenge
- // infer that the user also wants to exclude all other challenges
- client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01})
- }
- if c.GlobalIsSet("http") {
- if strings.Index(c.GlobalString("http"), ":") == -1 {
- logger().Fatalf("The --http switch only accepts interface:port or :port for its argument.")
- }
- client.SetHTTPAddress(c.GlobalString("http"))
- }
-
- if c.GlobalIsSet("tls") {
- if strings.Index(c.GlobalString("tls"), ":") == -1 {
- logger().Fatalf("The --tls switch only accepts interface:port or :port for its argument.")
- }
- client.SetTLSAddress(c.GlobalString("tls"))
- }
-
- if c.GlobalIsSet("dns") {
- provider, err := dns.NewDNSChallengeProviderByName(c.GlobalString("dns"))
- if err != nil {
- logger().Fatal(err)
- }
-
- client.SetChallengeProvider(acme.DNS01, provider)
-
- // --dns=foo indicates that the user specifically want to do a DNS challenge
- // infer that the user also wants to exclude all other challenges
- client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01})
- }
-
- return conf, acc, client
-}
-
-func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
- // We store the certificate, private key and metadata in different files
- // as web servers would not be able to work with a combined file.
- certOut := path.Join(conf.CertPath(), certRes.Domain+".crt")
- privOut := path.Join(conf.CertPath(), certRes.Domain+".key")
- pemOut := path.Join(conf.CertPath(), certRes.Domain+".pem")
- metaOut := path.Join(conf.CertPath(), certRes.Domain+".json")
- issuerOut := path.Join(conf.CertPath(), certRes.Domain+".issuer.crt")
-
- err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
- if err != nil {
- logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
- }
-
- if certRes.IssuerCertificate != nil {
- err = ioutil.WriteFile(issuerOut, certRes.IssuerCertificate, 0600)
- if err != nil {
- logger().Fatalf("Unable to save IssuerCertificate for domain %s\n\t%s", certRes.Domain, err.Error())
- }
- }
-
- if certRes.PrivateKey != nil {
- // if we were given a CSR, we don't know the private key
- err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
- if err != nil {
- logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
- }
-
- if conf.context.GlobalBool("pem") {
- err = ioutil.WriteFile(pemOut, bytes.Join([][]byte{certRes.Certificate, certRes.PrivateKey}, nil), 0600)
- if err != nil {
- logger().Fatalf("Unable to save Certificate and PrivateKey in .pem for domain %s\n\t%s", certRes.Domain, err.Error())
- }
- }
-
- } else if conf.context.GlobalBool("pem") {
- // we don't have the private key; can't write the .pem file
- logger().Fatalf("Unable to save pem without private key for domain %s\n\t%s; are you using a CSR?", certRes.Domain, err.Error())
- }
-
- jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
- if err != nil {
- logger().Fatalf("Unable to marshal CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
- }
-
- err = ioutil.WriteFile(metaOut, jsonBytes, 0600)
- if err != nil {
- logger().Fatalf("Unable to save CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
- }
-}
-
-func handleTOS(c *cli.Context, client *acme.Client, acc *Account) {
- // Check for a global accept override
- if c.GlobalBool("accept-tos") {
- err := client.AgreeToTOS()
- if err != nil {
- logger().Fatalf("Could not agree to TOS: %s", err.Error())
- }
-
- acc.Save()
- return
- }
-
- reader := bufio.NewReader(os.Stdin)
- logger().Printf("Please review the TOS at %s", acc.Registration.TosURL)
-
- for {
- logger().Println("Do you accept the TOS? Y/n")
- text, err := reader.ReadString('\n')
- if err != nil {
- logger().Fatalf("Could not read from console: %s", err.Error())
- }
-
- text = strings.Trim(text, "\r\n")
-
- if text == "n" {
- logger().Fatal("You did not accept the TOS. Unable to proceed.")
- }
-
- if text == "Y" || text == "y" || text == "" {
- err = client.AgreeToTOS()
- if err != nil {
- logger().Fatalf("Could not agree to TOS: %s", err.Error())
- }
- acc.Save()
- break
- }
-
- logger().Println("Your input was invalid. Please answer with one of Y/y, n or by pressing enter.")
- }
-}
-
-func readCSRFile(filename string) (*x509.CertificateRequest, error) {
- bytes, err := ioutil.ReadFile(filename)
- if err != nil {
- return nil, err
- }
- raw := bytes
-
- // see if we can find a PEM-encoded CSR
- var p *pem.Block
- rest := bytes
- for {
- // decode a PEM block
- p, rest = pem.Decode(rest)
-
- // did we fail?
- if p == nil {
- break
- }
-
- // did we get a CSR?
- if p.Type == "CERTIFICATE REQUEST" {
- raw = p.Bytes
- }
- }
-
- // no PEM-encoded CSR
- // assume we were given a DER-encoded ASN.1 CSR
- // (if this assumption is wrong, parsing these bytes will fail)
- return x509.ParseCertificateRequest(raw)
-}
-
-func run(c *cli.Context) error {
- conf, acc, client := setup(c)
- if acc.Registration == nil {
- reg, err := client.Register()
- if err != nil {
- logger().Fatalf("Could not complete registration\n\t%s", err.Error())
- }
-
- acc.Registration = reg
- acc.Save()
-
- logger().Print("!!!! HEADS UP !!!!")
- logger().Printf(`
- Your account credentials have been saved in your Let's Encrypt
- configuration directory at "%s".
- You should make a secure backup of this folder now. This
- configuration directory will also contain certificates and
- private keys obtained from Let's Encrypt so making regular
- backups of this folder is ideal.`, conf.AccountPath(c.GlobalString("email")))
-
- }
-
- // If the agreement URL is empty, the account still needs to accept the LE TOS.
- if acc.Registration.Body.Agreement == "" {
- handleTOS(c, client, acc)
- }
-
- // we require either domains or csr, but not both
- hasDomains := len(c.GlobalStringSlice("domains")) > 0
- hasCsr := len(c.GlobalString("csr")) > 0
- if hasDomains && hasCsr {
- logger().Fatal("Please specify either --domains/-d or --csr/-c, but not both")
- }
- if !hasDomains && !hasCsr {
- logger().Fatal("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
- }
-
- var cert acme.CertificateResource
- var failures map[string]error
-
- if hasDomains {
- // obtain a certificate, generating a new private key
- cert, failures = client.ObtainCertificate(c.GlobalStringSlice("domains"), !c.Bool("no-bundle"), nil, c.Bool("must-staple"))
- } else {
- // read the CSR
- csr, err := readCSRFile(c.GlobalString("csr"))
- if err != nil {
- // we couldn't read the CSR
- failures = map[string]error{"csr": err}
- } else {
- // obtain a certificate for this CSR
- cert, failures = client.ObtainCertificateForCSR(*csr, !c.Bool("no-bundle"))
- }
- }
-
- if len(failures) > 0 {
- for k, v := range failures {
- logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
- }
-
- // Make sure to return a non-zero exit code if ObtainSANCertificate
- // returned at least one error. Due to us not returning partial
- // certificate we can just exit here instead of at the end.
- os.Exit(1)
- }
-
- err := checkFolder(conf.CertPath())
- if err != nil {
- logger().Fatalf("Could not check/create path: %s", err.Error())
- }
-
- saveCertRes(cert, conf)
-
- return nil
-}
-
-func revoke(c *cli.Context) error {
- conf, acc, client := setup(c)
- if acc.Registration == nil {
- logger().Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email)
- }
-
- err := checkFolder(conf.CertPath())
- if err != nil {
- logger().Fatalf("Could not check/create path: %s", err.Error())
- }
-
- for _, domain := range c.GlobalStringSlice("domains") {
- logger().Printf("Trying to revoke certificate for domain %s", domain)
-
- certPath := path.Join(conf.CertPath(), domain+".crt")
- certBytes, err := ioutil.ReadFile(certPath)
-
- err = client.RevokeCertificate(certBytes)
- if err != nil {
- logger().Fatalf("Error while revoking the certificate for domain %s\n\t%s", domain, err.Error())
- } else {
- logger().Print("Certificate was revoked.")
- }
- }
-
- return nil
-}
-
-func renew(c *cli.Context) error {
- conf, acc, client := setup(c)
- if acc.Registration == nil {
- logger().Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email)
- }
-
- if len(c.GlobalStringSlice("domains")) <= 0 {
- logger().Fatal("Please specify at least one domain.")
- }
-
- domain := c.GlobalStringSlice("domains")[0]
-
- // load the cert resource from files.
- // We store the certificate, private key and metadata in different files
- // as web servers would not be able to work with a combined file.
- certPath := path.Join(conf.CertPath(), domain+".crt")
- privPath := path.Join(conf.CertPath(), domain+".key")
- metaPath := path.Join(conf.CertPath(), domain+".json")
-
- certBytes, err := ioutil.ReadFile(certPath)
- if err != nil {
- logger().Fatalf("Error while loading the certificate for domain %s\n\t%s", domain, err.Error())
- }
-
- if c.IsSet("days") {
- expTime, err := acme.GetPEMCertExpiration(certBytes)
- if err != nil {
- logger().Printf("Could not get Certification expiration for domain %s", domain)
- }
-
- if int(expTime.Sub(time.Now()).Hours()/24.0) > c.Int("days") {
- return nil
- }
- }
-
- metaBytes, err := ioutil.ReadFile(metaPath)
- if err != nil {
- logger().Fatalf("Error while loading the meta data for domain %s\n\t%s", domain, err.Error())
- }
-
- var certRes acme.CertificateResource
- err = json.Unmarshal(metaBytes, &certRes)
- if err != nil {
- logger().Fatalf("Error while marshalling the meta data for domain %s\n\t%s", domain, err.Error())
- }
-
- if c.Bool("reuse-key") {
- keyBytes, err := ioutil.ReadFile(privPath)
- if err != nil {
- logger().Fatalf("Error while loading the private key for domain %s\n\t%s", domain, err.Error())
- }
- certRes.PrivateKey = keyBytes
- }
-
- certRes.Certificate = certBytes
-
- newCert, err := client.RenewCertificate(certRes, !c.Bool("no-bundle"), c.Bool("must-staple"))
- if err != nil {
- logger().Fatalf("%s", err.Error())
- }
-
- saveCertRes(newCert, conf)
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/configuration.go b/vendor/github.com/xenolf/lego/configuration.go
deleted file mode 100644
index f92c1fe96..000000000
--- a/vendor/github.com/xenolf/lego/configuration.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package main
-
-import (
- "fmt"
- "net/url"
- "os"
- "path"
- "strings"
-
- "github.com/urfave/cli"
- "github.com/xenolf/lego/acme"
-)
-
-// Configuration type from CLI and config files.
-type Configuration struct {
- context *cli.Context
-}
-
-// NewConfiguration creates a new configuration from CLI data.
-func NewConfiguration(c *cli.Context) *Configuration {
- return &Configuration{context: c}
-}
-
-// KeyType the type from which private keys should be generated
-func (c *Configuration) KeyType() (acme.KeyType, error) {
- switch strings.ToUpper(c.context.GlobalString("key-type")) {
- case "RSA2048":
- return acme.RSA2048, nil
- case "RSA4096":
- return acme.RSA4096, nil
- case "RSA8192":
- return acme.RSA8192, nil
- case "EC256":
- return acme.EC256, nil
- case "EC384":
- return acme.EC384, nil
- }
-
- return "", fmt.Errorf("Unsupported KeyType: %s", c.context.GlobalString("key-type"))
-}
-
-// ExcludedSolvers is a list of solvers that are to be excluded.
-func (c *Configuration) ExcludedSolvers() (cc []acme.Challenge) {
- for _, s := range c.context.GlobalStringSlice("exclude") {
- cc = append(cc, acme.Challenge(s))
- }
- return
-}
-
-// ServerPath returns the OS dependent path to the data for a specific CA
-func (c *Configuration) ServerPath() string {
- srv, _ := url.Parse(c.context.GlobalString("server"))
- srvStr := strings.Replace(srv.Host, ":", "_", -1)
- return strings.Replace(srvStr, "/", string(os.PathSeparator), -1)
-}
-
-// CertPath gets the path for certificates.
-func (c *Configuration) CertPath() string {
- return path.Join(c.context.GlobalString("path"), "certificates")
-}
-
-// AccountsPath returns the OS dependent path to the
-// local accounts for a specific CA
-func (c *Configuration) AccountsPath() string {
- return path.Join(c.context.GlobalString("path"), "accounts", c.ServerPath())
-}
-
-// AccountPath returns the OS dependent path to a particular account
-func (c *Configuration) AccountPath(acc string) string {
- return path.Join(c.AccountsPath(), acc)
-}
-
-// AccountKeysPath returns the OS dependent path to the keys of a particular account
-func (c *Configuration) AccountKeysPath(acc string) string {
- return path.Join(c.AccountPath(acc), "keys")
-}
diff --git a/vendor/github.com/xenolf/lego/crypto.go b/vendor/github.com/xenolf/lego/crypto.go
deleted file mode 100644
index 8b23e2fc1..000000000
--- a/vendor/github.com/xenolf/lego/crypto.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package main
-
-import (
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/x509"
- "encoding/pem"
- "errors"
- "io/ioutil"
- "os"
-)
-
-func generatePrivateKey(file string) (crypto.PrivateKey, error) {
-
- privateKey, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
- if err != nil {
- return nil, err
- }
-
- keyBytes, err := x509.MarshalECPrivateKey(privateKey)
- if err != nil {
- return nil, err
- }
-
- pemKey := pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
-
- certOut, err := os.Create(file)
- if err != nil {
- return nil, err
- }
-
- pem.Encode(certOut, &pemKey)
- certOut.Close()
-
- return privateKey, nil
-}
-
-func loadPrivateKey(file string) (crypto.PrivateKey, error) {
- keyBytes, err := ioutil.ReadFile(file)
- if err != nil {
- return nil, err
- }
-
- keyBlock, _ := pem.Decode(keyBytes)
-
- switch keyBlock.Type {
- case "RSA PRIVATE KEY":
- return x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
- case "EC PRIVATE KEY":
- return x509.ParseECPrivateKey(keyBlock.Bytes)
- }
-
- return nil, errors.New("Unknown private key type.")
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go b/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go
deleted file mode 100644
index 55b48f9b4..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go
+++ /dev/null
@@ -1,141 +0,0 @@
-package auroradns
-
-import (
- "fmt"
- "github.com/edeckers/auroradnsclient"
- "github.com/edeckers/auroradnsclient/records"
- "github.com/edeckers/auroradnsclient/zones"
- "github.com/xenolf/lego/acme"
- "os"
- "sync"
-)
-
-// DNSProvider describes a provider for AuroraDNS
-type DNSProvider struct {
- recordIDs map[string]string
- recordIDsMu sync.Mutex
- client *auroradnsclient.AuroraDNSClient
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for AuroraDNS.
-// Credentials must be passed in the environment variables: AURORA_USER_ID
-// and AURORA_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- userID := os.Getenv("AURORA_USER_ID")
- key := os.Getenv("AURORA_KEY")
-
- endpoint := os.Getenv("AURORA_ENDPOINT")
- if endpoint == "" {
- endpoint = "https://api.auroradns.eu"
- }
-
- return NewDNSProviderCredentials(endpoint, userID, key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for AuroraDNS.
-func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSProvider, error) {
- client, err := auroradnsclient.NewAuroraDNSClient(baseURL, userID, key)
- if err != nil {
- return nil, err
- }
-
- return &DNSProvider{
- client: client,
- recordIDs: make(map[string]string),
- }, nil
-}
-
-func (provider *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
- zs, err := provider.client.GetZones()
-
- if err != nil {
- return zones.ZoneRecord{}, err
- }
-
- for _, element := range zs {
- if element.Name == name {
- return element, nil
- }
- }
-
- return zones.ZoneRecord{}, fmt.Errorf("Could not find Zone record")
-}
-
-// Present creates a record with a secret
-func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- // 1. Aurora will happily create the TXT record when it is provided a fqdn,
- // but it will only appear in the control panel and will not be
- // propagated to DNS servers. Extract and use subdomain instead.
- // 2. A trailing dot in the fqdn will cause Aurora to add a trailing dot to
- // the subdomain, resulting in _acme-challenge..<domain> rather
- // than _acme-challenge.<domain>
-
- subdomain := fqdn[0 : len(fqdn)-len(authZone)-1]
-
- authZone = acme.UnFqdn(authZone)
-
- zoneRecord, err := provider.getZoneInformationByName(authZone)
-
- reqData :=
- records.CreateRecordRequest{
- RecordType: "TXT",
- Name: subdomain,
- Content: value,
- TTL: 300,
- }
-
- respData, err := provider.client.CreateRecord(zoneRecord.ID, reqData)
- if err != nil {
- return fmt.Errorf("Could not create record: '%s'.", err)
- }
-
- provider.recordIDsMu.Lock()
- provider.recordIDs[fqdn] = respData.ID
- provider.recordIDsMu.Unlock()
-
- return nil
-}
-
-// CleanUp removes a given record that was generated by Present
-func (provider *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- provider.recordIDsMu.Lock()
- recordID, ok := provider.recordIDs[fqdn]
- provider.recordIDsMu.Unlock()
-
- if !ok {
- return fmt.Errorf("Unknown recordID for '%s'", fqdn)
- }
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- authZone = acme.UnFqdn(authZone)
-
- zoneRecord, err := provider.getZoneInformationByName(authZone)
- if err != nil {
- return err
- }
-
- _, err = provider.client.RemoveRecord(zoneRecord.ID, recordID)
- if err != nil {
- return err
- }
-
- provider.recordIDsMu.Lock()
- delete(provider.recordIDs, fqdn)
- provider.recordIDsMu.Unlock()
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns_test.go b/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns_test.go
deleted file mode 100644
index f4df7fa61..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns_test.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package auroradns
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-var fakeAuroraDNSUserId = "asdf1234"
-var fakeAuroraDNSKey = "key"
-
-func TestAuroraDNSPresent(t *testing.T) {
- var requestReceived bool
-
- mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.Method == "GET" && r.URL.Path == "/zones" {
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `[{
- "id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
- "name": "example.com"
- }]`)
- return
- }
-
- requestReceived = true
-
- if got, want := r.Method, "POST"; got != want {
- t.Errorf("Expected method to be '%s' but got '%s'", want, got)
- }
-
- if got, want := r.URL.Path, "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records"; got != want {
- t.Errorf("Expected path to be '%s' but got '%s'", want, got)
- }
-
- if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
- t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
- }
-
- reqBody, err := ioutil.ReadAll(r.Body)
- if err != nil {
- t.Fatalf("Error reading request body: %v", err)
- }
-
- if got, want := string(reqBody),
- `{"type":"TXT","name":"_acme-challenge","content":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI","ttl":300}`; got != want {
-
- t.Errorf("Expected body data to be: `%s` but got `%s`", want, got)
- }
-
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `{
- "id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
- "type": "TXT",
- "name": "_acme-challenge",
- "ttl": 300
- }`)
- }))
-
- defer mock.Close()
-
- auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserId, fakeAuroraDNSKey)
- if auroraProvider == nil {
- t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
- }
-
- if err != nil {
- t.Fatalf("Expected no error creating provider, but got: %v", err)
- }
-
- err = auroraProvider.Present("example.com", "", "foobar")
- if err != nil {
- t.Fatalf("Expected no error creating TXT record, but got: %v", err)
- }
-
- if !requestReceived {
- t.Error("Expected request to be received by mock backend, but it wasn't")
- }
-}
-
-func TestAuroraDNSCleanUp(t *testing.T) {
- var requestReceived bool
-
- mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.Method == "GET" && r.URL.Path == "/zones" {
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `[{
- "id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
- "name": "example.com"
- }]`)
- return
- }
-
- if r.Method == "POST" && r.URL.Path == "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records" {
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `{
- "id": "ec56a4180-65aa-42ec-a945-5fd21dec0538",
- "type": "TXT",
- "name": "_acme-challenge",
- "ttl": 300
- }`)
- return
- }
-
- requestReceived = true
-
- if got, want := r.Method, "DELETE"; got != want {
- t.Errorf("Expected method to be '%s' but got '%s'", want, got)
- }
-
- if got, want := r.URL.Path,
- "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records/ec56a4180-65aa-42ec-a945-5fd21dec0538"; got != want {
- t.Errorf("Expected path to be '%s' but got '%s'", want, got)
- }
-
- if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
- t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
- }
-
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `{}`)
- }))
- defer mock.Close()
-
- auroraProvider, err := NewDNSProviderCredentials(mock.URL, fakeAuroraDNSUserId, fakeAuroraDNSKey)
- if auroraProvider == nil {
- t.Fatal("Expected non-nil AuroraDNS provider, but was nil")
- }
-
- if err != nil {
- t.Fatalf("Expected no error creating provider, but got: %v", err)
- }
-
- err = auroraProvider.Present("example.com", "", "foobar")
- if err != nil {
- t.Fatalf("Expected no error creating TXT record, but got: %v", err)
- }
-
- err = auroraProvider.CleanUp("example.com", "", "foobar")
- if err != nil {
- t.Fatalf("Expected no error removing TXT record, but got: %v", err)
- }
-
- if !requestReceived {
- t.Error("Expected request to be received by mock backend, but it wasn't")
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
deleted file mode 100644
index 6a30b318a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Package azure implements a DNS provider for solving the DNS-01
-// challenge using azure DNS.
-// Azure doesn't like trailing dots on domain names, most of the acme code does.
-package azure
-
-import (
- "fmt"
- "os"
- "time"
-
- "github.com/Azure/azure-sdk-for-go/arm/dns"
-
- "strings"
-
- "github.com/Azure/go-autorest/autorest"
- "github.com/Azure/go-autorest/autorest/adal"
- "github.com/Azure/go-autorest/autorest/azure"
- "github.com/Azure/go-autorest/autorest/to"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-type DNSProvider struct {
- clientId string
- clientSecret string
- subscriptionId string
- tenantId string
- resourceGroup string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for azure.
-// Credentials must be passed in the environment variables: AZURE_CLIENT_ID,
-// AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP
-func NewDNSProvider() (*DNSProvider, error) {
- clientId := os.Getenv("AZURE_CLIENT_ID")
- clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
- subscriptionId := os.Getenv("AZURE_SUBSCRIPTION_ID")
- tenantId := os.Getenv("AZURE_TENANT_ID")
- resourceGroup := os.Getenv("AZURE_RESOURCE_GROUP")
- return NewDNSProviderCredentials(clientId, clientSecret, subscriptionId, tenantId, resourceGroup)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for azure.
-func NewDNSProviderCredentials(clientId, clientSecret, subscriptionId, tenantId, resourceGroup string) (*DNSProvider, error) {
- if clientId == "" || clientSecret == "" || subscriptionId == "" || tenantId == "" || resourceGroup == "" {
- return nil, fmt.Errorf("Azure configuration missing")
- }
-
- return &DNSProvider{
- clientId: clientId,
- clientSecret: clientSecret,
- subscriptionId: subscriptionId,
- tenantId: tenantId,
- resourceGroup: resourceGroup,
- }, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 120 * time.Second, 2 * time.Second
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zone, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- rsc := dns.NewRecordSetsClient(c.subscriptionId)
- spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
- rsc.Authorizer = autorest.NewBearerAuthorizer(spt)
-
- relative := toRelativeRecord(fqdn, acme.ToFqdn(zone))
- rec := dns.RecordSet{
- Name: &relative,
- RecordSetProperties: &dns.RecordSetProperties{
- TTL: to.Int64Ptr(60),
- TxtRecords: &[]dns.TxtRecord{dns.TxtRecord{Value: &[]string{value}}},
- },
- }
- _, err = rsc.CreateOrUpdate(c.resourceGroup, zone, relative, dns.TXT, rec, "", "")
-
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// Returns the relative record to the domain
-func toRelativeRecord(domain, zone string) string {
- return acme.UnFqdn(strings.TrimSuffix(domain, zone))
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- relative := toRelativeRecord(fqdn, acme.ToFqdn(zone))
- rsc := dns.NewRecordSetsClient(c.subscriptionId)
- spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
- rsc.Authorizer = autorest.NewBearerAuthorizer(spt)
- _, err = rsc.Delete(c.resourceGroup, zone, relative, dns.TXT, "")
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// Checks that azure has a zone for this domain name.
-func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- // Now we want to to Azure and get the zone.
- spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
-
- dc := dns.NewZonesClient(c.subscriptionId)
- dc.Authorizer = autorest.NewBearerAuthorizer(spt)
-
- zone, err := dc.Get(c.resourceGroup, acme.UnFqdn(authZone))
-
- if err != nil {
- return "", err
- }
-
- // zone.Name shouldn't have a trailing dot(.)
- return to.String(zone.Name), nil
-}
-
-// NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
-// passed credentials map.
-func (c *DNSProvider) newServicePrincipalTokenFromCredentials(scope string) (*adal.ServicePrincipalToken, error) {
- oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, c.tenantId)
- if err != nil {
- panic(err)
- }
- return adal.NewServicePrincipalToken(*oauthConfig, c.clientId, c.clientSecret, scope)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/azure/azure_test.go b/vendor/github.com/xenolf/lego/providers/dns/azure/azure_test.go
deleted file mode 100644
index db55f578a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/azure/azure_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package azure
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- azureLiveTest bool
- azureClientID string
- azureClientSecret string
- azureSubscriptionID string
- azureTenantID string
- azureResourceGroup string
- azureDomain string
-)
-
-func init() {
- azureClientID = os.Getenv("AZURE_CLIENT_ID")
- azureClientSecret = os.Getenv("AZURE_CLIENT_SECRET")
- azureSubscriptionID = os.Getenv("AZURE_SUBSCRIPTION_ID")
- azureTenantID = os.Getenv("AZURE_TENANT_ID")
- azureResourceGroup = os.Getenv("AZURE_RESOURCE_GROUP")
- azureDomain = os.Getenv("AZURE_DOMAIN")
- if len(azureClientID) > 0 && len(azureClientSecret) > 0 {
- azureLiveTest = true
- }
-}
-
-func restoreAzureEnv() {
- os.Setenv("AZURE_CLIENT_ID", azureClientID)
- os.Setenv("AZURE_SUBSCRIPTION_ID", azureSubscriptionID)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- if !azureLiveTest {
- t.Skip("skipping live test (requires credentials)")
- }
- os.Setenv("AZURE_CLIENT_ID", "")
- _, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
- assert.NoError(t, err)
- restoreAzureEnv()
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- if !azureLiveTest {
- t.Skip("skipping live test (requires credentials)")
- }
- os.Setenv("AZURE_CLIENT_ID", "other")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restoreAzureEnv()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("AZURE_SUBSCRIPTION_ID", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "Azure configuration missing")
- restoreAzureEnv()
-}
-
-func TestLiveAzurePresent(t *testing.T) {
- if !azureLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
- assert.NoError(t, err)
-
- err = provider.Present(azureDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveAzureCleanUp(t *testing.T) {
- if !azureLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(azureClientID, azureClientSecret, azureSubscriptionID, azureTenantID, azureResourceGroup)
- time.Sleep(time.Second * 1)
-
- assert.NoError(t, err)
-
- err = provider.CleanUp(azureDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go b/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go
deleted file mode 100644
index 84952238d..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Package cloudflare implements a DNS provider for solving the DNS-01
-// challenge using cloudflare DNS.
-package cloudflare
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// CloudFlareAPIURL represents the API endpoint to call.
-// TODO: Unexport?
-const CloudFlareAPIURL = "https://api.cloudflare.com/client/v4"
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-type DNSProvider struct {
- authEmail string
- authKey string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for cloudflare.
-// Credentials must be passed in the environment variables: CLOUDFLARE_EMAIL
-// and CLOUDFLARE_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- email := os.Getenv("CLOUDFLARE_EMAIL")
- key := os.Getenv("CLOUDFLARE_API_KEY")
- return NewDNSProviderCredentials(email, key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for cloudflare.
-func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
- if email == "" || key == "" {
- return nil, fmt.Errorf("CloudFlare credentials missing")
- }
-
- return &DNSProvider{
- authEmail: email,
- authKey: key,
- }, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 120 * time.Second, 2 * time.Second
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- rec := cloudFlareRecord{
- Type: "TXT",
- Name: acme.UnFqdn(fqdn),
- Content: value,
- TTL: 120,
- }
-
- body, err := json.Marshal(rec)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("POST", fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewReader(body))
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- record, err := c.findTxtRecord(fqdn)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("DELETE", fmt.Sprintf("/zones/%s/dns_records/%s", record.ZoneID, record.ID), nil)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
- // HostedZone represents a CloudFlare DNS zone
- type HostedZone struct {
- ID string `json:"id"`
- Name string `json:"name"`
- }
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- result, err := c.makeRequest("GET", "/zones?name="+acme.UnFqdn(authZone), nil)
- if err != nil {
- return "", err
- }
-
- var hostedZone []HostedZone
- err = json.Unmarshal(result, &hostedZone)
- if err != nil {
- return "", err
- }
-
- if len(hostedZone) != 1 {
- return "", fmt.Errorf("Zone %s not found in CloudFlare for domain %s", authZone, fqdn)
- }
-
- return hostedZone[0].ID, nil
-}
-
-func (c *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return nil, err
- }
-
- result, err := c.makeRequest(
- "GET",
- fmt.Sprintf("/zones/%s/dns_records?per_page=1000&type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)),
- nil,
- )
- if err != nil {
- return nil, err
- }
-
- var records []cloudFlareRecord
- err = json.Unmarshal(result, &records)
- if err != nil {
- return nil, err
- }
-
- for _, rec := range records {
- if rec.Name == acme.UnFqdn(fqdn) {
- return &rec, nil
- }
- }
-
- return nil, fmt.Errorf("No existing record found for %s", fqdn)
-}
-
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
- // APIError contains error details for failed requests
- type APIError struct {
- Code int `json:"code,omitempty"`
- Message string `json:"message,omitempty"`
- ErrorChain []APIError `json:"error_chain,omitempty"`
- }
-
- // APIResponse represents a response from CloudFlare API
- type APIResponse struct {
- Success bool `json:"success"`
- Errors []*APIError `json:"errors"`
- Result json.RawMessage `json:"result"`
- }
-
- req, err := http.NewRequest(method, fmt.Sprintf("%s%s", CloudFlareAPIURL, uri), body)
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("X-Auth-Email", c.authEmail)
- req.Header.Set("X-Auth-Key", c.authKey)
- //req.Header.Set("User-Agent", userAgent())
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error querying Cloudflare API -> %v", err)
- }
-
- defer resp.Body.Close()
-
- var r APIResponse
- err = json.NewDecoder(resp.Body).Decode(&r)
- if err != nil {
- return nil, err
- }
-
- if !r.Success {
- if len(r.Errors) > 0 {
- errStr := ""
- for _, apiErr := range r.Errors {
- errStr += fmt.Sprintf("\t Error: %d: %s", apiErr.Code, apiErr.Message)
- for _, chainErr := range apiErr.ErrorChain {
- errStr += fmt.Sprintf("<- %d: %s", chainErr.Code, chainErr.Message)
- }
- }
- return nil, fmt.Errorf("Cloudflare API Error \n%s", errStr)
- }
- return nil, fmt.Errorf("Cloudflare API error")
- }
-
- return r.Result, nil
-}
-
-// cloudFlareRecord represents a CloudFlare DNS record
-type cloudFlareRecord struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Content string `json:"content"`
- ID string `json:"id,omitempty"`
- TTL int `json:"ttl,omitempty"`
- ZoneID string `json:"zone_id,omitempty"`
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare_test.go b/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare_test.go
deleted file mode 100644
index 19b5a40b9..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare_test.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package cloudflare
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- cflareLiveTest bool
- cflareEmail string
- cflareAPIKey string
- cflareDomain string
-)
-
-func init() {
- cflareEmail = os.Getenv("CLOUDFLARE_EMAIL")
- cflareAPIKey = os.Getenv("CLOUDFLARE_API_KEY")
- cflareDomain = os.Getenv("CLOUDFLARE_DOMAIN")
- if len(cflareEmail) > 0 && len(cflareAPIKey) > 0 && len(cflareDomain) > 0 {
- cflareLiveTest = true
- }
-}
-
-func restoreCloudFlareEnv() {
- os.Setenv("CLOUDFLARE_EMAIL", cflareEmail)
- os.Setenv("CLOUDFLARE_API_KEY", cflareAPIKey)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- os.Setenv("CLOUDFLARE_EMAIL", "")
- os.Setenv("CLOUDFLARE_API_KEY", "")
- _, err := NewDNSProviderCredentials("123", "123")
- assert.NoError(t, err)
- restoreCloudFlareEnv()
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("CLOUDFLARE_EMAIL", "test@example.com")
- os.Setenv("CLOUDFLARE_API_KEY", "123")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restoreCloudFlareEnv()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("CLOUDFLARE_EMAIL", "")
- os.Setenv("CLOUDFLARE_API_KEY", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "CloudFlare credentials missing")
- restoreCloudFlareEnv()
-}
-
-func TestCloudFlarePresent(t *testing.T) {
- if !cflareLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey)
- assert.NoError(t, err)
-
- err = provider.Present(cflareDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestCloudFlareCleanUp(t *testing.T) {
- if !cflareLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 2)
-
- provider, err := NewDNSProviderCredentials(cflareEmail, cflareAPIKey)
- assert.NoError(t, err)
-
- err = provider.CleanUp(cflareDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go b/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go
deleted file mode 100644
index da261b39a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// Package digitalocean implements a DNS provider for solving the DNS-01
-// challenge using digitalocean DNS.
-package digitalocean
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "os"
- "sync"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-// that uses DigitalOcean's REST API to manage TXT records for a domain.
-type DNSProvider struct {
- apiAuthToken string
- recordIDs map[string]int
- recordIDsMu sync.Mutex
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Digital
-// Ocean. Credentials must be passed in the environment variable:
-// DO_AUTH_TOKEN.
-func NewDNSProvider() (*DNSProvider, error) {
- apiAuthToken := os.Getenv("DO_AUTH_TOKEN")
- return NewDNSProviderCredentials(apiAuthToken)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Digital Ocean.
-func NewDNSProviderCredentials(apiAuthToken string) (*DNSProvider, error) {
- if apiAuthToken == "" {
- return nil, fmt.Errorf("DigitalOcean credentials missing")
- }
- return &DNSProvider{
- apiAuthToken: apiAuthToken,
- recordIDs: make(map[string]int),
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- // txtRecordRequest represents the request body to DO's API to make a TXT record
- type txtRecordRequest struct {
- RecordType string `json:"type"`
- Name string `json:"name"`
- Data string `json:"data"`
- }
-
- // txtRecordResponse represents a response from DO's API after making a TXT record
- type txtRecordResponse struct {
- DomainRecord struct {
- ID int `json:"id"`
- Type string `json:"type"`
- Name string `json:"name"`
- Data string `json:"data"`
- } `json:"domain_record"`
- }
-
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- authZone = acme.UnFqdn(authZone)
-
- reqURL := fmt.Sprintf("%s/v2/domains/%s/records", digitalOceanBaseURL, authZone)
- reqData := txtRecordRequest{RecordType: "TXT", Name: fqdn, Data: value}
- body, err := json.Marshal(reqData)
- if err != nil {
- return err
- }
-
- req, err := http.NewRequest("POST", reqURL, bytes.NewReader(body))
- if err != nil {
- return err
- }
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.apiAuthToken))
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- var errInfo digitalOceanAPIError
- json.NewDecoder(resp.Body).Decode(&errInfo)
- return fmt.Errorf("HTTP %d: %s: %s", resp.StatusCode, errInfo.ID, errInfo.Message)
- }
-
- // Everything looks good; but we'll need the ID later to delete the record
- var respData txtRecordResponse
- err = json.NewDecoder(resp.Body).Decode(&respData)
- if err != nil {
- return err
- }
- d.recordIDsMu.Lock()
- d.recordIDs[fqdn] = respData.DomainRecord.ID
- d.recordIDsMu.Unlock()
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- // get the record's unique ID from when we created it
- d.recordIDsMu.Lock()
- recordID, ok := d.recordIDs[fqdn]
- d.recordIDsMu.Unlock()
- if !ok {
- return fmt.Errorf("unknown record ID for '%s'", fqdn)
- }
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- authZone = acme.UnFqdn(authZone)
-
- reqURL := fmt.Sprintf("%s/v2/domains/%s/records/%d", digitalOceanBaseURL, authZone, recordID)
- req, err := http.NewRequest("DELETE", reqURL, nil)
- if err != nil {
- return err
- }
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.apiAuthToken))
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- var errInfo digitalOceanAPIError
- json.NewDecoder(resp.Body).Decode(&errInfo)
- return fmt.Errorf("HTTP %d: %s: %s", resp.StatusCode, errInfo.ID, errInfo.Message)
- }
-
- // Delete record ID from map
- d.recordIDsMu.Lock()
- delete(d.recordIDs, fqdn)
- d.recordIDsMu.Unlock()
-
- return nil
-}
-
-type digitalOceanAPIError struct {
- ID string `json:"id"`
- Message string `json:"message"`
-}
-
-var digitalOceanBaseURL = "https://api.digitalocean.com"
diff --git a/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean_test.go b/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean_test.go
deleted file mode 100644
index 7498508ba..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean_test.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package digitalocean
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-var fakeDigitalOceanAuth = "asdf1234"
-
-func TestDigitalOceanPresent(t *testing.T) {
- var requestReceived bool
-
- mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- requestReceived = true
-
- if got, want := r.Method, "POST"; got != want {
- t.Errorf("Expected method to be '%s' but got '%s'", want, got)
- }
- if got, want := r.URL.Path, "/v2/domains/example.com/records"; got != want {
- t.Errorf("Expected path to be '%s' but got '%s'", want, got)
- }
- if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
- t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
- }
- if got, want := r.Header.Get("Authorization"), "Bearer asdf1234"; got != want {
- t.Errorf("Expected Authorization to be '%s' but got '%s'", want, got)
- }
-
- reqBody, err := ioutil.ReadAll(r.Body)
- if err != nil {
- t.Fatalf("Error reading request body: %v", err)
- }
- if got, want := string(reqBody), `{"type":"TXT","name":"_acme-challenge.example.com.","data":"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI"}`; got != want {
- t.Errorf("Expected body data to be: `%s` but got `%s`", want, got)
- }
-
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `{
- "domain_record": {
- "id": 1234567,
- "type": "TXT",
- "name": "_acme-challenge",
- "data": "w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI",
- "priority": null,
- "port": null,
- "weight": null
- }
- }`)
- }))
- defer mock.Close()
- digitalOceanBaseURL = mock.URL
-
- doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
- if doprov == nil {
- t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
- }
- if err != nil {
- t.Fatalf("Expected no error creating provider, but got: %v", err)
- }
-
- err = doprov.Present("example.com", "", "foobar")
- if err != nil {
- t.Fatalf("Expected no error creating TXT record, but got: %v", err)
- }
- if !requestReceived {
- t.Error("Expected request to be received by mock backend, but it wasn't")
- }
-}
-
-func TestDigitalOceanCleanUp(t *testing.T) {
- var requestReceived bool
-
- mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- requestReceived = true
-
- if got, want := r.Method, "DELETE"; got != want {
- t.Errorf("Expected method to be '%s' but got '%s'", want, got)
- }
- if got, want := r.URL.Path, "/v2/domains/example.com/records/1234567"; got != want {
- t.Errorf("Expected path to be '%s' but got '%s'", want, got)
- }
- // NOTE: Even though the body is empty, DigitalOcean API docs still show setting this Content-Type...
- if got, want := r.Header.Get("Content-Type"), "application/json"; got != want {
- t.Errorf("Expected Content-Type to be '%s' but got '%s'", want, got)
- }
- if got, want := r.Header.Get("Authorization"), "Bearer asdf1234"; got != want {
- t.Errorf("Expected Authorization to be '%s' but got '%s'", want, got)
- }
-
- w.WriteHeader(http.StatusNoContent)
- }))
- defer mock.Close()
- digitalOceanBaseURL = mock.URL
-
- doprov, err := NewDNSProviderCredentials(fakeDigitalOceanAuth)
- if doprov == nil {
- t.Fatal("Expected non-nil DigitalOcean provider, but was nil")
- }
- if err != nil {
- t.Fatalf("Expected no error creating provider, but got: %v", err)
- }
-
- doprov.recordIDsMu.Lock()
- doprov.recordIDs["_acme-challenge.example.com."] = 1234567
- doprov.recordIDsMu.Unlock()
-
- err = doprov.CleanUp("example.com", "", "")
- if err != nil {
- t.Fatalf("Expected no error removing TXT record, but got: %v", err)
- }
- if !requestReceived {
- t.Error("Expected request to be received by mock backend, but it wasn't")
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dns_providers.go b/vendor/github.com/xenolf/lego/providers/dns/dns_providers.go
deleted file mode 100644
index d7530f788..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dns_providers.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Factory for DNS providers
-package dns
-
-import (
- "fmt"
-
- "github.com/xenolf/lego/acme"
- "github.com/xenolf/lego/providers/dns/auroradns"
- "github.com/xenolf/lego/providers/dns/azure"
- "github.com/xenolf/lego/providers/dns/cloudflare"
- "github.com/xenolf/lego/providers/dns/digitalocean"
- "github.com/xenolf/lego/providers/dns/dnsimple"
- "github.com/xenolf/lego/providers/dns/dnsmadeeasy"
- "github.com/xenolf/lego/providers/dns/dnspod"
- "github.com/xenolf/lego/providers/dns/dyn"
- "github.com/xenolf/lego/providers/dns/exoscale"
- "github.com/xenolf/lego/providers/dns/gandi"
- "github.com/xenolf/lego/providers/dns/godaddy"
- "github.com/xenolf/lego/providers/dns/googlecloud"
- "github.com/xenolf/lego/providers/dns/linode"
- "github.com/xenolf/lego/providers/dns/namecheap"
- "github.com/xenolf/lego/providers/dns/ns1"
- "github.com/xenolf/lego/providers/dns/otc"
- "github.com/xenolf/lego/providers/dns/ovh"
- "github.com/xenolf/lego/providers/dns/pdns"
- "github.com/xenolf/lego/providers/dns/rackspace"
- "github.com/xenolf/lego/providers/dns/rfc2136"
- "github.com/xenolf/lego/providers/dns/route53"
- "github.com/xenolf/lego/providers/dns/vultr"
-)
-
-func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error) {
- var err error
- var provider acme.ChallengeProvider
- switch name {
- case "azure":
- provider, err = azure.NewDNSProvider()
- case "auroradns":
- provider, err = auroradns.NewDNSProvider()
- case "cloudflare":
- provider, err = cloudflare.NewDNSProvider()
- case "digitalocean":
- provider, err = digitalocean.NewDNSProvider()
- case "dnsimple":
- provider, err = dnsimple.NewDNSProvider()
- case "dnsmadeeasy":
- provider, err = dnsmadeeasy.NewDNSProvider()
- case "dnspod":
- provider, err = dnspod.NewDNSProvider()
- case "dyn":
- provider, err = dyn.NewDNSProvider()
- case "exoscale":
- provider, err = exoscale.NewDNSProvider()
- case "gandi":
- provider, err = gandi.NewDNSProvider()
- case "gcloud":
- provider, err = googlecloud.NewDNSProvider()
- case "godaddy":
- provider, err = godaddy.NewDNSProvider()
- case "linode":
- provider, err = linode.NewDNSProvider()
- case "manual":
- provider, err = acme.NewDNSProviderManual()
- case "namecheap":
- provider, err = namecheap.NewDNSProvider()
- case "rackspace":
- provider, err = rackspace.NewDNSProvider()
- case "route53":
- provider, err = route53.NewDNSProvider()
- case "rfc2136":
- provider, err = rfc2136.NewDNSProvider()
- case "vultr":
- provider, err = vultr.NewDNSProvider()
- case "ovh":
- provider, err = ovh.NewDNSProvider()
- case "pdns":
- provider, err = pdns.NewDNSProvider()
- case "ns1":
- provider, err = ns1.NewDNSProvider()
- case "otc":
- provider, err = otc.NewDNSProvider()
- default:
- err = fmt.Errorf("Unrecognised DNS provider: %s", name)
- }
- return provider, err
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dns_providers_test.go b/vendor/github.com/xenolf/lego/providers/dns/dns_providers_test.go
deleted file mode 100644
index 3f87ffd33..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dns_providers_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package dns
-
-import (
- "os"
- "reflect"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/xenolf/lego/providers/dns/exoscale"
-)
-
-var (
- apiKey string
- apiSecret string
-)
-
-func init() {
- apiSecret = os.Getenv("EXOSCALE_API_SECRET")
- apiKey = os.Getenv("EXOSCALE_API_KEY")
-}
-
-func restoreExoscaleEnv() {
- os.Setenv("EXOSCALE_API_KEY", apiKey)
- os.Setenv("EXOSCALE_API_SECRET", apiSecret)
-}
-
-func TestKnownDNSProviderSuccess(t *testing.T) {
- os.Setenv("EXOSCALE_API_KEY", "abc")
- os.Setenv("EXOSCALE_API_SECRET", "123")
- provider, err := NewDNSChallengeProviderByName("exoscale")
- assert.NoError(t, err)
- assert.NotNil(t, provider)
- if reflect.TypeOf(provider) != reflect.TypeOf(&exoscale.DNSProvider{}) {
- t.Errorf("Not loaded correct DNS proviver: %v is not *exoscale.DNSProvider", reflect.TypeOf(provider))
- }
- restoreExoscaleEnv()
-}
-
-func TestKnownDNSProviderError(t *testing.T) {
- os.Setenv("EXOSCALE_API_KEY", "")
- os.Setenv("EXOSCALE_API_SECRET", "")
- _, err := NewDNSChallengeProviderByName("exoscale")
- assert.Error(t, err)
- restoreExoscaleEnv()
-}
-
-func TestUnknownDNSProvider(t *testing.T) {
- _, err := NewDNSChallengeProviderByName("foobar")
- assert.Error(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go b/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go
deleted file mode 100644
index e3fea79ec..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// Package dnsimple implements a DNS provider for solving the DNS-01 challenge
-// using dnsimple DNS.
-package dnsimple
-
-import (
- "fmt"
- "os"
- "strconv"
- "strings"
-
- "github.com/dnsimple/dnsimple-go/dnsimple"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface.
-type DNSProvider struct {
- client *dnsimple.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for dnsimple.
-// Credentials must be passed in the environment variables: DNSIMPLE_OAUTH_TOKEN.
-//
-// See: https://developer.dnsimple.com/v2/#authentication
-func NewDNSProvider() (*DNSProvider, error) {
- accessToken := os.Getenv("DNSIMPLE_OAUTH_TOKEN")
- baseUrl := os.Getenv("DNSIMPLE_BASE_URL")
-
- return NewDNSProviderCredentials(accessToken, baseUrl)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for dnsimple.
-func NewDNSProviderCredentials(accessToken, baseUrl string) (*DNSProvider, error) {
- if accessToken == "" {
- return nil, fmt.Errorf("DNSimple OAuth token is missing")
- }
-
- client := dnsimple.NewClient(dnsimple.NewOauthTokenCredentials(accessToken))
- client.UserAgent = "lego"
-
- if baseUrl != "" {
- client.BaseURL = baseUrl
- }
-
- return &DNSProvider{client: client}, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- zoneName, err := c.getHostedZone(domain)
-
- if err != nil {
- return err
- }
-
- accountID, err := c.getAccountID()
- if err != nil {
- return err
- }
-
- recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
- _, err = c.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes)
- if err != nil {
- return fmt.Errorf("DNSimple API call failed: %v", err)
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- records, err := c.findTxtRecords(domain, fqdn)
- if err != nil {
- return err
- }
-
- accountID, err := c.getAccountID()
- if err != nil {
- return err
- }
-
- for _, rec := range records {
- _, err := c.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- accountID, err := c.getAccountID()
- if err != nil {
- return "", err
- }
-
- zoneName := acme.UnFqdn(authZone)
-
- zones, err := c.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName})
- if err != nil {
- return "", fmt.Errorf("DNSimple API call failed: %v", err)
- }
-
- var hostedZone dnsimple.Zone
- for _, zone := range zones.Data {
- if zone.Name == zoneName {
- hostedZone = zone
- }
- }
-
- if hostedZone.ID == 0 {
- return "", fmt.Errorf("Zone %s not found in DNSimple for domain %s", authZone, domain)
-
- }
-
- return hostedZone.Name, nil
-}
-
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) {
- zoneName, err := c.getHostedZone(domain)
- if err != nil {
- return nil, err
- }
-
- accountID, err := c.getAccountID()
- if err != nil {
- return nil, err
- }
-
- recordName := c.extractRecordName(fqdn, zoneName)
-
- result, err := c.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
- if err != nil {
- return []dnsimple.ZoneRecord{}, fmt.Errorf("DNSimple API call has failed: %v", err)
- }
-
- return result.Data, nil
-}
-
-func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord {
- name := c.extractRecordName(fqdn, zoneName)
-
- return &dnsimple.ZoneRecord{
- Type: "TXT",
- Name: name,
- Content: value,
- TTL: ttl,
- }
-}
-
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
- name := acme.UnFqdn(fqdn)
- if idx := strings.Index(name, "."+domain); idx != -1 {
- return name[:idx]
- }
- return name
-}
-
-func (c *DNSProvider) getAccountID() (string, error) {
- whoamiResponse, err := c.client.Identity.Whoami()
- if err != nil {
- return "", err
- }
-
- if whoamiResponse.Data.Account == nil {
- return "", fmt.Errorf("DNSimple user tokens are not supported, please use an account token.")
- }
-
- return strconv.Itoa(whoamiResponse.Data.Account.ID), nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple_test.go b/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple_test.go
deleted file mode 100644
index bd35790d7..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-package dnsimple
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- dnsimpleLiveTest bool
- dnsimpleOauthToken string
- dnsimpleDomain string
- dnsimpleBaseUrl string
-)
-
-func init() {
- dnsimpleOauthToken = os.Getenv("DNSIMPLE_OAUTH_TOKEN")
- dnsimpleDomain = os.Getenv("DNSIMPLE_DOMAIN")
- dnsimpleBaseUrl = "https://api.sandbox.dnsimple.com"
-
- if len(dnsimpleOauthToken) > 0 && len(dnsimpleDomain) > 0 {
- baseUrl := os.Getenv("DNSIMPLE_BASE_URL")
-
- if baseUrl != "" {
- dnsimpleBaseUrl = baseUrl
- }
-
- dnsimpleLiveTest = true
- }
-}
-
-func restoreDNSimpleEnv() {
- os.Setenv("DNSIMPLE_OAUTH_TOKEN", dnsimpleOauthToken)
- os.Setenv("DNSIMPLE_BASE_URL", dnsimpleBaseUrl)
-}
-
-//
-// NewDNSProvider
-//
-
-func TestNewDNSProviderValid(t *testing.T) {
- defer restoreDNSimpleEnv()
-
- os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
- provider, err := NewDNSProvider()
-
- assert.NotNil(t, provider)
- assert.Equal(t, "lego", provider.client.UserAgent)
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderValidWithBaseUrl(t *testing.T) {
- defer restoreDNSimpleEnv()
-
- os.Setenv("DNSIMPLE_OAUTH_TOKEN", "123")
- os.Setenv("DNSIMPLE_BASE_URL", "https://api.dnsimple.test")
- provider, err := NewDNSProvider()
-
- assert.NotNil(t, provider)
- assert.NoError(t, err)
-
- assert.Equal(t, provider.client.BaseURL, "https://api.dnsimple.test")
-}
-
-func TestNewDNSProviderInvalidWithMissingOauthToken(t *testing.T) {
- if dnsimpleLiveTest {
- t.Skip("skipping test in live mode")
- }
-
- defer restoreDNSimpleEnv()
-
- provider, err := NewDNSProvider()
-
- assert.Nil(t, provider)
- assert.EqualError(t, err, "DNSimple OAuth token is missing")
-}
-
-//
-// NewDNSProviderCredentials
-//
-
-func TestNewDNSProviderCredentialsValid(t *testing.T) {
- provider, err := NewDNSProviderCredentials("123", "")
-
- assert.NotNil(t, provider)
- assert.Equal(t, "lego", provider.client.UserAgent)
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderCredentialsValidWithBaseUrl(t *testing.T) {
- provider, err := NewDNSProviderCredentials("123", "https://api.dnsimple.test")
-
- assert.NotNil(t, provider)
- assert.NoError(t, err)
-
- assert.Equal(t, provider.client.BaseURL, "https://api.dnsimple.test")
-}
-
-func TestNewDNSProviderCredentialsInvalidWithMissingOauthToken(t *testing.T) {
- provider, err := NewDNSProviderCredentials("", "")
-
- assert.Nil(t, provider)
- assert.EqualError(t, err, "DNSimple OAuth token is missing")
-}
-
-//
-// Present
-//
-
-func TestLiveDNSimplePresent(t *testing.T) {
- if !dnsimpleLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(dnsimpleOauthToken, dnsimpleBaseUrl)
- assert.NoError(t, err)
-
- err = provider.Present(dnsimpleDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-//
-// Cleanup
-//
-
-func TestLiveDNSimpleCleanUp(t *testing.T) {
- if !dnsimpleLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProviderCredentials(dnsimpleOauthToken, dnsimpleBaseUrl)
- assert.NoError(t, err)
-
- err = provider.CleanUp(dnsimpleDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go b/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go
deleted file mode 100644
index c4363a4eb..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go
+++ /dev/null
@@ -1,248 +0,0 @@
-package dnsmadeeasy
-
-import (
- "bytes"
- "crypto/hmac"
- "crypto/sha1"
- "crypto/tls"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "net/http"
- "os"
- "strconv"
- "strings"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
-// DNSMadeEasy's DNS API to manage TXT records for a domain.
-type DNSProvider struct {
- baseURL string
- apiKey string
- apiSecret string
-}
-
-// Domain holds the DNSMadeEasy API representation of a Domain
-type Domain struct {
- ID int `json:"id"`
- Name string `json:"name"`
-}
-
-// Record holds the DNSMadeEasy API representation of a Domain Record
-type Record struct {
- ID int `json:"id"`
- Type string `json:"type"`
- Name string `json:"name"`
- Value string `json:"value"`
- TTL int `json:"ttl"`
- SourceID int `json:"sourceId"`
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for DNSMadeEasy DNS.
-// Credentials must be passed in the environment variables: DNSMADEEASY_API_KEY
-// and DNSMADEEASY_API_SECRET.
-func NewDNSProvider() (*DNSProvider, error) {
- dnsmadeeasyAPIKey := os.Getenv("DNSMADEEASY_API_KEY")
- dnsmadeeasyAPISecret := os.Getenv("DNSMADEEASY_API_SECRET")
- dnsmadeeasySandbox := os.Getenv("DNSMADEEASY_SANDBOX")
-
- var baseURL string
-
- sandbox, _ := strconv.ParseBool(dnsmadeeasySandbox)
- if sandbox {
- baseURL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
- } else {
- baseURL = "https://api.dnsmadeeasy.com/V2.0"
- }
-
- return NewDNSProviderCredentials(baseURL, dnsmadeeasyAPIKey, dnsmadeeasyAPISecret)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for DNSMadeEasy.
-func NewDNSProviderCredentials(baseURL, apiKey, apiSecret string) (*DNSProvider, error) {
- if baseURL == "" || apiKey == "" || apiSecret == "" {
- return nil, fmt.Errorf("DNS Made Easy credentials missing")
- }
-
- return &DNSProvider{
- baseURL: baseURL,
- apiKey: apiKey,
- apiSecret: apiSecret,
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters
-func (d *DNSProvider) Present(domainName, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domainName, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- // fetch the domain details
- domain, err := d.getDomain(authZone)
- if err != nil {
- return err
- }
-
- // create the TXT record
- name := strings.Replace(fqdn, "."+authZone, "", 1)
- record := &Record{Type: "TXT", Name: name, Value: value, TTL: ttl}
-
- err = d.createRecord(domain, record)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT records matching the specified parameters
-func (d *DNSProvider) CleanUp(domainName, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domainName, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- // fetch the domain details
- domain, err := d.getDomain(authZone)
- if err != nil {
- return err
- }
-
- // find matching records
- name := strings.Replace(fqdn, "."+authZone, "", 1)
- records, err := d.getRecords(domain, name, "TXT")
- if err != nil {
- return err
- }
-
- // delete records
- for _, record := range *records {
- err = d.deleteRecord(record)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func (d *DNSProvider) getDomain(authZone string) (*Domain, error) {
- domainName := authZone[0 : len(authZone)-1]
- resource := fmt.Sprintf("%s%s", "/dns/managed/name?domainname=", domainName)
-
- resp, err := d.sendRequest("GET", resource, nil)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- domain := &Domain{}
- err = json.NewDecoder(resp.Body).Decode(&domain)
- if err != nil {
- return nil, err
- }
-
- return domain, nil
-}
-
-func (d *DNSProvider) getRecords(domain *Domain, recordName, recordType string) (*[]Record, error) {
- resource := fmt.Sprintf("%s/%d/%s%s%s%s", "/dns/managed", domain.ID, "records?recordName=", recordName, "&type=", recordType)
-
- resp, err := d.sendRequest("GET", resource, nil)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- type recordsResponse struct {
- Records *[]Record `json:"data"`
- }
-
- records := &recordsResponse{}
- err = json.NewDecoder(resp.Body).Decode(&records)
- if err != nil {
- return nil, err
- }
-
- return records.Records, nil
-}
-
-func (d *DNSProvider) createRecord(domain *Domain, record *Record) error {
- url := fmt.Sprintf("%s/%d/%s", "/dns/managed", domain.ID, "records")
-
- resp, err := d.sendRequest("POST", url, record)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- return nil
-}
-
-func (d *DNSProvider) deleteRecord(record Record) error {
- resource := fmt.Sprintf("%s/%d/%s/%d", "/dns/managed", record.SourceID, "records", record.ID)
-
- resp, err := d.sendRequest("DELETE", resource, nil)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- return nil
-}
-
-func (d *DNSProvider) sendRequest(method, resource string, payload interface{}) (*http.Response, error) {
- url := fmt.Sprintf("%s%s", d.baseURL, resource)
-
- body, err := json.Marshal(payload)
- if err != nil {
- return nil, err
- }
-
- timestamp := time.Now().UTC().Format(time.RFC1123)
- signature := computeHMAC(timestamp, d.apiSecret)
-
- req, err := http.NewRequest(method, url, bytes.NewReader(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("x-dnsme-apiKey", d.apiKey)
- req.Header.Set("x-dnsme-requestDate", timestamp)
- req.Header.Set("x-dnsme-hmac", signature)
- req.Header.Set("accept", "application/json")
- req.Header.Set("content-type", "application/json")
-
- transport := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
- }
- client := &http.Client{
- Transport: transport,
- Timeout: time.Duration(10 * time.Second),
- }
- resp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
-
- if resp.StatusCode > 299 {
- return nil, fmt.Errorf("DNSMadeEasy API request failed with HTTP status code %d", resp.StatusCode)
- }
-
- return resp, nil
-}
-
-func computeHMAC(message string, secret string) string {
- key := []byte(secret)
- h := hmac.New(sha1.New, key)
- h.Write([]byte(message))
- return hex.EncodeToString(h.Sum(nil))
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy_test.go b/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy_test.go
deleted file mode 100644
index e860ecb69..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package dnsmadeeasy
-
-import (
- "os"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- testLive bool
- testAPIKey string
- testAPISecret string
- testDomain string
-)
-
-func init() {
- testAPIKey = os.Getenv("DNSMADEEASY_API_KEY")
- testAPISecret = os.Getenv("DNSMADEEASY_API_SECRET")
- testDomain = os.Getenv("DNSMADEEASY_DOMAIN")
- os.Setenv("DNSMADEEASY_SANDBOX", "true")
- testLive = len(testAPIKey) > 0 && len(testAPISecret) > 0
-}
-
-func TestPresentAndCleanup(t *testing.T) {
- if !testLive {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
-
- err = provider.Present(testDomain, "", "123d==")
- assert.NoError(t, err)
-
- err = provider.CleanUp(testDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go b/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go
deleted file mode 100644
index 0ce08a8bb..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go
+++ /dev/null
@@ -1,146 +0,0 @@
-// Package dnspod implements a DNS provider for solving the DNS-01 challenge
-// using dnspod DNS.
-package dnspod
-
-import (
- "fmt"
- "os"
- "strings"
-
- "github.com/decker502/dnspod-go"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface.
-type DNSProvider struct {
- client *dnspod.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for dnspod.
-// Credentials must be passed in the environment variables: DNSPOD_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- key := os.Getenv("DNSPOD_API_KEY")
- return NewDNSProviderCredentials(key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for dnspod.
-func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
- if key == "" {
- return nil, fmt.Errorf("dnspod credentials missing")
- }
-
- params := dnspod.CommonParams{LoginToken: key, Format: "json"}
- return &DNSProvider{
- client: dnspod.NewClient(params),
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- zoneID, zoneName, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
- _, _, err = c.client.Domains.CreateRecord(zoneID, *recordAttributes)
- if err != nil {
- return fmt.Errorf("dnspod API call failed: %v", err)
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- records, err := c.findTxtRecords(domain, fqdn)
- if err != nil {
- return err
- }
-
- zoneID, _, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- for _, rec := range records {
- _, err := c.client.Domains.DeleteRecord(zoneID, rec.ID)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
- zones, _, err := c.client.Domains.List()
- if err != nil {
- return "", "", fmt.Errorf("dnspod API call failed: %v", err)
- }
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return "", "", err
- }
-
- var hostedZone dnspod.Domain
- for _, zone := range zones {
- if zone.Name == acme.UnFqdn(authZone) {
- hostedZone = zone
- }
- }
-
- if hostedZone.ID == 0 {
- return "", "", fmt.Errorf("Zone %s not found in dnspod for domain %s", authZone, domain)
-
- }
-
- return fmt.Sprintf("%v", hostedZone.ID), hostedZone.Name, nil
-}
-
-func (c *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Record {
- name := c.extractRecordName(fqdn, zone)
-
- return &dnspod.Record{
- Type: "TXT",
- Name: name,
- Value: value,
- Line: "默认",
- TTL: "600",
- }
-}
-
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, error) {
- zoneID, zoneName, err := c.getHostedZone(domain)
- if err != nil {
- return nil, err
- }
-
- var records []dnspod.Record
- result, _, err := c.client.Domains.ListRecords(zoneID, "")
- if err != nil {
- return records, fmt.Errorf("dnspod API call has failed: %v", err)
- }
-
- recordName := c.extractRecordName(fqdn, zoneName)
-
- for _, record := range result {
- if record.Name == recordName {
- records = append(records, record)
- }
- }
-
- return records, nil
-}
-
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
- name := acme.UnFqdn(fqdn)
- if idx := strings.Index(name, "."+domain); idx != -1 {
- return name[:idx]
- }
- return name
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod_test.go b/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod_test.go
deleted file mode 100644
index 3311eb0a6..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod_test.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package dnspod
-
-import (
- "github.com/stretchr/testify/assert"
- "os"
- "testing"
- "time"
-)
-
-var (
- dnspodLiveTest bool
- dnspodAPIKey string
- dnspodDomain string
-)
-
-func init() {
- dnspodAPIKey = os.Getenv("DNSPOD_API_KEY")
- dnspodDomain = os.Getenv("DNSPOD_DOMAIN")
- if len(dnspodAPIKey) > 0 && len(dnspodDomain) > 0 {
- dnspodLiveTest = true
- }
-}
-
-func restorednspodEnv() {
- os.Setenv("DNSPOD_API_KEY", dnspodAPIKey)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- os.Setenv("DNSPOD_API_KEY", "")
- _, err := NewDNSProviderCredentials("123")
- assert.NoError(t, err)
- restorednspodEnv()
-}
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("DNSPOD_API_KEY", "123")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restorednspodEnv()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("DNSPOD_API_KEY", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "dnspod credentials missing")
- restorednspodEnv()
-}
-
-func TestLivednspodPresent(t *testing.T) {
- if !dnspodLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(dnspodAPIKey)
- assert.NoError(t, err)
-
- err = provider.Present(dnspodDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLivednspodCleanUp(t *testing.T) {
- if !dnspodLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProviderCredentials(dnspodAPIKey)
- assert.NoError(t, err)
-
- err = provider.CleanUp(dnspodDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go b/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go
deleted file mode 100644
index 384bc850c..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go
+++ /dev/null
@@ -1,274 +0,0 @@
-// Package dyn implements a DNS provider for solving the DNS-01 challenge
-// using Dyn Managed DNS.
-package dyn
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "os"
- "strconv"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-var dynBaseURL = "https://api.dynect.net/REST"
-
-type dynResponse struct {
- // One of 'success', 'failure', or 'incomplete'
- Status string `json:"status"`
-
- // The structure containing the actual results of the request
- Data json.RawMessage `json:"data"`
-
- // The ID of the job that was created in response to a request.
- JobID int `json:"job_id"`
-
- // A list of zero or more messages
- Messages json.RawMessage `json:"msgs"`
-}
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
-// Dyn's Managed DNS API to manage TXT records for a domain.
-type DNSProvider struct {
- customerName string
- userName string
- password string
- token string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Dyn DNS.
-// Credentials must be passed in the environment variables: DYN_CUSTOMER_NAME,
-// DYN_USER_NAME and DYN_PASSWORD.
-func NewDNSProvider() (*DNSProvider, error) {
- customerName := os.Getenv("DYN_CUSTOMER_NAME")
- userName := os.Getenv("DYN_USER_NAME")
- password := os.Getenv("DYN_PASSWORD")
- return NewDNSProviderCredentials(customerName, userName, password)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Dyn DNS.
-func NewDNSProviderCredentials(customerName, userName, password string) (*DNSProvider, error) {
- if customerName == "" || userName == "" || password == "" {
- return nil, fmt.Errorf("DynDNS credentials missing")
- }
-
- return &DNSProvider{
- customerName: customerName,
- userName: userName,
- password: password,
- }, nil
-}
-
-func (d *DNSProvider) sendRequest(method, resource string, payload interface{}) (*dynResponse, error) {
- url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
-
- body, err := json.Marshal(payload)
- if err != nil {
- return nil, err
- }
-
- req, err := http.NewRequest(method, url, bytes.NewReader(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
- if len(d.token) > 0 {
- req.Header.Set("Auth-Token", d.token)
- }
-
- client := &http.Client{Timeout: time.Duration(10 * time.Second)}
- resp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return nil, fmt.Errorf("Dyn API request failed with HTTP status code %d", resp.StatusCode)
- } else if resp.StatusCode == 307 {
- // TODO add support for HTTP 307 response and long running jobs
- return nil, fmt.Errorf("Dyn API request returned HTTP 307. This is currently unsupported")
- }
-
- var dynRes dynResponse
- err = json.NewDecoder(resp.Body).Decode(&dynRes)
- if err != nil {
- return nil, err
- }
-
- if dynRes.Status == "failure" {
- // TODO add better error handling
- return nil, fmt.Errorf("Dyn API request failed: %s", dynRes.Messages)
- }
-
- return &dynRes, nil
-}
-
-// Starts a new Dyn API Session. Authenticates using customerName, userName,
-// password and receives a token to be used in for subsequent requests.
-func (d *DNSProvider) login() error {
- type creds struct {
- Customer string `json:"customer_name"`
- User string `json:"user_name"`
- Pass string `json:"password"`
- }
-
- type session struct {
- Token string `json:"token"`
- Version string `json:"version"`
- }
-
- payload := &creds{Customer: d.customerName, User: d.userName, Pass: d.password}
- dynRes, err := d.sendRequest("POST", "Session", payload)
- if err != nil {
- return err
- }
-
- var s session
- err = json.Unmarshal(dynRes.Data, &s)
- if err != nil {
- return err
- }
-
- d.token = s.Token
-
- return nil
-}
-
-// Destroys Dyn Session
-func (d *DNSProvider) logout() error {
- if len(d.token) == 0 {
- // nothing to do
- return nil
- }
-
- url := fmt.Sprintf("%s/Session", dynBaseURL)
- req, err := http.NewRequest("DELETE", url, nil)
- if err != nil {
- return err
- }
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Auth-Token", d.token)
-
- client := &http.Client{Timeout: time.Duration(10 * time.Second)}
- resp, err := client.Do(req)
- if err != nil {
- return err
- }
- resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return fmt.Errorf("Dyn API request failed to delete session with HTTP status code %d", resp.StatusCode)
- }
-
- d.token = ""
-
- return nil
-}
-
-// Present creates a TXT record using the specified parameters
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- err = d.login()
- if err != nil {
- return err
- }
-
- data := map[string]interface{}{
- "rdata": map[string]string{
- "txtdata": value,
- },
- "ttl": strconv.Itoa(ttl),
- }
-
- resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
- _, err = d.sendRequest("POST", resource, data)
- if err != nil {
- return err
- }
-
- err = d.publish(authZone, "Added TXT record for ACME dns-01 challenge using lego client")
- if err != nil {
- return err
- }
-
- err = d.logout()
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (d *DNSProvider) publish(zone, notes string) error {
- type publish struct {
- Publish bool `json:"publish"`
- Notes string `json:"notes"`
- }
-
- pub := &publish{Publish: true, Notes: notes}
- resource := fmt.Sprintf("Zone/%s/", zone)
- _, err := d.sendRequest("PUT", resource, pub)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- err = d.login()
- if err != nil {
- return err
- }
-
- resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
- url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
- req, err := http.NewRequest("DELETE", url, nil)
- if err != nil {
- return err
- }
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Auth-Token", d.token)
-
- client := &http.Client{Timeout: time.Duration(10 * time.Second)}
- resp, err := client.Do(req)
- if err != nil {
- return err
- }
- resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return fmt.Errorf("Dyn API request failed to delete TXT record HTTP status code %d", resp.StatusCode)
- }
-
- err = d.publish(authZone, "Removed TXT record for ACME dns-01 challenge using lego client")
- if err != nil {
- return err
- }
-
- err = d.logout()
- if err != nil {
- return err
- }
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn_test.go b/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn_test.go
deleted file mode 100644
index 0d28d5d0e..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/dyn/dyn_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package dyn
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- dynLiveTest bool
- dynCustomerName string
- dynUserName string
- dynPassword string
- dynDomain string
-)
-
-func init() {
- dynCustomerName = os.Getenv("DYN_CUSTOMER_NAME")
- dynUserName = os.Getenv("DYN_USER_NAME")
- dynPassword = os.Getenv("DYN_PASSWORD")
- dynDomain = os.Getenv("DYN_DOMAIN")
- if len(dynCustomerName) > 0 && len(dynUserName) > 0 && len(dynPassword) > 0 && len(dynDomain) > 0 {
- dynLiveTest = true
- }
-}
-
-func TestLiveDynPresent(t *testing.T) {
- if !dynLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.Present(dynDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveDynCleanUp(t *testing.T) {
- if !dynLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.CleanUp(dynDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go b/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go
deleted file mode 100644
index 4b125e8df..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Package exoscale implements a DNS provider for solving the DNS-01 challenge
-// using exoscale DNS.
-package exoscale
-
-import (
- "errors"
- "fmt"
- "os"
-
- "github.com/exoscale/egoscale"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface.
-type DNSProvider struct {
- client *egoscale.Client
-}
-
-// Credentials must be passed in the environment variables:
-// EXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT.
-func NewDNSProvider() (*DNSProvider, error) {
- key := os.Getenv("EXOSCALE_API_KEY")
- secret := os.Getenv("EXOSCALE_API_SECRET")
- endpoint := os.Getenv("EXOSCALE_ENDPOINT")
- return NewDNSProviderClient(key, secret, endpoint)
-}
-
-// Uses the supplied parameters to return a DNSProvider instance
-// configured for Exoscale.
-func NewDNSProviderClient(key, secret, endpoint string) (*DNSProvider, error) {
- if key == "" || secret == "" {
- return nil, fmt.Errorf("Exoscale credentials missing")
- }
- if endpoint == "" {
- endpoint = "https://api.exoscale.ch/dns"
- }
-
- return &DNSProvider{
- client: egoscale.NewClient(endpoint, key, secret),
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
- if err != nil {
- return err
- }
-
- recordID, err := c.FindExistingRecordId(zone, recordName)
- if err != nil {
- return err
- }
-
- record := egoscale.DNSRecord{
- Name: recordName,
- TTL: ttl,
- Content: value,
- RecordType: "TXT",
- }
-
- if recordID == 0 {
- _, err := c.client.CreateRecord(zone, record)
- if err != nil {
- return errors.New("Error while creating DNS record: " + err.Error())
- }
- } else {
- record.ID = recordID
- _, err := c.client.UpdateRecord(zone, record)
- if err != nil {
- return errors.New("Error while updating DNS record: " + err.Error())
- }
- }
-
- return nil
-}
-
-// CleanUp removes the record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
- zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
- if err != nil {
- return err
- }
-
- recordID, err := c.FindExistingRecordId(zone, recordName)
- if err != nil {
- return err
- }
-
- if recordID != 0 {
- err = c.client.DeleteRecord(zone, recordID)
- if err != nil {
- return errors.New("Error while deleting DNS record: " + err.Error())
- }
- }
-
- return nil
-}
-
-// Query Exoscale to find an existing record for this name.
-// Returns nil if no record could be found
-func (c *DNSProvider) FindExistingRecordId(zone, recordName string) (int64, error) {
- records, err := c.client.GetRecords(zone)
- if err != nil {
- return -1, errors.New("Error while retrievening DNS records: " + err.Error())
- }
- for _, record := range records {
- if record.Name == recordName {
- return record.ID, nil
- }
- }
- return 0, nil
-}
-
-// Extract DNS zone and DNS entry name
-func (c *DNSProvider) FindZoneAndRecordName(fqdn, domain string) (string, string, error) {
- zone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return "", "", err
- }
- zone = acme.UnFqdn(zone)
- name := acme.UnFqdn(fqdn)
- name = name[:len(name)-len("."+zone)]
-
- return zone, name, nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale_test.go b/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale_test.go
deleted file mode 100644
index 343dd56f8..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package exoscale
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- exoscaleLiveTest bool
- exoscaleAPIKey string
- exoscaleAPISecret string
- exoscaleDomain string
-)
-
-func init() {
- exoscaleAPISecret = os.Getenv("EXOSCALE_API_SECRET")
- exoscaleAPIKey = os.Getenv("EXOSCALE_API_KEY")
- exoscaleDomain = os.Getenv("EXOSCALE_DOMAIN")
- if len(exoscaleAPIKey) > 0 && len(exoscaleAPISecret) > 0 && len(exoscaleDomain) > 0 {
- exoscaleLiveTest = true
- }
-}
-
-func restoreExoscaleEnv() {
- os.Setenv("EXOSCALE_API_KEY", exoscaleAPIKey)
- os.Setenv("EXOSCALE_API_SECRET", exoscaleAPISecret)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- os.Setenv("EXOSCALE_API_KEY", "")
- os.Setenv("EXOSCALE_API_SECRET", "")
- _, err := NewDNSProviderClient("example@example.com", "123", "")
- assert.NoError(t, err)
- restoreExoscaleEnv()
-}
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("EXOSCALE_API_KEY", "example@example.com")
- os.Setenv("EXOSCALE_API_SECRET", "123")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restoreExoscaleEnv()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("EXOSCALE_API_KEY", "")
- os.Setenv("EXOSCALE_API_SECRET", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "Exoscale credentials missing")
- restoreExoscaleEnv()
-}
-
-func TestExtractRootRecordName(t *testing.T) {
- provider, err := NewDNSProviderClient("example@example.com", "123", "")
- assert.NoError(t, err)
-
- zone, recordName, err := provider.FindZoneAndRecordName("_acme-challenge.bar.com.", "bar.com")
- assert.NoError(t, err)
- assert.Equal(t, "bar.com", zone)
- assert.Equal(t, "_acme-challenge", recordName)
-}
-
-func TestExtractSubRecordName(t *testing.T) {
- provider, err := NewDNSProviderClient("example@example.com", "123", "")
- assert.NoError(t, err)
-
- zone, recordName, err := provider.FindZoneAndRecordName("_acme-challenge.foo.bar.com.", "foo.bar.com")
- assert.NoError(t, err)
- assert.Equal(t, "bar.com", zone)
- assert.Equal(t, "_acme-challenge.foo", recordName)
-}
-
-func TestLiveExoscalePresent(t *testing.T) {
- if !exoscaleLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderClient(exoscaleAPIKey, exoscaleAPISecret, "")
- assert.NoError(t, err)
-
- err = provider.Present(exoscaleDomain, "", "123d==")
- assert.NoError(t, err)
-
- // Present Twice to handle create / update
- err = provider.Present(exoscaleDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveExoscaleCleanUp(t *testing.T) {
- if !exoscaleLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProviderClient(exoscaleAPIKey, exoscaleAPISecret, "")
- assert.NoError(t, err)
-
- err = provider.CleanUp(exoscaleDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go b/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go
deleted file mode 100644
index 422b02a21..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go
+++ /dev/null
@@ -1,472 +0,0 @@
-// Package gandi implements a DNS provider for solving the DNS-01
-// challenge using Gandi DNS.
-package gandi
-
-import (
- "bytes"
- "encoding/xml"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "strings"
- "sync"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// Gandi API reference: http://doc.rpc.gandi.net/index.html
-// Gandi API domain examples: http://doc.rpc.gandi.net/domain/faq.html
-
-var (
- // endpoint is the Gandi XML-RPC endpoint used by Present and
- // CleanUp. It is overridden during tests.
- endpoint = "https://rpc.gandi.net/xmlrpc/"
- // findZoneByFqdn determines the DNS zone of an fqdn. It is overridden
- // during tests.
- findZoneByFqdn = acme.FindZoneByFqdn
-)
-
-// inProgressInfo contains information about an in-progress challenge
-type inProgressInfo struct {
- zoneID int // zoneID of gandi zone to restore in CleanUp
- newZoneID int // zoneID of temporary gandi zone containing TXT record
- authZone string // the domain name registered at gandi with trailing "."
-}
-
-// DNSProvider is an implementation of the
-// acme.ChallengeProviderTimeout interface that uses Gandi's XML-RPC
-// API to manage TXT records for a domain.
-type DNSProvider struct {
- apiKey string
- inProgressFQDNs map[string]inProgressInfo
- inProgressAuthZones map[string]struct{}
- inProgressMu sync.Mutex
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Gandi.
-// Credentials must be passed in the environment variable: GANDI_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- apiKey := os.Getenv("GANDI_API_KEY")
- return NewDNSProviderCredentials(apiKey)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Gandi.
-func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
- if apiKey == "" {
- return nil, fmt.Errorf("No Gandi API Key given")
- }
- return &DNSProvider{
- apiKey: apiKey,
- inProgressFQDNs: make(map[string]inProgressInfo),
- inProgressAuthZones: make(map[string]struct{}),
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters. It
-// does this by creating and activating a new temporary Gandi DNS
-// zone. This new zone contains the TXT record.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- if ttl < 300 {
- ttl = 300 // 300 is gandi minimum value for ttl
- }
- // find authZone and Gandi zone_id for fqdn
- authZone, err := findZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Gandi DNS: findZoneByFqdn failure: %v", err)
- }
- zoneID, err := d.getZoneID(authZone)
- if err != nil {
- return err
- }
- // determine name of TXT record
- if !strings.HasSuffix(
- strings.ToLower(fqdn), strings.ToLower("."+authZone)) {
- return fmt.Errorf(
- "Gandi DNS: unexpected authZone %s for fqdn %s", authZone, fqdn)
- }
- name := fqdn[:len(fqdn)-len("."+authZone)]
- // acquire lock and check there is not a challenge already in
- // progress for this value of authZone
- d.inProgressMu.Lock()
- defer d.inProgressMu.Unlock()
- if _, ok := d.inProgressAuthZones[authZone]; ok {
- return fmt.Errorf(
- "Gandi DNS: challenge already in progress for authZone %s",
- authZone)
- }
- // perform API actions to create and activate new gandi zone
- // containing the required TXT record
- newZoneName := fmt.Sprintf(
- "%s [ACME Challenge %s]",
- acme.UnFqdn(authZone), time.Now().Format(time.RFC822Z))
- newZoneID, err := d.cloneZone(zoneID, newZoneName)
- if err != nil {
- return err
- }
- newZoneVersion, err := d.newZoneVersion(newZoneID)
- if err != nil {
- return err
- }
- err = d.addTXTRecord(newZoneID, newZoneVersion, name, value, ttl)
- if err != nil {
- return err
- }
- err = d.setZoneVersion(newZoneID, newZoneVersion)
- if err != nil {
- return err
- }
- err = d.setZone(authZone, newZoneID)
- if err != nil {
- return err
- }
- // save data necessary for CleanUp
- d.inProgressFQDNs[fqdn] = inProgressInfo{
- zoneID: zoneID,
- newZoneID: newZoneID,
- authZone: authZone,
- }
- d.inProgressAuthZones[authZone] = struct{}{}
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified
-// parameters. It does this by restoring the old Gandi DNS zone and
-// removing the temporary one created by Present.
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
- // acquire lock and retrieve zoneID, newZoneID and authZone
- d.inProgressMu.Lock()
- defer d.inProgressMu.Unlock()
- if _, ok := d.inProgressFQDNs[fqdn]; !ok {
- // if there is no cleanup information then just return
- return nil
- }
- zoneID := d.inProgressFQDNs[fqdn].zoneID
- newZoneID := d.inProgressFQDNs[fqdn].newZoneID
- authZone := d.inProgressFQDNs[fqdn].authZone
- delete(d.inProgressFQDNs, fqdn)
- delete(d.inProgressAuthZones, authZone)
- // perform API actions to restore old gandi zone for authZone
- err := d.setZone(authZone, zoneID)
- if err != nil {
- return err
- }
- err = d.deleteZone(newZoneID)
- if err != nil {
- return err
- }
- return nil
-}
-
-// Timeout returns the values (40*time.Minute, 60*time.Second) which
-// are used by the acme package as timeout and check interval values
-// when checking for DNS record propagation with Gandi.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 40 * time.Minute, 60 * time.Second
-}
-
-// types for XML-RPC method calls and parameters
-
-type param interface {
- param()
-}
-type paramString struct {
- XMLName xml.Name `xml:"param"`
- Value string `xml:"value>string"`
-}
-type paramInt struct {
- XMLName xml.Name `xml:"param"`
- Value int `xml:"value>int"`
-}
-
-type structMember interface {
- structMember()
-}
-type structMemberString struct {
- Name string `xml:"name"`
- Value string `xml:"value>string"`
-}
-type structMemberInt struct {
- Name string `xml:"name"`
- Value int `xml:"value>int"`
-}
-type paramStruct struct {
- XMLName xml.Name `xml:"param"`
- StructMembers []structMember `xml:"value>struct>member"`
-}
-
-func (p paramString) param() {}
-func (p paramInt) param() {}
-func (m structMemberString) structMember() {}
-func (m structMemberInt) structMember() {}
-func (p paramStruct) param() {}
-
-type methodCall struct {
- XMLName xml.Name `xml:"methodCall"`
- MethodName string `xml:"methodName"`
- Params []param `xml:"params"`
-}
-
-// types for XML-RPC responses
-
-type response interface {
- faultCode() int
- faultString() string
-}
-
-type responseFault struct {
- FaultCode int `xml:"fault>value>struct>member>value>int"`
- FaultString string `xml:"fault>value>struct>member>value>string"`
-}
-
-func (r responseFault) faultCode() int { return r.FaultCode }
-func (r responseFault) faultString() string { return r.FaultString }
-
-type responseStruct struct {
- responseFault
- StructMembers []struct {
- Name string `xml:"name"`
- ValueInt int `xml:"value>int"`
- } `xml:"params>param>value>struct>member"`
-}
-
-type responseInt struct {
- responseFault
- Value int `xml:"params>param>value>int"`
-}
-
-type responseBool struct {
- responseFault
- Value bool `xml:"params>param>value>boolean"`
-}
-
-// POSTing/Marshalling/Unmarshalling
-
-type rpcError struct {
- faultCode int
- faultString string
-}
-
-func (e rpcError) Error() string {
- return fmt.Sprintf(
- "Gandi DNS: RPC Error: (%d) %s", e.faultCode, e.faultString)
-}
-
-func httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
- client := http.Client{Timeout: 60 * time.Second}
- resp, err := client.Post(url, bodyType, body)
- if err != nil {
- return nil, fmt.Errorf("Gandi DNS: HTTP Post Error: %v", err)
- }
- defer resp.Body.Close()
- b, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, fmt.Errorf("Gandi DNS: HTTP Post Error: %v", err)
- }
- return b, nil
-}
-
-// rpcCall makes an XML-RPC call to Gandi's RPC endpoint by
-// marshalling the data given in the call argument to XML and sending
-// that via HTTP Post to Gandi. The response is then unmarshalled into
-// the resp argument.
-func rpcCall(call *methodCall, resp response) error {
- // marshal
- b, err := xml.MarshalIndent(call, "", " ")
- if err != nil {
- return fmt.Errorf("Gandi DNS: Marshal Error: %v", err)
- }
- // post
- b = append([]byte(`<?xml version="1.0"?>`+"\n"), b...)
- respBody, err := httpPost(endpoint, "text/xml", bytes.NewReader(b))
- if err != nil {
- return err
- }
- // unmarshal
- err = xml.Unmarshal(respBody, resp)
- if err != nil {
- return fmt.Errorf("Gandi DNS: Unmarshal Error: %v", err)
- }
- if resp.faultCode() != 0 {
- return rpcError{
- faultCode: resp.faultCode(), faultString: resp.faultString()}
- }
- return nil
-}
-
-// functions to perform API actions
-
-func (d *DNSProvider) getZoneID(domain string) (int, error) {
- resp := &responseStruct{}
- err := rpcCall(&methodCall{
- MethodName: "domain.info",
- Params: []param{
- paramString{Value: d.apiKey},
- paramString{Value: domain},
- },
- }, resp)
- if err != nil {
- return 0, err
- }
- var zoneID int
- for _, member := range resp.StructMembers {
- if member.Name == "zone_id" {
- zoneID = member.ValueInt
- }
- }
- if zoneID == 0 {
- return 0, fmt.Errorf(
- "Gandi DNS: Could not determine zone_id for %s", domain)
- }
- return zoneID, nil
-}
-
-func (d *DNSProvider) cloneZone(zoneID int, name string) (int, error) {
- resp := &responseStruct{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.clone",
- Params: []param{
- paramString{Value: d.apiKey},
- paramInt{Value: zoneID},
- paramInt{Value: 0},
- paramStruct{
- StructMembers: []structMember{
- structMemberString{
- Name: "name",
- Value: name,
- }},
- },
- },
- }, resp)
- if err != nil {
- return 0, err
- }
- var newZoneID int
- for _, member := range resp.StructMembers {
- if member.Name == "id" {
- newZoneID = member.ValueInt
- }
- }
- if newZoneID == 0 {
- return 0, fmt.Errorf("Gandi DNS: Could not determine cloned zone_id")
- }
- return newZoneID, nil
-}
-
-func (d *DNSProvider) newZoneVersion(zoneID int) (int, error) {
- resp := &responseInt{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.version.new",
- Params: []param{
- paramString{Value: d.apiKey},
- paramInt{Value: zoneID},
- },
- }, resp)
- if err != nil {
- return 0, err
- }
- if resp.Value == 0 {
- return 0, fmt.Errorf("Gandi DNS: Could not create new zone version")
- }
- return resp.Value, nil
-}
-
-func (d *DNSProvider) addTXTRecord(zoneID int, version int, name string, value string, ttl int) error {
- resp := &responseStruct{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.record.add",
- Params: []param{
- paramString{Value: d.apiKey},
- paramInt{Value: zoneID},
- paramInt{Value: version},
- paramStruct{
- StructMembers: []structMember{
- structMemberString{
- Name: "type",
- Value: "TXT",
- }, structMemberString{
- Name: "name",
- Value: name,
- }, structMemberString{
- Name: "value",
- Value: value,
- }, structMemberInt{
- Name: "ttl",
- Value: ttl,
- }},
- },
- },
- }, resp)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (d *DNSProvider) setZoneVersion(zoneID int, version int) error {
- resp := &responseBool{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.version.set",
- Params: []param{
- paramString{Value: d.apiKey},
- paramInt{Value: zoneID},
- paramInt{Value: version},
- },
- }, resp)
- if err != nil {
- return err
- }
- if !resp.Value {
- return fmt.Errorf("Gandi DNS: could not set zone version")
- }
- return nil
-}
-
-func (d *DNSProvider) setZone(domain string, zoneID int) error {
- resp := &responseStruct{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.set",
- Params: []param{
- paramString{Value: d.apiKey},
- paramString{Value: domain},
- paramInt{Value: zoneID},
- },
- }, resp)
- if err != nil {
- return err
- }
- var respZoneID int
- for _, member := range resp.StructMembers {
- if member.Name == "zone_id" {
- respZoneID = member.ValueInt
- }
- }
- if respZoneID != zoneID {
- return fmt.Errorf(
- "Gandi DNS: Could not set new zone_id for %s", domain)
- }
- return nil
-}
-
-func (d *DNSProvider) deleteZone(zoneID int) error {
- resp := &responseBool{}
- err := rpcCall(&methodCall{
- MethodName: "domain.zone.delete",
- Params: []param{
- paramString{Value: d.apiKey},
- paramInt{Value: zoneID},
- },
- }, resp)
- if err != nil {
- return err
- }
- if !resp.Value {
- return fmt.Errorf("Gandi DNS: could not delete zone_id")
- }
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi_test.go b/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi_test.go
deleted file mode 100644
index 451333ca1..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/gandi/gandi_test.go
+++ /dev/null
@@ -1,939 +0,0 @@
-package gandi
-
-import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "io"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "os"
- "regexp"
- "strings"
- "testing"
-
- "github.com/xenolf/lego/acme"
-)
-
-// stagingServer is the Let's Encrypt staging server used by the live test
-const stagingServer = "https://acme-staging.api.letsencrypt.org/directory"
-
-// user implements acme.User and is used by the live test
-type user struct {
- Email string
- Registration *acme.RegistrationResource
- key crypto.PrivateKey
-}
-
-func (u *user) GetEmail() string {
- return u.Email
-}
-func (u *user) GetRegistration() *acme.RegistrationResource {
- return u.Registration
-}
-func (u *user) GetPrivateKey() crypto.PrivateKey {
- return u.key
-}
-
-// TestDNSProvider runs Present and CleanUp against a fake Gandi RPC
-// Server, whose responses are predetermined for particular requests.
-func TestDNSProvider(t *testing.T) {
- fakeAPIKey := "123412341234123412341234"
- fakeKeyAuth := "XXXX"
- provider, err := NewDNSProviderCredentials(fakeAPIKey)
- if err != nil {
- t.Fatal(err)
- }
- regexpDate, err := regexp.Compile(`\[ACME Challenge [^\]:]*:[^\]]*\]`)
- if err != nil {
- t.Fatal(err)
- }
- // start fake RPC server
- fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if r.Header.Get("Content-Type") != "text/xml" {
- t.Fatalf("Content-Type: text/xml header not found")
- }
- req, err := ioutil.ReadAll(r.Body)
- if err != nil {
- t.Fatal(err)
- }
- req = regexpDate.ReplaceAllLiteral(
- req, []byte(`[ACME Challenge 01 Jan 16 00:00 +0000]`))
- resp, ok := serverResponses[string(req)]
- if !ok {
- t.Fatalf("Server response for request not found")
- }
- _, err = io.Copy(w, strings.NewReader(resp))
- if err != nil {
- t.Fatal(err)
- }
- }))
- defer fakeServer.Close()
- // define function to override findZoneByFqdn with
- fakeFindZoneByFqdn := func(fqdn string, nameserver []string) (string, error) {
- return "example.com.", nil
- }
- // override gandi endpoint and findZoneByFqdn function
- savedEndpoint, savedFindZoneByFqdn := endpoint, findZoneByFqdn
- defer func() {
- endpoint, findZoneByFqdn = savedEndpoint, savedFindZoneByFqdn
- }()
- endpoint, findZoneByFqdn = fakeServer.URL+"/", fakeFindZoneByFqdn
- // run Present
- err = provider.Present("abc.def.example.com", "", fakeKeyAuth)
- if err != nil {
- t.Fatal(err)
- }
- // run CleanUp
- err = provider.CleanUp("abc.def.example.com", "", fakeKeyAuth)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-// TestDNSProviderLive performs a live test to obtain a certificate
-// using the Let's Encrypt staging server. It runs provided that both
-// the environment variables GANDI_API_KEY and GANDI_TEST_DOMAIN are
-// set. Otherwise the test is skipped.
-//
-// To complete this test, go test must be run with the -timeout=40m
-// flag, since the default timeout of 10m is insufficient.
-func TestDNSProviderLive(t *testing.T) {
- apiKey := os.Getenv("GANDI_API_KEY")
- domain := os.Getenv("GANDI_TEST_DOMAIN")
- if apiKey == "" || domain == "" {
- t.Skip("skipping live test")
- }
- // create a user.
- const rsaKeySize = 2048
- privateKey, err := rsa.GenerateKey(rand.Reader, rsaKeySize)
- if err != nil {
- t.Fatal(err)
- }
- myUser := user{
- Email: "test@example.com",
- key: privateKey,
- }
- // create a client using staging server
- client, err := acme.NewClient(stagingServer, &myUser, acme.RSA2048)
- if err != nil {
- t.Fatal(err)
- }
- provider, err := NewDNSProviderCredentials(apiKey)
- if err != nil {
- t.Fatal(err)
- }
- err = client.SetChallengeProvider(acme.DNS01, provider)
- if err != nil {
- t.Fatal(err)
- }
- client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01})
- // register and agree tos
- reg, err := client.Register()
- if err != nil {
- t.Fatal(err)
- }
- myUser.Registration = reg
- err = client.AgreeToTOS()
- if err != nil {
- t.Fatal(err)
- }
- // complete the challenge
- bundle := false
- _, failures := client.ObtainCertificate([]string{domain}, bundle, nil, false)
- if len(failures) > 0 {
- t.Fatal(failures)
- }
-}
-
-// serverResponses is the XML-RPC Request->Response map used by the
-// fake RPC server. It was generated by recording a real RPC session
-// which resulted in the successful issue of a cert, and then
-// anonymizing the RPC data.
-var serverResponses = map[string]string{
- // Present Request->Response 1 (getZoneID)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.info</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <string>example.com.</string>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><struct>
-<member>
-<name>date_updated</name>
-<value><dateTime.iso8601>20160216T16:14:23</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_delete</name>
-<value><dateTime.iso8601>20170331T16:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>is_premium</name>
-<value><boolean>0</boolean></value>
-</member>
-<member>
-<name>date_hold_begin</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_registry_end</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>authinfo_expiration_date</name>
-<value><dateTime.iso8601>20161211T21:31:20</dateTime.iso8601></value>
-</member>
-<member>
-<name>contacts</name>
-<value><struct>
-<member>
-<name>owner</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>admin</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>bill</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>tech</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>reseller</name>
-<value><nil/></value></member>
-</struct></value>
-</member>
-<member>
-<name>nameservers</name>
-<value><array><data>
-<value><string>a.dns.gandi.net</string></value>
-<value><string>b.dns.gandi.net</string></value>
-<value><string>c.dns.gandi.net</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_restore_end</name>
-<value><dateTime.iso8601>20170501T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>id</name>
-<value><int>2222222</int></value>
-</member>
-<member>
-<name>authinfo</name>
-<value><string>ABCDABCDAB</string></value>
-</member>
-<member>
-<name>status</name>
-<value><array><data>
-<value><string>clientTransferProhibited</string></value>
-<value><string>serverTransferProhibited</string></value>
-</data></array></value>
-</member>
-<member>
-<name>tags</name>
-<value><array><data>
-</data></array></value>
-</member>
-<member>
-<name>date_hold_end</name>
-<value><dateTime.iso8601>20170401T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>services</name>
-<value><array><data>
-<value><string>gandidns</string></value>
-<value><string>gandimail</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_pending_delete_end</name>
-<value><dateTime.iso8601>20170506T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>zone_id</name>
-<value><int>1234567</int></value>
-</member>
-<member>
-<name>date_renew_begin</name>
-<value><dateTime.iso8601>20120101T00:00:00</dateTime.iso8601></value>
-</member>
-<member>
-<name>fqdn</name>
-<value><string>example.com</string></value>
-</member>
-<member>
-<name>autorenew</name>
-<value><nil/></value></member>
-<member>
-<name>date_registry_creation</name>
-<value><dateTime.iso8601>20150215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>tld</name>
-<value><string>org</string></value>
-</member>
-<member>
-<name>date_created</name>
-<value><dateTime.iso8601>20150215T03:04:06</dateTime.iso8601></value>
-</member>
-</struct></value>
-</param>
-</params>
-</methodResponse>
-`,
- // Present Request->Response 2 (cloneZone)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.clone</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <int>1234567</int>
- </value>
- </param>
- <param>
- <value>
- <int>0</int>
- </value>
- </param>
- <param>
- <value>
- <struct>
- <member>
- <name>name</name>
- <value>
- <string>example.com [ACME Challenge 01 Jan 16 00:00 +0000]</string>
- </value>
- </member>
- </struct>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><struct>
-<member>
-<name>name</name>
-<value><string>example.com [ACME Challenge 01 Jan 16 00:00 +0000]</string></value>
-</member>
-<member>
-<name>versions</name>
-<value><array><data>
-<value><int>1</int></value>
-</data></array></value>
-</member>
-<member>
-<name>date_updated</name>
-<value><dateTime.iso8601>20160216T16:24:29</dateTime.iso8601></value>
-</member>
-<member>
-<name>id</name>
-<value><int>7654321</int></value>
-</member>
-<member>
-<name>owner</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>version</name>
-<value><int>1</int></value>
-</member>
-<member>
-<name>domains</name>
-<value><int>0</int></value>
-</member>
-<member>
-<name>public</name>
-<value><boolean>0</boolean></value>
-</member>
-</struct></value>
-</param>
-</params>
-</methodResponse>
-`,
- // Present Request->Response 3 (newZoneVersion)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.version.new</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <int>7654321</int>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><int>2</int></value>
-</param>
-</params>
-</methodResponse>
-`,
- // Present Request->Response 4 (addTXTRecord)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.record.add</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <int>7654321</int>
- </value>
- </param>
- <param>
- <value>
- <int>2</int>
- </value>
- </param>
- <param>
- <value>
- <struct>
- <member>
- <name>type</name>
- <value>
- <string>TXT</string>
- </value>
- </member>
- <member>
- <name>name</name>
- <value>
- <string>_acme-challenge.abc.def</string>
- </value>
- </member>
- <member>
- <name>value</name>
- <value>
- <string>ezRpBPY8wH8djMLYjX2uCKPwiKDkFZ1SFMJ6ZXGlHrQ</string>
- </value>
- </member>
- <member>
- <name>ttl</name>
- <value>
- <int>300</int>
- </value>
- </member>
- </struct>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><struct>
-<member>
-<name>name</name>
-<value><string>_acme-challenge.abc.def</string></value>
-</member>
-<member>
-<name>type</name>
-<value><string>TXT</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>333333333</int></value>
-</member>
-<member>
-<name>value</name>
-<value><string>"ezRpBPY8wH8djMLYjX2uCKPwiKDkFZ1SFMJ6ZXGlHrQ"</string></value>
-</member>
-<member>
-<name>ttl</name>
-<value><int>300</int></value>
-</member>
-</struct></value>
-</param>
-</params>
-</methodResponse>
-`,
- // Present Request->Response 5 (setZoneVersion)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.version.set</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <int>7654321</int>
- </value>
- </param>
- <param>
- <value>
- <int>2</int>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><boolean>1</boolean></value>
-</param>
-</params>
-</methodResponse>
-`,
- // Present Request->Response 6 (setZone)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.set</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <string>example.com.</string>
- </value>
- </param>
- <param>
- <value>
- <int>7654321</int>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><struct>
-<member>
-<name>date_updated</name>
-<value><dateTime.iso8601>20160216T16:14:23</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_delete</name>
-<value><dateTime.iso8601>20170331T16:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>is_premium</name>
-<value><boolean>0</boolean></value>
-</member>
-<member>
-<name>date_hold_begin</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_registry_end</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>authinfo_expiration_date</name>
-<value><dateTime.iso8601>20161211T21:31:20</dateTime.iso8601></value>
-</member>
-<member>
-<name>contacts</name>
-<value><struct>
-<member>
-<name>owner</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>admin</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>bill</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>tech</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>reseller</name>
-<value><nil/></value></member>
-</struct></value>
-</member>
-<member>
-<name>nameservers</name>
-<value><array><data>
-<value><string>a.dns.gandi.net</string></value>
-<value><string>b.dns.gandi.net</string></value>
-<value><string>c.dns.gandi.net</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_restore_end</name>
-<value><dateTime.iso8601>20170501T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>id</name>
-<value><int>2222222</int></value>
-</member>
-<member>
-<name>authinfo</name>
-<value><string>ABCDABCDAB</string></value>
-</member>
-<member>
-<name>status</name>
-<value><array><data>
-<value><string>clientTransferProhibited</string></value>
-<value><string>serverTransferProhibited</string></value>
-</data></array></value>
-</member>
-<member>
-<name>tags</name>
-<value><array><data>
-</data></array></value>
-</member>
-<member>
-<name>date_hold_end</name>
-<value><dateTime.iso8601>20170401T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>services</name>
-<value><array><data>
-<value><string>gandidns</string></value>
-<value><string>gandimail</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_pending_delete_end</name>
-<value><dateTime.iso8601>20170506T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>zone_id</name>
-<value><int>7654321</int></value>
-</member>
-<member>
-<name>date_renew_begin</name>
-<value><dateTime.iso8601>20120101T00:00:00</dateTime.iso8601></value>
-</member>
-<member>
-<name>fqdn</name>
-<value><string>example.com</string></value>
-</member>
-<member>
-<name>autorenew</name>
-<value><nil/></value></member>
-<member>
-<name>date_registry_creation</name>
-<value><dateTime.iso8601>20150215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>tld</name>
-<value><string>org</string></value>
-</member>
-<member>
-<name>date_created</name>
-<value><dateTime.iso8601>20150215T03:04:06</dateTime.iso8601></value>
-</member>
-</struct></value>
-</param>
-</params>
-</methodResponse>
-`,
- // CleanUp Request->Response 1 (setZone)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.set</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <string>example.com.</string>
- </value>
- </param>
- <param>
- <value>
- <int>1234567</int>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><struct>
-<member>
-<name>date_updated</name>
-<value><dateTime.iso8601>20160216T16:24:38</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_delete</name>
-<value><dateTime.iso8601>20170331T16:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>is_premium</name>
-<value><boolean>0</boolean></value>
-</member>
-<member>
-<name>date_hold_begin</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>date_registry_end</name>
-<value><dateTime.iso8601>20170215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>authinfo_expiration_date</name>
-<value><dateTime.iso8601>20161211T21:31:20</dateTime.iso8601></value>
-</member>
-<member>
-<name>contacts</name>
-<value><struct>
-<member>
-<name>owner</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>admin</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>bill</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>tech</name>
-<value><struct>
-<member>
-<name>handle</name>
-<value><string>LEGO-GANDI</string></value>
-</member>
-<member>
-<name>id</name>
-<value><int>111111</int></value>
-</member>
-</struct></value>
-</member>
-<member>
-<name>reseller</name>
-<value><nil/></value></member>
-</struct></value>
-</member>
-<member>
-<name>nameservers</name>
-<value><array><data>
-<value><string>a.dns.gandi.net</string></value>
-<value><string>b.dns.gandi.net</string></value>
-<value><string>c.dns.gandi.net</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_restore_end</name>
-<value><dateTime.iso8601>20170501T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>id</name>
-<value><int>2222222</int></value>
-</member>
-<member>
-<name>authinfo</name>
-<value><string>ABCDABCDAB</string></value>
-</member>
-<member>
-<name>status</name>
-<value><array><data>
-<value><string>clientTransferProhibited</string></value>
-<value><string>serverTransferProhibited</string></value>
-</data></array></value>
-</member>
-<member>
-<name>tags</name>
-<value><array><data>
-</data></array></value>
-</member>
-<member>
-<name>date_hold_end</name>
-<value><dateTime.iso8601>20170401T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>services</name>
-<value><array><data>
-<value><string>gandidns</string></value>
-<value><string>gandimail</string></value>
-</data></array></value>
-</member>
-<member>
-<name>date_pending_delete_end</name>
-<value><dateTime.iso8601>20170506T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>zone_id</name>
-<value><int>1234567</int></value>
-</member>
-<member>
-<name>date_renew_begin</name>
-<value><dateTime.iso8601>20120101T00:00:00</dateTime.iso8601></value>
-</member>
-<member>
-<name>fqdn</name>
-<value><string>example.com</string></value>
-</member>
-<member>
-<name>autorenew</name>
-<value><nil/></value></member>
-<member>
-<name>date_registry_creation</name>
-<value><dateTime.iso8601>20150215T02:04:06</dateTime.iso8601></value>
-</member>
-<member>
-<name>tld</name>
-<value><string>org</string></value>
-</member>
-<member>
-<name>date_created</name>
-<value><dateTime.iso8601>20150215T03:04:06</dateTime.iso8601></value>
-</member>
-</struct></value>
-</param>
-</params>
-</methodResponse>
-`,
- // CleanUp Request->Response 2 (deleteZone)
- `<?xml version="1.0"?>
-<methodCall>
- <methodName>domain.zone.delete</methodName>
- <param>
- <value>
- <string>123412341234123412341234</string>
- </value>
- </param>
- <param>
- <value>
- <int>7654321</int>
- </value>
- </param>
-</methodCall>`: `<?xml version='1.0'?>
-<methodResponse>
-<params>
-<param>
-<value><boolean>1</boolean></value>
-</param>
-</params>
-</methodResponse>
-`,
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go b/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go
deleted file mode 100644
index 4112f6628..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Package godaddy implements a DNS provider for solving the DNS-01 challenge using godaddy DNS.
-package godaddy
-
-import (
- "fmt"
- "io"
- "net/http"
- "os"
- "time"
-
- "bytes"
- "encoding/json"
- "github.com/xenolf/lego/acme"
- "io/ioutil"
- "strings"
-)
-
-// GoDaddyAPIURL represents the API endpoint to call.
-const apiURL = "https://api.godaddy.com"
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-type DNSProvider struct {
- apiKey string
- apiSecret string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for godaddy.
-// Credentials must be passed in the environment variables: GODADDY_API_KEY
-// and GODADDY_API_SECRET.
-func NewDNSProvider() (*DNSProvider, error) {
- apikey := os.Getenv("GODADDY_API_KEY")
- secret := os.Getenv("GODADDY_API_SECRET")
- return NewDNSProviderCredentials(apikey, secret)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for godaddy.
-func NewDNSProviderCredentials(apiKey, apiSecret string) (*DNSProvider, error) {
- if apiKey == "" || apiSecret == "" {
- return nil, fmt.Errorf("GoDaddy credentials missing")
- }
-
- return &DNSProvider{apiKey, apiSecret}, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 120 * time.Second, 2 * time.Second
-}
-
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
- name := acme.UnFqdn(fqdn)
- if idx := strings.Index(name, "."+domain); idx != -1 {
- return name[:idx]
- }
- return name
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- domainZone, err := c.getZone(fqdn)
- if err != nil {
- return err
- }
-
- if ttl < 600 {
- ttl = 600
- }
-
- recordName := c.extractRecordName(fqdn, domainZone)
- rec := []DNSRecord{
- {
- Type: "TXT",
- Name: recordName,
- Data: value,
- Ttl: ttl,
- },
- }
-
- return c.updateRecords(rec, domainZone, recordName)
-}
-
-func (c *DNSProvider) updateRecords(records []DNSRecord, domainZone string, recordName string) error {
- body, err := json.Marshal(records)
- if err != nil {
- return err
- }
-
- var resp *http.Response
- resp, err = c.makeRequest("PUT", fmt.Sprintf("/v1/domains/%s/records/TXT/%s", domainZone, recordName), bytes.NewReader(body))
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- bodyBytes, _ := ioutil.ReadAll(resp.Body)
- return fmt.Errorf("Could not create record %v; Status: %v; Body: %s\n", string(body), resp.StatusCode, string(bodyBytes))
- }
- return nil
-}
-
-// CleanUp sets null value in the TXT DNS record as GoDaddy has no proper DELETE record method
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
- domainZone, err := c.getZone(fqdn)
- if err != nil {
- return err
- }
-
- recordName := c.extractRecordName(fqdn, domainZone)
- rec := []DNSRecord{
- {
- Type: "TXT",
- Name: recordName,
- Data: "null",
- },
- }
-
- return c.updateRecords(rec, domainZone, recordName)
-}
-
-func (c *DNSProvider) getZone(fqdn string) (string, error) {
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- return acme.UnFqdn(authZone), nil
-}
-
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Response, error) {
- req, err := http.NewRequest(method, fmt.Sprintf("%s%s", apiURL, uri), body)
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("Accept", "application/json")
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Authorization", fmt.Sprintf("sso-key %s:%s", c.apiKey, c.apiSecret))
-
- client := http.Client{Timeout: 30 * time.Second}
- return client.Do(req)
-}
-
-type DNSRecord struct {
- Type string `json:"type"`
- Name string `json:"name"`
- Data string `json:"data"`
- Priority int `json:"priority,omitempty"`
- Ttl int `json:"ttl,omitempty"`
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy_test.go b/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy_test.go
deleted file mode 100644
index de84d827e..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package godaddy
-
-import (
- "os"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- godaddyAPIKey string
- godaddyAPISecret string
- godaddyDomain string
- godaddyLiveTest bool
-)
-
-func init() {
- godaddyAPIKey = os.Getenv("GODADDY_API_KEY")
- godaddyAPISecret = os.Getenv("GODADDY_API_SECRET")
- godaddyDomain = os.Getenv("GODADDY_DOMAIN")
-
- if len(godaddyAPIKey) > 0 && len(godaddyAPISecret) > 0 && len(godaddyDomain) > 0 {
- godaddyLiveTest = true
- }
-}
-
-func TestNewDNSProvider(t *testing.T) {
- provider, err := NewDNSProvider()
-
- if !godaddyLiveTest {
- assert.Error(t, err)
- } else {
- assert.NotNil(t, provider)
- assert.NoError(t, err)
- }
-}
-
-func TestDNSProvider_Present(t *testing.T) {
- if !godaddyLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.Present(godaddyDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestDNSProvider_CleanUp(t *testing.T) {
- if !godaddyLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.CleanUp(godaddyDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud.go b/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud.go
deleted file mode 100644
index ba753f6dc..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud.go
+++ /dev/null
@@ -1,205 +0,0 @@
-// Package googlecloud implements a DNS provider for solving the DNS-01
-// challenge using Google Cloud DNS.
-package googlecloud
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
-
- "golang.org/x/net/context"
- "golang.org/x/oauth2"
- "golang.org/x/oauth2/google"
-
- "google.golang.org/api/dns/v1"
-)
-
-// DNSProvider is an implementation of the DNSProvider interface.
-type DNSProvider struct {
- project string
- client *dns.Service
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Google Cloud
-// DNS. Project name must be passed in the environment variable: GCE_PROJECT.
-// A Service Account file can be passed in the environment variable:
-// GCE_SERVICE_ACCOUNT_FILE
-func NewDNSProvider() (*DNSProvider, error) {
- project := os.Getenv("GCE_PROJECT")
- if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
- return NewDNSProviderServiceAccount(project, saFile)
- }
- return NewDNSProviderCredentials(project)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Google Cloud DNS.
-func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
- if project == "" {
- return nil, fmt.Errorf("Google Cloud project name missing")
- }
-
- client, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
- if err != nil {
- return nil, fmt.Errorf("Unable to get Google Cloud client: %v", err)
- }
- svc, err := dns.New(client)
- if err != nil {
- return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err)
- }
- return &DNSProvider{
- project: project,
- client: svc,
- }, nil
-}
-
-// NewDNSProviderServiceAccount uses the supplied service account JSON file to
-// return a DNSProvider instance configured for Google Cloud DNS.
-func NewDNSProviderServiceAccount(project string, saFile string) (*DNSProvider, error) {
- if project == "" {
- return nil, fmt.Errorf("Google Cloud project name missing")
- }
- if saFile == "" {
- return nil, fmt.Errorf("Google Cloud Service Account file missing")
- }
-
- dat, err := ioutil.ReadFile(saFile)
- if err != nil {
- return nil, fmt.Errorf("Unable to read Service Account file: %v", err)
- }
- conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
- if err != nil {
- return nil, fmt.Errorf("Unable to acquire config: %v", err)
- }
- client := conf.Client(oauth2.NoContext)
-
- svc, err := dns.New(client)
- if err != nil {
- return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err)
- }
- return &DNSProvider{
- project: project,
- client: svc,
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- rec := &dns.ResourceRecordSet{
- Name: fqdn,
- Rrdatas: []string{value},
- Ttl: int64(ttl),
- Type: "TXT",
- }
- change := &dns.Change{
- Additions: []*dns.ResourceRecordSet{rec},
- }
-
- // Look for existing records.
- list, err := c.client.ResourceRecordSets.List(c.project, zone).Name(fqdn).Type("TXT").Do()
- if err != nil {
- return err
- }
- if len(list.Rrsets) > 0 {
- // Attempt to delete the existing records when adding our new one.
- change.Deletions = list.Rrsets
- }
-
- chg, err := c.client.Changes.Create(c.project, zone, change).Do()
- if err != nil {
- return err
- }
-
- // wait for change to be acknowledged
- for chg.Status == "pending" {
- time.Sleep(time.Second)
-
- chg, err = c.client.Changes.Get(c.project, zone, chg.Id).Do()
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- records, err := c.findTxtRecords(zone, fqdn)
- if err != nil {
- return err
- }
-
- for _, rec := range records {
- change := &dns.Change{
- Deletions: []*dns.ResourceRecordSet{rec},
- }
- _, err = c.client.Changes.Create(c.project, zone, change).Do()
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// Timeout customizes the timeout values used by the ACME package for checking
-// DNS record validity.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 180 * time.Second, 5 * time.Second
-}
-
-// getHostedZone returns the managed-zone
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- zones, err := c.client.ManagedZones.
- List(c.project).
- DnsName(authZone).
- Do()
- if err != nil {
- return "", fmt.Errorf("GoogleCloud API call failed: %v", err)
- }
-
- if len(zones.ManagedZones) == 0 {
- return "", fmt.Errorf("No matching GoogleCloud domain found for domain %s", authZone)
- }
-
- return zones.ManagedZones[0].Name, nil
-}
-
-func (c *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSet, error) {
-
- recs, err := c.client.ResourceRecordSets.List(c.project, zone).Do()
- if err != nil {
- return nil, err
- }
-
- found := []*dns.ResourceRecordSet{}
- for _, r := range recs.Rrsets {
- if r.Type == "TXT" && r.Name == fqdn {
- found = append(found, r)
- }
- }
-
- return found, nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud_test.go b/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud_test.go
deleted file mode 100644
index 75a10d9a4..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/googlecloud/googlecloud_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package googlecloud
-
-import (
- "os"
- "testing"
- "time"
-
- "golang.org/x/net/context"
- "golang.org/x/oauth2/google"
- "google.golang.org/api/dns/v1"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- gcloudLiveTest bool
- gcloudProject string
- gcloudDomain string
-)
-
-func init() {
- gcloudProject = os.Getenv("GCE_PROJECT")
- gcloudDomain = os.Getenv("GCE_DOMAIN")
- _, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
- if err == nil && len(gcloudProject) > 0 && len(gcloudDomain) > 0 {
- gcloudLiveTest = true
- }
-}
-
-func restoreGCloudEnv() {
- os.Setenv("GCE_PROJECT", gcloudProject)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- if !gcloudLiveTest {
- t.Skip("skipping live test (requires credentials)")
- }
- os.Setenv("GCE_PROJECT", "")
- _, err := NewDNSProviderCredentials("my-project")
- assert.NoError(t, err)
- restoreGCloudEnv()
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- if !gcloudLiveTest {
- t.Skip("skipping live test (requires credentials)")
- }
- os.Setenv("GCE_PROJECT", "my-project")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restoreGCloudEnv()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("GCE_PROJECT", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "Google Cloud project name missing")
- restoreGCloudEnv()
-}
-
-func TestLiveGoogleCloudPresent(t *testing.T) {
- if !gcloudLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(gcloudProject)
- assert.NoError(t, err)
-
- err = provider.Present(gcloudDomain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveGoogleCloudPresentMultiple(t *testing.T) {
- if !gcloudLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(gcloudProject)
- assert.NoError(t, err)
-
- // Check that we're able to create multiple entries
- err = provider.Present(gcloudDomain, "1", "123d==")
- err = provider.Present(gcloudDomain, "2", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveGoogleCloudCleanUp(t *testing.T) {
- if !gcloudLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProviderCredentials(gcloudProject)
- assert.NoError(t, err)
-
- err = provider.CleanUp(gcloudDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/linode/linode.go b/vendor/github.com/xenolf/lego/providers/dns/linode/linode.go
deleted file mode 100644
index a91d2b489..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/linode/linode.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Package linode implements a DNS provider for solving the DNS-01 challenge
-// using Linode DNS.
-package linode
-
-import (
- "errors"
- "os"
- "strings"
- "time"
-
- "github.com/timewasted/linode/dns"
- "github.com/xenolf/lego/acme"
-)
-
-const (
- dnsMinTTLSecs = 300
- dnsUpdateFreqMins = 15
- dnsUpdateFudgeSecs = 120
-)
-
-type hostedZoneInfo struct {
- domainId int
- resourceName string
-}
-
-// DNSProvider implements the acme.ChallengeProvider interface.
-type DNSProvider struct {
- linode *dns.DNS
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Linode.
-// Credentials must be passed in the environment variable: LINODE_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- apiKey := os.Getenv("LINODE_API_KEY")
- return NewDNSProviderCredentials(apiKey)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Linode.
-func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
- if len(apiKey) == 0 {
- return nil, errors.New("Linode credentials missing")
- }
-
- return &DNSProvider{
- linode: dns.New(apiKey),
- }, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (p *DNSProvider) Timeout() (timeout, interval time.Duration) {
- // Since Linode only updates their zone files every X minutes, we need
- // to figure out how many minutes we have to wait until we hit the next
- // interval of X. We then wait another couple of minutes, just to be
- // safe. Hopefully at some point during all of this, the record will
- // have propagated throughout Linode's network.
- minsRemaining := dnsUpdateFreqMins - (time.Now().Minute() % dnsUpdateFreqMins)
-
- timeout = (time.Duration(minsRemaining) * time.Minute) +
- (dnsMinTTLSecs * time.Second) +
- (dnsUpdateFudgeSecs * time.Second)
- interval = 15 * time.Second
- return
-}
-
-// Present creates a TXT record using the specified parameters.
-func (p *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zone, err := p.getHostedZoneInfo(fqdn)
- if err != nil {
- return err
- }
-
- if _, err = p.linode.CreateDomainResourceTXT(zone.domainId, acme.UnFqdn(fqdn), value, 60); err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (p *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zone, err := p.getHostedZoneInfo(fqdn)
- if err != nil {
- return err
- }
-
- // Get all TXT records for the specified domain.
- resources, err := p.linode.GetResourcesByType(zone.domainId, "TXT")
- if err != nil {
- return err
- }
-
- // Remove the specified resource, if it exists.
- for _, resource := range resources {
- if resource.Name == zone.resourceName && resource.Target == value {
- resp, err := p.linode.DeleteDomainResource(resource.DomainID, resource.ResourceID)
- if err != nil {
- return err
- }
- if resp.ResourceID != resource.ResourceID {
- return errors.New("Error deleting resource: resource IDs do not match!")
- }
- break
- }
- }
-
- return nil
-}
-
-func (p *DNSProvider) getHostedZoneInfo(fqdn string) (*hostedZoneInfo, error) {
- // Lookup the zone that handles the specified FQDN.
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return nil, err
- }
- resourceName := strings.TrimSuffix(fqdn, "."+authZone)
-
- // Query the authority zone.
- domain, err := p.linode.GetDomain(acme.UnFqdn(authZone))
- if err != nil {
- return nil, err
- }
-
- return &hostedZoneInfo{
- domainId: domain.DomainID,
- resourceName: resourceName,
- }, nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/linode/linode_test.go b/vendor/github.com/xenolf/lego/providers/dns/linode/linode_test.go
deleted file mode 100644
index d9713a275..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/linode/linode_test.go
+++ /dev/null
@@ -1,317 +0,0 @@
-package linode
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
- "net/http/httptest"
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "github.com/timewasted/linode"
- "github.com/timewasted/linode/dns"
-)
-
-type (
- LinodeResponse struct {
- Action string `json:"ACTION"`
- Data interface{} `json:"DATA"`
- Errors []linode.ResponseError `json:"ERRORARRAY"`
- }
- MockResponse struct {
- Response interface{}
- Errors []linode.ResponseError
- }
- MockResponseMap map[string]MockResponse
-)
-
-var (
- apiKey string
- isTestLive bool
-)
-
-func init() {
- apiKey = os.Getenv("LINODE_API_KEY")
- isTestLive = len(apiKey) != 0
-}
-
-func restoreEnv() {
- os.Setenv("LINODE_API_KEY", apiKey)
-}
-
-func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // Ensure that we support the requested action.
- action := r.URL.Query().Get("api_action")
- resp, ok := responses[action]
- if !ok {
- msg := fmt.Sprintf("Unsupported mock action: %s", action)
- require.FailNow(t, msg)
- }
-
- // Build the response that the server will return.
- linodeResponse := LinodeResponse{
- Action: action,
- Data: resp.Response,
- Errors: resp.Errors,
- }
- rawResponse, err := json.Marshal(linodeResponse)
- if err != nil {
- msg := fmt.Sprintf("Failed to JSON encode response: %v", err)
- require.FailNow(t, msg)
- }
-
- // Send the response.
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- w.Write(rawResponse)
- }))
-
- time.Sleep(100 * time.Millisecond)
- return srv
-}
-
-func TestNewDNSProviderWithEnv(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderWithoutEnv(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "Linode credentials missing")
-}
-
-func TestNewDNSProviderCredentialsWithKey(t *testing.T) {
- _, err := NewDNSProviderCredentials("testing")
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderCredentialsWithoutKey(t *testing.T) {
- _, err := NewDNSProviderCredentials("")
- assert.EqualError(t, err, "Linode credentials missing")
-}
-
-func TestDNSProvider_Present(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: domain,
- DomainID: 1234,
- },
- },
- },
- "domain.resource.create": MockResponse{
- Response: dns.ResourceResponse{
- ResourceID: 1234,
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.Present(domain, "", keyAuth)
- assert.NoError(t, err)
-}
-
-func TestDNSProvider_PresentNoDomain(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: "foobar.com",
- DomainID: 1234,
- },
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.Present(domain, "", keyAuth)
- assert.EqualError(t, err, "dns: requested domain not found")
-}
-
-func TestDNSProvider_PresentCreateFailed(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: domain,
- DomainID: 1234,
- },
- },
- },
- "domain.resource.create": MockResponse{
- Response: nil,
- Errors: []linode.ResponseError{
- linode.ResponseError{
- Code: 1234,
- Message: "Failed to create domain resource",
- },
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.Present(domain, "", keyAuth)
- assert.EqualError(t, err, "Failed to create domain resource")
-}
-
-func TestDNSProvider_PresentLive(t *testing.T) {
- if !isTestLive {
- t.Skip("Skipping live test")
- }
-}
-
-func TestDNSProvider_CleanUp(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: domain,
- DomainID: 1234,
- },
- },
- },
- "domain.resource.list": MockResponse{
- Response: []dns.Resource{
- dns.Resource{
- DomainID: 1234,
- Name: "_acme-challenge",
- ResourceID: 1234,
- Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
- Type: "TXT",
- },
- },
- },
- "domain.resource.delete": MockResponse{
- Response: dns.ResourceResponse{
- ResourceID: 1234,
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.CleanUp(domain, "", keyAuth)
- assert.NoError(t, err)
-}
-
-func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: "foobar.com",
- DomainID: 1234,
- },
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.CleanUp(domain, "", keyAuth)
- assert.EqualError(t, err, "dns: requested domain not found")
-}
-
-func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
- os.Setenv("LINODE_API_KEY", "testing")
- defer restoreEnv()
- p, err := NewDNSProvider()
- assert.NoError(t, err)
-
- domain := "example.com"
- keyAuth := "dGVzdGluZw=="
- mockResponses := MockResponseMap{
- "domain.list": MockResponse{
- Response: []dns.Domain{
- dns.Domain{
- Domain: domain,
- DomainID: 1234,
- },
- },
- },
- "domain.resource.list": MockResponse{
- Response: []dns.Resource{
- dns.Resource{
- DomainID: 1234,
- Name: "_acme-challenge",
- ResourceID: 1234,
- Target: "ElbOJKOkFWiZLQeoxf-wb3IpOsQCdvoM0y_wn0TEkxM",
- Type: "TXT",
- },
- },
- },
- "domain.resource.delete": MockResponse{
- Response: nil,
- Errors: []linode.ResponseError{
- linode.ResponseError{
- Code: 1234,
- Message: "Failed to delete domain resource",
- },
- },
- },
- }
- mockSrv := newMockServer(t, mockResponses)
- defer mockSrv.Close()
- p.linode.ToLinode().SetEndpoint(mockSrv.URL)
-
- err = p.CleanUp(domain, "", keyAuth)
- assert.EqualError(t, err, "Failed to delete domain resource")
-}
-
-func TestDNSProvider_CleanUpLive(t *testing.T) {
- if !isTestLive {
- t.Skip("Skipping live test")
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go b/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go
deleted file mode 100644
index d7eb40935..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go
+++ /dev/null
@@ -1,416 +0,0 @@
-// Package namecheap implements a DNS provider for solving the DNS-01
-// challenge using namecheap DNS.
-package namecheap
-
-import (
- "encoding/xml"
- "fmt"
- "io/ioutil"
- "net/http"
- "net/url"
- "os"
- "strings"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// Notes about namecheap's tool API:
-// 1. Using the API requires registration. Once registered, use your account
-// name and API key to access the API.
-// 2. There is no API to add or modify a single DNS record. Instead you must
-// read the entire list of records, make modifications, and then write the
-// entire updated list of records. (Yuck.)
-// 3. Namecheap's DNS updates can be slow to propagate. I've seen them take
-// as long as an hour.
-// 4. Namecheap requires you to whitelist the IP address from which you call
-// its APIs. It also requires all API calls to include the whitelisted IP
-// address as a form or query string value. This code uses a namecheap
-// service to query the client's IP address.
-
-var (
- debug = false
- defaultBaseURL = "https://api.namecheap.com/xml.response"
- getIPURL = "https://dynamicdns.park-your-domain.com/getip"
- httpClient = http.Client{Timeout: 60 * time.Second}
-)
-
-// DNSProvider is an implementation of the ChallengeProviderTimeout interface
-// that uses Namecheap's tool API to manage TXT records for a domain.
-type DNSProvider struct {
- baseURL string
- apiUser string
- apiKey string
- clientIP string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for namecheap.
-// Credentials must be passed in the environment variables: NAMECHEAP_API_USER
-// and NAMECHEAP_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- apiUser := os.Getenv("NAMECHEAP_API_USER")
- apiKey := os.Getenv("NAMECHEAP_API_KEY")
- return NewDNSProviderCredentials(apiUser, apiKey)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for namecheap.
-func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
- if apiUser == "" || apiKey == "" {
- return nil, fmt.Errorf("Namecheap credentials missing")
- }
-
- clientIP, err := getClientIP()
- if err != nil {
- return nil, err
- }
-
- return &DNSProvider{
- baseURL: defaultBaseURL,
- apiUser: apiUser,
- apiKey: apiKey,
- clientIP: clientIP,
- }, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Namecheap can sometimes take a long time to complete an
-// update, so wait up to 60 minutes for the update to propagate.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 60 * time.Minute, 15 * time.Second
-}
-
-// host describes a DNS record returned by the Namecheap DNS gethosts API.
-// Namecheap uses the term "host" to refer to all DNS records that include
-// a host field (A, AAAA, CNAME, NS, TXT, URL).
-type host struct {
- Type string `xml:",attr"`
- Name string `xml:",attr"`
- Address string `xml:",attr"`
- MXPref string `xml:",attr"`
- TTL string `xml:",attr"`
-}
-
-// apierror describes an error record in a namecheap API response.
-type apierror struct {
- Number int `xml:",attr"`
- Description string `xml:",innerxml"`
-}
-
-// getClientIP returns the client's public IP address. It uses namecheap's
-// IP discovery service to perform the lookup.
-func getClientIP() (addr string, err error) {
- resp, err := httpClient.Get(getIPURL)
- if err != nil {
- return "", err
- }
- defer resp.Body.Close()
-
- clientIP, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return "", err
- }
-
- if debug {
- fmt.Println("Client IP:", string(clientIP))
- }
- return string(clientIP), nil
-}
-
-// A challenge repesents all the data needed to specify a dns-01 challenge
-// to lets-encrypt.
-type challenge struct {
- domain string
- key string
- keyFqdn string
- keyValue string
- tld string
- sld string
- host string
-}
-
-// newChallenge builds a challenge record from a domain name, a challenge
-// authentication key, and a map of available TLDs.
-func newChallenge(domain, keyAuth string, tlds map[string]string) (*challenge, error) {
- domain = acme.UnFqdn(domain)
- parts := strings.Split(domain, ".")
-
- // Find the longest matching TLD.
- longest := -1
- for i := len(parts); i > 0; i-- {
- t := strings.Join(parts[i-1:], ".")
- if _, found := tlds[t]; found {
- longest = i - 1
- }
- }
- if longest < 1 {
- return nil, fmt.Errorf("Invalid domain name '%s'", domain)
- }
-
- tld := strings.Join(parts[longest:], ".")
- sld := parts[longest-1]
-
- var host string
- if longest >= 1 {
- host = strings.Join(parts[:longest-1], ".")
- }
-
- key, keyValue, _ := acme.DNS01Record(domain, keyAuth)
-
- return &challenge{
- domain: domain,
- key: "_acme-challenge." + host,
- keyFqdn: key,
- keyValue: keyValue,
- tld: tld,
- sld: sld,
- host: host,
- }, nil
-}
-
-// setGlobalParams adds the namecheap global parameters to the provided url
-// Values record.
-func (d *DNSProvider) setGlobalParams(v *url.Values, cmd string) {
- v.Set("ApiUser", d.apiUser)
- v.Set("ApiKey", d.apiKey)
- v.Set("UserName", d.apiUser)
- v.Set("ClientIp", d.clientIP)
- v.Set("Command", cmd)
-}
-
-// getTLDs requests the list of available TLDs from namecheap.
-func (d *DNSProvider) getTLDs() (tlds map[string]string, err error) {
- values := make(url.Values)
- d.setGlobalParams(&values, "namecheap.domains.getTldList")
-
- reqURL, _ := url.Parse(d.baseURL)
- reqURL.RawQuery = values.Encode()
-
- resp, err := httpClient.Get(reqURL.String())
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return nil, fmt.Errorf("getHosts HTTP error %d", resp.StatusCode)
- }
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- type GetTldsResponse struct {
- XMLName xml.Name `xml:"ApiResponse"`
- Errors []apierror `xml:"Errors>Error"`
- Result []struct {
- Name string `xml:",attr"`
- } `xml:"CommandResponse>Tlds>Tld"`
- }
-
- var gtr GetTldsResponse
- if err := xml.Unmarshal(body, &gtr); err != nil {
- return nil, err
- }
- if len(gtr.Errors) > 0 {
- return nil, fmt.Errorf("Namecheap error: %s [%d]",
- gtr.Errors[0].Description, gtr.Errors[0].Number)
- }
-
- tlds = make(map[string]string)
- for _, t := range gtr.Result {
- tlds[t.Name] = t.Name
- }
- return tlds, nil
-}
-
-// getHosts reads the full list of DNS host records using the Namecheap API.
-func (d *DNSProvider) getHosts(ch *challenge) (hosts []host, err error) {
- values := make(url.Values)
- d.setGlobalParams(&values, "namecheap.domains.dns.getHosts")
- values.Set("SLD", ch.sld)
- values.Set("TLD", ch.tld)
-
- reqURL, _ := url.Parse(d.baseURL)
- reqURL.RawQuery = values.Encode()
-
- resp, err := httpClient.Get(reqURL.String())
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return nil, fmt.Errorf("getHosts HTTP error %d", resp.StatusCode)
- }
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- type GetHostsResponse struct {
- XMLName xml.Name `xml:"ApiResponse"`
- Status string `xml:"Status,attr"`
- Errors []apierror `xml:"Errors>Error"`
- Hosts []host `xml:"CommandResponse>DomainDNSGetHostsResult>host"`
- }
-
- var ghr GetHostsResponse
- if err = xml.Unmarshal(body, &ghr); err != nil {
- return nil, err
- }
- if len(ghr.Errors) > 0 {
- return nil, fmt.Errorf("Namecheap error: %s [%d]",
- ghr.Errors[0].Description, ghr.Errors[0].Number)
- }
-
- return ghr.Hosts, nil
-}
-
-// setHosts writes the full list of DNS host records using the Namecheap API.
-func (d *DNSProvider) setHosts(ch *challenge, hosts []host) error {
- values := make(url.Values)
- d.setGlobalParams(&values, "namecheap.domains.dns.setHosts")
- values.Set("SLD", ch.sld)
- values.Set("TLD", ch.tld)
-
- for i, h := range hosts {
- ind := fmt.Sprintf("%d", i+1)
- values.Add("HostName"+ind, h.Name)
- values.Add("RecordType"+ind, h.Type)
- values.Add("Address"+ind, h.Address)
- values.Add("MXPref"+ind, h.MXPref)
- values.Add("TTL"+ind, h.TTL)
- }
-
- resp, err := httpClient.PostForm(d.baseURL, values)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return fmt.Errorf("setHosts HTTP error %d", resp.StatusCode)
- }
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return err
- }
-
- type SetHostsResponse struct {
- XMLName xml.Name `xml:"ApiResponse"`
- Status string `xml:"Status,attr"`
- Errors []apierror `xml:"Errors>Error"`
- Result struct {
- IsSuccess string `xml:",attr"`
- } `xml:"CommandResponse>DomainDNSSetHostsResult"`
- }
-
- var shr SetHostsResponse
- if err := xml.Unmarshal(body, &shr); err != nil {
- return err
- }
- if len(shr.Errors) > 0 {
- return fmt.Errorf("Namecheap error: %s [%d]",
- shr.Errors[0].Description, shr.Errors[0].Number)
- }
- if shr.Result.IsSuccess != "true" {
- return fmt.Errorf("Namecheap setHosts failed.")
- }
-
- return nil
-}
-
-// addChallengeRecord adds a DNS challenge TXT record to a list of namecheap
-// host records.
-func (d *DNSProvider) addChallengeRecord(ch *challenge, hosts *[]host) {
- host := host{
- Name: ch.key,
- Type: "TXT",
- Address: ch.keyValue,
- MXPref: "10",
- TTL: "120",
- }
-
- // If there's already a TXT record with the same name, replace it.
- for i, h := range *hosts {
- if h.Name == ch.key && h.Type == "TXT" {
- (*hosts)[i] = host
- return
- }
- }
-
- // No record was replaced, so add a new one.
- *hosts = append(*hosts, host)
-}
-
-// removeChallengeRecord removes a DNS challenge TXT record from a list of
-// namecheap host records. Return true if a record was removed.
-func (d *DNSProvider) removeChallengeRecord(ch *challenge, hosts *[]host) bool {
- // Find the challenge TXT record and remove it if found.
- for i, h := range *hosts {
- if h.Name == ch.key && h.Type == "TXT" {
- *hosts = append((*hosts)[:i], (*hosts)[i+1:]...)
- return true
- }
- }
-
- return false
-}
-
-// Present installs a TXT record for the DNS challenge.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- tlds, err := d.getTLDs()
- if err != nil {
- return err
- }
-
- ch, err := newChallenge(domain, keyAuth, tlds)
- if err != nil {
- return err
- }
-
- hosts, err := d.getHosts(ch)
- if err != nil {
- return err
- }
-
- d.addChallengeRecord(ch, &hosts)
-
- if debug {
- for _, h := range hosts {
- fmt.Printf(
- "%-5.5s %-30.30s %-6s %-70.70s\n",
- h.Type, h.Name, h.TTL, h.Address)
- }
- }
-
- return d.setHosts(ch, hosts)
-}
-
-// CleanUp removes a TXT record used for a previous DNS challenge.
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- tlds, err := d.getTLDs()
- if err != nil {
- return err
- }
-
- ch, err := newChallenge(domain, keyAuth, tlds)
- if err != nil {
- return err
- }
-
- hosts, err := d.getHosts(ch)
- if err != nil {
- return err
- }
-
- if removed := d.removeChallengeRecord(ch, &hosts); !removed {
- return nil
- }
-
- return d.setHosts(ch, hosts)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap_test.go b/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap_test.go
deleted file mode 100644
index 0631d4a3e..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap_test.go
+++ /dev/null
@@ -1,402 +0,0 @@
-package namecheap
-
-import (
- "fmt"
- "net/http"
- "net/http/httptest"
- "net/url"
- "testing"
-)
-
-var (
- fakeUser = "foo"
- fakeKey = "bar"
- fakeClientIP = "10.0.0.1"
-
- tlds = map[string]string{
- "com.au": "com.au",
- "com": "com",
- "co.uk": "co.uk",
- "uk": "uk",
- "edu": "edu",
- "co.com": "co.com",
- "za.com": "za.com",
- }
-)
-
-func assertEq(t *testing.T, variable, got, want string) {
- if got != want {
- t.Errorf("Expected %s to be '%s' but got '%s'", variable, want, got)
- }
-}
-
-func assertHdr(tc *testcase, t *testing.T, values *url.Values) {
- ch, _ := newChallenge(tc.domain, "", tlds)
-
- assertEq(t, "ApiUser", values.Get("ApiUser"), fakeUser)
- assertEq(t, "ApiKey", values.Get("ApiKey"), fakeKey)
- assertEq(t, "UserName", values.Get("UserName"), fakeUser)
- assertEq(t, "ClientIp", values.Get("ClientIp"), fakeClientIP)
- assertEq(t, "SLD", values.Get("SLD"), ch.sld)
- assertEq(t, "TLD", values.Get("TLD"), ch.tld)
-}
-
-func mockServer(tc *testcase, t *testing.T, w http.ResponseWriter, r *http.Request) {
- switch r.Method {
-
- case "GET":
- values := r.URL.Query()
- cmd := values.Get("Command")
- switch cmd {
- case "namecheap.domains.dns.getHosts":
- assertHdr(tc, t, &values)
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, tc.getHostsResponse)
- case "namecheap.domains.getTldList":
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, responseGetTlds)
- default:
- t.Errorf("Unexpected GET command: %s", cmd)
- }
-
- case "POST":
- r.ParseForm()
- values := r.Form
- cmd := values.Get("Command")
- switch cmd {
- case "namecheap.domains.dns.setHosts":
- assertHdr(tc, t, &values)
- w.WriteHeader(http.StatusOK)
- fmt.Fprint(w, tc.setHostsResponse)
- default:
- t.Errorf("Unexpected POST command: %s", cmd)
- }
-
- default:
- t.Errorf("Unexpected http method: %s", r.Method)
-
- }
-}
-
-func testGetHosts(tc *testcase, t *testing.T) {
- mock := httptest.NewServer(http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- mockServer(tc, t, w, r)
- }))
- defer mock.Close()
-
- prov := &DNSProvider{
- baseURL: mock.URL,
- apiUser: fakeUser,
- apiKey: fakeKey,
- clientIP: fakeClientIP,
- }
-
- ch, _ := newChallenge(tc.domain, "", tlds)
- hosts, err := prov.getHosts(ch)
- if tc.errString != "" {
- if err == nil || err.Error() != tc.errString {
- t.Errorf("Namecheap getHosts case %s expected error", tc.name)
- }
- } else {
- if err != nil {
- t.Errorf("Namecheap getHosts case %s failed\n%v", tc.name, err)
- }
- }
-
-next1:
- for _, h := range hosts {
- for _, th := range tc.hosts {
- if h == th {
- continue next1
- }
- }
- t.Errorf("getHosts case %s unexpected record [%s:%s:%s]",
- tc.name, h.Type, h.Name, h.Address)
- }
-
-next2:
- for _, th := range tc.hosts {
- for _, h := range hosts {
- if h == th {
- continue next2
- }
- }
- t.Errorf("getHosts case %s missing record [%s:%s:%s]",
- tc.name, th.Type, th.Name, th.Address)
- }
-}
-
-func mockDNSProvider(url string) *DNSProvider {
- return &DNSProvider{
- baseURL: url,
- apiUser: fakeUser,
- apiKey: fakeKey,
- clientIP: fakeClientIP,
- }
-}
-
-func testSetHosts(tc *testcase, t *testing.T) {
- mock := httptest.NewServer(http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- mockServer(tc, t, w, r)
- }))
- defer mock.Close()
-
- prov := mockDNSProvider(mock.URL)
- ch, _ := newChallenge(tc.domain, "", tlds)
- hosts, err := prov.getHosts(ch)
- if tc.errString != "" {
- if err == nil || err.Error() != tc.errString {
- t.Errorf("Namecheap getHosts case %s expected error", tc.name)
- }
- } else {
- if err != nil {
- t.Errorf("Namecheap getHosts case %s failed\n%v", tc.name, err)
- }
- }
- if err != nil {
- return
- }
-
- err = prov.setHosts(ch, hosts)
- if err != nil {
- t.Errorf("Namecheap setHosts case %s failed", tc.name)
- }
-}
-
-func testPresent(tc *testcase, t *testing.T) {
- mock := httptest.NewServer(http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- mockServer(tc, t, w, r)
- }))
- defer mock.Close()
-
- prov := mockDNSProvider(mock.URL)
- err := prov.Present(tc.domain, "", "dummyKey")
- if tc.errString != "" {
- if err == nil || err.Error() != tc.errString {
- t.Errorf("Namecheap Present case %s expected error", tc.name)
- }
- } else {
- if err != nil {
- t.Errorf("Namecheap Present case %s failed\n%v", tc.name, err)
- }
- }
-}
-
-func testCleanUp(tc *testcase, t *testing.T) {
- mock := httptest.NewServer(http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- mockServer(tc, t, w, r)
- }))
- defer mock.Close()
-
- prov := mockDNSProvider(mock.URL)
- err := prov.CleanUp(tc.domain, "", "dummyKey")
- if tc.errString != "" {
- if err == nil || err.Error() != tc.errString {
- t.Errorf("Namecheap CleanUp case %s expected error", tc.name)
- }
- } else {
- if err != nil {
- t.Errorf("Namecheap CleanUp case %s failed\n%v", tc.name, err)
- }
- }
-}
-
-func TestNamecheap(t *testing.T) {
- for _, tc := range testcases {
- testGetHosts(&tc, t)
- testSetHosts(&tc, t)
- testPresent(&tc, t)
- testCleanUp(&tc, t)
- }
-}
-
-func TestNamecheapDomainSplit(t *testing.T) {
- tests := []struct {
- domain string
- valid bool
- tld string
- sld string
- host string
- }{
- {"a.b.c.test.co.uk", true, "co.uk", "test", "a.b.c"},
- {"test.co.uk", true, "co.uk", "test", ""},
- {"test.com", true, "com", "test", ""},
- {"test.co.com", true, "co.com", "test", ""},
- {"www.test.com.au", true, "com.au", "test", "www"},
- {"www.za.com", true, "za.com", "www", ""},
- {"", false, "", "", ""},
- {"a", false, "", "", ""},
- {"com", false, "", "", ""},
- {"co.com", false, "", "", ""},
- {"co.uk", false, "", "", ""},
- {"test.au", false, "", "", ""},
- {"za.com", false, "", "", ""},
- {"www.za", false, "", "", ""},
- {"www.test.au", false, "", "", ""},
- {"www.test.unk", false, "", "", ""},
- }
-
- for _, test := range tests {
- valid := true
- ch, err := newChallenge(test.domain, "", tlds)
- if err != nil {
- valid = false
- }
-
- if test.valid && !valid {
- t.Errorf("Expected '%s' to split", test.domain)
- } else if !test.valid && valid {
- t.Errorf("Expected '%s' to produce error", test.domain)
- }
-
- if test.valid && valid {
- assertEq(t, "domain", ch.domain, test.domain)
- assertEq(t, "tld", ch.tld, test.tld)
- assertEq(t, "sld", ch.sld, test.sld)
- assertEq(t, "host", ch.host, test.host)
- }
- }
-}
-
-type testcase struct {
- name string
- domain string
- hosts []host
- errString string
- getHostsResponse string
- setHostsResponse string
-}
-
-var testcases = []testcase{
- {
- "Test:Success:1",
- "test.example.com",
- []host{
- {"A", "home", "10.0.0.1", "10", "1799"},
- {"A", "www", "10.0.0.2", "10", "1200"},
- {"AAAA", "a", "::0", "10", "1799"},
- {"CNAME", "*", "example.com.", "10", "1799"},
- {"MXE", "example.com", "10.0.0.5", "10", "1800"},
- {"URL", "xyz", "https://google.com", "10", "1799"},
- },
- "",
- responseGetHostsSuccess1,
- responseSetHostsSuccess1,
- },
- {
- "Test:Success:2",
- "example.com",
- []host{
- {"A", "@", "10.0.0.2", "10", "1200"},
- {"A", "www", "10.0.0.3", "10", "60"},
- },
- "",
- responseGetHostsSuccess2,
- responseSetHostsSuccess2,
- },
- {
- "Test:Error:BadApiKey:1",
- "test.example.com",
- nil,
- "Namecheap error: API Key is invalid or API access has not been enabled [1011102]",
- responseGetHostsErrorBadAPIKey1,
- "",
- },
-}
-
-var responseGetHostsSuccess1 = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
- <Errors />
- <Warnings />
- <RequestedCommand>namecheap.domains.dns.getHosts</RequestedCommand>
- <CommandResponse Type="namecheap.domains.dns.getHosts">
- <DomainDNSGetHostsResult Domain="example.com" EmailType="MXE" IsUsingOurDNS="true">
- <host HostId="217076" Name="www" Type="A" Address="10.0.0.2" MXPref="10" TTL="1200" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217069" Name="home" Type="A" Address="10.0.0.1" MXPref="10" TTL="1799" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217071" Name="a" Type="AAAA" Address="::0" MXPref="10" TTL="1799" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217075" Name="*" Type="CNAME" Address="example.com." MXPref="10" TTL="1799" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217073" Name="example.com" Type="MXE" Address="10.0.0.5" MXPref="10" TTL="1800" AssociatedAppTitle="MXE" FriendlyName="MXE1" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217077" Name="xyz" Type="URL" Address="https://google.com" MXPref="10" TTL="1799" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- </DomainDNSGetHostsResult>
- </CommandResponse>
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>3.338</ExecutionTime>
-</ApiResponse>`
-
-var responseSetHostsSuccess1 = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
- <Errors />
- <Warnings />
- <RequestedCommand>namecheap.domains.dns.setHosts</RequestedCommand>
- <CommandResponse Type="namecheap.domains.dns.setHosts">
- <DomainDNSSetHostsResult Domain="example.com" IsSuccess="true">
- <Warnings />
- </DomainDNSSetHostsResult>
- </CommandResponse>
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>2.347</ExecutionTime>
-</ApiResponse>`
-
-var responseGetHostsSuccess2 = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
- <Errors />
- <Warnings />
- <RequestedCommand>namecheap.domains.dns.getHosts</RequestedCommand>
- <CommandResponse Type="namecheap.domains.dns.getHosts">
- <DomainDNSGetHostsResult Domain="example.com" EmailType="MXE" IsUsingOurDNS="true">
- <host HostId="217076" Name="@" Type="A" Address="10.0.0.2" MXPref="10" TTL="1200" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- <host HostId="217069" Name="www" Type="A" Address="10.0.0.3" MXPref="10" TTL="60" AssociatedAppTitle="" FriendlyName="" IsActive="true" IsDDNSEnabled="false" />
- </DomainDNSGetHostsResult>
- </CommandResponse>
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>3.338</ExecutionTime>
-</ApiResponse>`
-
-var responseSetHostsSuccess2 = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
- <Errors />
- <Warnings />
- <RequestedCommand>namecheap.domains.dns.setHosts</RequestedCommand>
- <CommandResponse Type="namecheap.domains.dns.setHosts">
- <DomainDNSSetHostsResult Domain="example.com" IsSuccess="true">
- <Warnings />
- </DomainDNSSetHostsResult>
- </CommandResponse>
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>2.347</ExecutionTime>
-</ApiResponse>`
-
-var responseGetHostsErrorBadAPIKey1 = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="ERROR" xmlns="http://api.namecheap.com/xml.response">
- <Errors>
- <Error Number="1011102">API Key is invalid or API access has not been enabled</Error>
- </Errors>
- <Warnings />
- <RequestedCommand />
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>0</ExecutionTime>
-</ApiResponse>`
-
-var responseGetTlds = `<?xml version="1.0" encoding="utf-8"?>
-<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
- <Errors />
- <Warnings />
- <RequestedCommand>namecheap.domains.getTldList</RequestedCommand>
- <CommandResponse Type="namecheap.domains.getTldList">
- <Tlds>
- <Tld Name="com" NonRealTime="false" MinRegisterYears="1" MaxRegisterYears="10" MinRenewYears="1" MaxRenewYears="10" RenewalMinDays="0" RenewalMaxDays="4000" ReactivateMaxDays="27" MinTransferYears="1" MaxTransferYears="1" IsApiRegisterable="true" IsApiRenewable="true" IsApiTransferable="true" IsEppRequired="true" IsDisableModContact="false" IsDisableWGAllot="false" IsIncludeInExtendedSearchOnly="false" SequenceNumber="10" Type="GTLD" SubType="" IsSupportsIDN="true" Category="A" SupportsRegistrarLock="true" AddGracePeriodDays="5" WhoisVerification="false" ProviderApiDelete="true" TldState="" SearchGroup="" Registry="">Most recognized top level domain<Categories><TldCategory Name="popular" SequenceNumber="10" /></Categories></Tld>
- </Tlds>
- </CommandResponse>
- <Server>PHX01SBAPI01</Server>
- <GMTTimeDifference>--5:00</GMTTimeDifference>
- <ExecutionTime>0.004</ExecutionTime>
-</ApiResponse>`
diff --git a/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go b/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go
deleted file mode 100644
index 105d73f89..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Package ns1 implements a DNS provider for solving the DNS-01 challenge
-// using NS1 DNS.
-package ns1
-
-import (
- "fmt"
- "net/http"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
- "gopkg.in/ns1/ns1-go.v2/rest"
- "gopkg.in/ns1/ns1-go.v2/rest/model/dns"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface.
-type DNSProvider struct {
- client *rest.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for NS1.
-// Credentials must be passed in the environment variables: NS1_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- key := os.Getenv("NS1_API_KEY")
- if key == "" {
- return nil, fmt.Errorf("NS1 credentials missing")
- }
- return NewDNSProviderCredentials(key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for NS1.
-func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
- if key == "" {
- return nil, fmt.Errorf("NS1 credentials missing")
- }
-
- httpClient := &http.Client{Timeout: time.Second * 10}
- client := rest.NewClient(httpClient, rest.SetAPIKey(key))
-
- return &DNSProvider{client}, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- record := c.newTxtRecord(zone, fqdn, value, ttl)
- _, err = c.client.Records.Create(record)
- if err != nil && err != rest.ErrRecordExists {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- name := acme.UnFqdn(fqdn)
- _, err = c.client.Records.Delete(zone.Zone, name, "TXT")
- return err
-}
-
-func (c *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
- zone, _, err := c.client.Zones.Get(domain)
- if err != nil {
- return nil, err
- }
-
- return zone, nil
-}
-
-func (c *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record {
- name := acme.UnFqdn(fqdn)
-
- return &dns.Record{
- Type: "TXT",
- Zone: zone.Zone,
- Domain: name,
- TTL: ttl,
- Answers: []*dns.Answer{
- {Rdata: []string{value}},
- },
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1_test.go b/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1_test.go
deleted file mode 100644
index eb9150dde..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/ns1/ns1_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package ns1
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- liveTest bool
- apiKey string
- domain string
-)
-
-func init() {
- apiKey = os.Getenv("NS1_API_KEY")
- domain = os.Getenv("NS1_DOMAIN")
- if len(apiKey) > 0 && len(domain) > 0 {
- liveTest = true
- }
-}
-
-func restoreNS1Env() {
- os.Setenv("NS1_API_KEY", apiKey)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- os.Setenv("NS1_API_KEY", "")
- _, err := NewDNSProviderCredentials("123")
- assert.NoError(t, err)
- restoreNS1Env()
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("NS1_API_KEY", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "NS1 credentials missing")
- restoreNS1Env()
-}
-
-func TestLivePresent(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(apiKey)
- assert.NoError(t, err)
-
- err = provider.Present(domain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProviderCredentials(apiKey)
- assert.NoError(t, err)
-
- err = provider.CleanUp(domain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/otc/mock.go b/vendor/github.com/xenolf/lego/providers/dns/otc/mock.go
deleted file mode 100644
index 0f2acb4b4..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/otc/mock.go
+++ /dev/null
@@ -1,152 +0,0 @@
-package otc
-
-import (
- "fmt"
- "github.com/stretchr/testify/assert"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-var fakeOTCUserName = "test"
-var fakeOTCPassword = "test"
-var fakeOTCDomainName = "test"
-var fakeOTCProjectName = "test"
-var fakeOTCToken = "62244bc21da68d03ebac94e6636ff01f"
-
-type DNSMock struct {
- t *testing.T
- Server *httptest.Server
- Mux *http.ServeMux
-}
-
-func NewDNSMock(t *testing.T) *DNSMock {
- return &DNSMock{
- t: t,
- }
-}
-
-// Setup creates the mock server
-func (m *DNSMock) Setup() {
- m.Mux = http.NewServeMux()
- m.Server = httptest.NewServer(m.Mux)
-}
-
-// ShutdownServer creates the mock server
-func (m *DNSMock) ShutdownServer() {
- m.Server.Close()
-}
-
-func (m *DNSMock) HandleAuthSuccessfully() {
- m.Mux.HandleFunc("/v3/auth/token", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("X-Subject-Token", fakeOTCToken)
-
- fmt.Fprintf(w, `{
- "token": {
- "catalog": [
- {
- "type": "dns",
- "id": "56cd81db1f8445d98652479afe07c5ba",
- "name": "",
- "endpoints": [
- {
- "url": "%s",
- "region": "eu-de",
- "region_id": "eu-de",
- "interface": "public",
- "id": "0047a06690484d86afe04877074efddf"
- }
- ]
- }
- ]
- }}`, m.Server.URL)
- })
-}
-
-func (m *DNSMock) HandleListZonesSuccessfully() {
- m.Mux.HandleFunc("/v2/zones", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, `{
- "zones":[{
- "id":"123123"
- }]}
- `)
-
- assert.Equal(m.t, r.Method, "GET")
- assert.Equal(m.t, r.URL.Path, "/v2/zones")
- assert.Equal(m.t, r.URL.RawQuery, "name=example.com.")
- assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
- })
-}
-
-func (m *DNSMock) HandleListZonesEmpty() {
- m.Mux.HandleFunc("/v2/zones", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, `{
- "zones":[
- ]}
- `)
-
- assert.Equal(m.t, r.Method, "GET")
- assert.Equal(m.t, r.URL.Path, "/v2/zones")
- assert.Equal(m.t, r.URL.RawQuery, "name=example.com.")
- assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
- })
-}
-
-func (m *DNSMock) HandleDeleteRecordsetsSuccessfully() {
- m.Mux.HandleFunc("/v2/zones/123123/recordsets/321321", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, `{
- "zones":[{
- "id":"123123"
- }]}
- `)
-
- assert.Equal(m.t, r.Method, "DELETE")
- assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets/321321")
- assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
- })
-}
-
-func (m *DNSMock) HandleListRecordsetsEmpty() {
- m.Mux.HandleFunc("/v2/zones/123123/recordsets", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, `{
- "recordsets":[
- ]}
- `)
-
- assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets")
- assert.Equal(m.t, r.URL.RawQuery, "type=TXT&name=_acme-challenge.example.com.")
- })
-}
-func (m *DNSMock) HandleListRecordsetsSuccessfully() {
- m.Mux.HandleFunc("/v2/zones/123123/recordsets", func(w http.ResponseWriter, r *http.Request) {
- if r.Method == "GET" {
- fmt.Fprintf(w, `{
- "recordsets":[{
- "id":"321321"
- }]}
- `)
-
- assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets")
- assert.Equal(m.t, r.URL.RawQuery, "type=TXT&name=_acme-challenge.example.com.")
-
- } else if r.Method == "POST" {
- body, err := ioutil.ReadAll(r.Body)
-
- assert.Nil(m.t, err)
- exceptedString := "{\"name\":\"_acme-challenge.example.com.\",\"description\":\"Added TXT record for ACME dns-01 challenge using lego client\",\"type\":\"TXT\",\"ttl\":300,\"records\":[\"\\\"w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI\\\"\"]}"
- assert.Equal(m.t, string(body), exceptedString)
-
- fmt.Fprintf(w, `{
- "recordsets":[{
- "id":"321321"
- }]}
- `)
-
- } else {
- m.t.Errorf("Expected method to be 'GET' or 'POST' but got '%s'", r.Method)
- }
-
- assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
- })
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/otc/otc.go b/vendor/github.com/xenolf/lego/providers/dns/otc/otc.go
deleted file mode 100644
index 86bcaa9b7..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/otc/otc.go
+++ /dev/null
@@ -1,388 +0,0 @@
-// Package otc implements a DNS provider for solving the DNS-01 challenge
-// using Open Telekom Cloud Managed DNS.
-package otc
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
-// OTC's Managed DNS API to manage TXT records for a domain.
-type DNSProvider struct {
- identityEndpoint string
- otcBaseURL string
- domainName string
- projectName string
- userName string
- password string
- token string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for OTC DNS.
-// Credentials must be passed in the environment variables: OTC_USER_NAME,
-// OTC_DOMAIN_NAME, OTC_PASSWORD OTC_PROJECT_NAME and OTC_IDENTITY_ENDPOINT.
-func NewDNSProvider() (*DNSProvider, error) {
- domainName := os.Getenv("OTC_DOMAIN_NAME")
- userName := os.Getenv("OTC_USER_NAME")
- password := os.Getenv("OTC_PASSWORD")
- projectName := os.Getenv("OTC_PROJECT_NAME")
- identityEndpoint := os.Getenv("OTC_IDENTITY_ENDPOINT")
- return NewDNSProviderCredentials(domainName, userName, password, projectName, identityEndpoint)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for OTC DNS.
-func NewDNSProviderCredentials(domainName, userName, password, projectName, identityEndpoint string) (*DNSProvider, error) {
- if domainName == "" || userName == "" || password == "" || projectName == "" {
- return nil, fmt.Errorf("OTC credentials missing")
- }
-
- if identityEndpoint == "" {
- identityEndpoint = "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens"
- }
-
- return &DNSProvider{
- identityEndpoint: identityEndpoint,
- domainName: domainName,
- userName: userName,
- password: password,
- projectName: projectName,
- }, nil
-}
-
-func (d *DNSProvider) SendRequest(method, resource string, payload interface{}) (io.Reader, error) {
- url := fmt.Sprintf("%s/%s", d.otcBaseURL, resource)
-
- body, err := json.Marshal(payload)
- if err != nil {
- return nil, err
- }
-
- req, err := http.NewRequest(method, url, bytes.NewReader(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
- if len(d.token) > 0 {
- req.Header.Set("X-Auth-Token", d.token)
- }
-
- // Workaround for keep alive bug in otc api
- tr := http.DefaultTransport.(*http.Transport)
- tr.DisableKeepAlives = true
-
- client := &http.Client{
- Timeout: time.Duration(10 * time.Second),
- Transport: tr,
- }
- resp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return nil, fmt.Errorf("OTC API request %s failed with HTTP status code %d", url, resp.StatusCode)
- }
-
- body1, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- return bytes.NewReader(body1), nil
-}
-
-func (d *DNSProvider) loginRequest() error {
- type nameResponse struct {
- Name string `json:"name"`
- }
-
- type userResponse struct {
- Name string `json:"name"`
- Password string `json:"password"`
- Domain nameResponse `json:"domain"`
- }
-
- type passwordResponse struct {
- User userResponse `json:"user"`
- }
- type identityResponse struct {
- Methods []string `json:"methods"`
- Password passwordResponse `json:"password"`
- }
-
- type scopeResponse struct {
- Project nameResponse `json:"project"`
- }
-
- type authResponse struct {
- Identity identityResponse `json:"identity"`
- Scope scopeResponse `json:"scope"`
- }
-
- type loginResponse struct {
- Auth authResponse `json:"auth"`
- }
-
- userResp := userResponse{
- Name: d.userName,
- Password: d.password,
- Domain: nameResponse{
- Name: d.domainName,
- },
- }
-
- loginResp := loginResponse{
- Auth: authResponse{
- Identity: identityResponse{
- Methods: []string{"password"},
- Password: passwordResponse{
- User: userResp,
- },
- },
- Scope: scopeResponse{
- Project: nameResponse{
- Name: d.projectName,
- },
- },
- },
- }
-
- body, err := json.Marshal(loginResp)
- if err != nil {
- return err
- }
- req, err := http.NewRequest("POST", d.identityEndpoint, bytes.NewReader(body))
- if err != nil {
- return err
- }
- req.Header.Set("Content-Type", "application/json")
-
- client := &http.Client{Timeout: time.Duration(10 * time.Second)}
- resp, err := client.Do(req)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode >= 400 {
- return fmt.Errorf("OTC API request failed with HTTP status code %d", resp.StatusCode)
- }
-
- d.token = resp.Header.Get("X-Subject-Token")
-
- if d.token == "" {
- return fmt.Errorf("unable to get auth token")
- }
-
- type endpointResponse struct {
- Token struct {
- Catalog []struct {
- Type string `json:"type"`
- Endpoints []struct {
- URL string `json:"url"`
- } `json:"endpoints"`
- } `json:"catalog"`
- } `json:"token"`
- }
- var endpointResp endpointResponse
-
- err = json.NewDecoder(resp.Body).Decode(&endpointResp)
- if err != nil {
- return err
- }
-
- for _, v := range endpointResp.Token.Catalog {
- if v.Type == "dns" {
- for _, endpoint := range v.Endpoints {
- d.otcBaseURL = fmt.Sprintf("%s/v2", endpoint.URL)
- continue
- }
- }
- }
-
- if d.otcBaseURL == "" {
- return fmt.Errorf("unable to get dns endpoint")
- }
-
- return nil
-}
-
-// Starts a new OTC API Session. Authenticates using userName, password
-// and receives a token to be used in for subsequent requests.
-func (d *DNSProvider) login() error {
- err := d.loginRequest()
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (d *DNSProvider) getZoneID(zone string) (string, error) {
- type zoneItem struct {
- ID string `json:"id"`
- }
-
- type zonesResponse struct {
- Zones []zoneItem `json:"zones"`
- }
-
- resource := fmt.Sprintf("zones?name=%s", zone)
- resp, err := d.SendRequest("GET", resource, nil)
- if err != nil {
- return "", err
- }
-
- var zonesRes zonesResponse
- err = json.NewDecoder(resp).Decode(&zonesRes)
- if err != nil {
- return "", err
- }
-
- if len(zonesRes.Zones) < 1 {
- return "", fmt.Errorf("zone %s not found", zone)
- }
-
- if len(zonesRes.Zones) > 1 {
- return "", fmt.Errorf("to many zones found")
- }
-
- if zonesRes.Zones[0].ID == "" {
- return "", fmt.Errorf("id not found")
- }
-
- return zonesRes.Zones[0].ID, nil
-}
-
-func (d *DNSProvider) getRecordSetID(zoneID string, fqdn string) (string, error) {
- type recordSet struct {
- ID string `json:"id"`
- }
-
- type recordSetsResponse struct {
- RecordSets []recordSet `json:"recordsets"`
- }
-
- resource := fmt.Sprintf("zones/%s/recordsets?type=TXT&name=%s", zoneID, fqdn)
- resp, err := d.SendRequest("GET", resource, nil)
- if err != nil {
- return "", err
- }
-
- var recordSetsRes recordSetsResponse
- err = json.NewDecoder(resp).Decode(&recordSetsRes)
- if err != nil {
- return "", err
- }
-
- if len(recordSetsRes.RecordSets) < 1 {
- return "", fmt.Errorf("record not found")
- }
-
- if len(recordSetsRes.RecordSets) > 1 {
- return "", fmt.Errorf("to many records found")
- }
-
- if recordSetsRes.RecordSets[0].ID == "" {
- return "", fmt.Errorf("id not found")
- }
-
- return recordSetsRes.RecordSets[0].ID, nil
-}
-
-func (d *DNSProvider) deleteRecordSet(zoneID, recordID string) error {
- resource := fmt.Sprintf("zones/%s/recordsets/%s", zoneID, recordID)
-
- _, err := d.SendRequest("DELETE", resource, nil)
- if err != nil {
- return err
- }
- return nil
-}
-
-// Present creates a TXT record using the specified parameters
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- if ttl < 300 {
- ttl = 300 // 300 is otc minimum value for ttl
- }
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- err = d.login()
- if err != nil {
- return err
- }
-
- zoneID, err := d.getZoneID(authZone)
- if err != nil {
- return fmt.Errorf("unable to get zone: %s", err)
- }
-
- resource := fmt.Sprintf("zones/%s/recordsets", zoneID)
-
- type recordset struct {
- Name string `json:"name"`
- Description string `json:"description"`
- Type string `json:"type"`
- Ttl int `json:"ttl"`
- Records []string `json:"records"`
- }
-
- r1 := &recordset{
- Name: fqdn,
- Description: "Added TXT record for ACME dns-01 challenge using lego client",
- Type: "TXT",
- Ttl: 300,
- Records: []string{fmt.Sprintf("\"%s\"", value)},
- }
- _, err = d.SendRequest("POST", resource, r1)
-
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return err
- }
-
- err = d.login()
- if err != nil {
- return err
- }
-
- zoneID, err := d.getZoneID(authZone)
-
- if err != nil {
- return err
- }
-
- recordID, err := d.getRecordSetID(zoneID, fqdn)
- if err != nil {
- return fmt.Errorf("unable go get record %s for zone %s: %s", fqdn, domain, err)
- }
- return d.deleteRecordSet(zoneID, recordID)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/otc/otc_test.go b/vendor/github.com/xenolf/lego/providers/dns/otc/otc_test.go
deleted file mode 100644
index 0c05334a9..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/otc/otc_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package otc
-
-import (
- "fmt"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/suite"
- "os"
- "testing"
-)
-
-type OTCDNSTestSuite struct {
- suite.Suite
- Mock *DNSMock
-}
-
-func (s *OTCDNSTestSuite) TearDownSuite() {
- s.Mock.ShutdownServer()
-}
-
-func (s *OTCDNSTestSuite) SetupTest() {
- s.Mock = NewDNSMock(s.T())
- s.Mock.Setup()
- s.Mock.HandleAuthSuccessfully()
-
-}
-
-func TestOTCDNSTestSuite(t *testing.T) {
- suite.Run(t, new(OTCDNSTestSuite))
-}
-
-func (s *OTCDNSTestSuite) createDNSProvider() (*DNSProvider, error) {
- url := fmt.Sprintf("%s/v3/auth/token", s.Mock.Server.URL)
- return NewDNSProviderCredentials(fakeOTCUserName, fakeOTCPassword, fakeOTCDomainName, fakeOTCProjectName, url)
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSLoginEnv() {
- os.Setenv("OTC_DOMAIN_NAME", "unittest1")
- os.Setenv("OTC_USER_NAME", "unittest2")
- os.Setenv("OTC_PASSWORD", "unittest3")
- os.Setenv("OTC_PROJECT_NAME", "unittest4")
- os.Setenv("OTC_IDENTITY_ENDPOINT", "unittest5")
-
- provider, err := NewDNSProvider()
- assert.Nil(s.T(), err)
- assert.Equal(s.T(), provider.domainName, "unittest1")
- assert.Equal(s.T(), provider.userName, "unittest2")
- assert.Equal(s.T(), provider.password, "unittest3")
- assert.Equal(s.T(), provider.projectName, "unittest4")
- assert.Equal(s.T(), provider.identityEndpoint, "unittest5")
-
- os.Setenv("OTC_IDENTITY_ENDPOINT", "")
-
- provider, err = NewDNSProvider()
- assert.Nil(s.T(), err)
- assert.Equal(s.T(), provider.identityEndpoint, "https://iam.eu-de.otc.t-systems.com:443/v3/auth/tokens")
-
- os.Clearenv()
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSLoginEnvEmpty() {
- _, err := NewDNSProvider()
- assert.Equal(s.T(), "OTC credentials missing", err.Error())
-
- os.Clearenv()
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSLogin() {
- otcProvider, err := s.createDNSProvider()
-
- assert.Nil(s.T(), err)
- err = otcProvider.loginRequest()
- assert.Nil(s.T(), err)
- assert.Equal(s.T(), otcProvider.otcBaseURL, fmt.Sprintf("%s/v2", s.Mock.Server.URL))
- assert.Equal(s.T(), fakeOTCToken, otcProvider.token)
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSEmptyZone() {
- s.Mock.HandleListZonesEmpty()
- s.Mock.HandleListRecordsetsSuccessfully()
-
- otcProvider, _ := s.createDNSProvider()
- err := otcProvider.Present("example.com", "", "foobar")
- assert.NotNil(s.T(), err)
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSEmptyRecordset() {
- s.Mock.HandleListZonesSuccessfully()
- s.Mock.HandleListRecordsetsEmpty()
-
- otcProvider, _ := s.createDNSProvider()
- err := otcProvider.CleanUp("example.com", "", "foobar")
- assert.NotNil(s.T(), err)
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSPresent() {
- s.Mock.HandleListZonesSuccessfully()
- s.Mock.HandleListRecordsetsSuccessfully()
-
- otcProvider, _ := s.createDNSProvider()
- err := otcProvider.Present("example.com", "", "foobar")
- assert.Nil(s.T(), err)
-}
-
-func (s *OTCDNSTestSuite) TestOTCDNSCleanup() {
- s.Mock.HandleListZonesSuccessfully()
- s.Mock.HandleListRecordsetsSuccessfully()
- s.Mock.HandleDeleteRecordsetsSuccessfully()
-
- otcProvider, _ := s.createDNSProvider()
- err := otcProvider.CleanUp("example.com", "", "foobar")
- assert.Nil(s.T(), err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go b/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go
deleted file mode 100644
index 290a8d7df..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Package OVH implements a DNS provider for solving the DNS-01
-// challenge using OVH DNS.
-package ovh
-
-import (
- "fmt"
- "os"
- "strings"
- "sync"
-
- "github.com/ovh/go-ovh/ovh"
- "github.com/xenolf/lego/acme"
-)
-
-// OVH API reference: https://eu.api.ovh.com/
-// Create a Token: https://eu.api.ovh.com/createToken/
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-// that uses OVH's REST API to manage TXT records for a domain.
-type DNSProvider struct {
- client *ovh.Client
- recordIDs map[string]int
- recordIDsMu sync.Mutex
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for OVH
-// Credentials must be passed in the environment variable:
-// OVH_ENDPOINT : it must be ovh-eu or ovh-ca
-// OVH_APPLICATION_KEY
-// OVH_APPLICATION_SECRET
-// OVH_CONSUMER_KEY
-func NewDNSProvider() (*DNSProvider, error) {
- apiEndpoint := os.Getenv("OVH_ENDPOINT")
- applicationKey := os.Getenv("OVH_APPLICATION_KEY")
- applicationSecret := os.Getenv("OVH_APPLICATION_SECRET")
- consumerKey := os.Getenv("OVH_CONSUMER_KEY")
- return NewDNSProviderCredentials(apiEndpoint, applicationKey, applicationSecret, consumerKey)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for OVH.
-func NewDNSProviderCredentials(apiEndpoint, applicationKey, applicationSecret, consumerKey string) (*DNSProvider, error) {
- if apiEndpoint == "" || applicationKey == "" || applicationSecret == "" || consumerKey == "" {
- return nil, fmt.Errorf("OVH credentials missing")
- }
-
- ovhClient, _ := ovh.NewClient(
- apiEndpoint,
- applicationKey,
- applicationSecret,
- consumerKey,
- )
-
- return &DNSProvider{
- client: ovhClient,
- recordIDs: make(map[string]int),
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge.
-func (d *DNSProvider) Present(domain, token, keyAuth string) error {
-
- // txtRecordRequest represents the request body to DO's API to make a TXT record
- type txtRecordRequest struct {
- FieldType string `json:"fieldType"`
- SubDomain string `json:"subDomain"`
- Target string `json:"target"`
- TTL int `json:"ttl"`
- }
-
- // txtRecordResponse represents a response from DO's API after making a TXT record
- type txtRecordResponse struct {
- ID int `json:"id"`
- FieldType string `json:"fieldType"`
- SubDomain string `json:"subDomain"`
- Target string `json:"target"`
- TTL int `json:"ttl"`
- Zone string `json:"zone"`
- }
-
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- // Parse domain name
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- authZone = acme.UnFqdn(authZone)
- subDomain := d.extractRecordName(fqdn, authZone)
-
- reqURL := fmt.Sprintf("/domain/zone/%s/record", authZone)
- reqData := txtRecordRequest{FieldType: "TXT", SubDomain: subDomain, Target: value, TTL: ttl}
- var respData txtRecordResponse
-
- // Create TXT record
- err = d.client.Post(reqURL, reqData, &respData)
- if err != nil {
- fmt.Printf("Error when call OVH api to add record : %q \n", err)
- return err
- }
-
- // Apply the change
- reqURL = fmt.Sprintf("/domain/zone/%s/refresh", authZone)
- err = d.client.Post(reqURL, nil, nil)
- if err != nil {
- fmt.Printf("Error when call OVH api to refresh zone : %q \n", err)
- return err
- }
-
- d.recordIDsMu.Lock()
- d.recordIDs[fqdn] = respData.ID
- d.recordIDsMu.Unlock()
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- // get the record's unique ID from when we created it
- d.recordIDsMu.Lock()
- recordID, ok := d.recordIDs[fqdn]
- d.recordIDsMu.Unlock()
- if !ok {
- return fmt.Errorf("unknown record ID for '%s'", fqdn)
- }
-
- authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
- if err != nil {
- return fmt.Errorf("Could not determine zone for domain: '%s'. %s", domain, err)
- }
-
- authZone = acme.UnFqdn(authZone)
-
- reqURL := fmt.Sprintf("/domain/zone/%s/record/%d", authZone, recordID)
-
- err = d.client.Delete(reqURL, nil)
- if err != nil {
- fmt.Printf("Error when call OVH api to delete challenge record : %q \n", err)
- return err
- }
-
- // Delete record ID from map
- d.recordIDsMu.Lock()
- delete(d.recordIDs, fqdn)
- d.recordIDsMu.Unlock()
-
- return nil
-}
-
-func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
- name := acme.UnFqdn(fqdn)
- if idx := strings.Index(name, "."+domain); idx != -1 {
- return name[:idx]
- }
- return name
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh_test.go b/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh_test.go
deleted file mode 100644
index 47da60e57..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/ovh/ovh_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package ovh
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- liveTest bool
- apiEndpoint string
- applicationKey string
- applicationSecret string
- consumerKey string
- domain string
-)
-
-func init() {
- apiEndpoint = os.Getenv("OVH_ENDPOINT")
- applicationKey = os.Getenv("OVH_APPLICATION_KEY")
- applicationSecret = os.Getenv("OVH_APPLICATION_SECRET")
- consumerKey = os.Getenv("OVH_CONSUMER_KEY")
- liveTest = len(apiEndpoint) > 0 && len(applicationKey) > 0 && len(applicationSecret) > 0 && len(consumerKey) > 0
-}
-
-func restoreEnv() {
- os.Setenv("OVH_ENDPOINT", apiEndpoint)
- os.Setenv("OVH_APPLICATION_KEY", applicationKey)
- os.Setenv("OVH_APPLICATION_SECRET", applicationSecret)
- os.Setenv("OVH_CONSUMER_KEY", consumerKey)
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("OVH_ENDPOINT", "ovh-eu")
- os.Setenv("OVH_APPLICATION_KEY", "1234")
- os.Setenv("OVH_APPLICATION_SECRET", "5678")
- os.Setenv("OVH_CONSUMER_KEY", "abcde")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("OVH_ENDPOINT", "")
- os.Setenv("OVH_APPLICATION_KEY", "1234")
- os.Setenv("OVH_APPLICATION_SECRET", "5678")
- os.Setenv("OVH_CONSUMER_KEY", "abcde")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "OVH credentials missing")
-
- os.Setenv("OVH_ENDPOINT", "ovh-eu")
- os.Setenv("OVH_APPLICATION_KEY", "")
- os.Setenv("OVH_APPLICATION_SECRET", "5678")
- os.Setenv("OVH_CONSUMER_KEY", "abcde")
- defer restoreEnv()
- _, err = NewDNSProvider()
- assert.EqualError(t, err, "OVH credentials missing")
-
- os.Setenv("OVH_ENDPOINT", "ovh-eu")
- os.Setenv("OVH_APPLICATION_KEY", "1234")
- os.Setenv("OVH_APPLICATION_SECRET", "")
- os.Setenv("OVH_CONSUMER_KEY", "abcde")
- defer restoreEnv()
- _, err = NewDNSProvider()
- assert.EqualError(t, err, "OVH credentials missing")
-
- os.Setenv("OVH_ENDPOINT", "ovh-eu")
- os.Setenv("OVH_APPLICATION_KEY", "1234")
- os.Setenv("OVH_APPLICATION_SECRET", "5678")
- os.Setenv("OVH_CONSUMER_KEY", "")
- defer restoreEnv()
- _, err = NewDNSProvider()
- assert.EqualError(t, err, "OVH credentials missing")
-}
-
-func TestLivePresent(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.Present(domain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.CleanUp(domain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/pdns/README.md b/vendor/github.com/xenolf/lego/providers/dns/pdns/README.md
deleted file mode 100644
index 23abb7669..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/pdns/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## PowerDNS provider
-
-Tested and confirmed to work with PowerDNS authoratative server 3.4.8 and 4.0.1. Refer to [PowerDNS documentation](https://doc.powerdns.com/md/httpapi/README/) instructions on how to enable the built-in API interface.
-
-PowerDNS Notes:
-- PowerDNS API does not currently support SSL, therefore you should take care to ensure that traffic between lego and the PowerDNS API is over a trusted network, VPN etc.
-- In order to have the SOA serial automatically increment each time the `_acme-challenge` record is added/modified via the API, set `SOA-API-EDIT` to `INCEPTION-INCREMENT` for the zone in the `domainmetadata` table
diff --git a/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go b/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go
deleted file mode 100644
index a4fd22b0c..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go
+++ /dev/null
@@ -1,343 +0,0 @@
-// Package pdns implements a DNS provider for solving the DNS-01
-// challenge using PowerDNS nameserver.
-package pdns
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "os"
- "strconv"
- "strings"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-type DNSProvider struct {
- apiKey string
- host *url.URL
- apiVersion int
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for pdns.
-// Credentials must be passed in the environment variable:
-// PDNS_API_URL and PDNS_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- key := os.Getenv("PDNS_API_KEY")
- hostUrl, err := url.Parse(os.Getenv("PDNS_API_URL"))
- if err != nil {
- return nil, err
- }
-
- return NewDNSProviderCredentials(hostUrl, key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for pdns.
-func NewDNSProviderCredentials(host *url.URL, key string) (*DNSProvider, error) {
- if key == "" {
- return nil, fmt.Errorf("PDNS API key missing")
- }
-
- if host == nil || host.Host == "" {
- return nil, fmt.Errorf("PDNS API URL missing")
- }
-
- provider := &DNSProvider{
- host: host,
- apiKey: key,
- }
- provider.getAPIVersion()
-
- return provider, nil
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return 120 * time.Second, 2 * time.Second
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zone, err := c.getHostedZone(fqdn)
- if err != nil {
- return err
- }
-
- name := fqdn
-
- // pre-v1 API wants non-fqdn
- if c.apiVersion == 0 {
- name = acme.UnFqdn(fqdn)
- }
-
- rec := pdnsRecord{
- Content: "\"" + value + "\"",
- Disabled: false,
-
- // pre-v1 API
- Type: "TXT",
- Name: name,
- TTL: 120,
- }
-
- rrsets := rrSets{
- RRSets: []rrSet{
- rrSet{
- Name: name,
- ChangeType: "REPLACE",
- Type: "TXT",
- Kind: "Master",
- TTL: 120,
- Records: []pdnsRecord{rec},
- },
- },
- }
-
- body, err := json.Marshal(rrsets)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
- if err != nil {
- fmt.Println("here")
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- zone, err := c.getHostedZone(fqdn)
- if err != nil {
- return err
- }
-
- set, err := c.findTxtRecord(fqdn)
- if err != nil {
- return err
- }
-
- rrsets := rrSets{
- RRSets: []rrSet{
- rrSet{
- Name: set.Name,
- Type: set.Type,
- ChangeType: "DELETE",
- },
- },
- }
- body, err := json.Marshal(rrsets)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
- var zone hostedZone
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return nil, err
- }
-
- url := "/servers/localhost/zones"
- result, err := c.makeRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
-
- zones := []hostedZone{}
- err = json.Unmarshal(result, &zones)
- if err != nil {
- return nil, err
- }
-
- url = ""
- for _, zone := range zones {
- if acme.UnFqdn(zone.Name) == acme.UnFqdn(authZone) {
- url = zone.URL
- }
- }
-
- result, err = c.makeRequest("GET", url, nil)
- if err != nil {
- return nil, err
- }
-
- err = json.Unmarshal(result, &zone)
- if err != nil {
- return nil, err
- }
-
- // convert pre-v1 API result
- if len(zone.Records) > 0 {
- zone.RRSets = []rrSet{}
- for _, record := range zone.Records {
- set := rrSet{
- Name: record.Name,
- Type: record.Type,
- Records: []pdnsRecord{record},
- }
- zone.RRSets = append(zone.RRSets, set)
- }
- }
-
- return &zone, nil
-}
-
-func (c *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
- zone, err := c.getHostedZone(fqdn)
- if err != nil {
- return nil, err
- }
-
- _, err = c.makeRequest("GET", zone.URL, nil)
- if err != nil {
- return nil, err
- }
-
- for _, set := range zone.RRSets {
- if (set.Name == acme.UnFqdn(fqdn) || set.Name == fqdn) && set.Type == "TXT" {
- return &set, nil
- }
- }
-
- return nil, fmt.Errorf("No existing record found for %s", fqdn)
-}
-
-func (c *DNSProvider) getAPIVersion() {
- type APIVersion struct {
- URL string `json:"url"`
- Version int `json:"version"`
- }
-
- result, err := c.makeRequest("GET", "/api", nil)
- if err != nil {
- return
- }
-
- var versions []APIVersion
- err = json.Unmarshal(result, &versions)
- if err != nil {
- return
- }
-
- latestVersion := 0
- for _, v := range versions {
- if v.Version > latestVersion {
- latestVersion = v.Version
- }
- }
- c.apiVersion = latestVersion
-}
-
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
- type APIError struct {
- Error string `json:"error"`
- }
- var path = ""
- if c.host.Path != "/" {
- path = c.host.Path
- }
- if c.apiVersion > 0 {
- if !strings.HasPrefix(uri, "api/v") {
- uri = "/api/v" + strconv.Itoa(c.apiVersion) + uri
- } else {
- uri = "/" + uri
- }
- }
- url := c.host.Scheme + "://" + c.host.Host + path + uri
- req, err := http.NewRequest(method, url, body)
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("X-API-Key", c.apiKey)
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error talking to PDNS API -> %v", err)
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != 422 && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
- return nil, fmt.Errorf("Unexpected HTTP status code %d when fetching '%s'", resp.StatusCode, url)
- }
-
- var msg json.RawMessage
- err = json.NewDecoder(resp.Body).Decode(&msg)
- switch {
- case err == io.EOF:
- // empty body
- return nil, nil
- case err != nil:
- // other error
- return nil, err
- }
-
- // check for PowerDNS error message
- if len(msg) > 0 && msg[0] == '{' {
- var apiError APIError
- err = json.Unmarshal(msg, &apiError)
- if err != nil {
- return nil, err
- }
- if apiError.Error != "" {
- return nil, fmt.Errorf("Error talking to PDNS API -> %v", apiError.Error)
- }
- }
- return msg, nil
-}
-
-type pdnsRecord struct {
- Content string `json:"content"`
- Disabled bool `json:"disabled"`
-
- // pre-v1 API
- Name string `json:"name"`
- Type string `json:"type"`
- TTL int `json:"ttl,omitempty"`
-}
-
-type hostedZone struct {
- ID string `json:"id"`
- Name string `json:"name"`
- URL string `json:"url"`
- RRSets []rrSet `json:"rrsets"`
-
- // pre-v1 API
- Records []pdnsRecord `json:"records"`
-}
-
-type rrSet struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Kind string `json:"kind"`
- ChangeType string `json:"changetype"`
- Records []pdnsRecord `json:"records"`
- TTL int `json:"ttl,omitempty"`
-}
-
-type rrSets struct {
- RRSets []rrSet `json:"rrsets"`
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns_test.go b/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns_test.go
deleted file mode 100644
index 70e7670ed..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/pdns/pdns_test.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package pdns
-
-import (
- "net/url"
- "os"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- pdnsLiveTest bool
- pdnsURL *url.URL
- pdnsURLStr string
- pdnsAPIKey string
- pdnsDomain string
-)
-
-func init() {
- pdnsURLStr = os.Getenv("PDNS_API_URL")
- pdnsURL, _ = url.Parse(pdnsURLStr)
- pdnsAPIKey = os.Getenv("PDNS_API_KEY")
- pdnsDomain = os.Getenv("PDNS_DOMAIN")
- if len(pdnsURLStr) > 0 && len(pdnsAPIKey) > 0 && len(pdnsDomain) > 0 {
- pdnsLiveTest = true
- }
-}
-
-func restorePdnsEnv() {
- os.Setenv("PDNS_API_URL", pdnsURLStr)
- os.Setenv("PDNS_API_KEY", pdnsAPIKey)
-}
-
-func TestNewDNSProviderValid(t *testing.T) {
- os.Setenv("PDNS_API_URL", "")
- os.Setenv("PDNS_API_KEY", "")
- tmpURL, _ := url.Parse("http://localhost:8081")
- _, err := NewDNSProviderCredentials(tmpURL, "123")
- assert.NoError(t, err)
- restorePdnsEnv()
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("PDNS_API_URL", "http://localhost:8081")
- os.Setenv("PDNS_API_KEY", "123")
- _, err := NewDNSProvider()
- assert.NoError(t, err)
- restorePdnsEnv()
-}
-
-func TestNewDNSProviderMissingHostErr(t *testing.T) {
- os.Setenv("PDNS_API_URL", "")
- os.Setenv("PDNS_API_KEY", "123")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "PDNS API URL missing")
- restorePdnsEnv()
-}
-
-func TestNewDNSProviderMissingKeyErr(t *testing.T) {
- os.Setenv("PDNS_API_URL", pdnsURLStr)
- os.Setenv("PDNS_API_KEY", "")
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "PDNS API key missing")
- restorePdnsEnv()
-}
-
-func TestPdnsPresentAndCleanup(t *testing.T) {
- if !pdnsLiveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProviderCredentials(pdnsURL, pdnsAPIKey)
- assert.NoError(t, err)
-
- err = provider.Present(pdnsDomain, "", "123d==")
- assert.NoError(t, err)
-
- err = provider.CleanUp(pdnsDomain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go b/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
deleted file mode 100644
index 13daa8c8a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
+++ /dev/null
@@ -1,284 +0,0 @@
-// Package rackspace implements a DNS provider for solving the DNS-01
-// challenge using rackspace DNS.
-package rackspace
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// rackspaceAPIURL represents the Identity API endpoint to call
-var rackspaceAPIURL = "https://identity.api.rackspacecloud.com/v2.0/tokens"
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-// used to store the reusable token and DNS API endpoint
-type DNSProvider struct {
- token string
- cloudDNSEndpoint string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Rackspace.
-// Credentials must be passed in the environment variables: RACKSPACE_USER
-// and RACKSPACE_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- user := os.Getenv("RACKSPACE_USER")
- key := os.Getenv("RACKSPACE_API_KEY")
- return NewDNSProviderCredentials(user, key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Rackspace. It authenticates against
-// the API, also grabbing the DNS Endpoint.
-func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
- if user == "" || key == "" {
- return nil, fmt.Errorf("Rackspace credentials missing")
- }
-
- type APIKeyCredentials struct {
- Username string `json:"username"`
- APIKey string `json:"apiKey"`
- }
-
- type Auth struct {
- APIKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials"`
- }
-
- type RackspaceAuthData struct {
- Auth `json:"auth"`
- }
-
- type RackspaceIdentity struct {
- Access struct {
- ServiceCatalog []struct {
- Endpoints []struct {
- PublicURL string `json:"publicURL"`
- TenantID string `json:"tenantId"`
- } `json:"endpoints"`
- Name string `json:"name"`
- } `json:"serviceCatalog"`
- Token struct {
- ID string `json:"id"`
- } `json:"token"`
- } `json:"access"`
- }
-
- authData := RackspaceAuthData{
- Auth: Auth{
- APIKeyCredentials: APIKeyCredentials{
- Username: user,
- APIKey: key,
- },
- },
- }
-
- body, err := json.Marshal(authData)
- if err != nil {
- return nil, err
- }
-
- req, err := http.NewRequest("POST", rackspaceAPIURL, bytes.NewReader(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error querying Rackspace Identity API: %v", err)
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("Rackspace Authentication failed. Response code: %d", resp.StatusCode)
- }
-
- var rackspaceIdentity RackspaceIdentity
- err = json.NewDecoder(resp.Body).Decode(&rackspaceIdentity)
- if err != nil {
- return nil, err
- }
-
- // Iterate through the Service Catalog to get the DNS Endpoint
- var dnsEndpoint string
- for _, service := range rackspaceIdentity.Access.ServiceCatalog {
- if service.Name == "cloudDNS" {
- dnsEndpoint = service.Endpoints[0].PublicURL
- break
- }
- }
- if dnsEndpoint == "" {
- return nil, fmt.Errorf("Failed to populate DNS endpoint, check Rackspace API for changes.")
- }
-
- return &DNSProvider{
- token: rackspaceIdentity.Access.Token.ID,
- cloudDNSEndpoint: dnsEndpoint,
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- rec := RackspaceRecords{
- RackspaceRecord: []RackspaceRecord{{
- Name: acme.UnFqdn(fqdn),
- Type: "TXT",
- Data: value,
- TTL: 300,
- }},
- }
-
- body, err := json.Marshal(rec)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("POST", fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- record, err := c.findTxtRecord(fqdn, zoneID)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("DELETE", fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// getHostedZoneID performs a lookup to get the DNS zone which needs
-// modifying for a given FQDN
-func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
- // HostedZones represents the response when querying Rackspace DNS zones
- type ZoneSearchResponse struct {
- TotalEntries int `json:"totalEntries"`
- HostedZones []struct {
- ID int `json:"id"`
- Name string `json:"name"`
- } `json:"domains"`
- }
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return 0, err
- }
-
- result, err := c.makeRequest("GET", fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
- if err != nil {
- return 0, err
- }
-
- var zoneSearchResponse ZoneSearchResponse
- err = json.Unmarshal(result, &zoneSearchResponse)
- if err != nil {
- return 0, err
- }
-
- // If nothing was returned, or for whatever reason more than 1 was returned (the search uses exact match, so should not occur)
- if zoneSearchResponse.TotalEntries != 1 {
- return 0, fmt.Errorf("Found %d zones for %s in Rackspace for domain %s", zoneSearchResponse.TotalEntries, authZone, fqdn)
- }
-
- return zoneSearchResponse.HostedZones[0].ID, nil
-}
-
-// findTxtRecord searches a DNS zone for a TXT record with a specific name
-func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*RackspaceRecord, error) {
- result, err := c.makeRequest("GET", fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
- if err != nil {
- return nil, err
- }
-
- var records RackspaceRecords
- err = json.Unmarshal(result, &records)
- if err != nil {
- return nil, err
- }
-
- recordsLength := len(records.RackspaceRecord)
- switch recordsLength {
- case 1:
- break
- case 0:
- return nil, fmt.Errorf("No TXT record found for %s", fqdn)
- default:
- return nil, fmt.Errorf("More than 1 TXT record found for %s", fqdn)
- }
-
- return &records.RackspaceRecord[0], nil
-}
-
-// makeRequest is a wrapper function used for making DNS API requests
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
- url := c.cloudDNSEndpoint + uri
- req, err := http.NewRequest(method, url, body)
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("X-Auth-Token", c.token)
- req.Header.Set("Content-Type", "application/json")
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error querying DNS API: %v", err)
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
- return nil, fmt.Errorf("Request failed for %s %s. Response code: %d", method, url, resp.StatusCode)
- }
-
- var r json.RawMessage
- err = json.NewDecoder(resp.Body).Decode(&r)
- if err != nil {
- return nil, fmt.Errorf("JSON decode failed for %s %s. Response code: %d", method, url, resp.StatusCode)
- }
-
- return r, nil
-}
-
-// RackspaceRecords is the list of records sent/received from the DNS API
-type RackspaceRecords struct {
- RackspaceRecord []RackspaceRecord `json:"records"`
-}
-
-// RackspaceRecord represents a Rackspace DNS record
-type RackspaceRecord struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Data string `json:"data"`
- TTL int `json:"ttl,omitempty"`
- ID string `json:"id,omitempty"`
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace_test.go b/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace_test.go
deleted file mode 100644
index 22c979cad..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace_test.go
+++ /dev/null
@@ -1,220 +0,0 @@
-package rackspace
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "os"
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- rackspaceLiveTest bool
- rackspaceUser string
- rackspaceAPIKey string
- rackspaceDomain string
- testAPIURL string
-)
-
-func init() {
- rackspaceUser = os.Getenv("RACKSPACE_USER")
- rackspaceAPIKey = os.Getenv("RACKSPACE_API_KEY")
- rackspaceDomain = os.Getenv("RACKSPACE_DOMAIN")
- if len(rackspaceUser) > 0 && len(rackspaceAPIKey) > 0 && len(rackspaceDomain) > 0 {
- rackspaceLiveTest = true
- }
-}
-
-func testRackspaceEnv() {
- rackspaceAPIURL = testAPIURL
- os.Setenv("RACKSPACE_USER", "testUser")
- os.Setenv("RACKSPACE_API_KEY", "testKey")
-}
-
-func liveRackspaceEnv() {
- rackspaceAPIURL = "https://identity.api.rackspacecloud.com/v2.0/tokens"
- os.Setenv("RACKSPACE_USER", rackspaceUser)
- os.Setenv("RACKSPACE_API_KEY", rackspaceAPIKey)
-}
-
-func startTestServers() (identityAPI, dnsAPI *httptest.Server) {
- dnsAPI = httptest.NewServer(dnsMux())
- dnsEndpoint := dnsAPI.URL + "/123456"
-
- identityAPI = httptest.NewServer(identityHandler(dnsEndpoint))
- testAPIURL = identityAPI.URL + "/"
- return
-}
-
-func closeTestServers(identityAPI, dnsAPI *httptest.Server) {
- identityAPI.Close()
- dnsAPI.Close()
-}
-
-func identityHandler(dnsEndpoint string) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- reqBody, err := ioutil.ReadAll(r.Body)
- if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- resp, found := jsonMap[string(reqBody)]
- if !found {
- w.WriteHeader(http.StatusBadRequest)
- return
- }
- resp = strings.Replace(resp, "https://dns.api.rackspacecloud.com/v1.0/123456", dnsEndpoint, 1)
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, resp)
- })
-}
-
-func dnsMux() *http.ServeMux {
- mux := http.NewServeMux()
-
- // Used by `getHostedZoneID()` finding `zoneID` "?name=example.com"
- mux.HandleFunc("/123456/domains", func(w http.ResponseWriter, r *http.Request) {
- if r.URL.Query().Get("name") == "example.com" {
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, jsonMap["zoneDetails"])
- return
- }
- w.WriteHeader(http.StatusBadRequest)
- return
- })
-
- mux.HandleFunc("/123456/domains/112233/records", func(w http.ResponseWriter, r *http.Request) {
- switch r.Method {
- // Used by `Present()` creating the TXT record
- case http.MethodPost:
- reqBody, err := ioutil.ReadAll(r.Body)
- if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- resp, found := jsonMap[string(reqBody)]
- if !found {
- w.WriteHeader(http.StatusBadRequest)
- return
- }
- w.WriteHeader(http.StatusAccepted)
- fmt.Fprintf(w, resp)
- // Used by `findTxtRecord()` finding `record.ID` "?type=TXT&name=_acme-challenge.example.com"
- case http.MethodGet:
- if r.URL.Query().Get("type") == "TXT" && r.URL.Query().Get("name") == "_acme-challenge.example.com" {
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, jsonMap["recordDetails"])
- return
- }
- w.WriteHeader(http.StatusBadRequest)
- return
- // Used by `CleanUp()` deleting the TXT record "?id=445566"
- case http.MethodDelete:
- if r.URL.Query().Get("id") == "TXT-654321" {
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, jsonMap["recordDelete"])
- return
- }
- w.WriteHeader(http.StatusBadRequest)
- }
- })
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusNotFound)
- fmt.Printf("Not Found for Request: (%+v)\n\n", r)
- })
-
- return mux
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- testRackspaceEnv()
- _, err := NewDNSProviderCredentials("", "")
- assert.EqualError(t, err, "Rackspace credentials missing")
-}
-
-func TestOfflineRackspaceValid(t *testing.T) {
- testRackspaceEnv()
- provider, err := NewDNSProviderCredentials(os.Getenv("RACKSPACE_USER"), os.Getenv("RACKSPACE_API_KEY"))
-
- assert.NoError(t, err)
- assert.Equal(t, provider.token, "testToken", "The token should match")
-}
-
-func TestOfflineRackspacePresent(t *testing.T) {
- testRackspaceEnv()
- provider, err := NewDNSProvider()
-
- if assert.NoError(t, err) {
- err = provider.Present("example.com", "token", "keyAuth")
- assert.NoError(t, err)
- }
-}
-
-func TestOfflineRackspaceCleanUp(t *testing.T) {
- testRackspaceEnv()
- provider, err := NewDNSProvider()
-
- if assert.NoError(t, err) {
- err = provider.CleanUp("example.com", "token", "keyAuth")
- assert.NoError(t, err)
- }
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- if !rackspaceLiveTest {
- t.Skip("skipping live test")
- }
-
- liveRackspaceEnv()
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
- assert.Contains(t, provider.cloudDNSEndpoint, "https://dns.api.rackspacecloud.com/v1.0/", "The endpoint URL should contain the base")
-}
-
-func TestRackspacePresent(t *testing.T) {
- if !rackspaceLiveTest {
- t.Skip("skipping live test")
- }
-
- liveRackspaceEnv()
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.Present(rackspaceDomain, "", "112233445566==")
- assert.NoError(t, err)
-}
-
-func TestRackspaceCleanUp(t *testing.T) {
- if !rackspaceLiveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 15)
-
- liveRackspaceEnv()
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.CleanUp(rackspaceDomain, "", "112233445566==")
- assert.NoError(t, err)
-}
-
-func TestMain(m *testing.M) {
- identityAPI, dnsAPI := startTestServers()
- defer closeTestServers(identityAPI, dnsAPI)
- os.Exit(m.Run())
-}
-
-var jsonMap = map[string]string{
- `{"auth":{"RAX-KSKEY:apiKeyCredentials":{"username":"testUser","apiKey":"testKey"}}}`: `{"access":{"token":{"id":"testToken","expires":"1970-01-01T00:00:00.000Z","tenant":{"id":"123456","name":"123456"},"RAX-AUTH:authenticatedBy":["APIKEY"]},"serviceCatalog":[{"type":"rax:dns","endpoints":[{"publicURL":"https://dns.api.rackspacecloud.com/v1.0/123456","tenantId":"123456"}],"name":"cloudDNS"}],"user":{"id":"fakeUseID","name":"testUser"}}}`,
- "zoneDetails": `{"domains":[{"name":"example.com","id":112233,"emailAddress":"hostmaster@example.com","updated":"1970-01-01T00:00:00.000+0000","created":"1970-01-01T00:00:00.000+0000"}],"totalEntries":1}`,
- `{"records":[{"name":"_acme-challenge.example.com","type":"TXT","data":"pW9ZKG0xz_PCriK-nCMOjADy9eJcgGWIzkkj2fN4uZM","ttl":300}]}`: `{"request":"{\"records\":[{\"name\":\"_acme-challenge.example.com\",\"type\":\"TXT\",\"data\":\"pW9ZKG0xz_PCriK-nCMOjADy9eJcgGWIzkkj2fN4uZM\",\"ttl\":300}]}","status":"RUNNING","verb":"POST","jobId":"00000000-0000-0000-0000-0000000000","callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/123456/status/00000000-0000-0000-0000-0000000000","requestUrl":"https://dns.api.rackspacecloud.com/v1.0/123456/domains/112233/records"}`,
- "recordDetails": `{"records":[{"name":"_acme-challenge.example.com","id":"TXT-654321","type":"TXT","data":"pW9ZKG0xz_PCriK-nCMOjADy9eJcgGWIzkkj2fN4uZM","ttl":300,"updated":"1970-01-01T00:00:00.000+0000","created":"1970-01-01T00:00:00.000+0000"}]}`,
- "recordDelete": `{"status":"RUNNING","verb":"DELETE","jobId":"00000000-0000-0000-0000-0000000000","callbackUrl":"https://dns.api.rackspacecloud.com/v1.0/123456/status/00000000-0000-0000-0000-0000000000","requestUrl":"https://dns.api.rackspacecloud.com/v1.0/123456/domains/112233/recordsid=TXT-654321"}`,
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go b/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go
deleted file mode 100644
index dde42ddf1..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go
+++ /dev/null
@@ -1,152 +0,0 @@
-// Package rfc2136 implements a DNS provider for solving the DNS-01 challenge
-// using the rfc2136 dynamic update.
-package rfc2136
-
-import (
- "fmt"
- "net"
- "os"
- "strings"
- "time"
-
- "github.com/miekg/dns"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface that
-// uses dynamic DNS updates (RFC 2136) to create TXT records on a nameserver.
-type DNSProvider struct {
- nameserver string
- tsigAlgorithm string
- tsigKey string
- tsigSecret string
- timeout time.Duration
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for rfc2136
-// dynamic update. Configured with environment variables:
-// RFC2136_NAMESERVER: Network address in the form "host" or "host:port".
-// RFC2136_TSIG_ALGORITHM: Defaults to hmac-md5.sig-alg.reg.int. (HMAC-MD5).
-// See https://github.com/miekg/dns/blob/master/tsig.go for supported values.
-// RFC2136_TSIG_KEY: Name of the secret key as defined in DNS server configuration.
-// RFC2136_TSIG_SECRET: Secret key payload.
-// RFC2136_TIMEOUT: DNS propagation timeout in time.ParseDuration format. (60s)
-// To disable TSIG authentication, leave the RFC2136_TSIG* variables unset.
-func NewDNSProvider() (*DNSProvider, error) {
- nameserver := os.Getenv("RFC2136_NAMESERVER")
- tsigAlgorithm := os.Getenv("RFC2136_TSIG_ALGORITHM")
- tsigKey := os.Getenv("RFC2136_TSIG_KEY")
- tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
- timeout := os.Getenv("RFC2136_TIMEOUT")
- return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for rfc2136 dynamic update. To disable TSIG
-// authentication, leave the TSIG parameters as empty strings.
-// nameserver must be a network address in the form "host" or "host:port".
-func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout string) (*DNSProvider, error) {
- if nameserver == "" {
- return nil, fmt.Errorf("RFC2136 nameserver missing")
- }
-
- // Append the default DNS port if none is specified.
- if _, _, err := net.SplitHostPort(nameserver); err != nil {
- if strings.Contains(err.Error(), "missing port") {
- nameserver = net.JoinHostPort(nameserver, "53")
- } else {
- return nil, err
- }
- }
- d := &DNSProvider{
- nameserver: nameserver,
- }
- if tsigAlgorithm == "" {
- tsigAlgorithm = dns.HmacMD5
- }
- d.tsigAlgorithm = tsigAlgorithm
- if len(tsigKey) > 0 && len(tsigSecret) > 0 {
- d.tsigKey = tsigKey
- d.tsigSecret = tsigSecret
- }
-
- if timeout == "" {
- d.timeout = 60 * time.Second
- } else {
- t, err := time.ParseDuration(timeout)
- if err != nil {
- return nil, err
- } else if t < 0 {
- return nil, fmt.Errorf("Invalid/negative RFC2136_TIMEOUT: %v", timeout)
- } else {
- d.timeout = t
- }
- }
-
- return d, nil
-}
-
-// Returns the timeout configured with RFC2136_TIMEOUT, or 60s.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
- return d.timeout, 2 * time.Second
-}
-
-// Present creates a TXT record using the specified parameters
-func (r *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- return r.changeRecord("INSERT", fqdn, value, ttl)
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
- return r.changeRecord("REMOVE", fqdn, value, ttl)
-}
-
-func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
- // Find the zone for the given fqdn
- zone, err := acme.FindZoneByFqdn(fqdn, []string{r.nameserver})
- if err != nil {
- return err
- }
-
- // Create RR
- rr := new(dns.TXT)
- rr.Hdr = dns.RR_Header{Name: fqdn, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(ttl)}
- rr.Txt = []string{value}
- rrs := []dns.RR{rr}
-
- // Create dynamic update packet
- m := new(dns.Msg)
- m.SetUpdate(zone)
- switch action {
- case "INSERT":
- // Always remove old challenge left over from who knows what.
- m.RemoveRRset(rrs)
- m.Insert(rrs)
- case "REMOVE":
- m.Remove(rrs)
- default:
- return fmt.Errorf("Unexpected action: %s", action)
- }
-
- // Setup client
- c := new(dns.Client)
- c.SingleInflight = true
- // TSIG authentication / msg signing
- if len(r.tsigKey) > 0 && len(r.tsigSecret) > 0 {
- m.SetTsig(dns.Fqdn(r.tsigKey), r.tsigAlgorithm, 300, time.Now().Unix())
- c.TsigSecret = map[string]string{dns.Fqdn(r.tsigKey): r.tsigSecret}
- }
-
- // Send the query
- reply, _, err := c.Exchange(m, r.nameserver)
- if err != nil {
- return fmt.Errorf("DNS update failed: %v", err)
- }
- if reply != nil && reply.Rcode != dns.RcodeSuccess {
- return fmt.Errorf("DNS update failed. Server replied: %s", dns.RcodeToString[reply.Rcode])
- }
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136_test.go b/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136_test.go
deleted file mode 100644
index f3ca65b31..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136_test.go
+++ /dev/null
@@ -1,244 +0,0 @@
-package rfc2136
-
-import (
- "bytes"
- "fmt"
- "net"
- "strings"
- "sync"
- "testing"
- "time"
-
- "github.com/miekg/dns"
- "github.com/xenolf/lego/acme"
-)
-
-var (
- rfc2136TestDomain = "123456789.www.example.com"
- rfc2136TestKeyAuth = "123d=="
- rfc2136TestValue = "Now36o-3BmlB623-0c1qCIUmgWVVmDJb88KGl24pqpo"
- rfc2136TestFqdn = "_acme-challenge.123456789.www.example.com."
- rfc2136TestZone = "example.com."
- rfc2136TestTTL = 120
- rfc2136TestTsigKey = "example.com."
- rfc2136TestTsigSecret = "IwBTJx9wrDp4Y1RyC3H0gA=="
-)
-
-var reqChan = make(chan *dns.Msg, 10)
-
-func TestRFC2136CanaryLocalTestServer(t *testing.T) {
- acme.ClearFqdnCache()
- dns.HandleFunc("example.com.", serverHandlerHello)
- defer dns.HandleRemove("example.com.")
-
- server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
- if err != nil {
- t.Fatalf("Failed to start test server: %v", err)
- }
- defer server.Shutdown()
-
- c := new(dns.Client)
- m := new(dns.Msg)
- m.SetQuestion("example.com.", dns.TypeTXT)
- r, _, err := c.Exchange(m, addrstr)
- if err != nil || len(r.Extra) == 0 {
- t.Fatalf("Failed to communicate with test server: %v", err)
- }
- txt := r.Extra[0].(*dns.TXT).Txt[0]
- if txt != "Hello world" {
- t.Error("Expected test server to return 'Hello world' but got: ", txt)
- }
-}
-
-func TestRFC2136ServerSuccess(t *testing.T) {
- acme.ClearFqdnCache()
- dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
- defer dns.HandleRemove(rfc2136TestZone)
-
- server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
- if err != nil {
- t.Fatalf("Failed to start test server: %v", err)
- }
- defer server.Shutdown()
-
- provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
- if err != nil {
- t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
- }
- if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
- t.Errorf("Expected Present() to return no error but the error was -> %v", err)
- }
-}
-
-func TestRFC2136ServerError(t *testing.T) {
- acme.ClearFqdnCache()
- dns.HandleFunc(rfc2136TestZone, serverHandlerReturnErr)
- defer dns.HandleRemove(rfc2136TestZone)
-
- server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
- if err != nil {
- t.Fatalf("Failed to start test server: %v", err)
- }
- defer server.Shutdown()
-
- provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
- if err != nil {
- t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
- }
- if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err == nil {
- t.Errorf("Expected Present() to return an error but it did not.")
- } else if !strings.Contains(err.Error(), "NOTZONE") {
- t.Errorf("Expected Present() to return an error with the 'NOTZONE' rcode string but it did not.")
- }
-}
-
-func TestRFC2136TsigClient(t *testing.T) {
- acme.ClearFqdnCache()
- dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
- defer dns.HandleRemove(rfc2136TestZone)
-
- server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
- if err != nil {
- t.Fatalf("Failed to start test server: %v", err)
- }
- defer server.Shutdown()
-
- provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKey, rfc2136TestTsigSecret, "")
- if err != nil {
- t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
- }
- if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
- t.Errorf("Expected Present() to return no error but the error was -> %v", err)
- }
-}
-
-func TestRFC2136ValidUpdatePacket(t *testing.T) {
- acme.ClearFqdnCache()
- dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
- defer dns.HandleRemove(rfc2136TestZone)
-
- server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
- if err != nil {
- t.Fatalf("Failed to start test server: %v", err)
- }
- defer server.Shutdown()
-
- txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
- rrs := []dns.RR{txtRR}
- m := new(dns.Msg)
- m.SetUpdate(rfc2136TestZone)
- m.RemoveRRset(rrs)
- m.Insert(rrs)
- expectstr := m.String()
- expect, err := m.Pack()
- if err != nil {
- t.Fatalf("Error packing expect msg: %v", err)
- }
-
- provider, err := NewDNSProviderCredentials(addrstr, "", "", "", "")
- if err != nil {
- t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
- }
-
- if err := provider.Present(rfc2136TestDomain, "", "1234d=="); err != nil {
- t.Errorf("Expected Present() to return no error but the error was -> %v", err)
- }
-
- rcvMsg := <-reqChan
- rcvMsg.Id = m.Id
- actual, err := rcvMsg.Pack()
- if err != nil {
- t.Fatalf("Error packing actual msg: %v", err)
- }
-
- if !bytes.Equal(actual, expect) {
- tmp := new(dns.Msg)
- if err := tmp.Unpack(actual); err != nil {
- t.Fatalf("Error unpacking actual msg: %v", err)
- }
- t.Errorf("Expected msg:\n%s", expectstr)
- t.Errorf("Actual msg:\n%v", tmp)
- }
-}
-
-func runLocalDNSTestServer(listenAddr string, tsig bool) (*dns.Server, string, error) {
- pc, err := net.ListenPacket("udp", listenAddr)
- if err != nil {
- return nil, "", err
- }
- server := &dns.Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
- if tsig {
- server.TsigSecret = map[string]string{rfc2136TestTsigKey: rfc2136TestTsigSecret}
- }
-
- waitLock := sync.Mutex{}
- waitLock.Lock()
- server.NotifyStartedFunc = waitLock.Unlock
-
- go func() {
- server.ActivateAndServe()
- pc.Close()
- }()
-
- waitLock.Lock()
- return server, pc.LocalAddr().String(), nil
-}
-
-func serverHandlerHello(w dns.ResponseWriter, req *dns.Msg) {
- m := new(dns.Msg)
- m.SetReply(req)
- m.Extra = make([]dns.RR, 1)
- m.Extra[0] = &dns.TXT{
- Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0},
- Txt: []string{"Hello world"},
- }
- w.WriteMsg(m)
-}
-
-func serverHandlerReturnSuccess(w dns.ResponseWriter, req *dns.Msg) {
- m := new(dns.Msg)
- m.SetReply(req)
- if req.Opcode == dns.OpcodeQuery && req.Question[0].Qtype == dns.TypeSOA && req.Question[0].Qclass == dns.ClassINET {
- // Return SOA to appease findZoneByFqdn()
- soaRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN SOA ns1.%s admin.%s 2016022801 28800 7200 2419200 1200", rfc2136TestZone, rfc2136TestTTL, rfc2136TestZone, rfc2136TestZone))
- m.Answer = []dns.RR{soaRR}
- }
-
- if t := req.IsTsig(); t != nil {
- if w.TsigStatus() == nil {
- // Validated
- m.SetTsig(rfc2136TestZone, dns.HmacMD5, 300, time.Now().Unix())
- }
- }
-
- w.WriteMsg(m)
-}
-
-func serverHandlerReturnErr(w dns.ResponseWriter, req *dns.Msg) {
- m := new(dns.Msg)
- m.SetRcode(req, dns.RcodeNotZone)
- w.WriteMsg(m)
-}
-
-func serverHandlerPassBackRequest(w dns.ResponseWriter, req *dns.Msg) {
- m := new(dns.Msg)
- m.SetReply(req)
- if req.Opcode == dns.OpcodeQuery && req.Question[0].Qtype == dns.TypeSOA && req.Question[0].Qclass == dns.ClassINET {
- // Return SOA to appease findZoneByFqdn()
- soaRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN SOA ns1.%s admin.%s 2016022801 28800 7200 2419200 1200", rfc2136TestZone, rfc2136TestTTL, rfc2136TestZone, rfc2136TestZone))
- m.Answer = []dns.RR{soaRR}
- }
-
- if t := req.IsTsig(); t != nil {
- if w.TsigStatus() == nil {
- // Validated
- m.SetTsig(rfc2136TestZone, dns.HmacMD5, 300, time.Now().Unix())
- }
- }
-
- w.WriteMsg(m)
- if req.Opcode != dns.OpcodeQuery || req.Question[0].Qtype != dns.TypeSOA || req.Question[0].Qclass != dns.ClassINET {
- // Only talk back when it is not the SOA RR.
- reqChan <- req
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/route53/fixtures_test.go b/vendor/github.com/xenolf/lego/providers/dns/route53/fixtures_test.go
deleted file mode 100644
index a5cc9c878..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/route53/fixtures_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package route53
-
-var ChangeResourceRecordSetsResponse = `<?xml version="1.0" encoding="UTF-8"?>
-<ChangeResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
-<ChangeInfo>
- <Id>/change/123456</Id>
- <Status>PENDING</Status>
- <SubmittedAt>2016-02-10T01:36:41.958Z</SubmittedAt>
-</ChangeInfo>
-</ChangeResourceRecordSetsResponse>`
-
-var ListHostedZonesByNameResponse = `<?xml version="1.0" encoding="UTF-8"?>
-<ListHostedZonesByNameResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
- <HostedZones>
- <HostedZone>
- <Id>/hostedzone/ABCDEFG</Id>
- <Name>example.com.</Name>
- <CallerReference>D2224C5B-684A-DB4A-BB9A-E09E3BAFEA7A</CallerReference>
- <Config>
- <Comment>Test comment</Comment>
- <PrivateZone>false</PrivateZone>
- </Config>
- <ResourceRecordSetCount>10</ResourceRecordSetCount>
- </HostedZone>
- </HostedZones>
- <IsTruncated>true</IsTruncated>
- <NextDNSName>example2.com</NextDNSName>
- <NextHostedZoneId>ZLT12321321124</NextHostedZoneId>
- <MaxItems>1</MaxItems>
-</ListHostedZonesByNameResponse>`
-
-var GetChangeResponse = `<?xml version="1.0" encoding="UTF-8"?>
-<GetChangeResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
- <ChangeInfo>
- <Id>123456</Id>
- <Status>INSYNC</Status>
- <SubmittedAt>2016-02-10T01:36:41.958Z</SubmittedAt>
- </ChangeInfo>
-</GetChangeResponse>`
diff --git a/vendor/github.com/xenolf/lego/providers/dns/route53/route53.go b/vendor/github.com/xenolf/lego/providers/dns/route53/route53.go
deleted file mode 100644
index 934f0a2d4..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/route53/route53.go
+++ /dev/null
@@ -1,185 +0,0 @@
-// Package route53 implements a DNS provider for solving the DNS-01 challenge
-// using AWS Route 53 DNS.
-package route53
-
-import (
- "fmt"
- "math/rand"
- "os"
- "strings"
- "time"
-
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/client"
- "github.com/aws/aws-sdk-go/aws/request"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/route53"
- "github.com/xenolf/lego/acme"
-)
-
-const (
- maxRetries = 5
- route53TTL = 10
-)
-
-// DNSProvider implements the acme.ChallengeProvider interface
-type DNSProvider struct {
- client *route53.Route53
- hostedZoneID string
-}
-
-// customRetryer implements the client.Retryer interface by composing the
-// DefaultRetryer. It controls the logic for retrying recoverable request
-// errors (e.g. when rate limits are exceeded).
-type customRetryer struct {
- client.DefaultRetryer
-}
-
-// RetryRules overwrites the DefaultRetryer's method.
-// It uses a basic exponential backoff algorithm that returns an initial
-// delay of ~400ms with an upper limit of ~30 seconds which should prevent
-// causing a high number of consecutive throttling errors.
-// For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
-func (d customRetryer) RetryRules(r *request.Request) time.Duration {
- retryCount := r.RetryCount
- if retryCount > 7 {
- retryCount = 7
- }
-
- delay := (1 << uint(retryCount)) * (rand.Intn(50) + 200)
- return time.Duration(delay) * time.Millisecond
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for the AWS
-// Route 53 service.
-//
-// AWS Credentials are automatically detected in the following locations
-// and prioritized in the following order:
-// 1. Environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
-// AWS_REGION, [AWS_SESSION_TOKEN]
-// 2. Shared credentials file (defaults to ~/.aws/credentials)
-// 3. Amazon EC2 IAM role
-//
-// If AWS_HOSTED_ZONE_ID is not set, Lego tries to determine the correct
-// public hosted zone via the FQDN.
-//
-// See also: https://github.com/aws/aws-sdk-go/wiki/configuring-sdk
-func NewDNSProvider() (*DNSProvider, error) {
- hostedZoneID := os.Getenv("AWS_HOSTED_ZONE_ID")
-
- r := customRetryer{}
- r.NumMaxRetries = maxRetries
- config := request.WithRetryer(aws.NewConfig(), r)
- client := route53.New(session.New(config))
-
- return &DNSProvider{
- client: client,
- hostedZoneID: hostedZoneID,
- }, nil
-}
-
-// Present creates a TXT record using the specified parameters
-func (r *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- value = `"` + value + `"`
- return r.changeRecord("UPSERT", fqdn, value, route53TTL)
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- value = `"` + value + `"`
- return r.changeRecord("DELETE", fqdn, value, route53TTL)
-}
-
-func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
- hostedZoneID, err := r.getHostedZoneID(fqdn)
- if err != nil {
- return fmt.Errorf("Failed to determine Route 53 hosted zone ID: %v", err)
- }
-
- recordSet := newTXTRecordSet(fqdn, value, ttl)
- reqParams := &route53.ChangeResourceRecordSetsInput{
- HostedZoneId: aws.String(hostedZoneID),
- ChangeBatch: &route53.ChangeBatch{
- Comment: aws.String("Managed by Lego"),
- Changes: []*route53.Change{
- {
- Action: aws.String(action),
- ResourceRecordSet: recordSet,
- },
- },
- },
- }
-
- resp, err := r.client.ChangeResourceRecordSets(reqParams)
- if err != nil {
- return fmt.Errorf("Failed to change Route 53 record set: %v", err)
- }
-
- statusID := resp.ChangeInfo.Id
-
- return acme.WaitFor(120*time.Second, 4*time.Second, func() (bool, error) {
- reqParams := &route53.GetChangeInput{
- Id: statusID,
- }
- resp, err := r.client.GetChange(reqParams)
- if err != nil {
- return false, fmt.Errorf("Failed to query Route 53 change status: %v", err)
- }
- if *resp.ChangeInfo.Status == route53.ChangeStatusInsync {
- return true, nil
- }
- return false, nil
- })
-}
-
-func (r *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
- if r.hostedZoneID != "" {
- return r.hostedZoneID, nil
- }
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return "", err
- }
-
- // .DNSName should not have a trailing dot
- reqParams := &route53.ListHostedZonesByNameInput{
- DNSName: aws.String(acme.UnFqdn(authZone)),
- }
- resp, err := r.client.ListHostedZonesByName(reqParams)
- if err != nil {
- return "", err
- }
-
- var hostedZoneID string
- for _, hostedZone := range resp.HostedZones {
- // .Name has a trailing dot
- if !*hostedZone.Config.PrivateZone && *hostedZone.Name == authZone {
- hostedZoneID = *hostedZone.Id
- break
- }
- }
-
- if len(hostedZoneID) == 0 {
- return "", fmt.Errorf("Zone %s not found in Route 53 for domain %s", authZone, fqdn)
- }
-
- if strings.HasPrefix(hostedZoneID, "/hostedzone/") {
- hostedZoneID = strings.TrimPrefix(hostedZoneID, "/hostedzone/")
- }
-
- return hostedZoneID, nil
-}
-
-func newTXTRecordSet(fqdn, value string, ttl int) *route53.ResourceRecordSet {
- return &route53.ResourceRecordSet{
- Name: aws.String(fqdn),
- Type: aws.String("TXT"),
- TTL: aws.Int64(int64(ttl)),
- ResourceRecords: []*route53.ResourceRecord{
- {Value: aws.String(value)},
- },
- }
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/route53/route53_integration_test.go b/vendor/github.com/xenolf/lego/providers/dns/route53/route53_integration_test.go
deleted file mode 100644
index 17ba4a08a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/route53/route53_integration_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package route53
-
-import (
- "fmt"
- "os"
- "testing"
-
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/route53"
-)
-
-func TestRoute53TTL(t *testing.T) {
-
- m, err := testGetAndPreCheck()
- if err != nil {
- t.Skip(err.Error())
- }
-
- provider, err := NewDNSProvider()
- if err != nil {
- t.Fatalf("Fatal: %s", err.Error())
- }
-
- err = provider.Present(m["route53Domain"], "foo", "bar")
- if err != nil {
- t.Fatalf("Fatal: %s", err.Error())
- }
- // we need a separate R53 client here as the one in the DNS provider is
- // unexported.
- fqdn := "_acme-challenge." + m["route53Domain"] + "."
- svc := route53.New(session.New())
- zoneID, err := provider.getHostedZoneID(fqdn)
- if err != nil {
- provider.CleanUp(m["route53Domain"], "foo", "bar")
- t.Fatalf("Fatal: %s", err.Error())
- }
- params := &route53.ListResourceRecordSetsInput{
- HostedZoneId: aws.String(zoneID),
- }
- resp, err := svc.ListResourceRecordSets(params)
- if err != nil {
- provider.CleanUp(m["route53Domain"], "foo", "bar")
- t.Fatalf("Fatal: %s", err.Error())
- }
-
- for _, v := range resp.ResourceRecordSets {
- if *v.Name == fqdn && *v.Type == "TXT" && *v.TTL == 10 {
- provider.CleanUp(m["route53Domain"], "foo", "bar")
- return
- }
- }
- provider.CleanUp(m["route53Domain"], "foo", "bar")
- t.Fatalf("Could not find a TXT record for _acme-challenge.%s with a TTL of 10", m["route53Domain"])
-}
-
-func testGetAndPreCheck() (map[string]string, error) {
- m := map[string]string{
- "route53Key": os.Getenv("AWS_ACCESS_KEY_ID"),
- "route53Secret": os.Getenv("AWS_SECRET_ACCESS_KEY"),
- "route53Region": os.Getenv("AWS_REGION"),
- "route53Domain": os.Getenv("R53_DOMAIN"),
- }
- for _, v := range m {
- if v == "" {
- return nil, fmt.Errorf("AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, and R53_DOMAIN are needed to run this test")
- }
- }
- return m, nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/route53/route53_test.go b/vendor/github.com/xenolf/lego/providers/dns/route53/route53_test.go
deleted file mode 100644
index de4e28f3d..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/route53/route53_test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package route53
-
-import (
- "net/http/httptest"
- "os"
- "testing"
-
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/credentials"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/route53"
- "github.com/stretchr/testify/assert"
-)
-
-var (
- route53Secret string
- route53Key string
- route53Region string
- route53Zone string
-)
-
-func init() {
- route53Key = os.Getenv("AWS_ACCESS_KEY_ID")
- route53Secret = os.Getenv("AWS_SECRET_ACCESS_KEY")
- route53Region = os.Getenv("AWS_REGION")
- route53Zone = os.Getenv("AWS_HOSTED_ZONE_ID")
-}
-
-func restoreRoute53Env() {
- os.Setenv("AWS_ACCESS_KEY_ID", route53Key)
- os.Setenv("AWS_SECRET_ACCESS_KEY", route53Secret)
- os.Setenv("AWS_REGION", route53Region)
- os.Setenv("AWS_HOSTED_ZONE_ID", route53Zone)
-}
-
-func makeRoute53Provider(ts *httptest.Server) *DNSProvider {
- config := &aws.Config{
- Credentials: credentials.NewStaticCredentials("abc", "123", " "),
- Endpoint: aws.String(ts.URL),
- Region: aws.String("mock-region"),
- MaxRetries: aws.Int(1),
- }
-
- client := route53.New(session.New(config))
- return &DNSProvider{client: client}
-}
-
-func TestCredentialsFromEnv(t *testing.T) {
- os.Setenv("AWS_ACCESS_KEY_ID", "123")
- os.Setenv("AWS_SECRET_ACCESS_KEY", "123")
- os.Setenv("AWS_REGION", "us-east-1")
-
- config := &aws.Config{
- CredentialsChainVerboseErrors: aws.Bool(true),
- }
-
- sess := session.New(config)
- _, err := sess.Config.Credentials.Get()
- assert.NoError(t, err, "Expected credentials to be set from environment")
-
- restoreRoute53Env()
-}
-
-func TestRegionFromEnv(t *testing.T) {
- os.Setenv("AWS_REGION", "us-east-1")
-
- sess := session.New(aws.NewConfig())
- assert.Equal(t, "us-east-1", *sess.Config.Region, "Expected Region to be set from environment")
-
- restoreRoute53Env()
-}
-
-func TestHostedZoneIDFromEnv(t *testing.T) {
- const testZoneID = "testzoneid"
-
- defer restoreRoute53Env()
- os.Setenv("AWS_HOSTED_ZONE_ID", testZoneID)
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err, "Expected no error constructing DNSProvider")
-
- fqdn, err := provider.getHostedZoneID("whatever")
- assert.NoError(t, err, "Expected FQDN to be resolved to environment variable value")
-
- assert.Equal(t, testZoneID, fqdn)
-}
-
-func TestRoute53Present(t *testing.T) {
- mockResponses := MockResponseMap{
- "/2013-04-01/hostedzonesbyname": MockResponse{StatusCode: 200, Body: ListHostedZonesByNameResponse},
- "/2013-04-01/hostedzone/ABCDEFG/rrset/": MockResponse{StatusCode: 200, Body: ChangeResourceRecordSetsResponse},
- "/2013-04-01/change/123456": MockResponse{StatusCode: 200, Body: GetChangeResponse},
- }
-
- ts := newMockServer(t, mockResponses)
- defer ts.Close()
-
- provider := makeRoute53Provider(ts)
-
- domain := "example.com"
- keyAuth := "123456d=="
-
- err := provider.Present(domain, "", keyAuth)
- assert.NoError(t, err, "Expected Present to return no error")
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/route53/testutil_test.go b/vendor/github.com/xenolf/lego/providers/dns/route53/testutil_test.go
deleted file mode 100644
index e448a6858..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/route53/testutil_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package route53
-
-import (
- "fmt"
- "net/http"
- "net/http/httptest"
- "testing"
- "time"
-
- "github.com/stretchr/testify/require"
-)
-
-// MockResponse represents a predefined response used by a mock server
-type MockResponse struct {
- StatusCode int
- Body string
-}
-
-// MockResponseMap maps request paths to responses
-type MockResponseMap map[string]MockResponse
-
-func newMockServer(t *testing.T, responses MockResponseMap) *httptest.Server {
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- path := r.URL.Path
- resp, ok := responses[path]
- if !ok {
- msg := fmt.Sprintf("Requested path not found in response map: %s", path)
- require.FailNow(t, msg)
- }
-
- w.Header().Set("Content-Type", "application/xml")
- w.WriteHeader(resp.StatusCode)
- w.Write([]byte(resp.Body))
- }))
-
- time.Sleep(100 * time.Millisecond)
- return ts
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go b/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go
deleted file mode 100644
index bc2067579..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Package vultr implements a DNS provider for solving the DNS-01 challenge using
-// the vultr DNS.
-// See https://www.vultr.com/api/#dns
-package vultr
-
-import (
- "fmt"
- "os"
- "strings"
-
- vultr "github.com/JamesClonk/vultr/lib"
- "github.com/xenolf/lego/acme"
-)
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface.
-type DNSProvider struct {
- client *vultr.Client
-}
-
-// NewDNSProvider returns a DNSProvider instance with a configured Vultr client.
-// Authentication uses the VULTR_API_KEY environment variable.
-func NewDNSProvider() (*DNSProvider, error) {
- apiKey := os.Getenv("VULTR_API_KEY")
- return NewDNSProviderCredentials(apiKey)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a DNSProvider
-// instance configured for Vultr.
-func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
- if apiKey == "" {
- return nil, fmt.Errorf("Vultr credentials missing")
- }
-
- c := &DNSProvider{
- client: vultr.NewClient(apiKey, nil),
- }
-
- return c, nil
-}
-
-// Present creates a TXT record to fulfil the DNS-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-
- zoneDomain, err := c.getHostedZone(domain)
- if err != nil {
- return err
- }
-
- name := c.extractRecordName(fqdn, zoneDomain)
-
- err = c.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl)
- if err != nil {
- return fmt.Errorf("Vultr API call failed: %v", err)
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-
- zoneDomain, records, err := c.findTxtRecords(domain, fqdn)
- if err != nil {
- return err
- }
-
- for _, rec := range records {
- err := c.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
- domains, err := c.client.GetDNSDomains()
- if err != nil {
- return "", fmt.Errorf("Vultr API call failed: %v", err)
- }
-
- var hostedDomain vultr.DNSDomain
- for _, d := range domains {
- if strings.HasSuffix(domain, d.Domain) {
- if len(d.Domain) > len(hostedDomain.Domain) {
- hostedDomain = d
- }
- }
- }
- if hostedDomain.Domain == "" {
- return "", fmt.Errorf("No matching Vultr domain found for domain %s", domain)
- }
-
- return hostedDomain.Domain, nil
-}
-
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
- zoneDomain, err := c.getHostedZone(domain)
- if err != nil {
- return "", nil, err
- }
-
- var records []vultr.DNSRecord
- result, err := c.client.GetDNSRecords(zoneDomain)
- if err != nil {
- return "", records, fmt.Errorf("Vultr API call has failed: %v", err)
- }
-
- recordName := c.extractRecordName(fqdn, zoneDomain)
- for _, record := range result {
- if record.Type == "TXT" && record.Name == recordName {
- records = append(records, record)
- }
- }
-
- return zoneDomain, records, nil
-}
-
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
- name := acme.UnFqdn(fqdn)
- if idx := strings.Index(name, "."+domain); idx != -1 {
- return name[:idx]
- }
- return name
-}
diff --git a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr_test.go b/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr_test.go
deleted file mode 100644
index 7c8cdaf1e..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/vultr/vultr_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package vultr
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-var (
- liveTest bool
- apiKey string
- domain string
-)
-
-func init() {
- apiKey = os.Getenv("VULTR_API_KEY")
- domain = os.Getenv("VULTR_TEST_DOMAIN")
- liveTest = len(apiKey) > 0 && len(domain) > 0
-}
-
-func restoreEnv() {
- os.Setenv("VULTR_API_KEY", apiKey)
-}
-
-func TestNewDNSProviderValidEnv(t *testing.T) {
- os.Setenv("VULTR_API_KEY", "123")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.NoError(t, err)
-}
-
-func TestNewDNSProviderMissingCredErr(t *testing.T) {
- os.Setenv("VULTR_API_KEY", "")
- defer restoreEnv()
- _, err := NewDNSProvider()
- assert.EqualError(t, err, "Vultr credentials missing")
-}
-
-func TestLivePresent(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.Present(domain, "", "123d==")
- assert.NoError(t, err)
-}
-
-func TestLiveCleanUp(t *testing.T) {
- if !liveTest {
- t.Skip("skipping live test")
- }
-
- time.Sleep(time.Second * 1)
-
- provider, err := NewDNSProvider()
- assert.NoError(t, err)
-
- err = provider.CleanUp(domain, "", "123d==")
- assert.NoError(t, err)
-}
diff --git a/vendor/github.com/xenolf/lego/providers/http/memcached/README.md b/vendor/github.com/xenolf/lego/providers/http/memcached/README.md
deleted file mode 100644
index f14d216df..000000000
--- a/vendor/github.com/xenolf/lego/providers/http/memcached/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Memcached http provider
-
-Publishes challenges into memcached where they can be retrieved by nginx. Allows
-specifying multiple memcached servers and the responses will be published to all
-of them, making it easier to verify when your domain is hosted on a cluster of
-servers.
-
-Example nginx config:
-
-```
- location /.well-known/acme-challenge/ {
- set $memcached_key "$uri";
- memcached_pass 127.0.0.1:11211;
- }
-```
diff --git a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go
deleted file mode 100644
index 9ac8b811d..000000000
--- a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Package memcached implements a HTTP provider for solving the HTTP-01 challenge using memcached
-// in combination with a webserver.
-package memcached
-
-import (
- "fmt"
- "path"
-
- "github.com/rainycape/memcache"
- "github.com/xenolf/lego/acme"
-)
-
-// HTTPProvider implements ChallengeProvider for `http-01` challenge
-type MemcachedProvider struct {
- hosts []string
-}
-
-// NewHTTPProvider returns a HTTPProvider instance with a configured webroot path
-func NewMemcachedProvider(hosts []string) (*MemcachedProvider, error) {
- if len(hosts) == 0 {
- return nil, fmt.Errorf("No memcached hosts provided")
- }
-
- c := &MemcachedProvider{
- hosts: hosts,
- }
-
- return c, nil
-}
-
-// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path
-func (w *MemcachedProvider) Present(domain, token, keyAuth string) error {
- var errs []error
-
- challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
- for _, host := range w.hosts {
- mc, err := memcache.New(host)
- if err != nil {
- errs = append(errs, err)
- continue
- }
- mc.Add(&memcache.Item{
- Key: challengePath,
- Value: []byte(keyAuth),
- Expiration: 60,
- })
- }
-
- if len(errs) == len(w.hosts) {
- return fmt.Errorf("Unable to store key in any of the memcache hosts -> %v", errs)
- }
-
- return nil
-}
-
-// CleanUp removes the file created for the challenge
-func (w *MemcachedProvider) CleanUp(domain, token, keyAuth string) error {
- // Memcached will clean up itself, that's what expiration is for.
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached_test.go b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached_test.go
deleted file mode 100644
index 287a33304..000000000
--- a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached_test.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package memcached
-
-import (
- "os"
- "path"
- "strings"
- "testing"
-
- "github.com/rainycape/memcache"
- "github.com/stretchr/testify/assert"
- "github.com/xenolf/lego/acme"
-)
-
-var (
- memcachedHosts []string
-)
-
-const (
- domain = "lego.test"
- token = "foo"
- keyAuth = "bar"
-)
-
-func init() {
- memcachedHostsStr := os.Getenv("MEMCACHED_HOSTS")
- if len(memcachedHostsStr) > 0 {
- memcachedHosts = strings.Split(memcachedHostsStr, ",")
- }
-}
-
-func TestNewMemcachedProviderEmpty(t *testing.T) {
- emptyHosts := make([]string, 0)
- _, err := NewMemcachedProvider(emptyHosts)
- assert.EqualError(t, err, "No memcached hosts provided")
-}
-
-func TestNewMemcachedProviderValid(t *testing.T) {
- if len(memcachedHosts) == 0 {
- t.Skip("Skipping memcached tests")
- }
- _, err := NewMemcachedProvider(memcachedHosts)
- assert.NoError(t, err)
-}
-
-func TestMemcachedPresentSingleHost(t *testing.T) {
- if len(memcachedHosts) == 0 {
- t.Skip("Skipping memcached tests")
- }
- p, err := NewMemcachedProvider(memcachedHosts[0:1])
- assert.NoError(t, err)
-
- challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
-
- err = p.Present(domain, token, keyAuth)
- assert.NoError(t, err)
- mc, err := memcache.New(memcachedHosts[0])
- assert.NoError(t, err)
- i, err := mc.Get(challengePath)
- assert.NoError(t, err)
- assert.Equal(t, i.Value, []byte(keyAuth))
-}
-
-func TestMemcachedPresentMultiHost(t *testing.T) {
- if len(memcachedHosts) <= 1 {
- t.Skip("Skipping memcached multi-host tests")
- }
- p, err := NewMemcachedProvider(memcachedHosts)
- assert.NoError(t, err)
-
- challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
-
- err = p.Present(domain, token, keyAuth)
- assert.NoError(t, err)
- for _, host := range memcachedHosts {
- mc, err := memcache.New(host)
- assert.NoError(t, err)
- i, err := mc.Get(challengePath)
- assert.NoError(t, err)
- assert.Equal(t, i.Value, []byte(keyAuth))
- }
-}
-
-func TestMemcachedPresentPartialFailureMultiHost(t *testing.T) {
- if len(memcachedHosts) == 0 {
- t.Skip("Skipping memcached tests")
- }
- hosts := append(memcachedHosts, "5.5.5.5:11211")
- p, err := NewMemcachedProvider(hosts)
- assert.NoError(t, err)
-
- challengePath := path.Join("/", acme.HTTP01ChallengePath(token))
-
- err = p.Present(domain, token, keyAuth)
- assert.NoError(t, err)
- for _, host := range memcachedHosts {
- mc, err := memcache.New(host)
- assert.NoError(t, err)
- i, err := mc.Get(challengePath)
- assert.NoError(t, err)
- assert.Equal(t, i.Value, []byte(keyAuth))
- }
-}
-
-func TestMemcachedCleanup(t *testing.T) {
- if len(memcachedHosts) == 0 {
- t.Skip("Skipping memcached tests")
- }
- p, err := NewMemcachedProvider(memcachedHosts)
- assert.NoError(t, err)
- assert.NoError(t, p.CleanUp(domain, token, keyAuth))
-}
diff --git a/vendor/github.com/xenolf/lego/providers/http/webroot/webroot.go b/vendor/github.com/xenolf/lego/providers/http/webroot/webroot.go
deleted file mode 100644
index 4bf211f39..000000000
--- a/vendor/github.com/xenolf/lego/providers/http/webroot/webroot.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Package webroot implements a HTTP provider for solving the HTTP-01 challenge using web server's root path.
-package webroot
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path"
-
- "github.com/xenolf/lego/acme"
-)
-
-// HTTPProvider implements ChallengeProvider for `http-01` challenge
-type HTTPProvider struct {
- path string
-}
-
-// NewHTTPProvider returns a HTTPProvider instance with a configured webroot path
-func NewHTTPProvider(path string) (*HTTPProvider, error) {
- if _, err := os.Stat(path); os.IsNotExist(err) {
- return nil, fmt.Errorf("Webroot path does not exist")
- }
-
- c := &HTTPProvider{
- path: path,
- }
-
- return c, nil
-}
-
-// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path
-func (w *HTTPProvider) Present(domain, token, keyAuth string) error {
- var err error
-
- challengeFilePath := path.Join(w.path, acme.HTTP01ChallengePath(token))
- err = os.MkdirAll(path.Dir(challengeFilePath), 0755)
- if err != nil {
- return fmt.Errorf("Could not create required directories in webroot for HTTP challenge -> %v", err)
- }
-
- err = ioutil.WriteFile(challengeFilePath, []byte(keyAuth), 0644)
- if err != nil {
- return fmt.Errorf("Could not write file in webroot for HTTP challenge -> %v", err)
- }
-
- return nil
-}
-
-// CleanUp removes the file created for the challenge
-func (w *HTTPProvider) CleanUp(domain, token, keyAuth string) error {
- var err error
- err = os.Remove(path.Join(w.path, acme.HTTP01ChallengePath(token)))
- if err != nil {
- return fmt.Errorf("Could not remove file in webroot after HTTP challenge -> %v", err)
- }
-
- return nil
-}
diff --git a/vendor/github.com/xenolf/lego/providers/http/webroot/webroot_test.go b/vendor/github.com/xenolf/lego/providers/http/webroot/webroot_test.go
deleted file mode 100644
index 99c930ed3..000000000
--- a/vendor/github.com/xenolf/lego/providers/http/webroot/webroot_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package webroot
-
-import (
- "io/ioutil"
- "os"
- "testing"
-)
-
-func TestHTTPProvider(t *testing.T) {
- webroot := "webroot"
- domain := "domain"
- token := "token"
- keyAuth := "keyAuth"
- challengeFilePath := webroot + "/.well-known/acme-challenge/" + token
-
- os.MkdirAll(webroot+"/.well-known/acme-challenge", 0777)
- defer os.RemoveAll(webroot)
-
- provider, err := NewHTTPProvider(webroot)
- if err != nil {
- t.Errorf("Webroot provider error: got %v, want nil", err)
- }
-
- err = provider.Present(domain, token, keyAuth)
- if err != nil {
- t.Errorf("Webroot provider present() error: got %v, want nil", err)
- }
-
- if _, err := os.Stat(challengeFilePath); os.IsNotExist(err) {
- t.Error("Challenge file was not created in webroot")
- }
-
- data, err := ioutil.ReadFile(challengeFilePath)
- if err != nil {
- t.Errorf("Webroot provider ReadFile() error: got %v, want nil", err)
- }
- dataStr := string(data)
- if dataStr != keyAuth {
- t.Errorf("Challenge file content: got %q, want %q", dataStr, keyAuth)
- }
-
- err = provider.CleanUp(domain, token, keyAuth)
- if err != nil {
- t.Errorf("Webroot provider CleanUp() error: got %v, want nil", err)
- }
-}