From adc8afbb8989b8fca2fee60804c70635d3bd99a2 Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Fri, 29 Jan 2016 23:47:56 +0100 Subject: [PATCH 1/3] Update the path to the go lib --- acme/dns_challenge_dnsimple.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/dns_challenge_dnsimple.go b/acme/dns_challenge_dnsimple.go index 713f6ea4..85eb66d4 100644 --- a/acme/dns_challenge_dnsimple.go +++ b/acme/dns_challenge_dnsimple.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "github.com/weppos/go-dnsimple/dnsimple" + "github.com/weppos/dnsimple-go/dnsimple" ) // DNSProviderDNSimple is an implementation of the DNSProvider interface. From 753f9ca798944de5b330672a34c3adb319ff8010 Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Sat, 30 Jan 2016 00:03:50 +0100 Subject: [PATCH 2/3] DNSimpleProvider: Fix bug with subdomains When requesting a certificate for a subdomain, the DNS record was attached to the domain instead. E.g. Requested: ww1.example.com Created: _acme-challenge.example.com instead of _acme-challenge.ww1.example.com --- acme/dns_challenge_dnsimple.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/acme/dns_challenge_dnsimple.go b/acme/dns_challenge_dnsimple.go index 85eb66d4..977188a9 100644 --- a/acme/dns_challenge_dnsimple.go +++ b/acme/dns_challenge_dnsimple.go @@ -35,12 +35,12 @@ func NewDNSProviderDNSimple(dnsimpleEmail, dnsimpleApiKey string) (*DNSProviderD func (c *DNSProviderDNSimple) Present(domain, token, keyAuth string) error { fqdn, value, ttl := DNS01Record(domain, keyAuth) - zoneID, err := c.getHostedZoneID(domain) + zoneID, zoneName, err := c.getHostedZone(domain) if err != nil { return err } - recordAttributes := c.newTxtRecord(domain, fqdn, value, ttl) + recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl) _, _, err = c.client.Domains.CreateRecord(zoneID, *recordAttributes) if err != nil { return fmt.Errorf("DNSimple API call failed: %v", err) @@ -67,10 +67,10 @@ func (c *DNSProviderDNSimple) CleanUp(domain, token, keyAuth string) error { return nil } -func (c *DNSProviderDNSimple) getHostedZoneID(domain string) (string, error) { +func (c *DNSProviderDNSimple) getHostedZone(domain string) (string, string, error) { domains, _, err := c.client.Domains.List() if err != nil { - return "", fmt.Errorf("DNSimple API call failed: %v", err) + return "", "", fmt.Errorf("DNSimple API call failed: %v", err) } var hostedDomain dnsimple.Domain @@ -82,14 +82,14 @@ func (c *DNSProviderDNSimple) getHostedZoneID(domain string) (string, error) { } } if hostedDomain.Id == 0 { - return "", fmt.Errorf("No matching DNSimple domain found for domain %s", domain) + return "", "", fmt.Errorf("No matching DNSimple domain found for domain %s", domain) } - return fmt.Sprintf("%v", hostedDomain.Id), nil + return fmt.Sprintf("%v", hostedDomain.Id), hostedDomain.Name, nil } func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]*dnsimple.Record, error) { - zoneID, err := c.getHostedZoneID(domain) + zoneID, zoneName, err := c.getHostedZone(domain) if err != nil { return nil, err } @@ -100,7 +100,7 @@ func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]*dnsimple.R return records, fmt.Errorf("DNSimple API call has failed: %v", err) } - recordName := c.extractRecordName(fqdn, domain) + recordName := c.extractRecordName(fqdn, zoneName) for _, record := range result { if record.Name == recordName { records = append(records, &record) @@ -110,8 +110,8 @@ func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]*dnsimple.R return records, nil } -func (c *DNSProviderDNSimple) newTxtRecord(domain, fqdn, value string, ttl int) *dnsimple.Record { - name := c.extractRecordName(fqdn, domain) +func (c *DNSProviderDNSimple) newTxtRecord(zone, fqdn, value string, ttl int) *dnsimple.Record { + name := c.extractRecordName(fqdn, zone) return &dnsimple.Record{ Type: "TXT", From 2e32f171d2f74b67d77a47d01e54e9c2ed321db5 Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Sat, 30 Jan 2016 22:14:29 +0100 Subject: [PATCH 3/3] DNSimpleProvider: Fix wrong record deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a very subtle bug. In some specific circumstances, when the list of domains in the SAN was > 1, the library may delete the wrong record (specifically the last one) instead of the matching one. The issue is explained here https://groups.google.com/forum/#!topic/golang-nuts/tlWzJUWJKgA Here's the output from one of the various tests ➜ lego git:(dnsimple-subdomain) ✗ DNSIMPLE_DOMAIN=simone.io go test -v ./... --run "TestLiveDNSimpleCleanUp" ? github.com/xenolf/lego [no test files] === RUN TestLiveDNSimpleCleanUp 2016/01/30 01:10:45 Empty records: 2016/01/30 01:10:45 0 2016/01/30 01:10:46 Fetched records: 2016/01/30 01:10:46 [{5326536 41571 v=spf1 a include:_spf.google.com ~all 3600 0 TXT 2016-01-26 12:53:42.85 +0000 UTC 2016-01-26 12:53:42.85 +0000 UTC} {5026157 41571 google-site-verification=obstZAG6j2BVxYg696WxAsC46_d1-bzkv7D0qGm4K_0 3600 0 TXT 2015-10-19 11:21:03.586 +0000 UTC 2015-10-19 11:21:03.586 +0000 UTC} {5340655 41571 _acme-challenge ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-29 23:52:15.657 +0000 UTC 2016-01-29 23:52:15.657 +0000 UTC} {5340677 41571 _acme-challenge.www1 ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-30 00:03:19.89 +0000 UTC 2016-01-30 00:03:19.89 +0000 UTC}] 2016/01/30 01:10:46 Record name: 2016/01/30 01:10:46 _acme-challenge 2016/01/30 01:10:46 {5326536 41571 v=spf1 a include:_spf.google.com ~all 3600 0 TXT 2016-01-26 12:53:42.85 +0000 UTC 2016-01-26 12:53:42.85 +0000 UTC} 2016/01/30 01:10:46 {5026157 41571 google-site-verification=obstZAG6j2BVxYg696WxAsC46_d1-bzkv7D0qGm4K_0 3600 0 TXT 2015-10-19 11:21:03.586 +0000 UTC 2015-10-19 11:21:03.586 +0000 UTC} 2016/01/30 01:10:46 {5340655 41571 _acme-challenge ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-29 23:52:15.657 +0000 UTC 2016-01-29 23:52:15.657 +0000 UTC} 2016/01/30 01:10:46 Deleted>> 2016/01/30 01:10:46 {5340655 41571 _acme-challenge ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-29 23:52:15.657 +0000 UTC 2016-01-29 23:52:15.657 +0000 UTC} 2016/01/30 01:10:46 >>Deleted 2016/01/30 01:10:46 {5340677 41571 _acme-challenge.www1 ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-30 00:03:19.89 +0000 UTC 2016-01-30 00:03:19.89 +0000 UTC} 2016/01/30 01:10:46 Record to delete: 2016/01/30 01:10:46 1 2016/01/30 01:10:46 {5340677 41571 _acme-challenge.www1 ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-30 00:03:19.89 +0000 UTC 2016-01-30 00:03:19.89 +0000 UTC} 2016/01/30 01:10:46 Record to delete (foos): 2016/01/30 01:10:46 [{5340655 41571 _acme-challenge ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-29 23:52:15.657 +0000 UTC 2016-01-29 23:52:15.657 +0000 UTC}] 2016/01/30 01:10:46 Found records to delete: 2016/01/30 01:10:46 1 2016/01/30 01:10:46 [0xc8203be240] 2016/01/30 01:10:46 &{5340677 41571 _acme-challenge.www1 ADw2sEd82DUgXcQ9hNBZThJs7zVJkR5v9JeSbAb9mZY 120 0 TXT 2016-01-30 00:03:19.89 +0000 UTC 2016-01-30 00:03:19.89 +0000 UTC} --- PASS: TestLiveDNSimpleCleanUp (3.10s) PASS ok github.com/xenolf/lego/acme 3.121s The record 5340655 was supposed to be deleted, but 5340677 was deleted instead (notice how the deleted record was always the last one in the returned record set). And of course the validation never passed ➜ letsencrypt-dnsimple git:(master) go run main.go --user xxx --api-key "xxx" --email "xxx@gmail.com" simone.io,foo1.simone.io,foo2.simone.io,foo3.simone.io 2016/01/30 00:27:55 .data/users/xxx@gmail.com 2016/01/30 00:27:55 {xxx@gmail.com 0xc82009a300} 2016/01/30 00:27:56 [INFO] acme: Registering account for xxx@gmail.com 2016/01/30 00:27:57 &{{ 116016 {RSA xxx} [mailto:xxx@gmail.com] } https://acme-staging.api.letsencrypt.org/acme/reg/116016 https://acme-staging.api.letsencrypt.org/acme/new-authz https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf} 2016/01/30 00:27:58 [INFO][simone.io, foo1.simone.io, foo2.simone.io, foo3.simone.io] acme: Obtaining bundled SAN certificate 2016/01/30 00:27:59 [INFO][simone.io] acme: Could not find solver for: http-01 2016/01/30 00:27:59 [INFO][simone.io] acme: Trying to solve DNS-01 2016/01/30 00:28:00 simone.io 2016/01/30 00:28:00 &{0 0 _acme-challenge Uo7cIEDgw_sCgZhSOML_GU4DkKlgpB6p1Et8lxRVGLI 120 0 TXT } 2016/01/30 00:28:12 [INFO][simone.io] The server validated our request 2016/01/30 00:28:14 &{5340584 41571 _acme-challenge Uo7cIEDgw_sCgZhSOML_GU4DkKlgpB6p1Et8lxRVGLI 120 0 TXT 2016-01-29 23:28:00.828 +0000 UTC 2016-01-29 23:28:00.828 +0000 UTC} 2016/01/30 00:28:14 [INFO][foo1.simone.io] acme: Could not find solver for: http-01 2016/01/30 00:28:14 [INFO][foo1.simone.io] acme: Trying to solve DNS-01 2016/01/30 00:28:15 simone.io 2016/01/30 00:28:15 &{0 0 _acme-challenge.foo1 l_HB5ctb2M86FVcgpCaWgURVhCePNY9KIVQ0tsVH2Ew 120 0 TXT } 2016/01/30 00:28:19 &{5340585 41571 _acme-challenge.foo1 l_HB5ctb2M86FVcgpCaWgURVhCePNY9KIVQ0tsVH2Ew 120 0 TXT 2016-01-29 23:28:15.996 +0000 UTC 2016-01-29 23:28:15.996 +0000 UTC} 2016/01/30 00:28:19 [INFO][foo2.simone.io] acme: Could not find solver for: http-01 2016/01/30 00:28:19 [INFO][foo2.simone.io] acme: Could not find solver for: tls-sni-01 2016/01/30 00:28:19 [INFO][foo2.simone.io] acme: Trying to solve DNS-01 2016/01/30 00:28:20 simone.io 2016/01/30 00:28:20 &{0 0 _acme-challenge.foo2 rohi66Q0VHSEu0kR3LcGPkFEIftt47xHfeQercf8frU 120 0 TXT } 2016/01/30 00:28:22 [INFO][foo2.simone.io] The server validated our request 2016/01/30 00:28:23 &{5340586 41571 _acme-challenge.foo2 rohi66Q0VHSEu0kR3LcGPkFEIftt47xHfeQercf8frU 120 0 TXT 2016-01-29 23:28:21.051 +0000 UTC 2016-01-29 23:28:21.051 +0000 UTC} 2016/01/30 00:28:24 [INFO][foo3.simone.io] acme: Could not find solver for: tls-sni-01 2016/01/30 00:28:24 [INFO][foo3.simone.io] acme: Could not find solver for: http-01 2016/01/30 00:28:24 [INFO][foo3.simone.io] acme: Trying to solve DNS-01 2016/01/30 00:28:25 simone.io 2016/01/30 00:28:25 &{0 0 _acme-challenge.foo3 gmn1sKV_0gP3BiOT3yZQywZq95akKRGup0IJs1cqdVo 120 0 TXT } 2016/01/30 00:28:27 [INFO][foo3.simone.io] The server validated our request 2016/01/30 00:28:28 &{5340587 41571 _acme-challenge.foo3 gmn1sKV_0gP3BiOT3yZQywZq95akKRGup0IJs1cqdVo 120 0 TXT 2016-01-29 23:28:25.616 +0000 UTC 2016-01-29 23:28:25.616 +0000 UTC} 2016/01/30 00:28:28 map[foo1.simone.io:acme: Error 0 - urn:acme:error:connection - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.foo1.simone.io Error Detail: ] exit status 1 This is the result of the latest (successful) run: ➜ letsencrypt-dnsimple git:(master) ✗ go run main.go --user xxx --api-key "xxx" --email "xxx@gmail.com" simone.io,yy.simone.io,xx.simone.io 2016/01/30 21:34:01 .data/users/xxx@gmail.com 2016/01/30 21:34:01 {xxx@gmail.com 0xc820070480} 2016/01/30 21:34:02 [INFO] acme: Registering account for xxx@gmail.com 2016/01/30 21:34:03 &{{ 116199 {RSA xxx} [mailto:xxx@gmail.com] } https://acme-staging.api.letsencrypt.org/acme/reg/116199 https://acme-staging.api.letsencrypt.org/acme/new-authz https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf} 2016/01/30 21:34:03 [INFO][simone.io, yy.simone.io, xx.simone.io] acme: Obtaining bundled SAN certificate 2016/01/30 21:34:04 [INFO][simone.io] acme: Could not find solver for: tls-sni-01 2016/01/30 21:34:04 [INFO][simone.io] acme: Could not find solver for: http-01 2016/01/30 21:34:04 [INFO][simone.io] acme: Trying to solve DNS-01 2016/01/30 21:34:13 [INFO][simone.io] The server validated our request 2016/01/30 21:34:14 Searching for 2016/01/30 21:34:14 simone.io 2016/01/30 21:34:15 To delete: 2016/01/30 21:34:15 {5341831 41571 _acme-challenge TX8-77TN9XHZHO510Yw20u1j89UhdgGXcwScKZHRGNY 120 0 TXT 2016-01-30 20:34:05.859 +0000 UTC 2016-01-30 20:34:05.859 +0000 UTC} 2016/01/30 21:34:15 Will delete: 2016/01/30 21:34:15 [{5341831 41571 _acme-challenge TX8-77TN9XHZHO510Yw20u1j89UhdgGXcwScKZHRGNY 120 0 TXT 2016-01-30 20:34:05.859 +0000 UTC 2016-01-30 20:34:05.859 +0000 UTC}] 2016/01/30 21:34:15 [INFO][yy.simone.io] acme: Could not find solver for: http-01 2016/01/30 21:34:15 [INFO][yy.simone.io] acme: Could not find solver for: tls-sni-01 2016/01/30 21:34:15 [INFO][yy.simone.io] acme: Trying to solve DNS-01 2016/01/30 21:34:18 [INFO][yy.simone.io] The server validated our request 2016/01/30 21:34:19 Searching for 2016/01/30 21:34:19 yy.simone.io 2016/01/30 21:34:19 To delete: 2016/01/30 21:34:19 {5341832 41571 _acme-challenge.yy pHolYM_OqxCThmL3nBA91qRCI6-oEIMG0YOJj3R1Xww 120 0 TXT 2016-01-30 20:34:17.176 +0000 UTC 2016-01-30 20:34:17.176 +0000 UTC} 2016/01/30 21:34:19 Will delete: 2016/01/30 21:34:19 [{5341832 41571 _acme-challenge.yy pHolYM_OqxCThmL3nBA91qRCI6-oEIMG0YOJj3R1Xww 120 0 TXT 2016-01-30 20:34:17.176 +0000 UTC 2016-01-30 20:34:17.176 +0000 UTC}] 2016/01/30 21:34:20 [INFO][xx.simone.io] acme: Could not find solver for: tls-sni-01 2016/01/30 21:34:20 [INFO][xx.simone.io] acme: Trying to solve DNS-01 2016/01/30 21:34:23 [INFO][xx.simone.io] The server validated our request 2016/01/30 21:34:23 Searching for 2016/01/30 21:34:23 xx.simone.io 2016/01/30 21:34:24 To delete: 2016/01/30 21:34:24 {5341833 41571 _acme-challenge.xx LEr6l7KJCr6e7LlqyQgAbZbKCRmLFa5zNC8kNHK1FtQ 120 0 TXT 2016-01-30 20:34:21.793 +0000 UTC 2016-01-30 20:34:21.793 +0000 UTC} 2016/01/30 21:34:24 Will delete: 2016/01/30 21:34:24 [{5341833 41571 _acme-challenge.xx LEr6l7KJCr6e7LlqyQgAbZbKCRmLFa5zNC8kNHK1FtQ 120 0 TXT 2016-01-30 20:34:21.793 +0000 UTC 2016-01-30 20:34:21.793 +0000 UTC}] 2016/01/30 21:34:25 [INFO][simone.io, yy.simone.io, xx.simone.io] acme: Validations succeeded; requesting certificates 2016/01/30 21:34:26 [INFO] acme: Requesting issuer cert from https://acme-staging.api.letsencrypt.org/acme/issuer-cert 2016/01/30 21:34:26 [INFO][simone.io] Server responded with a certificate. [INFO][https://acme-staging.api.letsencrypt.org/acme/cert/fae971fcb1ce12 c4d3bb95a1f577786cccfe] Certificate simone.io, yy.simone.io, xx.simone.io2016/01/30 21:34:26 145 2016/01/30 21:34:26 .data/certs/1454186041 2016/01/30 21:34:26 completed! --- acme/dns_challenge_dnsimple.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acme/dns_challenge_dnsimple.go b/acme/dns_challenge_dnsimple.go index 977188a9..f22590c7 100644 --- a/acme/dns_challenge_dnsimple.go +++ b/acme/dns_challenge_dnsimple.go @@ -88,13 +88,13 @@ func (c *DNSProviderDNSimple) getHostedZone(domain string) (string, string, erro return fmt.Sprintf("%v", hostedDomain.Id), hostedDomain.Name, nil } -func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]*dnsimple.Record, error) { +func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]dnsimple.Record, error) { zoneID, zoneName, err := c.getHostedZone(domain) if err != nil { return nil, err } - var records []*dnsimple.Record + var records []dnsimple.Record result, _, err := c.client.Domains.ListRecords(zoneID, "", "TXT") if err != nil { return records, fmt.Errorf("DNSimple API call has failed: %v", err) @@ -103,7 +103,7 @@ func (c *DNSProviderDNSimple) findTxtRecords(domain, fqdn string) ([]*dnsimple.R recordName := c.extractRecordName(fqdn, zoneName) for _, record := range result { if record.Name == recordName { - records = append(records, &record) + records = append(records, record) } }