Update lego.
This commit is contained in:
parent
63c3ed3931
commit
0034bef6b9
27 changed files with 1663 additions and 14 deletions
2
vendor/github.com/go-acme/lego/acme/api/internal/sender/useragent.go
generated
vendored
2
vendor/github.com/go-acme/lego/acme/api/internal/sender/useragent.go
generated
vendored
|
@ -5,7 +5,7 @@ package sender
|
|||
|
||||
const (
|
||||
// ourUserAgent is the User-Agent of this underlying library package.
|
||||
ourUserAgent = "xenolf-acme/2.5.0"
|
||||
ourUserAgent = "xenolf-acme/2.6.0"
|
||||
|
||||
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
|
||||
// values: detach|release
|
||||
|
|
27
vendor/github.com/go-acme/lego/certificate/certificates.go
generated
vendored
27
vendor/github.com/go-acme/lego/certificate/certificates.go
generated
vendored
|
@ -464,6 +464,33 @@ func (c *Certifier) GetOCSP(bundle []byte) ([]byte, *ocsp.Response, error) {
|
|||
return ocspResBytes, ocspRes, nil
|
||||
}
|
||||
|
||||
// Get attempts to fetch the certificate at the supplied URL.
|
||||
// The URL is the same as what would normally be supplied at the Resource's CertURL.
|
||||
//
|
||||
// The returned Resource will not have the PrivateKey and CSR fields populated as these will not be available.
|
||||
//
|
||||
// If bundle is true, the Certificate field in the returned Resource includes the issuer certificate.
|
||||
func (c *Certifier) Get(url string, bundle bool) (*Resource, error) {
|
||||
cert, issuer, err := c.core.Certificates.Get(url, bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse the returned cert bundle so that we can grab the domain from the common name.
|
||||
x509Certs, err := certcrypto.ParsePEMBundle(cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Resource{
|
||||
Domain: x509Certs[0].Subject.CommonName,
|
||||
Certificate: cert,
|
||||
IssuerCertificate: issuer,
|
||||
CertURL: url,
|
||||
CertStableURL: url,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func checkOrderStatus(order acme.Order) (bool, error) {
|
||||
switch order.Status {
|
||||
case acme.StatusValid:
|
||||
|
|
7
vendor/github.com/go-acme/lego/challenge/dns01/dns_challenge_manual.go
generated
vendored
7
vendor/github.com/go-acme/lego/challenge/dns01/dns_challenge_manual.go
generated
vendored
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -50,3 +51,9 @@ func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sequential All DNS challenges for this provider will be resolved sequentially.
|
||||
// Returns the interval between each iteration.
|
||||
func (d *DNSProviderManual) Sequential() time.Duration {
|
||||
return DefaultPropagationTimeout
|
||||
}
|
||||
|
|
2
vendor/github.com/go-acme/lego/platform/config/env/env.go
generated
vendored
2
vendor/github.com/go-acme/lego/platform/config/env/env.go
generated
vendored
|
@ -159,5 +159,5 @@ func GetOrFile(envVar string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
return string(fileContents)
|
||||
return strings.TrimSuffix(string(fileContents), "\n")
|
||||
}
|
||||
|
|
99
vendor/github.com/go-acme/lego/providers/dns/bindman/bindman.go
generated
vendored
Normal file
99
vendor/github.com/go-acme/lego/providers/dns/bindman/bindman.go
generated
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
// Package bindman implements a DNS provider for solving the DNS-01 challenge.
|
||||
package bindman
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/challenge/dns01"
|
||||
"github.com/go-acme/lego/platform/config/env"
|
||||
"github.com/labbsr0x/bindman-dns-webhook/src/client"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider
|
||||
type Config struct {
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
BaseURL string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
PropagationTimeout: env.GetOrDefaultSecond("BINDMAN_PROPAGATION_TIMEOUT", dns01.DefaultPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond("BINDMAN_POLLING_INTERVAL", dns01.DefaultPollingInterval),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond("BINDMAN_HTTP_TIMEOUT", time.Minute),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
|
||||
// Bindman's Address Manager REST API to manage TXT records for a domain.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *client.DNSWebhookClient
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Bindman.
|
||||
// BINDMAN_MANAGER_ADDRESS should have the scheme, hostname, and port (if required) of the authoritative Bindman Manager server.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get("BINDMAN_MANAGER_ADDRESS")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bindman: %v", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.BaseURL = values["BINDMAN_MANAGER_ADDRESS"]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider instance configured for Bindman.
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("bindman: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.BaseURL == "" {
|
||||
return nil, fmt.Errorf("bindman: bindman manager address missing")
|
||||
}
|
||||
|
||||
bClient, err := client.New(config.BaseURL, config.HTTPClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bindman: %v", err)
|
||||
}
|
||||
|
||||
return &DNSProvider{config: config, client: bClient}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters.
|
||||
// This will *not* create a subzone to contain the TXT record,
|
||||
// so make sure the FQDN specified is within an extant zone.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
if err := d.client.AddRecord(fqdn, "TXT", value); err != nil {
|
||||
return fmt.Errorf("bindman: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
if err := d.client.RemoveRecord(fqdn, "TXT"); err != nil {
|
||||
return fmt.Errorf("bindman: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
// Adjusting here to cope with spikes in propagation times.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
6
vendor/github.com/go-acme/lego/providers/dns/digitalocean/client.go
generated
vendored
6
vendor/github.com/go-acme/lego/providers/dns/digitalocean/client.go
generated
vendored
|
@ -57,10 +57,10 @@ func (d *DNSProvider) removeTxtRecord(domain string, recordID int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addTxtRecord(domain, fqdn, value string) (*txtRecordResponse, error) {
|
||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
||||
func (d *DNSProvider) addTxtRecord(fqdn, value string) (*txtRecordResponse, error) {
|
||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(fqdn))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine zone for domain: '%s'. %s", domain, err)
|
||||
return nil, fmt.Errorf("could not determine zone for domain: '%s'. %s", fqdn, err)
|
||||
}
|
||||
|
||||
reqData := record{Type: "TXT", Name: fqdn, Data: value, TTL: d.config.TTL}
|
||||
|
|
9
vendor/github.com/go-acme/lego/providers/dns/digitalocean/digitalocean.go
generated
vendored
9
vendor/github.com/go-acme/lego/providers/dns/digitalocean/digitalocean.go
generated
vendored
|
@ -88,7 +88,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
|||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
respData, err := d.addTxtRecord(domain, fqdn, value)
|
||||
respData, err := d.addTxtRecord(fqdn, value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("digitalocean: %v", err)
|
||||
}
|
||||
|
@ -104,6 +104,11 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("digitalocean: %v", err)
|
||||
}
|
||||
|
||||
// get the record's unique ID from when we created it
|
||||
d.recordIDsMu.Lock()
|
||||
recordID, ok := d.recordIDs[fqdn]
|
||||
|
@ -112,7 +117,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return fmt.Errorf("digitalocean: unknown record ID for '%s'", fqdn)
|
||||
}
|
||||
|
||||
err := d.removeTxtRecord(domain, recordID)
|
||||
err = d.removeTxtRecord(authZone, recordID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("digitalocean: %v", err)
|
||||
}
|
||||
|
|
9
vendor/github.com/go-acme/lego/providers/dns/dns_providers.go
generated
vendored
9
vendor/github.com/go-acme/lego/providers/dns/dns_providers.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/go-acme/lego/providers/dns/alidns"
|
||||
"github.com/go-acme/lego/providers/dns/auroradns"
|
||||
"github.com/go-acme/lego/providers/dns/azure"
|
||||
"github.com/go-acme/lego/providers/dns/bindman"
|
||||
"github.com/go-acme/lego/providers/dns/bluecat"
|
||||
"github.com/go-acme/lego/providers/dns/cloudflare"
|
||||
"github.com/go-acme/lego/providers/dns/cloudns"
|
||||
|
@ -23,6 +24,7 @@ import (
|
|||
"github.com/go-acme/lego/providers/dns/dreamhost"
|
||||
"github.com/go-acme/lego/providers/dns/duckdns"
|
||||
"github.com/go-acme/lego/providers/dns/dyn"
|
||||
"github.com/go-acme/lego/providers/dns/easydns"
|
||||
"github.com/go-acme/lego/providers/dns/exec"
|
||||
"github.com/go-acme/lego/providers/dns/exoscale"
|
||||
"github.com/go-acme/lego/providers/dns/fastdns"
|
||||
|
@ -35,6 +37,7 @@ import (
|
|||
"github.com/go-acme/lego/providers/dns/httpreq"
|
||||
"github.com/go-acme/lego/providers/dns/iij"
|
||||
"github.com/go-acme/lego/providers/dns/inwx"
|
||||
"github.com/go-acme/lego/providers/dns/joker"
|
||||
"github.com/go-acme/lego/providers/dns/lightsail"
|
||||
"github.com/go-acme/lego/providers/dns/linode"
|
||||
"github.com/go-acme/lego/providers/dns/linodev4"
|
||||
|
@ -72,6 +75,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
|
|||
return azure.NewDNSProvider()
|
||||
case "auroradns":
|
||||
return auroradns.NewDNSProvider()
|
||||
case "bindman":
|
||||
return bindman.NewDNSProvider()
|
||||
case "bluecat":
|
||||
return bluecat.NewDNSProvider()
|
||||
case "cloudflare":
|
||||
|
@ -102,6 +107,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
|
|||
return dyn.NewDNSProvider()
|
||||
case "fastdns":
|
||||
return fastdns.NewDNSProvider()
|
||||
case "easydns":
|
||||
return easydns.NewDNSProvider()
|
||||
case "exec":
|
||||
return exec.NewDNSProvider()
|
||||
case "exoscale":
|
||||
|
@ -124,6 +131,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
|
|||
return iij.NewDNSProvider()
|
||||
case "inwx":
|
||||
return inwx.NewDNSProvider()
|
||||
case "joker":
|
||||
return joker.NewDNSProvider()
|
||||
case "lightsail":
|
||||
return lightsail.NewDNSProvider()
|
||||
case "linode":
|
||||
|
|
97
vendor/github.com/go-acme/lego/providers/dns/easydns/client.go
generated
vendored
Normal file
97
vendor/github.com/go-acme/lego/providers/dns/easydns/client.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
package easydns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
const defaultEndpoint = "https://rest.easydns.net"
|
||||
|
||||
type zoneRecord struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Domain string `json:"domain"`
|
||||
Host string `json:"host"`
|
||||
TTL string `json:"ttl"`
|
||||
Prio string `json:"prio"`
|
||||
Type string `json:"type"`
|
||||
Rdata string `json:"rdata"`
|
||||
LastMod string `json:"last_mod,omitempty"`
|
||||
Revoked int `json:"revoked,omitempty"`
|
||||
NewHost string `json:"new_host,omitempty"`
|
||||
}
|
||||
|
||||
type addRecordResponse struct {
|
||||
Msg string `json:"msg"`
|
||||
Tm int `json:"tm"`
|
||||
Data zoneRecord `json:"data"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addRecord(domain string, record interface{}) (string, error) {
|
||||
pathAdd := path.Join("/zones/records/add", domain, "TXT")
|
||||
|
||||
response := &addRecordResponse{}
|
||||
err := d.doRequest(http.MethodPut, pathAdd, record, response)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
recordID := response.Data.ID
|
||||
|
||||
return recordID, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) deleteRecord(domain, recordID string) error {
|
||||
pathDelete := path.Join("/zones/records", domain, recordID)
|
||||
|
||||
return d.doRequest(http.MethodDelete, pathDelete, nil, nil)
|
||||
}
|
||||
|
||||
func (d *DNSProvider) doRequest(method, path string, requestMsg, responseMsg interface{}) error {
|
||||
reqBody := &bytes.Buffer{}
|
||||
if requestMsg != nil {
|
||||
err := json.NewEncoder(reqBody).Encode(requestMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
endpoint, err := d.config.Endpoint.Parse(path + "?format=json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request, err := http.NewRequest(method, endpoint.String(), reqBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
request.Header.Set("Accept", "application/json")
|
||||
request.SetBasicAuth(d.config.Token, d.config.Key)
|
||||
|
||||
response, err := d.config.HTTPClient.Do(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode >= http.StatusBadRequest {
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%d: failed to read response body: %v", response.StatusCode, err)
|
||||
}
|
||||
|
||||
return fmt.Errorf("%d: request failed: %v", response.StatusCode, string(body))
|
||||
}
|
||||
|
||||
if responseMsg != nil {
|
||||
return json.NewDecoder(response.Body).Decode(responseMsg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
165
vendor/github.com/go-acme/lego/providers/dns/easydns/easydns.go
generated
vendored
Normal file
165
vendor/github.com/go-acme/lego/providers/dns/easydns/easydns.go
generated
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Package easydns implements a DNS provider for solving the DNS-01 challenge using EasyDNS API.
|
||||
package easydns
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
|
||||
"github.com/go-acme/lego/challenge/dns01"
|
||||
"github.com/go-acme/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider
|
||||
type Config struct {
|
||||
Endpoint *url.URL
|
||||
Token string
|
||||
Key string
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
SequenceInterval time.Duration
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
PropagationTimeout: env.GetOrDefaultSecond("EASYDNS_PROPAGATION_TIMEOUT", dns01.DefaultPropagationTimeout),
|
||||
SequenceInterval: env.GetOrDefaultSecond("EASYDNS_SEQUENCE_INTERVAL", dns01.DefaultPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond("EASYDNS_POLLING_INTERVAL", dns01.DefaultPollingInterval),
|
||||
TTL: env.GetOrDefaultInt("EASYDNS_TTL", dns01.DefaultTTL),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond("EASYDNS_HTTP_TIMEOUT", 30*time.Second),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider describes a provider for acme-proxy
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
recordIDs map[string]string
|
||||
recordIDsMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
config := NewDefaultConfig()
|
||||
|
||||
endpoint, err := url.Parse(env.GetOrDefaultString("EASYDNS_ENDPOINT", defaultEndpoint))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("easydns: %v", err)
|
||||
}
|
||||
config.Endpoint = endpoint
|
||||
|
||||
values, err := env.Get("EASYDNS_TOKEN", "EASYDNS_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("easydns: %v", err)
|
||||
}
|
||||
|
||||
config.Token = values["EASYDNS_TOKEN"]
|
||||
config.Key = values["EASYDNS_KEY"]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider .
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("easydns: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.Token == "" {
|
||||
return nil, errors.New("easydns: the API token is missing")
|
||||
}
|
||||
|
||||
if config.Key == "" {
|
||||
return nil, errors.New("easydns: the API key is missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{config: config, recordIDs: map[string]string{}}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfill the dns-01 challenge
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
apiHost, apiDomain := splitFqdn(fqdn)
|
||||
record := &zoneRecord{
|
||||
Domain: apiDomain,
|
||||
Host: apiHost,
|
||||
Type: "TXT",
|
||||
Rdata: value,
|
||||
TTL: strconv.Itoa(d.config.TTL),
|
||||
Prio: "0",
|
||||
}
|
||||
|
||||
recordID, err := d.addRecord(apiDomain, record)
|
||||
if err != nil {
|
||||
return fmt.Errorf("easydns: error adding zone record: %v", err)
|
||||
}
|
||||
|
||||
key := getMapKey(fqdn, value)
|
||||
|
||||
d.recordIDsMu.Lock()
|
||||
d.recordIDs[key] = recordID
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, challenge := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
key := getMapKey(fqdn, challenge)
|
||||
recordID, exists := d.recordIDs[key]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, apiDomain := splitFqdn(fqdn)
|
||||
err := d.deleteRecord(apiDomain, recordID)
|
||||
|
||||
d.recordIDsMu.Lock()
|
||||
defer delete(d.recordIDs, key)
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("easydns: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
// Adjusting here to cope with spikes in propagation times.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
// Sequential All DNS challenges for this provider will be resolved sequentially.
|
||||
// Returns the interval between each iteration.
|
||||
func (d *DNSProvider) Sequential() time.Duration {
|
||||
return d.config.SequenceInterval
|
||||
}
|
||||
|
||||
func splitFqdn(fqdn string) (host, domain string) {
|
||||
parts := dns.SplitDomainName(fqdn)
|
||||
length := len(parts)
|
||||
|
||||
host = strings.Join(parts[0:length-2], ".")
|
||||
domain = strings.Join(parts[length-2:length], ".")
|
||||
return
|
||||
}
|
||||
|
||||
func getMapKey(fqdn, value string) string {
|
||||
return fqdn + "|" + value
|
||||
}
|
6
vendor/github.com/go-acme/lego/providers/dns/exec/exec.go
generated
vendored
6
vendor/github.com/go-acme/lego/providers/dns/exec/exec.go
generated
vendored
|
@ -105,3 +105,9 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
// Sequential All DNS challenges for this provider will be resolved sequentially.
|
||||
// Returns the interval between each iteration.
|
||||
func (d *DNSProvider) Sequential() time.Duration {
|
||||
return d.config.PropagationTimeout
|
||||
}
|
||||
|
|
6
vendor/github.com/go-acme/lego/providers/dns/gcloud/googlecloud.go
generated
vendored
6
vendor/github.com/go-acme/lego/providers/dns/gcloud/googlecloud.go
generated
vendored
|
@ -156,7 +156,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
|||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
zone, err := d.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("googlecloud: %v", err)
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ func (d *DNSProvider) applyChanges(zone string, change *dns.Change) error {
|
|||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
zone, err := d.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("googlecloud: %v", err)
|
||||
}
|
||||
|
@ -311,7 +311,7 @@ func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
|||
}
|
||||
|
||||
for _, z := range zones.ManagedZones {
|
||||
if z.Visibility == "public" {
|
||||
if z.Visibility == "public" || z.Visibility == "" {
|
||||
return z.Name, nil
|
||||
}
|
||||
}
|
||||
|
|
197
vendor/github.com/go-acme/lego/providers/dns/joker/client.go
generated
vendored
Normal file
197
vendor/github.com/go-acme/lego/providers/dns/joker/client.go
generated
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
package joker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-acme/lego/challenge/dns01"
|
||||
"github.com/go-acme/lego/log"
|
||||
)
|
||||
|
||||
const defaultBaseURL = "https://dmapi.joker.com/request/"
|
||||
|
||||
// Joker DMAPI Response
|
||||
type response struct {
|
||||
Headers url.Values
|
||||
Body string
|
||||
StatusCode int
|
||||
StatusText string
|
||||
AuthSid string
|
||||
}
|
||||
|
||||
// parseResponse parses HTTP response body
|
||||
func parseResponse(message string) *response {
|
||||
r := &response{Headers: url.Values{}, StatusCode: -1}
|
||||
|
||||
parts := strings.SplitN(message, "\n\n", 2)
|
||||
|
||||
for _, line := range strings.Split(parts[0], "\n") {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
kv := strings.SplitN(line, ":", 2)
|
||||
|
||||
val := ""
|
||||
if len(kv) == 2 {
|
||||
val = strings.TrimSpace(kv[1])
|
||||
}
|
||||
|
||||
r.Headers.Add(kv[0], val)
|
||||
|
||||
switch kv[0] {
|
||||
case "Status-Code":
|
||||
i, err := strconv.Atoi(val)
|
||||
if err == nil {
|
||||
r.StatusCode = i
|
||||
}
|
||||
case "Status-Text":
|
||||
r.StatusText = val
|
||||
case "Auth-Sid":
|
||||
r.AuthSid = val
|
||||
}
|
||||
}
|
||||
|
||||
if len(parts) > 1 {
|
||||
r.Body = parts[1]
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// login performs a login to Joker's DMAPI
|
||||
func (d *DNSProvider) login() (*response, error) {
|
||||
if d.config.AuthSid != "" {
|
||||
// already logged in
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
response, err := d.postRequest("login", url.Values{"api-key": {d.config.APIKey}})
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
return nil, fmt.Errorf("login returned nil response")
|
||||
}
|
||||
|
||||
if response.AuthSid == "" {
|
||||
return response, fmt.Errorf("login did not return valid Auth-Sid")
|
||||
}
|
||||
|
||||
d.config.AuthSid = response.AuthSid
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// logout closes authenticated session with Joker's DMAPI
|
||||
func (d *DNSProvider) logout() (*response, error) {
|
||||
if d.config.AuthSid == "" {
|
||||
return nil, fmt.Errorf("already logged out")
|
||||
}
|
||||
|
||||
response, err := d.postRequest("logout", url.Values{})
|
||||
if err == nil {
|
||||
d.config.AuthSid = ""
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
// getZone returns content of DNS zone for domain
|
||||
func (d *DNSProvider) getZone(domain string) (*response, error) {
|
||||
if d.config.AuthSid == "" {
|
||||
return nil, fmt.Errorf("must be logged in to get zone")
|
||||
}
|
||||
|
||||
return d.postRequest("dns-zone-get", url.Values{"domain": {dns01.UnFqdn(domain)}})
|
||||
}
|
||||
|
||||
// putZone uploads DNS zone to Joker DMAPI
|
||||
func (d *DNSProvider) putZone(domain, zone string) (*response, error) {
|
||||
if d.config.AuthSid == "" {
|
||||
return nil, fmt.Errorf("must be logged in to put zone")
|
||||
}
|
||||
|
||||
return d.postRequest("dns-zone-put", url.Values{"domain": {dns01.UnFqdn(domain)}, "zone": {strings.TrimSpace(zone)}})
|
||||
}
|
||||
|
||||
// postRequest performs actual HTTP request
|
||||
func (d *DNSProvider) postRequest(cmd string, data url.Values) (*response, error) {
|
||||
uri := d.config.BaseURL + cmd
|
||||
|
||||
if d.config.AuthSid != "" {
|
||||
data.Set("auth-sid", d.config.AuthSid)
|
||||
}
|
||||
|
||||
if d.config.Debug {
|
||||
log.Infof("postRequest:\n\tURL: %q\n\tData: %v", uri, data)
|
||||
}
|
||||
|
||||
resp, err := d.config.HTTPClient.PostForm(uri, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("HTTP error %d [%s]: %v", resp.StatusCode, http.StatusText(resp.StatusCode), string(body))
|
||||
}
|
||||
|
||||
return parseResponse(string(body)), nil
|
||||
}
|
||||
|
||||
// Temporary workaround, until it get fixed on API side
|
||||
func fixTxtLines(line string) string {
|
||||
fields := strings.Fields(line)
|
||||
|
||||
if len(fields) < 6 || fields[1] != "TXT" {
|
||||
return line
|
||||
}
|
||||
|
||||
if fields[3][0] == '"' && fields[4] == `"` {
|
||||
fields[3] = strings.TrimSpace(fields[3]) + `"`
|
||||
fields = append(fields[:4], fields[5:]...)
|
||||
}
|
||||
|
||||
return strings.Join(fields, " ")
|
||||
}
|
||||
|
||||
// removeTxtEntryFromZone clean-ups all TXT records with given name
|
||||
func removeTxtEntryFromZone(zone, relative string) (string, bool) {
|
||||
prefix := fmt.Sprintf("%s TXT 0 ", relative)
|
||||
|
||||
modified := false
|
||||
var zoneEntries []string
|
||||
for _, line := range strings.Split(zone, "\n") {
|
||||
if strings.HasPrefix(line, prefix) {
|
||||
modified = true
|
||||
continue
|
||||
}
|
||||
zoneEntries = append(zoneEntries, line)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(strings.Join(zoneEntries, "\n")), modified
|
||||
}
|
||||
|
||||
// addTxtEntryToZone returns DNS zone with added TXT record
|
||||
func addTxtEntryToZone(zone, relative, value string, ttl int) string {
|
||||
var zoneEntries []string
|
||||
|
||||
for _, line := range strings.Split(zone, "\n") {
|
||||
zoneEntries = append(zoneEntries, fixTxtLines(line))
|
||||
}
|
||||
|
||||
newZoneEntry := fmt.Sprintf("%s TXT 0 %q %d", relative, value, ttl)
|
||||
zoneEntries = append(zoneEntries, newZoneEntry)
|
||||
|
||||
return strings.TrimSpace(strings.Join(zoneEntries, "\n"))
|
||||
}
|
174
vendor/github.com/go-acme/lego/providers/dns/joker/joker.go
generated
vendored
Normal file
174
vendor/github.com/go-acme/lego/providers/dns/joker/joker.go
generated
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
// Package joker implements a DNS provider for solving the DNS-01 challenge using joker.com DMAPI.
|
||||
package joker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/challenge/dns01"
|
||||
"github.com/go-acme/lego/log"
|
||||
"github.com/go-acme/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
Debug bool
|
||||
BaseURL string
|
||||
APIKey string
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
AuthSid string
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
BaseURL: defaultBaseURL,
|
||||
Debug: env.GetOrDefaultBool("JOKER_DEBUG", false),
|
||||
TTL: env.GetOrDefaultInt("JOKER_TTL", dns01.DefaultTTL),
|
||||
PropagationTimeout: env.GetOrDefaultSecond("JOKER_PROPAGATION_TIMEOUT", dns01.DefaultPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond("JOKER_POLLING_INTERVAL", dns01.DefaultPollingInterval),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond("JOKER_HTTP_TIMEOUT", 60*time.Second),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider is an implementation of the ChallengeProviderTimeout interface
|
||||
// that uses Joker's DMAPI to manage TXT records for a domain.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Joker DMAPI.
|
||||
// Credentials must be passed in the environment variable JOKER_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get("JOKER_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("joker: %v", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.APIKey = values["JOKER_API_KEY"]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider instance configured for Joker DMAPI.
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("joker: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.APIKey == "" {
|
||||
return nil, fmt.Errorf("joker: credentials missing")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(config.BaseURL, "/") {
|
||||
config.BaseURL += "/"
|
||||
}
|
||||
|
||||
return &DNSProvider{config: config}, nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
// Present installs a TXT record for the DNS challenge.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
zone, err := dns01.FindZoneByFqdn(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("joker: %v", err)
|
||||
}
|
||||
|
||||
relative := getRelative(fqdn, zone)
|
||||
|
||||
if d.config.Debug {
|
||||
log.Infof("[%s] joker: adding TXT record %q to zone %q with value %q", domain, relative, zone, value)
|
||||
}
|
||||
|
||||
response, err := d.login()
|
||||
if err != nil {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
|
||||
response, err = d.getZone(zone)
|
||||
if err != nil || response.StatusCode != 0 {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
|
||||
dnsZone := addTxtEntryToZone(response.Body, relative, value, d.config.TTL)
|
||||
|
||||
response, err = d.putZone(zone, dnsZone)
|
||||
if err != nil || response.StatusCode != 0 {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes a TXT record used for a previous DNS challenge.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
zone, err := dns01.FindZoneByFqdn(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("joker: %v", err)
|
||||
}
|
||||
|
||||
relative := getRelative(fqdn, zone)
|
||||
|
||||
if d.config.Debug {
|
||||
log.Infof("[%s] joker: removing entry %q from zone %q", domain, relative, zone)
|
||||
}
|
||||
|
||||
response, err := d.login()
|
||||
if err != nil {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// Try to logout in case of errors
|
||||
_, _ = d.logout()
|
||||
}()
|
||||
|
||||
response, err = d.getZone(zone)
|
||||
if err != nil || response.StatusCode != 0 {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
|
||||
dnsZone, modified := removeTxtEntryFromZone(response.Body, relative)
|
||||
if modified {
|
||||
response, err = d.putZone(zone, dnsZone)
|
||||
if err != nil || response.StatusCode != 0 {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
}
|
||||
|
||||
response, err = d.logout()
|
||||
if err != nil {
|
||||
return formatResponseError(response, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRelative(fqdn, zone string) string {
|
||||
return dns01.UnFqdn(strings.TrimSuffix(fqdn, dns01.ToFqdn(zone)))
|
||||
}
|
||||
|
||||
// formatResponseError formats error with optional details from DMAPI response
|
||||
func formatResponseError(response *response, err error) error {
|
||||
if response != nil {
|
||||
return fmt.Errorf("joker: DMAPI error: %v Response: %v", err, response.Headers)
|
||||
}
|
||||
return fmt.Errorf("joker: DMAPI error: %v", err)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue