Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
caddytls: Finish upgrading to libdns DNS providers for ACME challenges
Until we finish the migration to the new acme library, we have to bring the solver type in-house. It's small and temporary.
Matthew Holt committed
May 2, 2020 at 17:23 UTC
8e4266106034819fa0f4be8f0efbd628eb3e1634
5 files changed
+142
-28
caddyconfig/httpcaddyfile/builtins.go
+1
-1
@@ -202,7 +202,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
202
acmeIssuer.CA = arg[0]
203
204
case "dns":
205
- if !h.Next() {
205
+ if !h.NextArg() {
206
return nil, h.ArgErr()
207
}
208
provName := h.Val()
go.mod
+3
-8
@@ -7,18 +7,15 @@ require (
7
github.com/alecthomas/chroma v0.7.2
8
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a
9
github.com/caddyserver/certmagic v0.10.12
10
- github.com/cenkalti/backoff/v4 v4.0.2 // indirect
10
github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac
11
github.com/go-acme/lego/v3 v3.6.0
12
github.com/gogo/protobuf v1.3.1
13
github.com/google/cel-go v0.4.1
15
- github.com/imdario/mergo v0.3.9 // indirect
14
github.com/jsternberg/zap-logfmt v1.2.0
15
github.com/klauspost/compress v1.10.4
16
github.com/klauspost/cpuid v1.2.3
17
+ github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821
18
github.com/lucas-clemente/quic-go v0.15.3
20
- github.com/manifoldco/promptui v0.7.0 // indirect
21
- github.com/miekg/dns v1.1.29 // indirect
19
github.com/naoina/go-stringutil v0.1.0 // indirect
20
github.com/naoina/toml v0.1.1
21
github.com/smallstep/certificates v0.14.2
@@ -27,11 +24,9 @@ require (
24
github.com/yuin/goldmark v1.1.28
25
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691
26
go.uber.org/zap v1.14.1
30
- golang.org/x/crypto v0.0.0-20200414155820-4f8f47aa7992
31
- golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
32
- golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
27
+ golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc
28
+ golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0
29
google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36
30
gopkg.in/natefinch/lumberjack.v2 v2.0.0
35
- gopkg.in/square/go-jose.v2 v2.5.0 // indirect
31
gopkg.in/yaml.v2 v2.2.8
32
)
go.sum
+10
-18
@@ -143,8 +143,6 @@ github.com/caddyserver/certmagic v0.10.12 h1:aZtgzcIssiMSlP0jDdpDBbBzQ5INf5eKL9T
143
github.com/caddyserver/certmagic v0.10.12/go.mod h1:Y8jcUBctgk/IhpAzlHKfimZNyXCkfGgRTC0orl8gROQ=
144
github.com/cenkalti/backoff/v4 v4.0.0 h1:6VeaLF9aI+MAUQ95106HwWzYZgJJpZ4stumjj6RFYAU=
145
github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
146
-github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs=
147
-github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
146
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
147
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
148
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -399,9 +397,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
397
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428/go.mod h1:uhpZMVGznybq1itEKXj6RYw9I71qK4kH+OGMjRC4KEo=
398
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
399
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
400
+github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
401
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
403
-github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
404
-github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
402
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
403
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
404
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@@ -459,6 +456,8 @@ github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c
456
github.com/letsencrypt/pkcs11key v2.0.1-0.20170608213348-396559074696+incompatible/go.mod h1:iGYXKqDXt0cpBthCHdr9ZdsQwyGlYFh/+8xa4WzIQ34=
457
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
458
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
459
+github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821 h1:663opx/RKxiISi1ozf0WbvweQpYBgf34dx8hKSIau3w=
460
+github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
461
github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jvM=
462
github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA=
463
github.com/liquidweb/liquidweb-go v1.6.0 h1:vIj1I/Wf97fUnyirD+bi6Y63c0GiXk9nKI1+sFFl3G0=
@@ -466,17 +465,14 @@ github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVL
465
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
466
github.com/lucas-clemente/quic-go v0.15.3 h1:i6n4Jr7673z9TlurAjc87+GlE/BN10++r9XZIPS9j6I=
467
github.com/lucas-clemente/quic-go v0.15.3/go.mod h1:oj40DjNLuNugvtXWg4PwaYgv7tAbzAabrT57CC69EhI=
469
-github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
470
-github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
468
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
469
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
470
github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
471
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
472
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
473
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
474
+github.com/manifoldco/promptui v0.3.1 h1:BxqNa7q1hVHXIXy3iupJMkXYS3aHhbubJWv2Jmg6x64=
475
github.com/manifoldco/promptui v0.3.1/go.mod h1:zoCNXiJnyM03LlBgTsWv8mq28s7aTC71UgKasqRJHww=
478
-github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4=
479
-github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
476
github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniNuVSVg=
477
github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
478
github.com/marten-seemann/qtls v0.9.0 h1:8Zguhc72eS+DH5EAb0BpAPIy3HDXYcihQi4xoDZOnjQ=
@@ -502,9 +498,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
498
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
499
github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI=
500
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
501
+github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
502
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
506
-github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=
507
-github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
503
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
504
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
505
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@@ -845,8 +840,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqp
840
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
841
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
842
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
848
-golang.org/x/crypto v0.0.0-20200414155820-4f8f47aa7992 h1:B4Wjn2mWOWzjcWfyRYlf00lQ1/9h5vRKmQnhIKhMFR0=
849
-golang.org/x/crypto v0.0.0-20200414155820-4f8f47aa7992/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
843
+golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc h1:ZGI/fILM2+ueot/UixBSoj9188jCAxVHEZEGhqq67I4=
844
+golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
845
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
846
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
847
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -918,8 +913,8 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
913
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
914
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
915
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
921
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
922
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
916
+golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
917
+golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
918
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
919
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
920
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -986,8 +981,6 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0
981
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
982
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
983
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
989
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
990
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
984
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
985
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
986
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1161,9 +1154,8 @@ gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=
1154
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
1155
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
1156
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
1157
+gopkg.in/square/go-jose.v2 v2.4.0 h1:0kXPskUMGAXXWJlP05ktEMOV0vmzFQUWw6d+aZJQU8A=
1158
gopkg.in/square/go-jose.v2 v2.4.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
1165
-gopkg.in/square/go-jose.v2 v2.5.0 h1:OZ4sdq+Y+SHfYB7vfthi1Ei8b0vkP8ZPQgUfUwdUSqo=
1166
-gopkg.in/square/go-jose.v2 v2.5.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
1159
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
1160
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
1161
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
modules/caddytls/acmeissuer.go
+15
-1
@@ -91,7 +91,21 @@ func (m *ACMEIssuer) Provision(ctx caddy.Context) error {
91
if err != nil {
92
return fmt.Errorf("loading DNS provider module: %v", err)
93
}
94
- m.Challenges.DNS.provider = val.(challenge.Provider)
94
+ // TODO: For a temporary amount of time, we are allowing the use of
95
+ // DNS providers from go-acme/lego since there are so many implemented
96
+ // for it -- they are adapted as Caddy modules in this repository:
97
+ // https://github.com/caddy-dns/lego-deprecated - that module is
98
+ // a challenge.Provider value, so we use it directly. The user must set
99
+ // environment variables to configure it. Remove this shim once a sufficient
100
+ // number of DNS providers are implemented for the libdns APIs instead.
101
+ if grandfatheredProvider, ok := val.(challenge.Provider); ok {
102
+ m.Challenges.DNS.provider = grandfatheredProvider
103
+ } else {
104
+ m.Challenges.DNS.provider = &solver{
105
+ recordManager: val.(recordManager),
106
+ TTL: time.Duration(m.Challenges.DNS.TTL),
107
+ }
108
+ }
109
}
110
111
// add any custom CAs to trust store
modules/caddytls/dnssolver.go
new
+113
@@ -0,0 +1,113 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddytls
16
+
17
+import (
18
+ "context"
19
+ "fmt"
20
+ "sync"
21
+ "time"
22
+
23
+ "github.com/go-acme/lego/v3/challenge"
24
+ "github.com/go-acme/lego/v3/challenge/dns01"
25
+ "github.com/libdns/libdns"
26
+)
27
+
28
+// TODO: this is borrowed from https://github.com/mholt/acme - once we
29
+// switch to that acme library, this file will go away
30
+
31
+// solver is a type that makes libdns providers usable as ACME challenge solvers.
32
+type solver struct {
33
+ recordManager
34
+
35
+ TTL time.Duration
36
+
37
+ txtRecords map[string]libdns.Record // keyed by challenge token
38
+ txtRecordsMu sync.Mutex
39
+}
40
+
41
+func (s *solver) Present(domain, token, keyAuth string) error {
42
+ fqdn, value := dns01.GetRecord(domain, keyAuth)
43
+
44
+ rec := libdns.Record{
45
+ Type: "TXT",
46
+ Name: fqdn,
47
+ Value: value,
48
+ TTL: s.TTL,
49
+ }
50
+
51
+ zone, err := dns01.FindZoneByFqdn(fqdn)
52
+ if err != nil {
53
+ return fmt.Errorf("could not determine zone for domain %q: %v", fqdn, err)
54
+ }
55
+
56
+ results, err := s.recordManager.AppendRecords(context.TODO(), zone, []libdns.Record{rec})
57
+ if err != nil {
58
+ return err
59
+ }
60
+ if len(results) != 1 {
61
+ return fmt.Errorf("expected one record, got %d: %v", len(results), results)
62
+ }
63
+
64
+ // keep this record handy so we can clean it up more efficiently
65
+ s.txtRecordsMu.Lock()
66
+ if s.txtRecords == nil {
67
+ s.txtRecords = make(map[string]libdns.Record)
68
+ }
69
+ s.txtRecords[keyAuth] = results[0]
70
+ s.txtRecordsMu.Unlock()
71
+
72
+ // TODO: check for record propagation before continuing (accordig to config)
73
+
74
+ return nil
75
+}
76
+
77
+func (s *solver) CleanUp(domain, token, keyAuth string) error {
78
+ fqdn, _ := dns01.GetRecord(domain, keyAuth)
79
+ authZone, err := dns01.FindZoneByFqdn(fqdn)
80
+ if err != nil {
81
+ return err
82
+ }
83
+
84
+ // retrieve the record we created
85
+ s.txtRecordsMu.Lock()
86
+ txtRec, ok := s.txtRecords[keyAuth]
87
+ if !ok {
88
+ s.txtRecordsMu.Unlock()
89
+ return fmt.Errorf("no memory of presenting a DNS record for %v", domain)
90
+ }
91
+ s.txtRecordsMu.Unlock()
92
+
93
+ // clean up the record
94
+ _, err = s.recordManager.DeleteRecords(context.TODO(), authZone, []libdns.Record{txtRec})
95
+ if err != nil {
96
+ return err
97
+ }
98
+
99
+ // once it has been successfully cleaned up, we can forget about it
100
+ s.txtRecordsMu.Lock()
101
+ delete(s.txtRecords, keyAuth)
102
+ s.txtRecordsMu.Unlock()
103
+
104
+ return nil
105
+}
106
+
107
+// recordManager defines the set of operations required for ACME challenges.
108
+type recordManager interface {
109
+ libdns.RecordAppender
110
+ libdns.RecordDeleter
111
+}
112
+
113
+var _ challenge.Provider = (*solver)(nil)