ACME TLS ALPN
This commit is contained in:
parent
17ad5153b8
commit
139f280f35
258 changed files with 25528 additions and 1516 deletions
2
vendor/github.com/xenolf/lego/acme/challenges.go
generated
vendored
2
vendor/github.com/xenolf/lego/acme/challenges.go
generated
vendored
|
@ -10,4 +10,6 @@ const (
|
|||
// 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")
|
||||
// TLSALPN01 is the "tls-alpn-01" ACME challenge https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01
|
||||
TLSALPN01 = Challenge("tls-alpn-01")
|
||||
)
|
||||
|
|
145
vendor/github.com/xenolf/lego/acme/client.go
generated
vendored
145
vendor/github.com/xenolf/lego/acme/client.go
generated
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -81,8 +82,10 @@ func NewClient(caDirURL string, user User, keyType KeyType) (*Client, error) {
|
|||
// 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 := map[Challenge]solver{
|
||||
HTTP01: &httpChallenge{jws: jws, validate: validate, provider: &HTTPProviderServer{}},
|
||||
TLSALPN01: &tlsALPNChallenge{jws: jws, validate: validate, provider: &TLSALPNProviderServer{}},
|
||||
}
|
||||
|
||||
return &Client{directory: dir, user: user, jws: jws, keyType: keyType, solvers: solvers}, nil
|
||||
}
|
||||
|
@ -94,8 +97,10 @@ func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider)
|
|||
c.solvers[challenge] = &httpChallenge{jws: c.jws, validate: validate, provider: p}
|
||||
case DNS01:
|
||||
c.solvers[challenge] = &dnsChallenge{jws: c.jws, validate: validate, provider: p}
|
||||
case TLSALPN01:
|
||||
c.solvers[challenge] = &tlsALPNChallenge{jws: c.jws, validate: validate, provider: p}
|
||||
default:
|
||||
return fmt.Errorf("Unknown challenge %v", challenge)
|
||||
return fmt.Errorf("unknown challenge %v", challenge)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -119,6 +124,24 @@ func (c *Client) SetHTTPAddress(iface string) error {
|
|||
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-ALPN provider previously set by calling
|
||||
// c.SetChallengeProvider with the default TLS-ALPN 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[TLSALPN01]; ok {
|
||||
chlng.(*tlsALPNChallenge).provider = NewTLSALPNProviderServer(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.
|
||||
|
@ -142,7 +165,7 @@ func (c *Client) Register(tosAgreed bool) (*RegistrationResource, error) {
|
|||
if c == nil || c.user == nil {
|
||||
return nil, errors.New("acme: cannot register a nil client or user")
|
||||
}
|
||||
log.Printf("[INFO] acme: Registering account for %s", c.user.GetEmail())
|
||||
log.Infof("acme: Registering account for %s", c.user.GetEmail())
|
||||
|
||||
accMsg := accountMessage{}
|
||||
if c.user.GetEmail() != "" {
|
||||
|
@ -176,7 +199,7 @@ func (c *Client) RegisterWithExternalAccountBinding(tosAgreed bool, kid string,
|
|||
if c == nil || c.user == nil {
|
||||
return nil, errors.New("acme: cannot register a nil client or user")
|
||||
}
|
||||
log.Printf("[INFO] acme: Registering account (EAB) for %s", c.user.GetEmail())
|
||||
log.Infof("acme: Registering account (EAB) for %s", c.user.GetEmail())
|
||||
|
||||
accMsg := accountMessage{}
|
||||
if c.user.GetEmail() != "" {
|
||||
|
@ -222,7 +245,7 @@ func (c *Client) RegisterWithExternalAccountBinding(tosAgreed bool, kid string,
|
|||
// ResolveAccountByKey will attempt to look up an account using the given account key
|
||||
// and return its registration resource.
|
||||
func (c *Client) ResolveAccountByKey() (*RegistrationResource, error) {
|
||||
log.Printf("[INFO] acme: Trying to resolve account by key")
|
||||
log.Infof("acme: Trying to resolve account by key")
|
||||
|
||||
acc := accountMessage{OnlyReturnExisting: true}
|
||||
hdr, err := postJSON(c.jws, c.directory.NewAccountURL, acc, nil)
|
||||
|
@ -251,7 +274,7 @@ func (c *Client) DeleteRegistration() error {
|
|||
if c == nil || c.user == nil {
|
||||
return errors.New("acme: cannot unregister a nil client or user")
|
||||
}
|
||||
log.Printf("[INFO] acme: Deleting account for %s", c.user.GetEmail())
|
||||
log.Infof("acme: Deleting account for %s", c.user.GetEmail())
|
||||
|
||||
accMsg := accountMessage{
|
||||
Status: "deactivated",
|
||||
|
@ -271,7 +294,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) {
|
|||
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
|
||||
log.Printf("[INFO] acme: Querying account for %s", c.user.GetRegistration().URI)
|
||||
log.Infof("acme: Querying account for %s", c.user.GetRegistration().URI)
|
||||
|
||||
accMsg := accountMessage{}
|
||||
|
||||
|
@ -317,9 +340,9 @@ DNSNames:
|
|||
}
|
||||
|
||||
if bundle {
|
||||
log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
|
||||
} else {
|
||||
log.Printf("[INFO][%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
|
||||
}
|
||||
|
||||
order, err := c.createOrderForIdentifiers(domains)
|
||||
|
@ -341,7 +364,7 @@ DNSNames:
|
|||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
|
||||
|
||||
failures := make(ObtainError)
|
||||
cert, err := c.requestCertificateForCsr(order, bundle, csr.Raw, nil)
|
||||
|
@ -377,9 +400,9 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
|
|||
}
|
||||
|
||||
if bundle {
|
||||
log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
|
||||
} else {
|
||||
log.Printf("[INFO][%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
|
||||
}
|
||||
|
||||
order, err := c.createOrderForIdentifiers(domains)
|
||||
|
@ -401,7 +424,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
|
|||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
|
||||
log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
|
||||
|
||||
failures := make(ObtainError)
|
||||
cert, err := c.requestCertificateForOrder(order, bundle, privKey, mustStaple)
|
||||
|
@ -460,7 +483,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
|
|||
|
||||
// This is just meant to be informal for the user.
|
||||
timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
|
||||
log.Printf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
|
||||
log.Infof("[%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
|
||||
|
@ -534,7 +557,7 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
|
|||
for _, authz := range authorizations {
|
||||
if authz.Status == "valid" {
|
||||
// Boulder might recycle recent validated authz (see issue #267)
|
||||
log.Printf("[INFO][%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
|
||||
log.Infof("[%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -565,7 +588,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) {
|
|||
if solver, ok := c.solvers[Challenge(challenge.Type)]; ok {
|
||||
return i, solver
|
||||
}
|
||||
log.Printf("[INFO][%s] acme: Could not find solver for: %s", domain, challenge.Type)
|
||||
log.Infof("[%s] acme: Could not find solver for: %s", domain, challenge.Type)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
@ -617,7 +640,7 @@ func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, error)
|
|||
|
||||
func logAuthz(order orderResource) {
|
||||
for i, auth := range order.Authorizations {
|
||||
log.Printf("[INFO][%s] AuthURL: %s", order.Identifiers[i].Value, auth)
|
||||
log.Infof("[%s] AuthURL: %s", order.Identifiers[i].Value, auth)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -640,9 +663,18 @@ func (c *Client) requestCertificateForOrder(order orderResource, bundle bool, pr
|
|||
|
||||
// determine certificate name(s) based on the authorization resources
|
||||
commonName := order.Domains[0]
|
||||
var san []string
|
||||
|
||||
// ACME draft Section 7.4 "Applying for Certificate Issuance"
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4
|
||||
// says:
|
||||
// Clients SHOULD NOT make any assumptions about the sort order of
|
||||
// "identifiers" or "authorizations" elements in the returned order
|
||||
// object.
|
||||
san := []string{commonName}
|
||||
for _, auth := range order.Identifiers {
|
||||
san = append(san, auth.Value)
|
||||
if auth.Value != commonName {
|
||||
san = append(san, auth.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: should the CSR be customizable?
|
||||
|
@ -659,13 +691,13 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
|||
|
||||
csrString := base64.RawURLEncoding.EncodeToString(csr)
|
||||
var retOrder orderMessage
|
||||
_, error := postJSON(c.jws, order.Finalize, csrMessage{Csr: csrString}, &retOrder)
|
||||
if error != nil {
|
||||
return nil, error
|
||||
_, err := postJSON(c.jws, order.Finalize, csrMessage{Csr: csrString}, &retOrder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if retOrder.Status == "invalid" {
|
||||
return nil, error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certRes := CertificateResource{
|
||||
|
@ -686,25 +718,30 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
|
|||
}
|
||||
}
|
||||
|
||||
maxChecks := 1000
|
||||
for i := 0; i < maxChecks; i++ {
|
||||
_, err := getJSON(order.URL, &retOrder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
done, err := c.checkCertResponse(retOrder, &certRes, bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if done {
|
||||
break
|
||||
}
|
||||
if i == maxChecks-1 {
|
||||
return nil, fmt.Errorf("polled for certificate %d times; giving up", i)
|
||||
stopTimer := time.NewTimer(30 * time.Second)
|
||||
defer stopTimer.Stop()
|
||||
retryTick := time.NewTicker(500 * time.Millisecond)
|
||||
defer retryTick.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-stopTimer.C:
|
||||
return nil, errors.New("certificate polling timed out")
|
||||
case <-retryTick.C:
|
||||
_, err := getJSON(order.URL, &retOrder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
done, err := c.checkCertResponse(retOrder, &certRes, bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if done {
|
||||
return &certRes, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &certRes, nil
|
||||
}
|
||||
|
||||
// checkCertResponse checks to see if the certificate is ready and a link is contained in the
|
||||
|
@ -726,15 +763,16 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
|
|||
return false, err
|
||||
}
|
||||
|
||||
// The issuer certificate link is always supplied via an "up" link
|
||||
// in the response headers of a new certificate.
|
||||
// The issuer certificate link may be supplied via an "up" link
|
||||
// in the response headers of a new certificate. See
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.4.2
|
||||
links := parseLinks(resp.Header["Link"])
|
||||
if link, ok := links["up"]; ok {
|
||||
issuerCert, err := c.getIssuerCertificate(link)
|
||||
|
||||
if err != nil {
|
||||
// If we fail to acquire the issuer cert, return the issued certificate - do not fail.
|
||||
log.Printf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
|
||||
log.Warnf("[%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
|
||||
} else {
|
||||
issuerCert = pemEncode(derCertificateBytes(issuerCert))
|
||||
|
||||
|
@ -746,26 +784,33 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
|
|||
|
||||
certRes.IssuerCertificate = issuerCert
|
||||
}
|
||||
} else {
|
||||
// Get issuerCert from bundled response from Let's Encrypt
|
||||
// See https://community.letsencrypt.org/t/acme-v2-no-up-link-in-response/64962
|
||||
_, rest := pem.Decode(cert)
|
||||
if rest != nil {
|
||||
certRes.IssuerCertificate = rest
|
||||
}
|
||||
}
|
||||
|
||||
certRes.Certificate = cert
|
||||
certRes.CertURL = order.Certificate
|
||||
certRes.CertStableURL = order.Certificate
|
||||
log.Printf("[INFO][%s] Server responded with a certificate.", certRes.Domain)
|
||||
log.Infof("[%s] Server responded with a certificate.", certRes.Domain)
|
||||
return true, nil
|
||||
|
||||
case "processing":
|
||||
return false, nil
|
||||
case "invalid":
|
||||
return false, errors.New("Order has invalid state: invalid")
|
||||
return false, errors.New("order has invalid state: invalid")
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// getIssuerCertificate requests the issuer certificate
|
||||
func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
|
||||
log.Printf("[INFO] acme: Requesting issuer cert from %s", url)
|
||||
log.Infof("acme: Requesting issuer cert from %s", url)
|
||||
resp, err := httpGet(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -819,7 +864,7 @@ func validate(j *jws, domain, uri string, c challenge) error {
|
|||
for {
|
||||
switch chlng.Status {
|
||||
case "valid":
|
||||
log.Printf("[INFO][%s] The server validated our request", domain)
|
||||
log.Infof("[%s] The server validated our request", domain)
|
||||
return nil
|
||||
case "pending":
|
||||
case "processing":
|
||||
|
|
11
vendor/github.com/xenolf/lego/acme/crypto.go
generated
vendored
11
vendor/github.com/xenolf/lego/acme/crypto.go
generated
vendored
|
@ -215,9 +215,7 @@ func generatePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
|
|||
|
||||
func generateCsr(privateKey crypto.PrivateKey, domain string, san []string, mustStaple bool) ([]byte, error) {
|
||||
template := x509.CertificateRequest{
|
||||
Subject: pkix.Name{
|
||||
CommonName: domain,
|
||||
},
|
||||
Subject: pkix.Name{CommonName: domain},
|
||||
}
|
||||
|
||||
if len(san) > 0 {
|
||||
|
@ -303,8 +301,8 @@ func getCertExpiration(cert []byte) (time.Time, error) {
|
|||
return pCert.NotAfter, nil
|
||||
}
|
||||
|
||||
func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
|
||||
derBytes, err := generateDerCert(privKey, time.Time{}, domain)
|
||||
func generatePemCert(privKey *rsa.PrivateKey, domain string, extensions []pkix.Extension) ([]byte, error) {
|
||||
derBytes, err := generateDerCert(privKey, time.Time{}, domain, extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -312,7 +310,7 @@ func generatePemCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) {
|
|||
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
|
||||
}
|
||||
|
||||
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) {
|
||||
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string, extensions []pkix.Extension) ([]byte, error) {
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
if err != nil {
|
||||
|
@ -334,6 +332,7 @@ func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain strin
|
|||
KeyUsage: x509.KeyUsageKeyEncipherment,
|
||||
BasicConstraintsValid: true,
|
||||
DNSNames: []string{domain},
|
||||
ExtraExtensions: extensions,
|
||||
}
|
||||
|
||||
return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
|
||||
|
|
10
vendor/github.com/xenolf/lego/acme/dns_challenge.go
generated
vendored
10
vendor/github.com/xenolf/lego/acme/dns_challenge.go
generated
vendored
|
@ -72,10 +72,10 @@ type dnsChallenge struct {
|
|||
}
|
||||
|
||||
func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
|
||||
log.Printf("[INFO][%s] acme: Trying to solve DNS-01", domain)
|
||||
log.Infof("[%s] acme: Trying to solve DNS-01", domain)
|
||||
|
||||
if s.provider == nil {
|
||||
return errors.New("No DNS Provider configured")
|
||||
return errors.New("no DNS Provider configured")
|
||||
}
|
||||
|
||||
// Generate the Key Authorization for the challenge
|
||||
|
@ -86,18 +86,18 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
|
|||
|
||||
err = s.provider.Present(domain, chlng.Token, keyAuth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error presenting token: %s", err)
|
||||
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)
|
||||
log.Warnf("Error cleaning up %s: %v ", domain, err)
|
||||
}
|
||||
}()
|
||||
|
||||
fqdn, value, _ := DNS01Record(domain, keyAuth)
|
||||
|
||||
log.Printf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
|
||||
log.Infof("[%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
|
||||
|
||||
var timeout, interval time.Duration
|
||||
switch provider := s.provider.(type) {
|
||||
|
|
10
vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go
generated
vendored
10
vendor/github.com/xenolf/lego/acme/dns_challenge_manual.go
generated
vendored
|
@ -30,9 +30,9 @@ func (*DNSProviderManual) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Printf("[INFO] acme: Please create the following TXT record in your %s zone:", authZone)
|
||||
log.Printf("[INFO] acme: %s", dnsRecord)
|
||||
log.Printf("[INFO] acme: Press 'Enter' when you are done")
|
||||
log.Infof("acme: Please create the following TXT record in your %s zone:", authZone)
|
||||
log.Infof("acme: %s", dnsRecord)
|
||||
log.Infof("acme: Press 'Enter' when you are done")
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
_, _ = reader.ReadString('\n')
|
||||
|
@ -49,7 +49,7 @@ func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Printf("[INFO] acme: You can now remove this TXT record from your %s zone:", authZone)
|
||||
log.Printf("[INFO] acme: %s", dnsRecord)
|
||||
log.Infof("acme: You can now remove this TXT record from your %s zone:", authZone)
|
||||
log.Infof("acme: %s", dnsRecord)
|
||||
return nil
|
||||
}
|
||||
|
|
82
vendor/github.com/xenolf/lego/acme/http.go
generated
vendored
82
vendor/github.com/xenolf/lego/acme/http.go
generated
vendored
|
@ -1,33 +1,45 @@
|
|||
package acme
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UserAgent (if non-empty) will be tacked onto the User-Agent string in requests.
|
||||
var UserAgent string
|
||||
var (
|
||||
// UserAgent (if non-empty) will be tacked onto the User-Agent string in requests.
|
||||
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,
|
||||
},
|
||||
}
|
||||
// HTTPClient is an HTTP client with a reasonable timeout value and
|
||||
// potentially a custom *x509.CertPool based on the caCertificatesEnvVar
|
||||
// environment variable (see the `initCertPool` function)
|
||||
HTTPClient = http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
TLSHandshakeTimeout: 15 * time.Second,
|
||||
ResponseHeaderTimeout: 15 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
TLSClientConfig: &tls.Config{
|
||||
ServerName: os.Getenv(caServerNameEnvVar),
|
||||
RootCAs: initCertPool(),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultGoUserAgent is the Go HTTP package user agent string. Too
|
||||
|
@ -36,12 +48,46 @@ const (
|
|||
|
||||
// ourUserAgent is the User-Agent of this underlying library package.
|
||||
ourUserAgent = "xenolf-acme"
|
||||
|
||||
// caCertificatesEnvVar is the environment variable name that can be used to
|
||||
// specify the path to PEM encoded CA Certificates that can be used to
|
||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
||||
// the system-wide trusted root list.
|
||||
caCertificatesEnvVar = "LEGO_CA_CERTIFICATES"
|
||||
|
||||
// caServerNameEnvVar is the environment variable name that can be used to
|
||||
// specify the CA server name that can be used to
|
||||
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
||||
// the system-wide trusted root list.
|
||||
caServerNameEnvVar = "LEGO_CA_SERVER_NAME"
|
||||
)
|
||||
|
||||
// initCertPool creates a *x509.CertPool populated with the PEM certificates
|
||||
// found in the filepath specified in the caCertificatesEnvVar OS environment
|
||||
// variable. If the caCertificatesEnvVar is not set then initCertPool will
|
||||
// return nil. If there is an error creating a *x509.CertPool from the provided
|
||||
// caCertificatesEnvVar value then initCertPool will panic.
|
||||
func initCertPool() *x509.CertPool {
|
||||
if customCACertsPath := os.Getenv(caCertificatesEnvVar); customCACertsPath != "" {
|
||||
customCAs, err := ioutil.ReadFile(customCACertsPath)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error reading %s=%q: %v",
|
||||
caCertificatesEnvVar, customCACertsPath, err))
|
||||
}
|
||||
certPool := x509.NewCertPool()
|
||||
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
||||
panic(fmt.Sprintf("error creating x509 cert pool from %s=%q: %v",
|
||||
caCertificatesEnvVar, customCACertsPath, err))
|
||||
}
|
||||
return certPool
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
req, err := http.NewRequest(http.MethodHead, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to head %q: %v", url, err)
|
||||
}
|
||||
|
@ -59,7 +105,7 @@ func httpHead(url string) (resp *http.Response, err error) {
|
|||
// 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)
|
||||
req, err := http.NewRequest(http.MethodPost, url, body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to post %q: %v", url, err)
|
||||
}
|
||||
|
@ -72,7 +118,7 @@ func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response,
|
|||
// 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)
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get %q: %v", url, err)
|
||||
}
|
||||
|
|
4
vendor/github.com/xenolf/lego/acme/http_challenge.go
generated
vendored
4
vendor/github.com/xenolf/lego/acme/http_challenge.go
generated
vendored
|
@ -19,7 +19,7 @@ func HTTP01ChallengePath(token string) string {
|
|||
|
||||
func (s *httpChallenge) Solve(chlng challenge, domain string) error {
|
||||
|
||||
log.Printf("[INFO][%s] acme: Trying to solve HTTP-01", domain)
|
||||
log.Infof("[%s] acme: Trying to solve HTTP-01", domain)
|
||||
|
||||
// Generate the Key Authorization for the challenge
|
||||
keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
|
||||
|
@ -34,7 +34,7 @@ func (s *httpChallenge) Solve(chlng challenge, domain string) error {
|
|||
defer func() {
|
||||
err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
|
||||
if err != nil {
|
||||
log.Printf("[%s] error cleaning up: %v", domain, err)
|
||||
log.Warnf("[%s] error cleaning up: %v", domain, err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
6
vendor/github.com/xenolf/lego/acme/http_challenge_server.go
generated
vendored
6
vendor/github.com/xenolf/lego/acme/http_challenge_server.go
generated
vendored
|
@ -60,12 +60,12 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
|
|||
// 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" {
|
||||
if strings.HasPrefix(r.Host, domain) && r.Method == http.MethodGet {
|
||||
w.Header().Add("Content-Type", "text/plain")
|
||||
w.Write([]byte(keyAuth))
|
||||
log.Printf("[INFO][%s] Served key authentication", domain)
|
||||
log.Infof("[%s] Served key authentication", domain)
|
||||
} else {
|
||||
log.Printf("[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)
|
||||
log.Warnf("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"))
|
||||
}
|
||||
})
|
||||
|
|
104
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
generated
vendored
Normal file
104
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
package acme
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"fmt"
|
||||
|
||||
"github.com/xenolf/lego/log"
|
||||
)
|
||||
|
||||
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
|
||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.1
|
||||
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}
|
||||
|
||||
type tlsALPNChallenge struct {
|
||||
jws *jws
|
||||
validate validateFunc
|
||||
provider ChallengeProvider
|
||||
}
|
||||
|
||||
// Solve manages the provider to validate and solve the challenge.
|
||||
func (t *tlsALPNChallenge) Solve(chlng challenge, domain string) error {
|
||||
log.Infof("[%s] acme: Trying to solve TLS-ALPN-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.Warnf("[%s] error cleaning up: %v", domain, err)
|
||||
}
|
||||
}()
|
||||
|
||||
return t.validate(t.jws, domain, chlng.URL, challenge{Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
|
||||
}
|
||||
|
||||
// TLSALPNChallengeBlocks returns PEM blocks (certPEMBlock, keyPEMBlock) with the acmeValidation-v1 extension
|
||||
// and domain name for the `tls-alpn-01` challenge.
|
||||
func TLSALPNChallengeBlocks(domain, keyAuth string) ([]byte, []byte, error) {
|
||||
// Compute the SHA-256 digest of the key authorization.
|
||||
zBytes := sha256.Sum256([]byte(keyAuth))
|
||||
|
||||
value, err := asn1.Marshal(zBytes[:sha256.Size])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Add the keyAuth digest as the acmeValidation-v1 extension
|
||||
// (marked as critical such that it won't be used by non-ACME software).
|
||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3
|
||||
extensions := []pkix.Extension{
|
||||
{
|
||||
Id: idPeAcmeIdentifierV1,
|
||||
Critical: true,
|
||||
Value: value,
|
||||
},
|
||||
}
|
||||
|
||||
// Generate a new RSA key for the certificates.
|
||||
tempPrivKey, err := generatePrivateKey(RSA2048)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
|
||||
|
||||
// Generate the PEM certificate using the provided private key, domain, and extra extensions.
|
||||
tempCertPEM, err := generatePemCert(rsaPrivKey, domain, extensions)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Encode the private key into a PEM format. We'll need to use it to generate the x509 keypair.
|
||||
rsaPrivPEM := pemEncode(rsaPrivKey)
|
||||
|
||||
return tempCertPEM, rsaPrivPEM, nil
|
||||
}
|
||||
|
||||
// TLSALPNChallengeCert returns a certificate with the acmeValidation-v1 extension
|
||||
// and domain name for the `tls-alpn-01` challenge.
|
||||
func TLSALPNChallengeCert(domain, keyAuth string) (*tls.Certificate, error) {
|
||||
tempCertPEM, rsaPrivPEM, err := TLSALPNChallengeBlocks(domain, keyAuth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &certificate, nil
|
||||
}
|
86
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
generated
vendored
Normal file
86
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package acme
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// ACMETLS1Protocol is the ALPN Protocol ID for the ACME-TLS/1 Protocol.
|
||||
ACMETLS1Protocol = "acme-tls/1"
|
||||
|
||||
// defaultTLSPort is the port that the TLSALPNProviderServer will default to
|
||||
// when no other port is provided.
|
||||
defaultTLSPort = "443"
|
||||
)
|
||||
|
||||
// TLSALPNProviderServer implements ChallengeProvider for `TLS-ALPN-01`
|
||||
// challenge. It may be instantiated without using the NewTLSALPNProviderServer
|
||||
// if you want only to use the default values.
|
||||
type TLSALPNProviderServer struct {
|
||||
iface string
|
||||
port string
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
// NewTLSALPNProviderServer creates a new TLSALPNProviderServer 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 NewTLSALPNProviderServer(iface, port string) *TLSALPNProviderServer {
|
||||
return &TLSALPNProviderServer{iface: iface, port: port}
|
||||
}
|
||||
|
||||
// Present generates a certificate with a SHA-256 digest of the keyAuth provided
|
||||
// as the acmeValidation-v1 extension value to conform to the ACME-TLS-ALPN
|
||||
// spec.
|
||||
func (t *TLSALPNProviderServer) Present(domain, token, keyAuth string) error {
|
||||
if t.port == "" {
|
||||
// Fallback to port 443 if the port was not provided.
|
||||
t.port = defaultTLSPort
|
||||
}
|
||||
|
||||
// Generate the challenge certificate using the provided keyAuth and domain.
|
||||
cert, err := TLSALPNChallengeCert(domain, keyAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Place the generated certificate with the extension into the TLS config
|
||||
// so that it can serve the correct details.
|
||||
tlsConf := new(tls.Config)
|
||||
tlsConf.Certificates = []tls.Certificate{*cert}
|
||||
|
||||
// We must set that the `acme-tls/1` application level protocol is supported
|
||||
// so that the protocol negotiation can succeed. Reference:
|
||||
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.2
|
||||
tlsConf.NextProtos = []string{ACMETLS1Protocol}
|
||||
|
||||
// Create the listener with the created tls.Config.
|
||||
t.listener, err = tls.Listen("tcp", net.JoinHostPort(t.iface, t.port), tlsConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not start HTTPS server for challenge -> %v", err)
|
||||
}
|
||||
|
||||
// Shut the server down when we're finished.
|
||||
go func() {
|
||||
http.Serve(t.listener, nil)
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp closes the HTTPS server.
|
||||
func (t *TLSALPNProviderServer) CleanUp(domain, token, keyAuth string) error {
|
||||
if t.listener == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Server was created, close it.
|
||||
if err := t.listener.Close(); err != nil && err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
32
vendor/github.com/xenolf/lego/log/logger.go
generated
vendored
32
vendor/github.com/xenolf/lego/log/logger.go
generated
vendored
|
@ -6,54 +6,44 @@ import (
|
|||
)
|
||||
|
||||
// Logger is an optional custom logger.
|
||||
var Logger *log.Logger
|
||||
var Logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
|
||||
// Fatal writes a log entry.
|
||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
||||
func Fatal(args ...interface{}) {
|
||||
if Logger == nil {
|
||||
Logger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
Logger.Fatal(args...)
|
||||
}
|
||||
|
||||
// Fatalf writes a log entry.
|
||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
if Logger == nil {
|
||||
Logger = log.New(os.Stderr, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
Logger.Fatalf(format, args...)
|
||||
}
|
||||
|
||||
// Print writes a log entry.
|
||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
||||
func Print(args ...interface{}) {
|
||||
if Logger == nil {
|
||||
Logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
Logger.Print(args...)
|
||||
}
|
||||
|
||||
// Println writes a log entry.
|
||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
||||
func Println(args ...interface{}) {
|
||||
if Logger == nil {
|
||||
Logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
Logger.Println(args...)
|
||||
}
|
||||
|
||||
// Printf writes a log entry.
|
||||
// It uses Logger if not nil, otherwise it uses the default log.Logger.
|
||||
func Printf(format string, args ...interface{}) {
|
||||
if Logger == nil {
|
||||
Logger = log.New(os.Stdout, "", log.LstdFlags)
|
||||
}
|
||||
|
||||
Logger.Printf(format, args...)
|
||||
}
|
||||
|
||||
// Warnf writes a log entry.
|
||||
func Warnf(format string, args ...interface{}) {
|
||||
Printf("[WARN] "+format, args...)
|
||||
}
|
||||
|
||||
// Infof writes a log entry.
|
||||
func Infof(format string, args ...interface{}) {
|
||||
Printf("[INFO] "+format, args...)
|
||||
}
|
||||
|
|
27
vendor/github.com/xenolf/lego/platform/config/env/env.go
generated
vendored
Normal file
27
vendor/github.com/xenolf/lego/platform/config/env/env.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Get environment variables
|
||||
func Get(names ...string) (map[string]string, error) {
|
||||
values := map[string]string{}
|
||||
|
||||
var missingEnvVars []string
|
||||
for _, envVar := range names {
|
||||
value := os.Getenv(envVar)
|
||||
if value == "" {
|
||||
missingEnvVars = append(missingEnvVars, envVar)
|
||||
}
|
||||
values[envVar] = value
|
||||
}
|
||||
|
||||
if len(missingEnvVars) > 0 {
|
||||
return nil, fmt.Errorf("some credentials information are missing: %s", strings.Join(missingEnvVars, ","))
|
||||
}
|
||||
|
||||
return values, nil
|
||||
}
|
54
vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go
generated
vendored
54
vendor/github.com/xenolf/lego/providers/dns/auroradns/auroradns.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/edeckers/auroradnsclient/records"
|
||||
"github.com/edeckers/auroradnsclient/zones"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider describes a provider for AuroraDNS
|
||||
|
@ -22,20 +23,23 @@ type DNSProvider struct {
|
|||
// 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"
|
||||
values, err := env.Get("AURORA_USER_ID", "AURORA_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AuroraDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(endpoint, userID, key)
|
||||
endpoint := os.Getenv("AURORA_ENDPOINT")
|
||||
|
||||
return NewDNSProviderCredentials(endpoint, values["AURORA_USER_ID"], values["AURORA_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for AuroraDNS.
|
||||
func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSProvider, error) {
|
||||
if baseURL == "" {
|
||||
baseURL = "https://api.auroradns.eu"
|
||||
}
|
||||
|
||||
client, err := auroradnsclient.NewAuroraDNSClient(baseURL, userID, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -47,8 +51,8 @@ func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSP
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (provider *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
|
||||
zs, err := provider.client.GetZones()
|
||||
func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
|
||||
zs, err := d.client.GetZones()
|
||||
|
||||
if err != nil {
|
||||
return zones.ZoneRecord{}, err
|
||||
|
@ -64,12 +68,12 @@ func (provider *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRe
|
|||
}
|
||||
|
||||
// Present creates a record with a secret
|
||||
func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *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)
|
||||
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,
|
||||
|
@ -83,7 +87,7 @@ func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
|
||||
authZone = acme.UnFqdn(authZone)
|
||||
|
||||
zoneRecord, err := provider.getZoneInformationByName(authZone)
|
||||
zoneRecord, err := d.getZoneInformationByName(authZone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create record: %v", err)
|
||||
}
|
||||
|
@ -96,25 +100,25 @@ func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
TTL: 300,
|
||||
}
|
||||
|
||||
respData, err := provider.client.CreateRecord(zoneRecord.ID, reqData)
|
||||
respData, err := d.client.CreateRecord(zoneRecord.ID, reqData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create record: %v", err)
|
||||
}
|
||||
|
||||
provider.recordIDsMu.Lock()
|
||||
provider.recordIDs[fqdn] = respData.ID
|
||||
provider.recordIDsMu.Unlock()
|
||||
d.recordIDsMu.Lock()
|
||||
d.recordIDs[fqdn] = respData.ID
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes a given record that was generated by Present
|
||||
func (provider *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
provider.recordIDsMu.Lock()
|
||||
recordID, ok := provider.recordIDs[fqdn]
|
||||
provider.recordIDsMu.Unlock()
|
||||
d.recordIDsMu.Lock()
|
||||
recordID, ok := d.recordIDs[fqdn]
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown recordID for %q", fqdn)
|
||||
|
@ -127,19 +131,19 @@ func (provider *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
authZone = acme.UnFqdn(authZone)
|
||||
|
||||
zoneRecord, err := provider.getZoneInformationByName(authZone)
|
||||
zoneRecord, err := d.getZoneInformationByName(authZone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = provider.client.RemoveRecord(zoneRecord.ID, recordID)
|
||||
_, err = d.client.RemoveRecord(zoneRecord.ID, recordID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
provider.recordIDsMu.Lock()
|
||||
delete(provider.recordIDs, fqdn)
|
||||
provider.recordIDsMu.Unlock()
|
||||
d.recordIDsMu.Lock()
|
||||
delete(d.recordIDs, fqdn)
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
65
vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
generated
vendored
65
vendor/github.com/xenolf/lego/providers/dns/azure/azure.go
generated
vendored
|
@ -5,8 +5,8 @@ package azure
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
||||
|
@ -32,25 +33,25 @@ type DNSProvider struct {
|
|||
// 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)
|
||||
values, err := env.Get("AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_SUBSCRIPTION_ID", "AZURE_TENANT_ID", "AZURE_RESOURCE_GROUP")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Azure: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(
|
||||
values["AZURE_CLIENT_ID"],
|
||||
values["AZURE_CLIENT_SECRET"],
|
||||
values["AZURE_SUBSCRIPTION_ID"],
|
||||
values["AZURE_TENANT_ID"],
|
||||
values["AZURE_RESOURCE_GROUP"],
|
||||
)
|
||||
}
|
||||
|
||||
// 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 == "" {
|
||||
var missingEnvVars []string
|
||||
for _, envVar := range []string{"AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET", "AZURE_SUBSCRIPTION_ID", "AZURE_TENANT_ID", "AZURE_RESOURCE_GROUP"} {
|
||||
if os.Getenv(envVar) == "" {
|
||||
missingEnvVars = append(missingEnvVars, envVar)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Azure configuration missing: %s", strings.Join(missingEnvVars, ","))
|
||||
return nil, errors.New("Azure: some credentials information are missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
|
@ -66,20 +67,20 @@ func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID,
|
|||
|
||||
// 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) {
|
||||
func (d *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 {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zone, err := c.getHostedZoneID(fqdn)
|
||||
zone, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rsc := dns.NewRecordSetsClient(c.subscriptionID)
|
||||
spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
|
||||
rsc := dns.NewRecordSetsClient(d.subscriptionID)
|
||||
spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,7 +96,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
},
|
||||
}
|
||||
|
||||
_, err = rsc.CreateOrUpdate(c.context, c.resourceGroup, zone, relative, dns.TXT, rec, "", "")
|
||||
_, err = rsc.CreateOrUpdate(d.context, d.resourceGroup, zone, relative, dns.TXT, rec, "", "")
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -105,44 +106,44 @@ func toRelativeRecord(domain, zone string) string {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZoneID(fqdn)
|
||||
zone, err := d.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 := dns.NewRecordSetsClient(d.subscriptionID)
|
||||
spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rsc.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
|
||||
_, err = rsc.Delete(c.context, c.resourceGroup, zone, relative, dns.TXT, "")
|
||||
_, err = rsc.Delete(d.context, d.resourceGroup, zone, relative, dns.TXT, "")
|
||||
return err
|
||||
}
|
||||
|
||||
// Checks that azure has a zone for this domain name.
|
||||
func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
func (d *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)
|
||||
spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dc := dns.NewZonesClient(c.subscriptionID)
|
||||
dc := dns.NewZonesClient(d.subscriptionID)
|
||||
dc.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
|
||||
zone, err := dc.Get(c.context, c.resourceGroup, acme.UnFqdn(authZone))
|
||||
zone, err := dc.Get(d.context, d.resourceGroup, acme.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -153,10 +154,10 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
|||
|
||||
// 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)
|
||||
func (d *DNSProvider) newServicePrincipalTokenFromCredentials(scope string) (*adal.ServicePrincipalToken, error) {
|
||||
oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, d.tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return adal.NewServicePrincipalToken(*oauthConfig, c.clientID, c.clientSecret, scope)
|
||||
return adal.NewServicePrincipalToken(*oauthConfig, d.clientID, d.clientSecret, scope)
|
||||
}
|
||||
|
|
70
vendor/github.com/xenolf/lego/providers/dns/bluecat/bluecat.go
generated
vendored
70
vendor/github.com/xenolf/lego/providers/dns/bluecat/bluecat.go
generated
vendored
|
@ -6,16 +6,15 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
const bluecatURLTemplate = "%s/Services/REST/v1"
|
||||
|
@ -40,7 +39,7 @@ type DNSProvider struct {
|
|||
configName string
|
||||
dnsView string
|
||||
token string
|
||||
httpClient *http.Client
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Bluecat DNS.
|
||||
|
@ -51,29 +50,42 @@ type DNSProvider struct {
|
|||
// and external DNS View Name must be passed in BLUECAT_CONFIG_NAME and
|
||||
// BLUECAT_DNS_VIEW
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
server := os.Getenv("BLUECAT_SERVER_URL")
|
||||
userName := os.Getenv("BLUECAT_USER_NAME")
|
||||
password := os.Getenv("BLUECAT_PASSWORD")
|
||||
configName := os.Getenv("BLUECAT_CONFIG_NAME")
|
||||
dnsView := os.Getenv("BLUECAT_DNS_VIEW")
|
||||
httpClient := http.Client{Timeout: 30 * time.Second}
|
||||
return NewDNSProviderCredentials(server, userName, password, configName, dnsView, httpClient)
|
||||
values, err := env.Get("BLUECAT_SERVER_URL", "BLUECAT_USER_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_CONFIG_NAME", "BLUECAT_DNS_VIEW")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("BlueCat: %v", err)
|
||||
}
|
||||
|
||||
httpClient := &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
return NewDNSProviderCredentials(
|
||||
values["BLUECAT_SERVER_URL"],
|
||||
values["BLUECAT_USER_NAME"],
|
||||
values["BLUECAT_PASSWORD"],
|
||||
values["BLUECAT_CONFIG_NAME"],
|
||||
values["BLUECAT_DNS_VIEW"],
|
||||
httpClient,
|
||||
)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for Bluecat DNS.
|
||||
func NewDNSProviderCredentials(server, userName, password, configName, dnsView string, httpClient http.Client) (*DNSProvider, error) {
|
||||
func NewDNSProviderCredentials(server, userName, password, configName, dnsView string, httpClient *http.Client) (*DNSProvider, error) {
|
||||
if server == "" || userName == "" || password == "" || configName == "" || dnsView == "" {
|
||||
return nil, fmt.Errorf("Bluecat credentials missing")
|
||||
}
|
||||
|
||||
client := http.DefaultClient
|
||||
if httpClient != nil {
|
||||
client = httpClient
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
baseURL: fmt.Sprintf(bluecatURLTemplate, server),
|
||||
userName: userName,
|
||||
password: password,
|
||||
configName: configName,
|
||||
dnsView: dnsView,
|
||||
httpClient: http.DefaultClient,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -102,7 +114,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{},
|
|||
q.Add(argName, argVal)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
resp, err := d.httpClient.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -125,13 +137,16 @@ func (d *DNSProvider) login() error {
|
|||
"password": d.password,
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "login", nil, queryArgs)
|
||||
resp, err := d.sendRequest(http.MethodGet, "login", nil, queryArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
authBytes, _ := ioutil.ReadAll(resp.Body)
|
||||
authBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authResp := string(authBytes)
|
||||
|
||||
if strings.Contains(authResp, "Authentication Error") {
|
||||
|
@ -152,7 +167,7 @@ func (d *DNSProvider) logout() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "logout", nil, nil)
|
||||
resp, err := d.sendRequest(http.MethodGet, "logout", nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -162,7 +177,10 @@ func (d *DNSProvider) logout() error {
|
|||
return fmt.Errorf("Bluecat API request failed to delete session with HTTP status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
authBytes, _ := ioutil.ReadAll(resp.Body)
|
||||
authBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authResp := string(authBytes)
|
||||
|
||||
if !strings.Contains(authResp, "successfully") {
|
||||
|
@ -183,7 +201,7 @@ func (d *DNSProvider) lookupConfID() (uint, error) {
|
|||
"type": configType,
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
|
||||
resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -210,7 +228,7 @@ func (d *DNSProvider) lookupViewID(viewName string) (uint, error) {
|
|||
"type": viewType,
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
|
||||
resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -259,7 +277,7 @@ func (d *DNSProvider) getZone(parentID uint, name string) (uint, error) {
|
|||
"type": zoneType,
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
|
||||
resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
|
||||
// Return an empty zone if the named zone doesn't exist
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
return 0, fmt.Errorf("Bluecat API could not find zone named %s", name)
|
||||
|
@ -309,8 +327,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
Properties: fmt.Sprintf("ttl=%d|absoluteName=%s|txt=%s|", ttl, fqdn, value),
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("POST", "addEntity", body, queryArgs)
|
||||
|
||||
resp, err := d.sendRequest(http.MethodPost, "addEntity", body, queryArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -338,8 +355,7 @@ func (d *DNSProvider) deploy(entityID uint) error {
|
|||
"entityId": strconv.FormatUint(uint64(entityID), 10),
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("POST", "quickDeploy", nil, queryArgs)
|
||||
|
||||
resp, err := d.sendRequest(http.MethodPost, "quickDeploy", nil, queryArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -373,7 +389,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
"type": txtType,
|
||||
}
|
||||
|
||||
resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
|
||||
resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -388,7 +404,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
"objectId": strconv.FormatUint(uint64(txtRec.ID), 10),
|
||||
}
|
||||
|
||||
resp, err = d.sendRequest("DELETE", "delete", nil, queryArgs)
|
||||
resp, err = d.sendRequest(http.MethodDelete, http.MethodDelete, nil, queryArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
95
vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go
generated
vendored
95
vendor/github.com/xenolf/lego/providers/dns/cloudflare/cloudflare.go
generated
vendored
|
@ -5,15 +5,15 @@ package cloudflare
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// CloudFlareAPIURL represents the API endpoint to call.
|
||||
|
@ -24,47 +24,45 @@ const CloudFlareAPIURL = "https://api.cloudflare.com/client/v4"
|
|||
type DNSProvider struct {
|
||||
authEmail string
|
||||
authKey string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("CLOUDFLARE_EMAIL", "CLOUDFLARE_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CloudFlare: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["CLOUDFLARE_EMAIL"], values["CLOUDFLARE_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for cloudflare.
|
||||
func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
|
||||
if email == "" || key == "" {
|
||||
missingEnvVars := []string{}
|
||||
if email == "" {
|
||||
missingEnvVars = append(missingEnvVars, "CLOUDFLARE_EMAIL")
|
||||
}
|
||||
if key == "" {
|
||||
missingEnvVars = append(missingEnvVars, "CLOUDFLARE_API_KEY")
|
||||
}
|
||||
return nil, fmt.Errorf("CloudFlare credentials missing: %s", strings.Join(missingEnvVars, ","))
|
||||
return nil, errors.New("CloudFlare: some credentials information are missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
authEmail: email,
|
||||
authKey: key,
|
||||
client: &http.Client{Timeout: 30 * time.Second},
|
||||
}, 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) {
|
||||
func (d *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)
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -73,7 +71,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
Type: "TXT",
|
||||
Name: acme.UnFqdn(fqdn),
|
||||
Content: value,
|
||||
TTL: 120,
|
||||
TTL: ttl,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(rec)
|
||||
|
@ -81,24 +79,24 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("POST", fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewReader(body))
|
||||
_, err = d.doRequest(http.MethodPost, fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewReader(body))
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
record, err := c.findTxtRecord(fqdn)
|
||||
record, err := d.findTxtRecord(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("DELETE", fmt.Sprintf("/zones/%s/dns_records/%s", record.ZoneID, record.ID), nil)
|
||||
_, err = d.doRequest(http.MethodDelete, fmt.Sprintf("/zones/%s/dns_records/%s", record.ZoneID, record.ID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
// HostedZone represents a CloudFlare DNS zone
|
||||
type HostedZone struct {
|
||||
ID string `json:"id"`
|
||||
|
@ -110,7 +108,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
result, err := c.makeRequest("GET", "/zones?name="+acme.UnFqdn(authZone), nil)
|
||||
result, err := d.doRequest(http.MethodGet, "/zones?name="+acme.UnFqdn(authZone), nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -122,20 +120,20 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
|||
}
|
||||
|
||||
if len(hostedZone) != 1 {
|
||||
return "", fmt.Errorf("Zone %s not found in CloudFlare for domain %s", authZone, fqdn)
|
||||
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)
|
||||
func (d *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := c.makeRequest(
|
||||
"GET",
|
||||
result, err := d.doRequest(
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("/zones/%s/dns_records?per_page=1000&type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)),
|
||||
nil,
|
||||
)
|
||||
|
@ -158,33 +156,18 @@ func (c *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
|
|||
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"`
|
||||
}
|
||||
|
||||
func (d *DNSProvider) doRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
|
||||
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("X-Auth-Email", d.authEmail)
|
||||
req.Header.Set("X-Auth-Key", d.authKey)
|
||||
|
||||
client := http.Client{Timeout: 30 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error querying Cloudflare API -> %v", err)
|
||||
return nil, fmt.Errorf("error querying Cloudflare API -> %v", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
@ -216,6 +199,20 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
|
|||
return r.Result, nil
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// cloudFlareRecord represents a CloudFlare DNS record
|
||||
type cloudFlareRecord struct {
|
||||
Name string `json:"name"`
|
||||
|
|
51
vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go
generated
vendored
51
vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go
generated
vendored
|
@ -9,11 +9,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
const cloudXNSBaseURL = "https://www.cloudxns.net/api2/"
|
||||
|
@ -28,9 +28,12 @@ type DNSProvider struct {
|
|||
// Credentials must be passed in the environment variables: CLOUDXNS_API_KEY
|
||||
// and CLOUDXNS_SECRET_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiKey := os.Getenv("CLOUDXNS_API_KEY")
|
||||
secretKey := os.Getenv("CLOUDXNS_SECRET_KEY")
|
||||
return NewDNSProviderCredentials(apiKey, secretKey)
|
||||
values, err := env.Get("CLOUDXNS_API_KEY", "CLOUDXNS_SECRET_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CloudXNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["CLOUDXNS_API_KEY"], values["CLOUDXNS_SECRET_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -47,33 +50,33 @@ func NewDNSProviderCredentials(apiKey, secretKey string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, err := c.getHostedZoneID(fqdn)
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.addTxtRecord(zoneID, fqdn, value, ttl)
|
||||
return d.addTxtRecord(zoneID, fqdn, value, ttl)
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, err := c.getHostedZoneID(fqdn)
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordID, err := c.findTxtRecord(zoneID, fqdn)
|
||||
recordID, err := d.findTxtRecord(zoneID, fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.delTxtRecord(recordID, zoneID)
|
||||
return d.delTxtRecord(recordID, zoneID)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
type Data struct {
|
||||
ID string `json:"id"`
|
||||
Domain string `json:"domain"`
|
||||
|
@ -84,7 +87,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
result, err := c.makeRequest("GET", "domain", nil)
|
||||
result, err := d.makeRequest(http.MethodGet, "domain", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -104,8 +107,8 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
|||
return "", fmt.Errorf("zone %s not found in cloudxns for domain %s", authZone, fqdn)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
|
||||
result, err := c.makeRequest("GET", fmt.Sprintf("record/%s?host_id=0&offset=0&row_num=2000", zoneID), nil)
|
||||
func (d *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
|
||||
result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("record/%s?host_id=0&offset=0&row_num=2000", zoneID), nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -125,7 +128,7 @@ func (c *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
|
|||
return "", fmt.Errorf("no existing record found for %s", fqdn)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
|
||||
func (d *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
|
||||
id, err := strconv.Atoi(zoneID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -145,21 +148,21 @@ func (c *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("POST", "record", body)
|
||||
_, err = d.makeRequest(http.MethodPost, "record", body)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *DNSProvider) delTxtRecord(recordID, zoneID string) error {
|
||||
_, err := c.makeRequest("DELETE", fmt.Sprintf("record/%s/%s", recordID, zoneID), nil)
|
||||
func (d *DNSProvider) delTxtRecord(recordID, zoneID string) error {
|
||||
_, err := d.makeRequest(http.MethodDelete, fmt.Sprintf("record/%s/%s", recordID, zoneID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *DNSProvider) hmac(url, date, body string) string {
|
||||
sum := md5.Sum([]byte(c.apiKey + url + body + date + c.secretKey))
|
||||
func (d *DNSProvider) hmac(url, date, body string) string {
|
||||
sum := md5.Sum([]byte(d.apiKey + url + body + date + d.secretKey))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func (c *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMessage, error) {
|
||||
func (d *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMessage, error) {
|
||||
type APIResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
|
@ -174,9 +177,9 @@ func (c *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMess
|
|||
|
||||
requestDate := time.Now().Format(time.RFC1123Z)
|
||||
|
||||
req.Header.Set("API-KEY", c.apiKey)
|
||||
req.Header.Set("API-KEY", d.apiKey)
|
||||
req.Header.Set("API-REQUEST-DATE", requestDate)
|
||||
req.Header.Set("API-HMAC", c.hmac(url, requestDate, string(body)))
|
||||
req.Header.Set("API-HMAC", d.hmac(url, requestDate, string(body)))
|
||||
req.Header.Set("API-FORMAT", "json")
|
||||
|
||||
resp, err := acme.HTTPClient.Do(req)
|
||||
|
|
35
vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go
generated
vendored
35
vendor/github.com/xenolf/lego/providers/dns/digitalocean/digitalocean.go
generated
vendored
|
@ -7,11 +7,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
||||
|
@ -20,20 +20,19 @@ type DNSProvider struct {
|
|||
apiAuthToken string
|
||||
recordIDs map[string]int
|
||||
recordIDsMu sync.Mutex
|
||||
}
|
||||
|
||||
// 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 60 * time.Second, 5 * time.Second
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("DO_AUTH_TOKEN")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DigitalOcean: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["DO_AUTH_TOKEN"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -45,9 +44,16 @@ func NewDNSProviderCredentials(apiAuthToken string) (*DNSProvider, error) {
|
|||
return &DNSProvider{
|
||||
apiAuthToken: apiAuthToken,
|
||||
recordIDs: make(map[string]int),
|
||||
client: &http.Client{Timeout: 30 * time.Second},
|
||||
}, 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 60 * time.Second, 5 * time.Second
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
@ -66,15 +72,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", reqURL, bytes.NewReader(body))
|
||||
req, err := http.NewRequest(http.MethodPost, 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)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -119,15 +124,15 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
authZone = acme.UnFqdn(authZone)
|
||||
|
||||
reqURL := fmt.Sprintf("%s/v2/domains/%s/records/%d", digitalOceanBaseURL, authZone, recordID)
|
||||
req, err := http.NewRequest("DELETE", reqURL, nil)
|
||||
req, err := http.NewRequest(http.MethodDelete, 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)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
78
vendor/github.com/xenolf/lego/providers/dns/dns_providers.go
generated
vendored
78
vendor/github.com/xenolf/lego/providers/dns/dns_providers.go
generated
vendored
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/xenolf/lego/providers/dns/linode"
|
||||
"github.com/xenolf/lego/providers/dns/namecheap"
|
||||
"github.com/xenolf/lego/providers/dns/namedotcom"
|
||||
"github.com/xenolf/lego/providers/dns/nifcloud"
|
||||
"github.com/xenolf/lego/providers/dns/ns1"
|
||||
"github.com/xenolf/lego/providers/dns/otc"
|
||||
"github.com/xenolf/lego/providers/dns/ovh"
|
||||
|
@ -34,80 +35,85 @@ import (
|
|||
"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/sakuracloud"
|
||||
"github.com/xenolf/lego/providers/dns/vegadns"
|
||||
"github.com/xenolf/lego/providers/dns/vultr"
|
||||
)
|
||||
|
||||
// NewDNSChallengeProviderByName Factory for DNS providers
|
||||
func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error) {
|
||||
var err error
|
||||
var provider acme.ChallengeProvider
|
||||
switch name {
|
||||
case "azure":
|
||||
provider, err = azure.NewDNSProvider()
|
||||
return azure.NewDNSProvider()
|
||||
case "auroradns":
|
||||
provider, err = auroradns.NewDNSProvider()
|
||||
return auroradns.NewDNSProvider()
|
||||
case "bluecat":
|
||||
provider, err = bluecat.NewDNSProvider()
|
||||
return bluecat.NewDNSProvider()
|
||||
case "cloudflare":
|
||||
provider, err = cloudflare.NewDNSProvider()
|
||||
return cloudflare.NewDNSProvider()
|
||||
case "cloudxns":
|
||||
provider, err = cloudxns.NewDNSProvider()
|
||||
return cloudxns.NewDNSProvider()
|
||||
case "digitalocean":
|
||||
provider, err = digitalocean.NewDNSProvider()
|
||||
return digitalocean.NewDNSProvider()
|
||||
case "dnsimple":
|
||||
provider, err = dnsimple.NewDNSProvider()
|
||||
return dnsimple.NewDNSProvider()
|
||||
case "dnsmadeeasy":
|
||||
provider, err = dnsmadeeasy.NewDNSProvider()
|
||||
return dnsmadeeasy.NewDNSProvider()
|
||||
case "dnspod":
|
||||
provider, err = dnspod.NewDNSProvider()
|
||||
return dnspod.NewDNSProvider()
|
||||
case "duckdns":
|
||||
provider, err = duckdns.NewDNSProvider()
|
||||
return duckdns.NewDNSProvider()
|
||||
case "dyn":
|
||||
provider, err = dyn.NewDNSProvider()
|
||||
return dyn.NewDNSProvider()
|
||||
case "fastdns":
|
||||
provider, err = fastdns.NewDNSProvider()
|
||||
return fastdns.NewDNSProvider()
|
||||
case "exoscale":
|
||||
provider, err = exoscale.NewDNSProvider()
|
||||
return exoscale.NewDNSProvider()
|
||||
case "gandi":
|
||||
provider, err = gandi.NewDNSProvider()
|
||||
return gandi.NewDNSProvider()
|
||||
case "gandiv5":
|
||||
provider, err = gandiv5.NewDNSProvider()
|
||||
return gandiv5.NewDNSProvider()
|
||||
case "glesys":
|
||||
provider, err = glesys.NewDNSProvider()
|
||||
return glesys.NewDNSProvider()
|
||||
case "gcloud":
|
||||
provider, err = gcloud.NewDNSProvider()
|
||||
return gcloud.NewDNSProvider()
|
||||
case "godaddy":
|
||||
provider, err = godaddy.NewDNSProvider()
|
||||
return godaddy.NewDNSProvider()
|
||||
case "lightsail":
|
||||
provider, err = lightsail.NewDNSProvider()
|
||||
return lightsail.NewDNSProvider()
|
||||
case "linode":
|
||||
provider, err = linode.NewDNSProvider()
|
||||
return linode.NewDNSProvider()
|
||||
case "manual":
|
||||
provider, err = acme.NewDNSProviderManual()
|
||||
return acme.NewDNSProviderManual()
|
||||
case "namecheap":
|
||||
provider, err = namecheap.NewDNSProvider()
|
||||
return namecheap.NewDNSProvider()
|
||||
case "namedotcom":
|
||||
provider, err = namedotcom.NewDNSProvider()
|
||||
return namedotcom.NewDNSProvider()
|
||||
case "nifcloud":
|
||||
return nifcloud.NewDNSProvider()
|
||||
case "rackspace":
|
||||
provider, err = rackspace.NewDNSProvider()
|
||||
return rackspace.NewDNSProvider()
|
||||
case "route53":
|
||||
provider, err = route53.NewDNSProvider()
|
||||
return route53.NewDNSProvider()
|
||||
case "rfc2136":
|
||||
provider, err = rfc2136.NewDNSProvider()
|
||||
return rfc2136.NewDNSProvider()
|
||||
case "sakuracloud":
|
||||
return sakuracloud.NewDNSProvider()
|
||||
case "vultr":
|
||||
provider, err = vultr.NewDNSProvider()
|
||||
return vultr.NewDNSProvider()
|
||||
case "ovh":
|
||||
provider, err = ovh.NewDNSProvider()
|
||||
return ovh.NewDNSProvider()
|
||||
case "pdns":
|
||||
provider, err = pdns.NewDNSProvider()
|
||||
return pdns.NewDNSProvider()
|
||||
case "ns1":
|
||||
provider, err = ns1.NewDNSProvider()
|
||||
return ns1.NewDNSProvider()
|
||||
case "otc":
|
||||
provider, err = otc.NewDNSProvider()
|
||||
return otc.NewDNSProvider()
|
||||
case "exec":
|
||||
provider, err = exec.NewDNSProvider()
|
||||
return exec.NewDNSProvider()
|
||||
case "vegadns":
|
||||
return vegadns.NewDNSProvider()
|
||||
default:
|
||||
err = fmt.Errorf("unrecognised DNS provider: %s", name)
|
||||
return nil, fmt.Errorf("unrecognised DNS provider: %s", name)
|
||||
}
|
||||
return provider, err
|
||||
}
|
||||
|
|
44
vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go
generated
vendored
44
vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go
generated
vendored
|
@ -46,22 +46,22 @@ func NewDNSProviderCredentials(accessToken, baseURL string) (*DNSProvider, error
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zoneName, err := c.getHostedZone(domain)
|
||||
zoneName, err := d.getHostedZone(domain)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accountID, err := c.getAccountID()
|
||||
accountID, err := d.getAccountID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
|
||||
_, err = c.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes)
|
||||
recordAttributes := d.newTxtRecord(zoneName, fqdn, value, ttl)
|
||||
_, err = d.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DNSimple API call failed: %v", err)
|
||||
}
|
||||
|
@ -70,21 +70,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
records, err := c.findTxtRecords(domain, fqdn)
|
||||
records, err := d.findTxtRecords(domain, fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accountID, err := c.getAccountID()
|
||||
accountID, err := d.getAccountID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rec := range records {
|
||||
_, err := c.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID)
|
||||
_, err := d.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -93,20 +93,20 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
accountID, err := c.getAccountID()
|
||||
accountID, err := d.getAccountID()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
zoneName := acme.UnFqdn(authZone)
|
||||
|
||||
zones, err := c.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName})
|
||||
zones, err := d.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("DNSimple API call failed: %v", err)
|
||||
}
|
||||
|
@ -125,20 +125,20 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
|||
return hostedZone.Name, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) {
|
||||
zoneName, err := c.getHostedZone(domain)
|
||||
func (d *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) {
|
||||
zoneName, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accountID, err := c.getAccountID()
|
||||
accountID, err := d.getAccountID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recordName := c.extractRecordName(fqdn, zoneName)
|
||||
recordName := d.extractRecordName(fqdn, zoneName)
|
||||
|
||||
result, err := c.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
|
||||
result, err := d.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)
|
||||
}
|
||||
|
@ -146,8 +146,8 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord
|
|||
return result.Data, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord {
|
||||
name := c.extractRecordName(fqdn, zoneName)
|
||||
func (d *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord {
|
||||
name := d.extractRecordName(fqdn, zoneName)
|
||||
|
||||
return &dnsimple.ZoneRecord{
|
||||
Type: "TXT",
|
||||
|
@ -157,7 +157,7 @@ func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsim
|
|||
}
|
||||
}
|
||||
|
||||
func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||
return name[:idx]
|
||||
|
@ -165,8 +165,8 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
|||
return name
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getAccountID() (string, error) {
|
||||
whoamiResponse, err := c.client.Identity.Whoami()
|
||||
func (d *DNSProvider) getAccountID() (string, error) {
|
||||
whoamiResponse, err := d.client.Identity.Whoami()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
41
vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go
generated
vendored
41
vendor/github.com/xenolf/lego/providers/dns/dnsmadeeasy/dnsmadeeasy.go
generated
vendored
|
@ -15,6 +15,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
|
||||
|
@ -23,6 +24,7 @@ type DNSProvider struct {
|
|||
baseURL string
|
||||
apiKey string
|
||||
apiSecret string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// Domain holds the DNSMadeEasy API representation of a Domain
|
||||
|
@ -45,20 +47,19 @@ type Record struct {
|
|||
// 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")
|
||||
values, err := env.Get("DNSMADEEASY_API_KEY", "DNSMADEEASY_API_SECRET")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DNSMadeEasy: %v", err)
|
||||
}
|
||||
|
||||
var baseURL string
|
||||
|
||||
sandbox, _ := strconv.ParseBool(dnsmadeeasySandbox)
|
||||
if sandbox {
|
||||
if sandbox, _ := strconv.ParseBool(os.Getenv("DNSMADEEASY_SANDBOX")); sandbox {
|
||||
baseURL = "https://api.sandbox.dnsmadeeasy.com/V2.0"
|
||||
} else {
|
||||
baseURL = "https://api.dnsmadeeasy.com/V2.0"
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(baseURL, dnsmadeeasyAPIKey, dnsmadeeasyAPISecret)
|
||||
return NewDNSProviderCredentials(baseURL, values["DNSMADEEASY_API_KEY"], values["DNSMADEEASY_API_SECRET"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -68,10 +69,19 @@ func NewDNSProviderCredentials(baseURL, apiKey, apiSecret string) (*DNSProvider,
|
|||
return nil, fmt.Errorf("DNS Made Easy credentials missing")
|
||||
}
|
||||
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
baseURL: baseURL,
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -135,7 +145,7 @@ 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)
|
||||
resp, err := d.sendRequest(http.MethodGet, resource, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -153,7 +163,7 @@ func (d *DNSProvider) getDomain(authZone string) (*Domain, error) {
|
|||
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)
|
||||
resp, err := d.sendRequest(http.MethodGet, resource, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -175,7 +185,7 @@ func (d *DNSProvider) getRecords(domain *Domain, recordName, recordType string)
|
|||
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)
|
||||
resp, err := d.sendRequest(http.MethodPost, url, record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -187,7 +197,7 @@ func (d *DNSProvider) createRecord(domain *Domain, record *Record) error {
|
|||
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)
|
||||
resp, err := d.sendRequest(http.MethodDelete, resource, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -217,14 +227,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{})
|
|||
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: 10 * time.Second,
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
46
vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go
generated
vendored
46
vendor/github.com/xenolf/lego/providers/dns/dnspod/dnspod.go
generated
vendored
|
@ -4,11 +4,11 @@ package dnspod
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/decker502/dnspod-go"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
|
@ -19,8 +19,12 @@ type DNSProvider struct {
|
|||
// 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)
|
||||
values, err := env.Get("DNSPOD_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DNSPod: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["DNSPOD_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -37,15 +41,15 @@ func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, zoneName, err := c.getHostedZone(domain)
|
||||
zoneID, zoneName, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
|
||||
_, _, err = c.client.Domains.CreateRecord(zoneID, *recordAttributes)
|
||||
recordAttributes := d.newTxtRecord(zoneName, fqdn, value, ttl)
|
||||
_, _, err = d.client.Domains.CreateRecord(zoneID, *recordAttributes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnspod API call failed: %v", err)
|
||||
}
|
||||
|
@ -54,21 +58,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
records, err := c.findTxtRecords(domain, fqdn)
|
||||
records, err := d.findTxtRecords(domain, fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zoneID, _, err := c.getHostedZone(domain)
|
||||
zoneID, _, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rec := range records {
|
||||
_, err := c.client.Domains.DeleteRecord(zoneID, rec.ID)
|
||||
_, err := d.client.Domains.DeleteRecord(zoneID, rec.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -76,8 +80,8 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
|
||||
zones, _, err := c.client.Domains.List()
|
||||
func (d *DNSProvider) getHostedZone(domain string) (string, string, error) {
|
||||
zones, _, err := d.client.Domains.List()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("dnspod API call failed: %v", err)
|
||||
}
|
||||
|
@ -95,15 +99,15 @@ func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
|
|||
}
|
||||
|
||||
if hostedZone.ID == 0 {
|
||||
return "", "", fmt.Errorf("Zone %s not found in dnspod for domain %s", authZone, domain)
|
||||
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)
|
||||
func (d *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Record {
|
||||
name := d.extractRecordName(fqdn, zone)
|
||||
|
||||
return &dnspod.Record{
|
||||
Type: "TXT",
|
||||
|
@ -114,19 +118,19 @@ func (c *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Re
|
|||
}
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, error) {
|
||||
zoneID, zoneName, err := c.getHostedZone(domain)
|
||||
func (d *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, error) {
|
||||
zoneID, zoneName, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var records []dnspod.Record
|
||||
result, _, err := c.client.Domains.ListRecords(zoneID, "")
|
||||
result, _, err := d.client.Domains.ListRecords(zoneID, "")
|
||||
if err != nil {
|
||||
return records, fmt.Errorf("dnspod API call has failed: %v", err)
|
||||
}
|
||||
|
||||
recordName := c.extractRecordName(fqdn, zoneName)
|
||||
recordName := d.extractRecordName(fqdn, zoneName)
|
||||
|
||||
for _, record := range result {
|
||||
if record.Name == recordName {
|
||||
|
@ -137,7 +141,7 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, erro
|
|||
return records, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||
return name[:idx]
|
||||
|
|
15
vendor/github.com/xenolf/lego/providers/dns/duckdns/duckdns.go
generated
vendored
15
vendor/github.com/xenolf/lego/providers/dns/duckdns/duckdns.go
generated
vendored
|
@ -1,4 +1,4 @@
|
|||
// Package duckdns Adds lego support for http://duckdns.org .
|
||||
// Package duckdns Adds lego support for http://duckdns.org.
|
||||
// See http://www.duckdns.org/spec.jsp for more info on updating TXT records.
|
||||
package duckdns
|
||||
|
||||
|
@ -6,30 +6,33 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider adds and removes the record for the DNS challenge
|
||||
type DNSProvider struct {
|
||||
// The duckdns api token
|
||||
// The api token
|
||||
token string
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a new DNS provider using
|
||||
// environment variable DUCKDNS_TOKEN for adding and removing the DNS record.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
duckdnsToken := os.Getenv("DUCKDNS_TOKEN")
|
||||
values, err := env.Get("DUCKDNS_TOKEN")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DuckDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(duckdnsToken)
|
||||
return NewDNSProviderCredentials(values["DUCKDNS_TOKEN"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for http://duckdns.org .
|
||||
func NewDNSProviderCredentials(duckdnsToken string) (*DNSProvider, error) {
|
||||
if duckdnsToken == "" {
|
||||
return nil, errors.New("environment variable DUCKDNS_TOKEN not set")
|
||||
return nil, errors.New("DuckDNS: credentials missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{token: duckdnsToken}, nil
|
||||
|
|
35
vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go
generated
vendored
35
vendor/github.com/xenolf/lego/providers/dns/dyn/dyn.go
generated
vendored
|
@ -7,11 +7,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
var dynBaseURL = "https://api.dynect.net/REST"
|
||||
|
@ -37,16 +37,19 @@ type DNSProvider struct {
|
|||
userName string
|
||||
password string
|
||||
token string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("DYN_CUSTOMER_NAME", "DYN_USER_NAME", "DYN_PASSWORD")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("DynDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["DYN_CUSTOMER_NAME"], values["DYN_USER_NAME"], values["DYN_PASSWORD"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -60,6 +63,7 @@ func NewDNSProviderCredentials(customerName, userName, password string) (*DNSPro
|
|||
customerName: customerName,
|
||||
userName: userName,
|
||||
password: password,
|
||||
client: &http.Client{Timeout: 10 * time.Second},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -80,8 +84,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{})
|
|||
req.Header.Set("Auth-Token", d.token)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,7 +130,7 @@ func (d *DNSProvider) login() error {
|
|||
}
|
||||
|
||||
payload := &creds{Customer: d.customerName, User: d.userName, Pass: d.password}
|
||||
dynRes, err := d.sendRequest("POST", "Session", payload)
|
||||
dynRes, err := d.sendRequest(http.MethodPost, "Session", payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -151,15 +154,14 @@ func (d *DNSProvider) logout() error {
|
|||
}
|
||||
|
||||
url := fmt.Sprintf("%s/Session", dynBaseURL)
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
req, err := http.NewRequest(http.MethodDelete, 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: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -196,7 +198,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
|
||||
_, err = d.sendRequest("POST", resource, data)
|
||||
_, err = d.sendRequest(http.MethodPost, resource, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -218,7 +220,7 @@ func (d *DNSProvider) publish(zone, notes string) error {
|
|||
pub := &publish{Publish: true, Notes: notes}
|
||||
resource := fmt.Sprintf("Zone/%s/", zone)
|
||||
|
||||
_, err := d.sendRequest("PUT", resource, pub)
|
||||
_, err := d.sendRequest(http.MethodPut, resource, pub)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -238,15 +240,16 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
|
||||
url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
|
||||
req, err := http.NewRequest(http.MethodDelete, 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: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
8
vendor/github.com/xenolf/lego/providers/dns/exec/exec.go
generated
vendored
8
vendor/github.com/xenolf/lego/providers/dns/exec/exec.go
generated
vendored
|
@ -48,7 +48,13 @@ func NewDNSProvider() (*DNSProvider, error) {
|
|||
return nil, errors.New("environment variable EXEC_PATH not set")
|
||||
}
|
||||
|
||||
return &DNSProvider{program: s}, nil
|
||||
return NewDNSProviderProgram(s)
|
||||
}
|
||||
|
||||
// NewDNSProviderProgram returns a new DNS provider which runs the given program
|
||||
// for adding and removing the DNS record.
|
||||
func NewDNSProviderProgram(program string) (*DNSProvider, error) {
|
||||
return &DNSProvider{program: program}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
|
|
35
vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go
generated
vendored
35
vendor/github.com/xenolf/lego/providers/dns/exoscale/exoscale.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/exoscale/egoscale"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
|
@ -19,10 +20,13 @@ type DNSProvider struct {
|
|||
// NewDNSProvider 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")
|
||||
values, err := env.Get("EXOSCALE_API_KEY", "EXOSCALE_API_SECRET")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Exoscale: %v", err)
|
||||
}
|
||||
|
||||
endpoint := os.Getenv("EXOSCALE_ENDPOINT")
|
||||
return NewDNSProviderClient(key, secret, endpoint)
|
||||
return NewDNSProviderClient(values["EXOSCALE_API_KEY"], values["EXOSCALE_API_SECRET"], endpoint)
|
||||
}
|
||||
|
||||
// NewDNSProviderClient Uses the supplied parameters to return a DNSProvider instance
|
||||
|
@ -31,6 +35,7 @@ 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"
|
||||
}
|
||||
|
@ -41,14 +46,14 @@ func NewDNSProviderClient(key, secret, endpoint string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
|
||||
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordID, err := c.FindExistingRecordID(zone, recordName)
|
||||
recordID, err := d.FindExistingRecordID(zone, recordName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,13 +66,13 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
if recordID == 0 {
|
||||
_, err := c.client.CreateRecord(zone, record)
|
||||
_, err := d.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)
|
||||
_, err := d.client.UpdateRecord(zone, record)
|
||||
if err != nil {
|
||||
return errors.New("Error while updating DNS record: " + err.Error())
|
||||
}
|
||||
|
@ -77,20 +82,20 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
|
||||
zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordID, err := c.FindExistingRecordID(zone, recordName)
|
||||
recordID, err := d.FindExistingRecordID(zone, recordName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if recordID != 0 {
|
||||
err = c.client.DeleteRecord(zone, recordID)
|
||||
err = d.client.DeleteRecord(zone, recordID)
|
||||
if err != nil {
|
||||
return errors.New("Error while deleting DNS record: " + err.Error())
|
||||
}
|
||||
|
@ -101,8 +106,8 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
// FindExistingRecordID 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)
|
||||
func (d *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, error) {
|
||||
records, err := d.client.GetRecords(zone)
|
||||
if err != nil {
|
||||
return -1, errors.New("Error while retrievening DNS records: " + err.Error())
|
||||
}
|
||||
|
@ -115,7 +120,7 @@ func (c *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, erro
|
|||
}
|
||||
|
||||
// FindZoneAndRecordName Extract DNS zone and DNS entry name
|
||||
func (c *DNSProvider) FindZoneAndRecordName(fqdn, domain string) (string, string, error) {
|
||||
func (d *DNSProvider) FindZoneAndRecordName(fqdn, domain string) (string, string, error) {
|
||||
zone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
|
|
45
vendor/github.com/xenolf/lego/providers/dns/fastdns/fastdns.go
generated
vendored
45
vendor/github.com/xenolf/lego/providers/dns/fastdns/fastdns.go
generated
vendored
|
@ -2,12 +2,12 @@ package fastdns
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
configdns "github.com/akamai/AkamaiOPEN-edgegrid-golang/configdns-v1"
|
||||
"github.com/akamai/AkamaiOPEN-edgegrid-golang/edgegrid"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
|
@ -18,19 +18,24 @@ type DNSProvider struct {
|
|||
// NewDNSProvider uses the supplied environment variables to return a DNSProvider instance:
|
||||
// AKAMAI_HOST, AKAMAI_CLIENT_TOKEN, AKAMAI_CLIENT_SECRET, AKAMAI_ACCESS_TOKEN
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
host := os.Getenv("AKAMAI_HOST")
|
||||
clientToken := os.Getenv("AKAMAI_CLIENT_TOKEN")
|
||||
clientSecret := os.Getenv("AKAMAI_CLIENT_SECRET")
|
||||
accessToken := os.Getenv("AKAMAI_ACCESS_TOKEN")
|
||||
values, err := env.Get("AKAMAI_HOST", "AKAMAI_CLIENT_TOKEN", "AKAMAI_CLIENT_SECRET", "AKAMAI_ACCESS_TOKEN")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FastDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderClient(host, clientToken, clientSecret, accessToken)
|
||||
return NewDNSProviderClient(
|
||||
values["AKAMAI_HOST"],
|
||||
values["AKAMAI_CLIENT_TOKEN"],
|
||||
values["AKAMAI_CLIENT_SECRET"],
|
||||
values["AKAMAI_ACCESS_TOKEN"],
|
||||
)
|
||||
}
|
||||
|
||||
// NewDNSProviderClient uses the supplied parameters to return a DNSProvider instance
|
||||
// configured for FastDNS.
|
||||
func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (*DNSProvider, error) {
|
||||
if clientToken == "" || clientSecret == "" || accessToken == "" || host == "" {
|
||||
return nil, fmt.Errorf("Akamai FastDNS credentials missing")
|
||||
return nil, fmt.Errorf("FastDNS credentials are missing")
|
||||
}
|
||||
config := edgegrid.Config{
|
||||
Host: host,
|
||||
|
@ -46,14 +51,14 @@ func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fullfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
zoneName, recordName, err := c.findZoneAndRecordName(fqdn, domain)
|
||||
zoneName, recordName, err := d.findZoneAndRecordName(fqdn, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configdns.Init(c.config)
|
||||
configdns.Init(d.config)
|
||||
|
||||
zone, err := configdns.GetZone(zoneName)
|
||||
if err != nil {
|
||||
|
@ -66,35 +71,35 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
record.SetField("target", value)
|
||||
record.SetField("active", true)
|
||||
|
||||
existingRecord := c.findExistingRecord(zone, recordName)
|
||||
existingRecord := d.findExistingRecord(zone, recordName)
|
||||
|
||||
if existingRecord != nil {
|
||||
if reflect.DeepEqual(existingRecord.ToMap(), record.ToMap()) {
|
||||
return nil
|
||||
}
|
||||
zone.RemoveRecord(existingRecord)
|
||||
return c.createRecord(zone, record)
|
||||
return d.createRecord(zone, record)
|
||||
}
|
||||
|
||||
return c.createRecord(zone, record)
|
||||
return d.createRecord(zone, record)
|
||||
}
|
||||
|
||||
// CleanUp removes the record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zoneName, recordName, err := c.findZoneAndRecordName(fqdn, domain)
|
||||
zoneName, recordName, err := d.findZoneAndRecordName(fqdn, domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configdns.Init(c.config)
|
||||
configdns.Init(d.config)
|
||||
|
||||
zone, err := configdns.GetZone(zoneName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
existingRecord := c.findExistingRecord(zone, recordName)
|
||||
existingRecord := d.findExistingRecord(zone, recordName)
|
||||
|
||||
if existingRecord != nil {
|
||||
err := zone.RemoveRecord(existingRecord)
|
||||
|
@ -107,7 +112,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string, error) {
|
||||
func (d *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string, error) {
|
||||
zone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
|
@ -119,7 +124,7 @@ func (c *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string
|
|||
return zone, name, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string) *configdns.TxtRecord {
|
||||
func (d *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string) *configdns.TxtRecord {
|
||||
for _, r := range zone.Zone.Txt {
|
||||
if r.Name == recordName {
|
||||
return r
|
||||
|
@ -129,7 +134,7 @@ func (c *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) createRecord(zone *configdns.Zone, record *configdns.TxtRecord) error {
|
||||
func (d *DNSProvider) createRecord(zone *configdns.Zone, record *configdns.TxtRecord) error {
|
||||
err := zone.AddRecord(record)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
38
vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go
generated
vendored
38
vendor/github.com/xenolf/lego/providers/dns/gandi/gandi.go
generated
vendored
|
@ -9,12 +9,12 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Gandi API reference: http://doc.rpc.gandi.net/index.html
|
||||
|
@ -44,25 +44,31 @@ type DNSProvider struct {
|
|||
inProgressFQDNs map[string]inProgressInfo
|
||||
inProgressAuthZones map[string]struct{}
|
||||
inProgressMu sync.Mutex
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("GANDI_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GandiDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["GANDI_API_KEY"])
|
||||
}
|
||||
|
||||
// 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 nil, fmt.Errorf("no Gandi API Key given")
|
||||
}
|
||||
return &DNSProvider{
|
||||
apiKey: apiKey,
|
||||
inProgressFQDNs: make(map[string]inProgressInfo),
|
||||
inProgressAuthZones: make(map[string]struct{}),
|
||||
client: &http.Client{Timeout: 60 * time.Second},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -269,10 +275,8 @@ func (e rpcError) Error() string {
|
|||
"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)
|
||||
func (d *DNSProvider) httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
|
||||
resp, err := d.client.Post(url, bodyType, body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Gandi DNS: HTTP Post Error: %v", err)
|
||||
}
|
||||
|
@ -290,7 +294,7 @@ func httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
|
|||
// 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 {
|
||||
func (d *DNSProvider) rpcCall(call *methodCall, resp response) error {
|
||||
// marshal
|
||||
b, err := xml.MarshalIndent(call, "", " ")
|
||||
if err != nil {
|
||||
|
@ -299,7 +303,7 @@ func rpcCall(call *methodCall, resp response) error {
|
|||
|
||||
// post
|
||||
b = append([]byte(`<?xml version="1.0"?>`+"\n"), b...)
|
||||
respBody, err := httpPost(endpoint, "text/xml", bytes.NewReader(b))
|
||||
respBody, err := d.httpPost(endpoint, "text/xml", bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -320,7 +324,7 @@ func rpcCall(call *methodCall, resp response) error {
|
|||
|
||||
func (d *DNSProvider) getZoneID(domain string) (int, error) {
|
||||
resp := &responseStruct{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.info",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -347,7 +351,7 @@ func (d *DNSProvider) getZoneID(domain string) (int, error) {
|
|||
|
||||
func (d *DNSProvider) cloneZone(zoneID int, name string) (int, error) {
|
||||
resp := &responseStruct{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.clone",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -381,7 +385,7 @@ func (d *DNSProvider) cloneZone(zoneID int, name string) (int, error) {
|
|||
|
||||
func (d *DNSProvider) newZoneVersion(zoneID int) (int, error) {
|
||||
resp := &responseInt{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.version.new",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -400,7 +404,7 @@ func (d *DNSProvider) newZoneVersion(zoneID int) (int, error) {
|
|||
|
||||
func (d *DNSProvider) addTXTRecord(zoneID int, version int, name string, value string, ttl int) error {
|
||||
resp := &responseStruct{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.record.add",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -429,7 +433,7 @@ func (d *DNSProvider) addTXTRecord(zoneID int, version int, name string, value s
|
|||
|
||||
func (d *DNSProvider) setZoneVersion(zoneID int, version int) error {
|
||||
resp := &responseBool{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.version.set",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -449,7 +453,7 @@ func (d *DNSProvider) setZoneVersion(zoneID int, version int) error {
|
|||
|
||||
func (d *DNSProvider) setZone(domain string, zoneID int) error {
|
||||
resp := &responseStruct{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.set",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
@ -477,7 +481,7 @@ func (d *DNSProvider) setZone(domain string, zoneID int) error {
|
|||
|
||||
func (d *DNSProvider) deleteZone(zoneID int) error {
|
||||
resp := &responseBool{}
|
||||
err := rpcCall(&methodCall{
|
||||
err := d.rpcCall(&methodCall{
|
||||
MethodName: "domain.zone.delete",
|
||||
Params: []param{
|
||||
paramString{Value: d.apiKey},
|
||||
|
|
26
vendor/github.com/xenolf/lego/providers/dns/gandiv5/gandiv5.go
generated
vendored
26
vendor/github.com/xenolf/lego/providers/dns/gandiv5/gandiv5.go
generated
vendored
|
@ -7,12 +7,13 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/log"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Gandi API reference: http://doc.livedns.gandi.net/
|
||||
|
@ -40,13 +41,18 @@ type DNSProvider struct {
|
|||
apiKey string
|
||||
inProgressFQDNs map[string]inProgressInfo
|
||||
inProgressMu sync.Mutex
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for Gandi.
|
||||
// Credentials must be passed in the environment variable: GANDIV5_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiKey := os.Getenv("GANDIV5_API_KEY")
|
||||
return NewDNSProviderCredentials(apiKey)
|
||||
values, err := env.Get("GANDIV5_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GandiDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["GANDIV5_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -58,6 +64,7 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
|
|||
return &DNSProvider{
|
||||
apiKey: apiKey,
|
||||
inProgressFQDNs: make(map[string]inProgressInfo),
|
||||
client: &http.Client{Timeout: 10 * time.Second},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -165,8 +172,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
|
|||
req.Header.Set("X-Api-Key", d.apiKey)
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -177,7 +183,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
|
|||
}
|
||||
var response responseStruct
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
if err != nil && method != "DELETE" {
|
||||
if err != nil && method != http.MethodDelete {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -188,23 +194,23 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
|
|||
|
||||
func (d *DNSProvider) addTXTRecord(domain string, name string, value string, ttl int) error {
|
||||
target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
|
||||
response, err := d.sendRequest("PUT", target, addFieldRequest{
|
||||
response, err := d.sendRequest(http.MethodPut, target, addFieldRequest{
|
||||
RRSetTTL: ttl,
|
||||
RRSetValues: []string{value},
|
||||
})
|
||||
if response != nil {
|
||||
fmt.Printf("Gandi DNS: %s\n", response.Message)
|
||||
log.Infof("Gandi DNS: %s", response.Message)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DNSProvider) deleteTXTRecord(domain string, name string) error {
|
||||
target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
|
||||
response, err := d.sendRequest("DELETE", target, deleteFieldRequest{
|
||||
response, err := d.sendRequest(http.MethodDelete, target, deleteFieldRequest{
|
||||
Delete: true,
|
||||
})
|
||||
if response != nil && response.Message == "" {
|
||||
fmt.Printf("Gandi DNS: Zone record deleted\n")
|
||||
log.Infof("Gandi DNS: Zone record deleted")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
47
vendor/github.com/xenolf/lego/providers/dns/gcloud/googlecloud.go
generated
vendored
47
vendor/github.com/xenolf/lego/providers/dns/gcloud/googlecloud.go
generated
vendored
|
@ -31,6 +31,7 @@ func NewDNSProvider() (*DNSProvider, error) {
|
|||
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
|
||||
return NewDNSProviderServiceAccount(saFile)
|
||||
}
|
||||
|
||||
project := os.Getenv("GCE_PROJECT")
|
||||
return NewDNSProviderCredentials(project)
|
||||
}
|
||||
|
@ -44,11 +45,11 @@ func NewDNSProviderCredentials(project string) (*DNSProvider, error) {
|
|||
|
||||
client, err := google.DefaultClient(context.Background(), dns.NdevClouddnsReadwriteScope)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to get Google Cloud client: %v", err)
|
||||
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 nil, fmt.Errorf("unable to create Google Cloud DNS service: %v", err)
|
||||
}
|
||||
return &DNSProvider{
|
||||
project: project,
|
||||
|
@ -65,7 +66,7 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
|
|||
|
||||
dat, err := ioutil.ReadFile(saFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to read Service Account file: %v", err)
|
||||
return nil, fmt.Errorf("unable to read Service Account file: %v", err)
|
||||
}
|
||||
|
||||
// read project id from service account file
|
||||
|
@ -74,19 +75,19 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
|
|||
}
|
||||
err = json.Unmarshal(dat, &datJSON)
|
||||
if err != nil || datJSON.ProjectID == "" {
|
||||
return nil, fmt.Errorf("Project ID not found in Google Cloud Service Account file")
|
||||
return nil, fmt.Errorf("project ID not found in Google Cloud Service Account file")
|
||||
}
|
||||
project := datJSON.ProjectID
|
||||
|
||||
conf, err := google.JWTConfigFromJSON(dat, dns.NdevClouddnsReadwriteScope)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to acquire config: %v", err)
|
||||
return nil, fmt.Errorf("unable to acquire config: %v", err)
|
||||
}
|
||||
client := conf.Client(context.Background())
|
||||
|
||||
svc, err := dns.New(client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to create Google Cloud DNS service: %v", err)
|
||||
return nil, fmt.Errorf("unable to create Google Cloud DNS service: %v", err)
|
||||
}
|
||||
return &DNSProvider{
|
||||
project: project,
|
||||
|
@ -95,10 +96,10 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -114,7 +115,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// Look for existing records.
|
||||
list, err := c.client.ResourceRecordSets.List(c.project, zone).Name(fqdn).Type("TXT").Do()
|
||||
list, err := d.client.ResourceRecordSets.List(d.project, zone).Name(fqdn).Type("TXT").Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
change.Deletions = list.Rrsets
|
||||
}
|
||||
|
||||
chg, err := c.client.Changes.Create(c.project, zone, change).Do()
|
||||
chg, err := d.client.Changes.Create(d.project, zone, change).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -132,7 +133,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
for chg.Status == "pending" {
|
||||
time.Sleep(time.Second)
|
||||
|
||||
chg, err = c.client.Changes.Get(c.project, zone, chg.Id).Do()
|
||||
chg, err = d.client.Changes.Get(d.project, zone, chg.Id).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -142,15 +143,15 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records, err := c.findTxtRecords(zone, fqdn)
|
||||
records, err := d.findTxtRecords(zone, fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
change := &dns.Change{
|
||||
Deletions: []*dns.ResourceRecordSet{rec},
|
||||
}
|
||||
_, err = c.client.Changes.Create(c.project, zone, change).Do()
|
||||
_, err = d.client.Changes.Create(d.project, zone, change).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -169,19 +170,19 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
// Timeout customizes the timeout values used by the ACME package for checking
|
||||
// DNS record validity.
|
||||
func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
func (d *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) {
|
||||
func (d *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).
|
||||
zones, err := d.client.ManagedZones.
|
||||
List(d.project).
|
||||
DnsName(authZone).
|
||||
Do()
|
||||
if err != nil {
|
||||
|
@ -189,20 +190,20 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
|||
}
|
||||
|
||||
if len(zones.ManagedZones) == 0 {
|
||||
return "", fmt.Errorf("No matching GoogleCloud domain found for domain %s", authZone)
|
||||
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) {
|
||||
func (d *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSet, error) {
|
||||
|
||||
recs, err := c.client.ResourceRecordSets.List(c.project, zone).Do()
|
||||
recs, err := d.client.ResourceRecordSets.List(d.project, zone).Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
found := []*dns.ResourceRecordSet{}
|
||||
var found []*dns.ResourceRecordSet
|
||||
for _, r := range recs.Rrsets {
|
||||
if r.Type == "TXT" && r.Name == fqdn {
|
||||
found = append(found, r)
|
||||
|
|
38
vendor/github.com/xenolf/lego/providers/dns/glesys/glesys.go
generated
vendored
38
vendor/github.com/xenolf/lego/providers/dns/glesys/glesys.go
generated
vendored
|
@ -7,13 +7,13 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/log"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// GleSYS API reference: https://github.com/GleSYS/API/wiki/API-Documentation
|
||||
|
@ -29,15 +29,19 @@ type DNSProvider struct {
|
|||
apiKey string
|
||||
activeRecords map[string]int
|
||||
inProgressMu sync.Mutex
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for GleSYS.
|
||||
// Credentials must be passed in the environment variables: GLESYS_API_USER
|
||||
// and GLESYS_API_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
apiUser := os.Getenv("GLESYS_API_USER")
|
||||
apiKey := os.Getenv("GLESYS_API_KEY")
|
||||
return NewDNSProviderCredentials(apiUser, apiKey)
|
||||
values, err := env.Get("GLESYS_API_USER", "GLESYS_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GleSYS DNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["GLESYS_API_USER"], values["GLESYS_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -46,10 +50,12 @@ func NewDNSProviderCredentials(apiUser string, apiKey string) (*DNSProvider, err
|
|||
if apiUser == "" || apiKey == "" {
|
||||
return nil, fmt.Errorf("GleSYS DNS: Incomplete credentials provided")
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
apiUser: apiUser,
|
||||
apiKey: apiKey,
|
||||
activeRecords: make(map[string]int),
|
||||
client: &http.Client{Timeout: 10 * time.Second},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -118,7 +124,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
|||
// types for JSON method calls, parameters, and responses
|
||||
|
||||
type addRecordRequest struct {
|
||||
Domainname string `json:"domainname"`
|
||||
DomainName string `json:"domainname"`
|
||||
Host string `json:"host"`
|
||||
Type string `json:"type"`
|
||||
Data string `json:"data"`
|
||||
|
@ -126,7 +132,7 @@ type addRecordRequest struct {
|
|||
}
|
||||
|
||||
type deleteRecordRequest struct {
|
||||
Recordid int `json:"recordid"`
|
||||
RecordID int `json:"recordid"`
|
||||
}
|
||||
|
||||
type responseStruct struct {
|
||||
|
@ -156,8 +162,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
|
|||
req.Header.Set("Content-Type", "application/json")
|
||||
req.SetBasicAuth(d.apiUser, d.apiKey)
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -176,26 +181,27 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
|
|||
// functions to perform API actions
|
||||
|
||||
func (d *DNSProvider) addTXTRecord(fqdn string, domain string, name string, value string, ttl int) (int, error) {
|
||||
response, err := d.sendRequest("POST", "addrecord", addRecordRequest{
|
||||
Domainname: domain,
|
||||
response, err := d.sendRequest(http.MethodPost, "addrecord", addRecordRequest{
|
||||
DomainName: domain,
|
||||
Host: name,
|
||||
Type: "TXT",
|
||||
Data: value,
|
||||
TTL: ttl,
|
||||
})
|
||||
if response != nil && response.Response.Status.Code == 200 {
|
||||
log.Printf("[INFO][%s] GleSYS DNS: Successfully created recordid %d", fqdn, response.Response.Record.Recordid)
|
||||
return response.Response.Record.Recordid, nil
|
||||
|
||||
if response != nil && response.Response.Status.Code == http.StatusOK {
|
||||
log.Infof("[%s] GleSYS DNS: Successfully created record id %d", fqdn, response.Response.Record.RecordID)
|
||||
return response.Response.Record.RecordID, nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (d *DNSProvider) deleteTXTRecord(fqdn string, recordid int) error {
|
||||
response, err := d.sendRequest("POST", "deleterecord", deleteRecordRequest{
|
||||
Recordid: recordid,
|
||||
response, err := d.sendRequest(http.MethodPost, "deleterecord", deleteRecordRequest{
|
||||
RecordID: recordid,
|
||||
})
|
||||
if response != nil && response.Response.Status.Code == 200 {
|
||||
log.Printf("[INFO][%s] GleSYS DNS: Successfully deleted recordid %d", fqdn, recordid)
|
||||
log.Infof("[%s] GleSYS DNS: Successfully deleted record id %d", fqdn, recordid)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
60
vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go
generated
vendored
60
vendor/github.com/xenolf/lego/providers/dns/godaddy/godaddy.go
generated
vendored
|
@ -2,18 +2,17 @@
|
|||
package godaddy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// GoDaddyAPIURL represents the API endpoint to call.
|
||||
|
@ -23,15 +22,19 @@ const apiURL = "https://api.godaddy.com"
|
|||
type DNSProvider struct {
|
||||
apiKey string
|
||||
apiSecret string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("GODADDY_API_KEY", "GODADDY_API_SECRET")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GoDaddy: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["GODADDY_API_KEY"], values["GODADDY_API_SECRET"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -41,16 +44,20 @@ func NewDNSProviderCredentials(apiKey, apiSecret string) (*DNSProvider, error) {
|
|||
return nil, fmt.Errorf("GoDaddy credentials missing")
|
||||
}
|
||||
|
||||
return &DNSProvider{apiKey, apiSecret}, nil
|
||||
return &DNSProvider{
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
client: &http.Client{Timeout: 30 * time.Second},
|
||||
}, 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) {
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return 120 * time.Second, 2 * time.Second
|
||||
}
|
||||
|
||||
func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||
return name[:idx]
|
||||
|
@ -59,9 +66,9 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
domainZone, err := c.getZone(fqdn)
|
||||
domainZone, err := d.getZone(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -70,7 +77,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
ttl = 600
|
||||
}
|
||||
|
||||
recordName := c.extractRecordName(fqdn, domainZone)
|
||||
recordName := d.extractRecordName(fqdn, domainZone)
|
||||
rec := []DNSRecord{
|
||||
{
|
||||
Type: "TXT",
|
||||
|
@ -80,17 +87,17 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
},
|
||||
}
|
||||
|
||||
return c.updateRecords(rec, domainZone, recordName)
|
||||
return d.updateRecords(rec, domainZone, recordName)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) updateRecords(records []DNSRecord, domainZone string, recordName string) error {
|
||||
func (d *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))
|
||||
resp, err = d.makeRequest(http.MethodPut, fmt.Sprintf("/v1/domains/%s/records/TXT/%s", domainZone, recordName), bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -105,14 +112,14 @@ func (c *DNSProvider) updateRecords(records []DNSRecord, domainZone string, reco
|
|||
}
|
||||
|
||||
// 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 {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
domainZone, err := c.getZone(fqdn)
|
||||
domainZone, err := d.getZone(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordName := c.extractRecordName(fqdn, domainZone)
|
||||
recordName := d.extractRecordName(fqdn, domainZone)
|
||||
rec := []DNSRecord{
|
||||
{
|
||||
Type: "TXT",
|
||||
|
@ -121,10 +128,10 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
},
|
||||
}
|
||||
|
||||
return c.updateRecords(rec, domainZone, recordName)
|
||||
return d.updateRecords(rec, domainZone, recordName)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getZone(fqdn string) (string, error) {
|
||||
func (d *DNSProvider) getZone(fqdn string) (string, error) {
|
||||
authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -133,7 +140,7 @@ func (c *DNSProvider) getZone(fqdn string) (string, error) {
|
|||
return acme.UnFqdn(authZone), nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Response, error) {
|
||||
func (d *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
|
||||
|
@ -141,10 +148,9 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Res
|
|||
|
||||
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))
|
||||
req.Header.Set("Authorization", fmt.Sprintf("sso-key %s:%s", d.apiKey, d.apiSecret))
|
||||
|
||||
client := http.Client{Timeout: 30 * time.Second}
|
||||
return client.Do(req)
|
||||
return d.client.Do(req)
|
||||
}
|
||||
|
||||
// DNSRecord a DNS record
|
||||
|
|
34
vendor/github.com/xenolf/lego/providers/dns/lightsail/lightsail.go
generated
vendored
34
vendor/github.com/xenolf/lego/providers/dns/lightsail/lightsail.go
generated
vendored
|
@ -4,6 +4,7 @@ package lightsail
|
|||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
@ -20,7 +21,8 @@ const (
|
|||
|
||||
// DNSProvider implements the acme.ChallengeProvider interface
|
||||
type DNSProvider struct {
|
||||
client *lightsail.Lightsail
|
||||
client *lightsail.Lightsail
|
||||
dnsZone string
|
||||
}
|
||||
|
||||
// customRetryer implements the client.Retryer interface by composing the
|
||||
|
@ -35,7 +37,7 @@ type customRetryer struct {
|
|||
// 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 {
|
||||
func (c customRetryer) RetryRules(r *request.Request) time.Duration {
|
||||
retryCount := r.RetryCount
|
||||
if retryCount > 7 {
|
||||
retryCount = 7
|
||||
|
@ -61,47 +63,53 @@ func (d customRetryer) RetryRules(r *request.Request) time.Duration {
|
|||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
r := customRetryer{}
|
||||
r.NumMaxRetries = maxRetries
|
||||
config := request.WithRetryer(aws.NewConfig(), r)
|
||||
client := lightsail.New(session.New(config))
|
||||
|
||||
config := aws.NewConfig().WithRegion("us-east-1")
|
||||
sess, err := session.NewSession(request.WithRetryer(config, r))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
dnsZone: os.Getenv("DNS_ZONE"),
|
||||
client: lightsail.New(sess),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters
|
||||
func (r *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
value = `"` + value + `"`
|
||||
err := r.newTxtRecord(domain, fqdn, value)
|
||||
|
||||
err := d.newTxtRecord(domain, fqdn, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
value = `"` + value + `"`
|
||||
params := &lightsail.DeleteDomainEntryInput{
|
||||
DomainName: aws.String(domain),
|
||||
DomainName: aws.String(d.dnsZone),
|
||||
DomainEntry: &lightsail.DomainEntry{
|
||||
Name: aws.String(fqdn),
|
||||
Type: aws.String("TXT"),
|
||||
Target: aws.String(value),
|
||||
},
|
||||
}
|
||||
_, err := r.client.DeleteDomainEntry(params)
|
||||
_, err := d.client.DeleteDomainEntry(params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *DNSProvider) newTxtRecord(domain string, fqdn string, value string) error {
|
||||
func (d *DNSProvider) newTxtRecord(domain string, fqdn string, value string) error {
|
||||
params := &lightsail.CreateDomainEntryInput{
|
||||
DomainName: aws.String(domain),
|
||||
DomainName: aws.String(d.dnsZone),
|
||||
DomainEntry: &lightsail.DomainEntry{
|
||||
Name: aws.String(fqdn),
|
||||
Target: aws.String(value),
|
||||
Type: aws.String("TXT"),
|
||||
},
|
||||
}
|
||||
_, err := r.client.CreateDomainEntry(params)
|
||||
_, err := d.client.CreateDomainEntry(params)
|
||||
return err
|
||||
}
|
||||
|
|
23
vendor/github.com/xenolf/lego/providers/dns/linode/linode.go
generated
vendored
23
vendor/github.com/xenolf/lego/providers/dns/linode/linode.go
generated
vendored
|
@ -4,12 +4,13 @@ package linode
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/timewasted/linode/dns"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -25,14 +26,18 @@ type hostedZoneInfo struct {
|
|||
|
||||
// DNSProvider implements the acme.ChallengeProvider interface.
|
||||
type DNSProvider struct {
|
||||
linode *dns.DNS
|
||||
client *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)
|
||||
values, err := env.Get("LINODE_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Linode: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["LINODE_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -43,7 +48,7 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
return &DNSProvider{
|
||||
linode: dns.New(apiKey),
|
||||
client: dns.New(apiKey),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -72,7 +77,7 @@ func (p *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if _, err = p.linode.CreateDomainResourceTXT(zone.domainID, acme.UnFqdn(fqdn), value, 60); err != nil {
|
||||
if _, err = p.client.CreateDomainResourceTXT(zone.domainID, acme.UnFqdn(fqdn), value, 60); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -88,7 +93,7 @@ func (p *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// Get all TXT records for the specified domain.
|
||||
resources, err := p.linode.GetResourcesByType(zone.domainID, "TXT")
|
||||
resources, err := p.client.GetResourcesByType(zone.domainID, "TXT")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -96,7 +101,7 @@ func (p *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
// 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)
|
||||
resp, err := p.client.DeleteDomainResource(resource.DomainID, resource.ResourceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -119,7 +124,7 @@ func (p *DNSProvider) getHostedZoneInfo(fqdn string) (*hostedZoneInfo, error) {
|
|||
resourceName := strings.TrimSuffix(fqdn, "."+authZone)
|
||||
|
||||
// Query the authority zone.
|
||||
domain, err := p.linode.GetDomain(acme.UnFqdn(authZone))
|
||||
domain, err := p.client.GetDomain(acme.UnFqdn(authZone))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
35
vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go
generated
vendored
35
vendor/github.com/xenolf/lego/providers/dns/namecheap/namecheap.go
generated
vendored
|
@ -8,11 +8,12 @@ import (
|
|||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/log"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// Notes about namecheap's tool API:
|
||||
|
@ -32,7 +33,6 @@ 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
|
||||
|
@ -42,15 +42,19 @@ type DNSProvider struct {
|
|||
apiUser string
|
||||
apiKey string
|
||||
clientIP string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("NAMECHEAP_API_USER", "NAMECHEAP_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NameCheap: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["NAMECHEAP_API_USER"], values["NAMECHEAP_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -60,7 +64,9 @@ func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
|
|||
return nil, fmt.Errorf("Namecheap credentials missing")
|
||||
}
|
||||
|
||||
clientIP, err := getClientIP()
|
||||
client := &http.Client{Timeout: 60 * time.Second}
|
||||
|
||||
clientIP, err := getClientIP(client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,6 +76,7 @@ func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
|
|||
apiUser: apiUser,
|
||||
apiKey: apiKey,
|
||||
clientIP: clientIP,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -99,8 +106,8 @@ type apierror struct {
|
|||
|
||||
// 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)
|
||||
func getClientIP(client *http.Client) (addr string, err error) {
|
||||
resp, err := client.Get(getIPURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -112,12 +119,12 @@ func getClientIP() (addr string, err error) {
|
|||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println("Client IP:", string(clientIP))
|
||||
log.Println("Client IP:", string(clientIP))
|
||||
}
|
||||
return string(clientIP), nil
|
||||
}
|
||||
|
||||
// A challenge repesents all the data needed to specify a dns-01 challenge
|
||||
// A challenge represents all the data needed to specify a dns-01 challenge
|
||||
// to lets-encrypt.
|
||||
type challenge struct {
|
||||
domain string
|
||||
|
@ -186,7 +193,7 @@ func (d *DNSProvider) getTLDs() (tlds map[string]string, err error) {
|
|||
reqURL, _ := url.Parse(d.baseURL)
|
||||
reqURL.RawQuery = values.Encode()
|
||||
|
||||
resp, err := httpClient.Get(reqURL.String())
|
||||
resp, err := d.client.Get(reqURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -235,7 +242,7 @@ func (d *DNSProvider) getHosts(ch *challenge) (hosts []host, err error) {
|
|||
reqURL, _ := url.Parse(d.baseURL)
|
||||
reqURL.RawQuery = values.Encode()
|
||||
|
||||
resp, err := httpClient.Get(reqURL.String())
|
||||
resp, err := d.client.Get(reqURL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -285,7 +292,7 @@ func (d *DNSProvider) setHosts(ch *challenge, hosts []host) error {
|
|||
values.Add("TTL"+ind, h.TTL)
|
||||
}
|
||||
|
||||
resp, err := httpClient.PostForm(d.baseURL, values)
|
||||
resp, err := d.client.PostForm(d.baseURL, values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -382,7 +389,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
|
||||
if debug {
|
||||
for _, h := range hosts {
|
||||
fmt.Printf(
|
||||
log.Printf(
|
||||
"%-5.5s %-30.30s %-6s %-70.70s\n",
|
||||
h.Type, h.Name, h.TTL, h.Address)
|
||||
}
|
||||
|
|
31
vendor/github.com/xenolf/lego/providers/dns/namedotcom/namedotcom.go
generated
vendored
31
vendor/github.com/xenolf/lego/providers/dns/namedotcom/namedotcom.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/namedotcom/go/namecom"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
|
@ -19,11 +20,13 @@ type DNSProvider struct {
|
|||
// NewDNSProvider returns a DNSProvider instance configured for namedotcom.
|
||||
// Credentials must be passed in the environment variables: NAMECOM_USERNAME and NAMECOM_API_TOKEN
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
username := os.Getenv("NAMECOM_USERNAME")
|
||||
apiToken := os.Getenv("NAMECOM_API_TOKEN")
|
||||
server := os.Getenv("NAMECOM_SERVER")
|
||||
values, err := env.Get("NAMECOM_USERNAME", "NAMECOM_API_TOKEN")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Name.com: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(username, apiToken, server)
|
||||
server := os.Getenv("NAMECOM_SERVER")
|
||||
return NewDNSProviderCredentials(values["NAMECOM_USERNAME"], values["NAMECOM_API_TOKEN"], server)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -46,30 +49,30 @@ func NewDNSProviderCredentials(username, apiToken, server string) (*DNSProvider,
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
request := &namecom.Record{
|
||||
DomainName: domain,
|
||||
Host: c.extractRecordName(fqdn, domain),
|
||||
Host: d.extractRecordName(fqdn, domain),
|
||||
Type: "TXT",
|
||||
TTL: uint32(ttl),
|
||||
Answer: value,
|
||||
}
|
||||
|
||||
_, err := c.client.CreateRecord(request)
|
||||
_, err := d.client.CreateRecord(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("namedotcom API call failed: %v", err)
|
||||
return fmt.Errorf("Name.com 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 {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
records, err := c.getRecords(domain)
|
||||
records, err := d.getRecords(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -80,7 +83,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
DomainName: domain,
|
||||
ID: rec.ID,
|
||||
}
|
||||
_, err := c.client.DeleteRecord(request)
|
||||
_, err := d.client.DeleteRecord(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -90,7 +93,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
|
||||
func (d *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
|
||||
var (
|
||||
err error
|
||||
records []*namecom.Record
|
||||
|
@ -103,7 +106,7 @@ func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
|
|||
}
|
||||
|
||||
for request.Page > 0 {
|
||||
response, err = c.client.ListRecords(request)
|
||||
response, err = d.client.ListRecords(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -115,7 +118,7 @@ func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
|
|||
return records, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||
return name[:idx]
|
||||
|
|
235
vendor/github.com/xenolf/lego/providers/dns/nifcloud/client.go
generated
vendored
Normal file
235
vendor/github.com/xenolf/lego/providers/dns/nifcloud/client.go
generated
vendored
Normal file
|
@ -0,0 +1,235 @@
|
|||
// Package nifcloud implements a DNS provider for solving the DNS-01 challenge
|
||||
// using NIFCLOUD DNS.
|
||||
package nifcloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultEndpoint = "https://dns.api.cloud.nifty.com"
|
||||
apiVersion = "2012-12-12N2013-12-16"
|
||||
xmlNs = "https://route53.amazonaws.com/doc/2012-12-12/"
|
||||
)
|
||||
|
||||
// ChangeResourceRecordSetsRequest is a complex type that contains change information for the resource record set.
|
||||
type ChangeResourceRecordSetsRequest struct {
|
||||
XMLNs string `xml:"xmlns,attr"`
|
||||
ChangeBatch ChangeBatch `xml:"ChangeBatch"`
|
||||
}
|
||||
|
||||
// ChangeResourceRecordSetsResponse is a complex type containing the response for the request.
|
||||
type ChangeResourceRecordSetsResponse struct {
|
||||
ChangeInfo ChangeInfo `xml:"ChangeInfo"`
|
||||
}
|
||||
|
||||
// GetChangeResponse is a complex type that contains the ChangeInfo element.
|
||||
type GetChangeResponse struct {
|
||||
ChangeInfo ChangeInfo `xml:"ChangeInfo"`
|
||||
}
|
||||
|
||||
// ErrorResponse is the information for any errors.
|
||||
type ErrorResponse struct {
|
||||
Error struct {
|
||||
Type string `xml:"Type"`
|
||||
Message string `xml:"Message"`
|
||||
Code string `xml:"Code"`
|
||||
} `xml:"Error"`
|
||||
RequestID string `xml:"RequestId"`
|
||||
}
|
||||
|
||||
// ChangeBatch is the information for a change request.
|
||||
type ChangeBatch struct {
|
||||
Changes Changes `xml:"Changes"`
|
||||
Comment string `xml:"Comment"`
|
||||
}
|
||||
|
||||
// Changes is array of Change.
|
||||
type Changes struct {
|
||||
Change []Change `xml:"Change"`
|
||||
}
|
||||
|
||||
// Change is the information for each resource record set that you want to change.
|
||||
type Change struct {
|
||||
Action string `xml:"Action"`
|
||||
ResourceRecordSet ResourceRecordSet `xml:"ResourceRecordSet"`
|
||||
}
|
||||
|
||||
// ResourceRecordSet is the information about the resource record set to create or delete.
|
||||
type ResourceRecordSet struct {
|
||||
Name string `xml:"Name"`
|
||||
Type string `xml:"Type"`
|
||||
TTL int `xml:"TTL"`
|
||||
ResourceRecords ResourceRecords `xml:"ResourceRecords"`
|
||||
}
|
||||
|
||||
// ResourceRecords is array of ResourceRecord.
|
||||
type ResourceRecords struct {
|
||||
ResourceRecord []ResourceRecord `xml:"ResourceRecord"`
|
||||
}
|
||||
|
||||
// ResourceRecord is the information specific to the resource record.
|
||||
type ResourceRecord struct {
|
||||
Value string `xml:"Value"`
|
||||
}
|
||||
|
||||
// ChangeInfo is A complex type that describes change information about changes made to your hosted zone.
|
||||
type ChangeInfo struct {
|
||||
ID string `xml:"Id"`
|
||||
Status string `xml:"Status"`
|
||||
SubmittedAt string `xml:"SubmittedAt"`
|
||||
}
|
||||
|
||||
func newClient(httpClient *http.Client, accessKey string, secretKey string, endpoint string) *Client {
|
||||
client := http.DefaultClient
|
||||
if httpClient != nil {
|
||||
client = httpClient
|
||||
}
|
||||
|
||||
return &Client{
|
||||
accessKey: accessKey,
|
||||
secretKey: secretKey,
|
||||
endpoint: endpoint,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
// Client client of NIFCLOUD DNS
|
||||
type Client struct {
|
||||
accessKey string
|
||||
secretKey string
|
||||
endpoint string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// ChangeResourceRecordSets Call ChangeResourceRecordSets API and return response.
|
||||
func (c *Client) ChangeResourceRecordSets(hostedZoneID string, input ChangeResourceRecordSetsRequest) (*ChangeResourceRecordSetsResponse, error) {
|
||||
requestURL := fmt.Sprintf("%s/%s/hostedzone/%s/rrset", c.endpoint, apiVersion, hostedZoneID)
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
body.Write([]byte(xml.Header))
|
||||
err := xml.NewEncoder(body).Encode(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, requestURL, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "text/xml; charset=utf-8")
|
||||
|
||||
err = c.sign(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred during the creation of the signature: %v", err)
|
||||
}
|
||||
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Body == nil {
|
||||
return nil, errors.New("the response body is nil")
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
errResp := &ErrorResponse{}
|
||||
err = xml.NewDecoder(res.Body).Decode(errResp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred while unmarshaling the error body to XML: %v", err)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("an error occurred: %s", errResp.Error.Message)
|
||||
}
|
||||
|
||||
output := &ChangeResourceRecordSetsResponse{}
|
||||
err = xml.NewDecoder(res.Body).Decode(output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred while unmarshaling the response body to XML: %v", err)
|
||||
}
|
||||
|
||||
return output, err
|
||||
}
|
||||
|
||||
// GetChange Call GetChange API and return response.
|
||||
func (c *Client) GetChange(statusID string) (*GetChangeResponse, error) {
|
||||
requestURL := fmt.Sprintf("%s/%s/change/%s", c.endpoint, apiVersion, statusID)
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, requestURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = c.sign(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred during the creation of the signature: %v", err)
|
||||
}
|
||||
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Body == nil {
|
||||
return nil, errors.New("the response body is nil")
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
errResp := &ErrorResponse{}
|
||||
err = xml.NewDecoder(res.Body).Decode(errResp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred while unmarshaling the error body to XML: %v", err)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("an error occurred: %s", errResp.Error.Message)
|
||||
}
|
||||
|
||||
output := &GetChangeResponse{}
|
||||
err = xml.NewDecoder(res.Body).Decode(output)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("an error occurred while unmarshaling the response body to XML: %v", err)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (c *Client) sign(req *http.Request) error {
|
||||
if req.Header.Get("Date") == "" {
|
||||
location, err := time.LoadLocation("GMT")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Date", time.Now().In(location).Format(time.RFC1123))
|
||||
}
|
||||
|
||||
if req.URL.Path == "" {
|
||||
req.URL.Path += "/"
|
||||
}
|
||||
|
||||
mac := hmac.New(sha1.New, []byte(c.secretKey))
|
||||
_, err := mac.Write([]byte(req.Header.Get("Date")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hashed := mac.Sum(nil)
|
||||
signature := base64.StdEncoding.EncodeToString(hashed)
|
||||
|
||||
auth := fmt.Sprintf("NIFTY3-HTTPS NiftyAccessKeyId=%s,Algorithm=HmacSHA1,Signature=%s", c.accessKey, signature)
|
||||
req.Header.Set("X-Nifty-Authorization", auth)
|
||||
|
||||
return nil
|
||||
}
|
103
vendor/github.com/xenolf/lego/providers/dns/nifcloud/nifcloud.go
generated
vendored
Normal file
103
vendor/github.com/xenolf/lego/providers/dns/nifcloud/nifcloud.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Package nifcloud implements a DNS provider for solving the DNS-01 challenge
|
||||
// using NIFCLOUD DNS.
|
||||
package nifcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider implements the acme.ChallengeProvider interface
|
||||
type DNSProvider struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for the NIFCLOUD DNS service.
|
||||
// Credentials must be passed in the environment variables: NIFCLOUD_ACCESS_KEY_ID and NIFCLOUD_SECRET_ACCESS_KEY.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get("NIFCLOUD_ACCESS_KEY_ID", "NIFCLOUD_SECRET_ACCESS_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NIFCLOUD: %v", err)
|
||||
}
|
||||
|
||||
endpoint := os.Getenv("NIFCLOUD_DNS_ENDPOINT")
|
||||
if endpoint == "" {
|
||||
endpoint = defaultEndpoint
|
||||
}
|
||||
|
||||
httpClient := &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
return NewDNSProviderCredentials(httpClient, endpoint, values["NIFCLOUD_ACCESS_KEY_ID"], values["NIFCLOUD_SECRET_ACCESS_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for NIFCLOUD.
|
||||
func NewDNSProviderCredentials(httpClient *http.Client, endpoint, accessKey, secretKey string) (*DNSProvider, error) {
|
||||
client := newClient(httpClient, accessKey, secretKey, endpoint)
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
}, 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)
|
||||
return d.changeRecord("CREATE", fqdn, value, domain, ttl)
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
return d.changeRecord("DELETE", fqdn, value, domain, ttl)
|
||||
}
|
||||
|
||||
func (d *DNSProvider) changeRecord(action, fqdn, value, domain string, ttl int) error {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
|
||||
reqParams := ChangeResourceRecordSetsRequest{
|
||||
XMLNs: xmlNs,
|
||||
ChangeBatch: ChangeBatch{
|
||||
Comment: "Managed by Lego",
|
||||
Changes: Changes{
|
||||
Change: []Change{
|
||||
{
|
||||
Action: action,
|
||||
ResourceRecordSet: ResourceRecordSet{
|
||||
Name: name,
|
||||
Type: "TXT",
|
||||
TTL: ttl,
|
||||
ResourceRecords: ResourceRecords{
|
||||
ResourceRecord: []ResourceRecord{
|
||||
{
|
||||
Value: value,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := d.client.ChangeResourceRecordSets(domain, reqParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to change NIFCLOUD record set: %v", err)
|
||||
}
|
||||
|
||||
statusID := resp.ChangeInfo.ID
|
||||
|
||||
return acme.WaitFor(120*time.Second, 4*time.Second, func() (bool, error) {
|
||||
resp, err := d.client.GetChange(statusID)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to query NIFCLOUD DNS change status: %v", err)
|
||||
}
|
||||
return resp.ChangeInfo.Status == "INSYNC", nil
|
||||
})
|
||||
}
|
31
vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go
generated
vendored
31
vendor/github.com/xenolf/lego/providers/dns/ns1/ns1.go
generated
vendored
|
@ -5,10 +5,10 @@ package ns1
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
"gopkg.in/ns1/ns1-go.v2/rest"
|
||||
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
|
||||
)
|
||||
|
@ -21,11 +21,12 @@ type DNSProvider struct {
|
|||
// 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")
|
||||
values, err := env.Get("NS1_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NS1: %v", err)
|
||||
}
|
||||
return NewDNSProviderCredentials(key)
|
||||
|
||||
return NewDNSProviderCredentials(values["NS1_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -42,16 +43,16 @@ func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
|
|||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := c.newTxtRecord(zone, fqdn, value, ttl)
|
||||
_, err = c.client.Records.Create(record)
|
||||
record := d.newTxtRecord(zone, fqdn, value, ttl)
|
||||
_, err = d.client.Records.Create(record)
|
||||
if err != nil && err != rest.ErrRecordExists {
|
||||
return err
|
||||
}
|
||||
|
@ -60,21 +61,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZone(domain)
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := acme.UnFqdn(fqdn)
|
||||
_, err = c.client.Records.Delete(zone.Zone, name, "TXT")
|
||||
_, err = d.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)
|
||||
func (d *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
|
||||
zone, _, err := d.client.Zones.Get(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ func (c *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
|
|||
return zone, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record {
|
||||
func (d *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
|
||||
return &dns.Record{
|
||||
|
|
10
vendor/github.com/xenolf/lego/providers/dns/otc/mock.go
generated
vendored
10
vendor/github.com/xenolf/lego/providers/dns/otc/mock.go
generated
vendored
|
@ -77,7 +77,7 @@ func (m *DNSMock) HandleListZonesSuccessfully() {
|
|||
}]}
|
||||
`)
|
||||
|
||||
assert.Equal(m.t, r.Method, "GET")
|
||||
assert.Equal(m.t, r.Method, http.MethodGet)
|
||||
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")
|
||||
|
@ -92,7 +92,7 @@ func (m *DNSMock) HandleListZonesEmpty() {
|
|||
]}
|
||||
`)
|
||||
|
||||
assert.Equal(m.t, r.Method, "GET")
|
||||
assert.Equal(m.t, r.Method, http.MethodGet)
|
||||
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")
|
||||
|
@ -108,7 +108,7 @@ func (m *DNSMock) HandleDeleteRecordsetsSuccessfully() {
|
|||
}]}
|
||||
`)
|
||||
|
||||
assert.Equal(m.t, r.Method, "DELETE")
|
||||
assert.Equal(m.t, r.Method, http.MethodDelete)
|
||||
assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets/321321")
|
||||
assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
|
||||
})
|
||||
|
@ -130,7 +130,7 @@ func (m *DNSMock) HandleListRecordsetsEmpty() {
|
|||
// HandleListRecordsetsSuccessfully Handle list recordsets successfully
|
||||
func (m *DNSMock) HandleListRecordsetsSuccessfully() {
|
||||
m.Mux.HandleFunc("/v2/zones/123123/recordsets", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
if r.Method == http.MethodGet {
|
||||
fmt.Fprintf(w, `{
|
||||
"recordsets":[{
|
||||
"id":"321321"
|
||||
|
@ -140,7 +140,7 @@ func (m *DNSMock) HandleListRecordsetsSuccessfully() {
|
|||
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" {
|
||||
} else if r.Method == http.MethodPost {
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
assert.Nil(m.t, err)
|
||||
|
|
29
vendor/github.com/xenolf/lego/providers/dns/otc/otc.go
generated
vendored
29
vendor/github.com/xenolf/lego/providers/dns/otc/otc.go
generated
vendored
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface that uses
|
||||
|
@ -31,12 +32,18 @@ type DNSProvider struct {
|
|||
// 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)
|
||||
values, err := env.Get("OTC_DOMAIN_NAME", "OTC_USER_NAME", "OTC_PASSWORD", "OTC_PROJECT_NAME")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("OTC: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(
|
||||
values["OTC_DOMAIN_NAME"],
|
||||
values["OTC_USER_NAME"],
|
||||
values["OTC_PASSWORD"],
|
||||
values["OTC_PROJECT_NAME"],
|
||||
os.Getenv("OTC_IDENTITY_ENDPOINT"),
|
||||
)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -163,7 +170,7 @@ func (d *DNSProvider) loginRequest() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest("POST", d.identityEndpoint, bytes.NewReader(body))
|
||||
req, err := http.NewRequest(http.MethodPost, d.identityEndpoint, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -235,7 +242,7 @@ func (d *DNSProvider) getZoneID(zone string) (string, error) {
|
|||
}
|
||||
|
||||
resource := fmt.Sprintf("zones?name=%s", zone)
|
||||
resp, err := d.SendRequest("GET", resource, nil)
|
||||
resp, err := d.SendRequest(http.MethodGet, resource, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -271,7 +278,7 @@ func (d *DNSProvider) getRecordSetID(zoneID string, fqdn string) (string, error)
|
|||
}
|
||||
|
||||
resource := fmt.Sprintf("zones/%s/recordsets?type=TXT&name=%s", zoneID, fqdn)
|
||||
resp, err := d.SendRequest("GET", resource, nil)
|
||||
resp, err := d.SendRequest(http.MethodGet, resource, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -300,7 +307,7 @@ func (d *DNSProvider) getRecordSetID(zoneID string, fqdn string) (string, error)
|
|||
func (d *DNSProvider) deleteRecordSet(zoneID, recordID string) error {
|
||||
resource := fmt.Sprintf("zones/%s/recordsets/%s", zoneID, recordID)
|
||||
|
||||
_, err := d.SendRequest("DELETE", resource, nil)
|
||||
_, err := d.SendRequest(http.MethodDelete, resource, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -344,7 +351,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
TTL: ttl,
|
||||
Records: []string{fmt.Sprintf("\"%s\"", value)},
|
||||
}
|
||||
_, err = d.SendRequest("POST", resource, r1)
|
||||
_, err = d.SendRequest(http.MethodPost, resource, r1)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
27
vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go
generated
vendored
27
vendor/github.com/xenolf/lego/providers/dns/ovh/ovh.go
generated
vendored
|
@ -4,12 +4,12 @@ package ovh
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ovh/go-ovh/ovh"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// OVH API reference: https://eu.api.ovh.com/
|
||||
|
@ -30,11 +30,17 @@ type DNSProvider struct {
|
|||
// 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)
|
||||
values, err := env.Get("OVH_ENDPOINT", "OVH_APPLICATION_KEY", "OVH_APPLICATION_SECRET", "OVH_CONSUMER_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("OVH: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(
|
||||
values["OVH_ENDPOINT"],
|
||||
values["OVH_APPLICATION_KEY"],
|
||||
values["OVH_APPLICATION_SECRET"],
|
||||
values["OVH_CONSUMER_KEY"],
|
||||
)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -96,16 +102,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
// 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
|
||||
return fmt.Errorf("error when call OVH api to add record: %v", 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
|
||||
return fmt.Errorf("error when call OVH api to refresh zone: %v", err)
|
||||
}
|
||||
|
||||
d.recordIDsMu.Lock()
|
||||
|
@ -138,8 +142,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
|
||||
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
|
||||
return fmt.Errorf("error when call OVH api to delete challenge record: %v", err)
|
||||
}
|
||||
|
||||
// Delete record ID from map
|
||||
|
|
100
vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go
generated
vendored
100
vendor/github.com/xenolf/lego/providers/dns/pdns/pdns.go
generated
vendored
|
@ -9,12 +9,13 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/log"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface
|
||||
|
@ -22,19 +23,24 @@ type DNSProvider struct {
|
|||
apiKey string
|
||||
host *url.URL
|
||||
apiVersion int
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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"))
|
||||
values, err := env.Get("PDNS_API_KEY", "PDNS_API_URL")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("PDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(hostURL, key)
|
||||
hostURL, err := url.Parse(values["PDNS_API_URL"])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("PDNS: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(hostURL, values["PDNS_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -48,25 +54,31 @@ func NewDNSProviderCredentials(host *url.URL, key string) (*DNSProvider, error)
|
|||
return nil, fmt.Errorf("PDNS API URL missing")
|
||||
}
|
||||
|
||||
provider := &DNSProvider{
|
||||
d := &DNSProvider{
|
||||
host: host,
|
||||
apiKey: key,
|
||||
client: &http.Client{Timeout: 30 * time.Second},
|
||||
}
|
||||
provider.getAPIVersion()
|
||||
|
||||
return provider, nil
|
||||
apiVersion, err := d.getAPIVersion()
|
||||
if err != nil {
|
||||
log.Warnf("PDNS: failed to get API version %v", err)
|
||||
}
|
||||
d.apiVersion = apiVersion
|
||||
|
||||
return d, 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) {
|
||||
func (d *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 {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zone, err := c.getHostedZone(fqdn)
|
||||
zone, err := d.getHostedZone(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,7 +86,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
name := fqdn
|
||||
|
||||
// pre-v1 API wants non-fqdn
|
||||
if c.apiVersion == 0 {
|
||||
if d.apiVersion == 0 {
|
||||
name = acme.UnFqdn(fqdn)
|
||||
}
|
||||
|
||||
|
@ -106,20 +118,20 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
|
||||
_, err = d.makeRequest(http.MethodPatch, zone.URL, bytes.NewReader(body))
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := c.getHostedZone(fqdn)
|
||||
zone, err := d.getHostedZone(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
set, err := c.findTxtRecord(fqdn)
|
||||
set, err := d.findTxtRecord(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -138,11 +150,11 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
|
||||
_, err = d.makeRequest(http.MethodPatch, zone.URL, bytes.NewReader(body))
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
|
||||
func (d *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
|
||||
var zone hostedZone
|
||||
authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
|
@ -150,12 +162,12 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
|
|||
}
|
||||
|
||||
url := "/servers/localhost/zones"
|
||||
result, err := c.makeRequest("GET", url, nil)
|
||||
result, err := d.makeRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zones := []hostedZone{}
|
||||
var zones []hostedZone
|
||||
err = json.Unmarshal(result, &zones)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -168,7 +180,7 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
|
|||
}
|
||||
}
|
||||
|
||||
result, err = c.makeRequest("GET", url, nil)
|
||||
result, err = d.makeRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -194,13 +206,13 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
|
|||
return &zone, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
|
||||
zone, err := c.getHostedZone(fqdn)
|
||||
func (d *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
|
||||
zone, err := d.getHostedZone(fqdn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("GET", zone.URL, nil)
|
||||
_, err = d.makeRequest(http.MethodGet, zone.URL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -214,21 +226,21 @@ func (c *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
|
|||
return nil, fmt.Errorf("no existing record found for %s", fqdn)
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getAPIVersion() {
|
||||
func (d *DNSProvider) getAPIVersion() (int, error) {
|
||||
type APIVersion struct {
|
||||
URL string `json:"url"`
|
||||
Version int `json:"version"`
|
||||
}
|
||||
|
||||
result, err := c.makeRequest("GET", "/api", nil)
|
||||
result, err := d.makeRequest(http.MethodGet, "/api", nil)
|
||||
if err != nil {
|
||||
return
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var versions []APIVersion
|
||||
err = json.Unmarshal(result, &versions)
|
||||
if err != nil {
|
||||
return
|
||||
return 0, err
|
||||
}
|
||||
|
||||
latestVersion := 0
|
||||
|
@ -237,41 +249,45 @@ func (c *DNSProvider) getAPIVersion() {
|
|||
latestVersion = v.Version
|
||||
}
|
||||
}
|
||||
c.apiVersion = latestVersion
|
||||
|
||||
return latestVersion, err
|
||||
}
|
||||
|
||||
func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
|
||||
func (d *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 d.host.Path != "/" {
|
||||
path = d.host.Path
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(uri, "/") {
|
||||
uri = "/" + uri
|
||||
}
|
||||
if c.apiVersion > 0 && !strings.HasPrefix(uri, "/api/v") {
|
||||
uri = "/api/v" + strconv.Itoa(c.apiVersion) + uri
|
||||
|
||||
if d.apiVersion > 0 && !strings.HasPrefix(uri, "/api/v") {
|
||||
uri = "/api/v" + strconv.Itoa(d.apiVersion) + uri
|
||||
}
|
||||
url := c.host.Scheme + "://" + c.host.Host + path + uri
|
||||
|
||||
url := d.host.Scheme + "://" + d.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)
|
||||
req.Header.Set("X-API-Key", d.apiKey)
|
||||
|
||||
client := http.Client{Timeout: 30 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := d.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error talking to PDNS API -> %v", err)
|
||||
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)
|
||||
if resp.StatusCode != http.StatusUnprocessableEntity && (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
|
||||
|
@ -293,7 +309,7 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
|
|||
return nil, err
|
||||
}
|
||||
if apiError.Error != "" {
|
||||
return nil, fmt.Errorf("Error talking to PDNS API -> %v", apiError.Error)
|
||||
return nil, fmt.Errorf("error talking to PDNS API -> %v", apiError.Error)
|
||||
}
|
||||
}
|
||||
return msg, nil
|
||||
|
|
109
vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
generated
vendored
109
vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
generated
vendored
|
@ -8,10 +8,10 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// rackspaceAPIURL represents the Identity API endpoint to call
|
||||
|
@ -22,15 +22,19 @@ var rackspaceAPIURL = "https://identity.api.rackspacecloud.com/v2.0/tokens"
|
|||
type DNSProvider struct {
|
||||
token string
|
||||
cloudDNSEndpoint string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// 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)
|
||||
values, err := env.Get("RACKSPACE_USER", "RACKSPACE_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Rackspace: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["RACKSPACE_USER"], values["RACKSPACE_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
|
@ -41,35 +45,7 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
|
|||
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{
|
||||
authData := AuthData{
|
||||
Auth: Auth{
|
||||
APIKeyCredentials: APIKeyCredentials{
|
||||
Username: user,
|
||||
|
@ -83,13 +59,13 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", rackspaceAPIURL, bytes.NewReader(body))
|
||||
req, err := http.NewRequest(http.MethodPost, rackspaceAPIURL, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := http.Client{Timeout: 30 * time.Second}
|
||||
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)
|
||||
|
@ -100,7 +76,7 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
|
|||
return nil, fmt.Errorf("Rackspace Authentication failed. Response code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var rackspaceIdentity RackspaceIdentity
|
||||
var rackspaceIdentity Identity
|
||||
err = json.NewDecoder(resp.Body).Decode(&rackspaceIdentity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -121,13 +97,14 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
|
|||
return &DNSProvider{
|
||||
token: rackspaceIdentity.Access.Token.ID,
|
||||
cloudDNSEndpoint: dnsEndpoint,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, err := c.getHostedZoneID(fqdn)
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -146,30 +123,30 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("POST", fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
|
||||
_, err = d.makeRequest(http.MethodPost, fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
|
||||
return err
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
zoneID, err := c.getHostedZoneID(fqdn)
|
||||
zoneID, err := d.getHostedZoneID(fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record, err := c.findTxtRecord(fqdn, zoneID)
|
||||
record, err := d.findTxtRecord(fqdn, zoneID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.makeRequest("DELETE", fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
|
||||
_, err = d.makeRequest(http.MethodDelete, fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// getHostedZoneID performs a lookup to get the DNS zone which needs
|
||||
// modifying for a given FQDN
|
||||
func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
|
||||
func (d *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
|
||||
// HostedZones represents the response when querying Rackspace DNS zones
|
||||
type ZoneSearchResponse struct {
|
||||
TotalEntries int `json:"totalEntries"`
|
||||
|
@ -184,7 +161,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
result, err := c.makeRequest("GET", fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
|
||||
result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -204,8 +181,8 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
|
|||
}
|
||||
|
||||
// findTxtRecord searches a DNS zone for a TXT record with a specific name
|
||||
func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
|
||||
result, err := c.makeRequest("GET", fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
|
||||
func (d *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
|
||||
result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -229,14 +206,14 @@ func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
|
|||
}
|
||||
|
||||
// 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
|
||||
func (d *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
|
||||
url := d.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("X-Auth-Token", d.token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := http.Client{Timeout: 30 * time.Second}
|
||||
|
@ -260,6 +237,38 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
|
|||
return r, nil
|
||||
}
|
||||
|
||||
// APIKeyCredentials API credential
|
||||
type APIKeyCredentials struct {
|
||||
Username string `json:"username"`
|
||||
APIKey string `json:"apiKey"`
|
||||
}
|
||||
|
||||
// Auth auth credentials
|
||||
type Auth struct {
|
||||
APIKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials"`
|
||||
}
|
||||
|
||||
// AuthData Auth data
|
||||
type AuthData struct {
|
||||
Auth `json:"auth"`
|
||||
}
|
||||
|
||||
// Identity Identity
|
||||
type Identity 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"`
|
||||
}
|
||||
|
||||
// Records is the list of records sent/received from the DNS API
|
||||
type Records struct {
|
||||
Record []Record `json:"records"`
|
||||
|
|
8
vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go
generated
vendored
8
vendor/github.com/xenolf/lego/providers/dns/rfc2136/rfc2136.go
generated
vendored
|
@ -38,6 +38,7 @@ func NewDNSProvider() (*DNSProvider, error) {
|
|||
tsigKey := os.Getenv("RFC2136_TSIG_KEY")
|
||||
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
||||
timeout := os.Getenv("RFC2136_TIMEOUT")
|
||||
|
||||
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, timeout)
|
||||
}
|
||||
|
||||
|
@ -58,13 +59,14 @@ func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKey, tsigSecret, t
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
d := &DNSProvider{
|
||||
nameserver: nameserver,
|
||||
}
|
||||
|
||||
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
|
||||
|
|
144
vendor/github.com/xenolf/lego/providers/dns/sakuracloud/sakuracloud.go
generated
vendored
Normal file
144
vendor/github.com/xenolf/lego/providers/dns/sakuracloud/sakuracloud.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
// Package sakuracloud implements a DNS provider for solving the DNS-01 challenge
|
||||
// using sakuracloud DNS.
|
||||
package sakuracloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/sacloud/libsacloud/api"
|
||||
"github.com/sacloud/libsacloud/sacloud"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
type DNSProvider struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for sakuracloud.
|
||||
// Credentials must be passed in the environment variables: SAKURACLOUD_ACCESS_TOKEN & SAKURACLOUD_ACCESS_TOKEN_SECRET
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get("SAKURACLOUD_ACCESS_TOKEN", "SAKURACLOUD_ACCESS_TOKEN_SECRET")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SakuraCloud: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["SAKURACLOUD_ACCESS_TOKEN"], values["SAKURACLOUD_ACCESS_TOKEN_SECRET"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for sakuracloud.
|
||||
func NewDNSProviderCredentials(token, secret string) (*DNSProvider, error) {
|
||||
if token == "" {
|
||||
return nil, errors.New("SakuraCloud AccessToken is missing")
|
||||
}
|
||||
if secret == "" {
|
||||
return nil, errors.New("SakuraCloud AccessSecret is missing")
|
||||
}
|
||||
|
||||
client := api.NewClient(token, secret, "tk1a")
|
||||
client.UserAgent = acme.UserAgent
|
||||
|
||||
return &DNSProvider{client: client}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := d.extractRecordName(fqdn, zone.Name)
|
||||
|
||||
zone.AddRecord(zone.CreateNewRecord(name, "TXT", value, ttl))
|
||||
_, err = d.client.GetDNSAPI().Update(zone.ID, zone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SakuraCloud API call failed: %v", 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)
|
||||
|
||||
zone, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records, err := d.findTxtRecords(fqdn, zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
var updRecords []sacloud.DNSRecordSet
|
||||
for _, r := range zone.Settings.DNS.ResourceRecordSets {
|
||||
if !(r.Name == record.Name && r.Type == record.Type && r.RData == record.RData) {
|
||||
updRecords = append(updRecords, r)
|
||||
}
|
||||
}
|
||||
zone.Settings.DNS.ResourceRecordSets = updRecords
|
||||
}
|
||||
|
||||
_, err = d.client.GetDNSAPI().Update(zone.ID, zone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SakuraCloud API call failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getHostedZone(domain string) (*sacloud.DNS, error) {
|
||||
authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
zoneName := acme.UnFqdn(authZone)
|
||||
|
||||
res, err := d.client.GetDNSAPI().WithNameLike(zoneName).Find()
|
||||
if err != nil {
|
||||
if notFound, ok := err.(api.Error); ok && notFound.ResponseCode() == http.StatusNotFound {
|
||||
return nil, fmt.Errorf("zone %s not found on SakuraCloud DNS: %v", zoneName, err)
|
||||
}
|
||||
return nil, fmt.Errorf("SakuraCloud API call failed: %v", err)
|
||||
}
|
||||
|
||||
for _, zone := range res.CommonServiceDNSItems {
|
||||
if zone.Name == zoneName {
|
||||
return &zone, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("zone %s not found on SakuraCloud DNS", zoneName)
|
||||
}
|
||||
|
||||
func (d *DNSProvider) findTxtRecords(fqdn string, zone *sacloud.DNS) ([]sacloud.DNSRecordSet, error) {
|
||||
recordName := d.extractRecordName(fqdn, zone.Name)
|
||||
|
||||
var res []sacloud.DNSRecordSet
|
||||
for _, record := range zone.Settings.DNS.ResourceRecordSets {
|
||||
if record.Name == recordName && record.Type == "TXT" {
|
||||
res = append(res, record)
|
||||
}
|
||||
}
|
||||
return res, 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
|
||||
}
|
85
vendor/github.com/xenolf/lego/providers/dns/vegadns/vegadns.go
generated
vendored
Normal file
85
vendor/github.com/xenolf/lego/providers/dns/vegadns/vegadns.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Package vegadns implements a DNS provider for solving the DNS-01
|
||||
// challenge using VegaDNS.
|
||||
package vegadns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
vegaClient "github.com/OpenDNS/vegadns2client"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider describes a provider for VegaDNS
|
||||
type DNSProvider struct {
|
||||
client vegaClient.VegaDNSClient
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for VegaDNS.
|
||||
// Credentials must be passed in the environment variables:
|
||||
// VEGADNS_URL, SECRET_VEGADNS_KEY, SECRET_VEGADNS_SECRET.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get("VEGADNS_URL")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("VegaDNS: %v", err)
|
||||
}
|
||||
|
||||
key := os.Getenv("SECRET_VEGADNS_KEY")
|
||||
secret := os.Getenv("SECRET_VEGADNS_SECRET")
|
||||
|
||||
return NewDNSProviderCredentials(values["VEGADNS_URL"], key, secret)
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||
// DNSProvider instance configured for VegaDNS.
|
||||
func NewDNSProviderCredentials(vegaDNSURL string, key string, secret string) (*DNSProvider, error) {
|
||||
vega := vegaClient.NewVegaDNSClient(vegaDNSURL)
|
||||
vega.APIKey = key
|
||||
vega.APISecret = secret
|
||||
|
||||
return &DNSProvider{
|
||||
client: vega,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS
|
||||
// propagation. Adjusting here to cope with spikes in propagation times.
|
||||
func (r *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
timeout = 12 * time.Minute
|
||||
interval = 1 * time.Minute
|
||||
return
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the dns-01 challenge
|
||||
func (r *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
_, domainID, err := r.client.GetAuthZone(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't find Authoritative Zone for %s in Present: %v", fqdn, err)
|
||||
}
|
||||
|
||||
return r.client.CreateTXT(domainID, fqdn, value, 10)
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
_, domainID, err := r.client.GetAuthZone(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't find Authoritative Zone for %s in CleanUp: %v", fqdn, err)
|
||||
}
|
||||
|
||||
txt := strings.TrimSuffix(fqdn, ".")
|
||||
|
||||
recordID, err := r.client.GetRecordID(domainID, txt, "TXT")
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't get Record ID in CleanUp: %s", err)
|
||||
}
|
||||
|
||||
return r.client.DeleteRecord(recordID)
|
||||
}
|
52
vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go
generated
vendored
52
vendor/github.com/xenolf/lego/providers/dns/vultr/vultr.go
generated
vendored
|
@ -5,11 +5,11 @@ package vultr
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
vultr "github.com/JamesClonk/vultr/lib"
|
||||
"github.com/xenolf/lego/acme"
|
||||
"github.com/xenolf/lego/platform/config/env"
|
||||
)
|
||||
|
||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||
|
@ -20,8 +20,12 @@ type DNSProvider struct {
|
|||
// 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)
|
||||
values, err := env.Get("VULTR_API_KEY")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Vultr: %v", err)
|
||||
}
|
||||
|
||||
return NewDNSProviderCredentials(values["VULTR_API_KEY"])
|
||||
}
|
||||
|
||||
// NewDNSProviderCredentials uses the supplied credentials to return a DNSProvider
|
||||
|
@ -31,25 +35,21 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
|
|||
return nil, fmt.Errorf("Vultr credentials missing")
|
||||
}
|
||||
|
||||
c := &DNSProvider{
|
||||
client: vultr.NewClient(apiKey, nil),
|
||||
}
|
||||
|
||||
return c, nil
|
||||
return &DNSProvider{client: vultr.NewClient(apiKey, nil)}, nil
|
||||
}
|
||||
|
||||
// Present creates a TXT record to fulfil the DNS-01 challenge.
|
||||
func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zoneDomain, err := c.getHostedZone(domain)
|
||||
zoneDomain, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name := c.extractRecordName(fqdn, zoneDomain)
|
||||
name := d.extractRecordName(fqdn, zoneDomain)
|
||||
|
||||
err = c.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl)
|
||||
err = d.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Vultr API call failed: %v", err)
|
||||
}
|
||||
|
@ -58,16 +58,16 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
|
|||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
|
||||
|
||||
zoneDomain, records, err := c.findTxtRecords(domain, fqdn)
|
||||
zoneDomain, records, err := d.findTxtRecords(domain, fqdn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rec := range records {
|
||||
err := c.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
|
||||
err := d.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -75,17 +75,17 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
domains, err := c.client.GetDNSDomains()
|
||||
func (d *DNSProvider) getHostedZone(domain string) (string, error) {
|
||||
domains, err := d.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
|
||||
for _, dom := range domains {
|
||||
if strings.HasSuffix(domain, dom.Domain) {
|
||||
if len(dom.Domain) > len(hostedDomain.Domain) {
|
||||
hostedDomain = dom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,19 +96,19 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
|
|||
return hostedDomain.Domain, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
|
||||
zoneDomain, err := c.getHostedZone(domain)
|
||||
func (d *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
|
||||
zoneDomain, err := d.getHostedZone(domain)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var records []vultr.DNSRecord
|
||||
result, err := c.client.GetDNSRecords(zoneDomain)
|
||||
result, err := d.client.GetDNSRecords(zoneDomain)
|
||||
if err != nil {
|
||||
return "", records, fmt.Errorf("Vultr API call has failed: %v", err)
|
||||
}
|
||||
|
||||
recordName := c.extractRecordName(fqdn, zoneDomain)
|
||||
recordName := d.extractRecordName(fqdn, zoneDomain)
|
||||
for _, record := range result {
|
||||
if record.Type == "TXT" && record.Name == recordName {
|
||||
records = append(records, record)
|
||||
|
@ -118,7 +118,7 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRe
|
|||
return zoneDomain, records, nil
|
||||
}
|
||||
|
||||
func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||
name := acme.UnFqdn(fqdn)
|
||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||
return name[:idx]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue