summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go')
-rw-r--r--vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go284
1 files changed, 0 insertions, 284 deletions
diff --git a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go b/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
deleted file mode 100644
index 13daa8c8a..000000000
--- a/vendor/github.com/xenolf/lego/providers/dns/rackspace/rackspace.go
+++ /dev/null
@@ -1,284 +0,0 @@
-// Package rackspace implements a DNS provider for solving the DNS-01
-// challenge using rackspace DNS.
-package rackspace
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "os"
- "time"
-
- "github.com/xenolf/lego/acme"
-)
-
-// rackspaceAPIURL represents the Identity API endpoint to call
-var rackspaceAPIURL = "https://identity.api.rackspacecloud.com/v2.0/tokens"
-
-// DNSProvider is an implementation of the acme.ChallengeProvider interface
-// used to store the reusable token and DNS API endpoint
-type DNSProvider struct {
- token string
- cloudDNSEndpoint string
-}
-
-// NewDNSProvider returns a DNSProvider instance configured for Rackspace.
-// Credentials must be passed in the environment variables: RACKSPACE_USER
-// and RACKSPACE_API_KEY.
-func NewDNSProvider() (*DNSProvider, error) {
- user := os.Getenv("RACKSPACE_USER")
- key := os.Getenv("RACKSPACE_API_KEY")
- return NewDNSProviderCredentials(user, key)
-}
-
-// NewDNSProviderCredentials uses the supplied credentials to return a
-// DNSProvider instance configured for Rackspace. It authenticates against
-// the API, also grabbing the DNS Endpoint.
-func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
- if user == "" || key == "" {
- return nil, fmt.Errorf("Rackspace credentials missing")
- }
-
- type APIKeyCredentials struct {
- Username string `json:"username"`
- APIKey string `json:"apiKey"`
- }
-
- type Auth struct {
- APIKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials"`
- }
-
- type RackspaceAuthData struct {
- Auth `json:"auth"`
- }
-
- type RackspaceIdentity struct {
- Access struct {
- ServiceCatalog []struct {
- Endpoints []struct {
- PublicURL string `json:"publicURL"`
- TenantID string `json:"tenantId"`
- } `json:"endpoints"`
- Name string `json:"name"`
- } `json:"serviceCatalog"`
- Token struct {
- ID string `json:"id"`
- } `json:"token"`
- } `json:"access"`
- }
-
- authData := RackspaceAuthData{
- Auth: Auth{
- APIKeyCredentials: APIKeyCredentials{
- Username: user,
- APIKey: key,
- },
- },
- }
-
- body, err := json.Marshal(authData)
- if err != nil {
- return nil, err
- }
-
- req, err := http.NewRequest("POST", rackspaceAPIURL, bytes.NewReader(body))
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error querying Rackspace Identity API: %v", err)
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- return nil, fmt.Errorf("Rackspace Authentication failed. Response code: %d", resp.StatusCode)
- }
-
- var rackspaceIdentity RackspaceIdentity
- err = json.NewDecoder(resp.Body).Decode(&rackspaceIdentity)
- if err != nil {
- return nil, err
- }
-
- // Iterate through the Service Catalog to get the DNS Endpoint
- var dnsEndpoint string
- for _, service := range rackspaceIdentity.Access.ServiceCatalog {
- if service.Name == "cloudDNS" {
- dnsEndpoint = service.Endpoints[0].PublicURL
- break
- }
- }
- if dnsEndpoint == "" {
- return nil, fmt.Errorf("Failed to populate DNS endpoint, check Rackspace API for changes.")
- }
-
- return &DNSProvider{
- token: rackspaceIdentity.Access.Token.ID,
- cloudDNSEndpoint: dnsEndpoint,
- }, nil
-}
-
-// Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
- fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- rec := RackspaceRecords{
- RackspaceRecord: []RackspaceRecord{{
- Name: acme.UnFqdn(fqdn),
- Type: "TXT",
- Data: value,
- TTL: 300,
- }},
- }
-
- body, err := json.Marshal(rec)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("POST", fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
- zoneID, err := c.getHostedZoneID(fqdn)
- if err != nil {
- return err
- }
-
- record, err := c.findTxtRecord(fqdn, zoneID)
- if err != nil {
- return err
- }
-
- _, err = c.makeRequest("DELETE", fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// getHostedZoneID performs a lookup to get the DNS zone which needs
-// modifying for a given FQDN
-func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
- // HostedZones represents the response when querying Rackspace DNS zones
- type ZoneSearchResponse struct {
- TotalEntries int `json:"totalEntries"`
- HostedZones []struct {
- ID int `json:"id"`
- Name string `json:"name"`
- } `json:"domains"`
- }
-
- authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
- if err != nil {
- return 0, err
- }
-
- result, err := c.makeRequest("GET", fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
- if err != nil {
- return 0, err
- }
-
- var zoneSearchResponse ZoneSearchResponse
- err = json.Unmarshal(result, &zoneSearchResponse)
- if err != nil {
- return 0, err
- }
-
- // If nothing was returned, or for whatever reason more than 1 was returned (the search uses exact match, so should not occur)
- if zoneSearchResponse.TotalEntries != 1 {
- return 0, fmt.Errorf("Found %d zones for %s in Rackspace for domain %s", zoneSearchResponse.TotalEntries, authZone, fqdn)
- }
-
- return zoneSearchResponse.HostedZones[0].ID, nil
-}
-
-// findTxtRecord searches a DNS zone for a TXT record with a specific name
-func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*RackspaceRecord, error) {
- result, err := c.makeRequest("GET", fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
- if err != nil {
- return nil, err
- }
-
- var records RackspaceRecords
- err = json.Unmarshal(result, &records)
- if err != nil {
- return nil, err
- }
-
- recordsLength := len(records.RackspaceRecord)
- switch recordsLength {
- case 1:
- break
- case 0:
- return nil, fmt.Errorf("No TXT record found for %s", fqdn)
- default:
- return nil, fmt.Errorf("More than 1 TXT record found for %s", fqdn)
- }
-
- return &records.RackspaceRecord[0], nil
-}
-
-// makeRequest is a wrapper function used for making DNS API requests
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
- url := c.cloudDNSEndpoint + uri
- req, err := http.NewRequest(method, url, body)
- if err != nil {
- return nil, err
- }
-
- req.Header.Set("X-Auth-Token", c.token)
- req.Header.Set("Content-Type", "application/json")
-
- client := http.Client{Timeout: 30 * time.Second}
- resp, err := client.Do(req)
- if err != nil {
- return nil, fmt.Errorf("Error querying DNS API: %v", err)
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
- return nil, fmt.Errorf("Request failed for %s %s. Response code: %d", method, url, resp.StatusCode)
- }
-
- var r json.RawMessage
- err = json.NewDecoder(resp.Body).Decode(&r)
- if err != nil {
- return nil, fmt.Errorf("JSON decode failed for %s %s. Response code: %d", method, url, resp.StatusCode)
- }
-
- return r, nil
-}
-
-// RackspaceRecords is the list of records sent/received from the DNS API
-type RackspaceRecords struct {
- RackspaceRecord []RackspaceRecord `json:"records"`
-}
-
-// RackspaceRecord represents a Rackspace DNS record
-type RackspaceRecord struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Data string `json:"data"`
- TTL int `json:"ttl,omitempty"`
- ID string `json:"id,omitempty"`
-}