Change Aurora DNS client (#683)
This commit is contained in:
parent
5511373184
commit
a68cb214d3
16 changed files with 434 additions and 392 deletions
27
Gopkg.lock
generated
27
Gopkg.lock
generated
|
@ -174,21 +174,6 @@
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "35bcc6b47c20ec9bf3a53adcb7fa9665a75f0e7b"
|
revision = "35bcc6b47c20ec9bf3a53adcb7fa9665a75f0e7b"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:82127d77b40b617d650e64dc287cfc190f31d1030bd01cae5110780dd1e5bbb3"
|
|
||||||
name = "github.com/edeckers/auroradnsclient"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"records",
|
|
||||||
"requests",
|
|
||||||
"requests/errors",
|
|
||||||
"tokens",
|
|
||||||
"zones",
|
|
||||||
]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "1563e622aaca0a8bb895a448f31d4a430ab97586"
|
|
||||||
version = "v1.0.3"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:e096f1857eedd49e2bd0885d05105d1d4af1bfcf8b1d07fa5710718e6641fd48"
|
digest = "1:e096f1857eedd49e2bd0885d05105d1d4af1bfcf8b1d07fa5710718e6641fd48"
|
||||||
name = "github.com/exoscale/egoscale"
|
name = "github.com/exoscale/egoscale"
|
||||||
|
@ -271,6 +256,14 @@
|
||||||
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:417193ba917954c4837c6fc48c6ac241b3fefd13fc0889367b4a7e43b69d582c"
|
||||||
|
name = "github.com/ldez/go-auroradns"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "NUT"
|
||||||
|
revision = "b40dfcae7c417f8129579362695dc1f3cfe5928d"
|
||||||
|
version = "v2.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:111ff5a09a32895248270bfaef9b8b6ac163a8cde9cdd603fed64b3e4b59e8ab"
|
digest = "1:111ff5a09a32895248270bfaef9b8b6ac163a8cde9cdd603fed64b3e4b59e8ab"
|
||||||
name = "github.com/linode/linodego"
|
name = "github.com/linode/linodego"
|
||||||
|
@ -604,12 +597,10 @@
|
||||||
"github.com/cpu/goacmedns",
|
"github.com/cpu/goacmedns",
|
||||||
"github.com/decker502/dnspod-go",
|
"github.com/decker502/dnspod-go",
|
||||||
"github.com/dnsimple/dnsimple-go/dnsimple",
|
"github.com/dnsimple/dnsimple-go/dnsimple",
|
||||||
"github.com/edeckers/auroradnsclient",
|
|
||||||
"github.com/edeckers/auroradnsclient/records",
|
|
||||||
"github.com/edeckers/auroradnsclient/zones",
|
|
||||||
"github.com/exoscale/egoscale",
|
"github.com/exoscale/egoscale",
|
||||||
"github.com/iij/doapi",
|
"github.com/iij/doapi",
|
||||||
"github.com/iij/doapi/protocol",
|
"github.com/iij/doapi/protocol",
|
||||||
|
"github.com/ldez/go-auroradns",
|
||||||
"github.com/linode/linodego",
|
"github.com/linode/linodego",
|
||||||
"github.com/miekg/dns",
|
"github.com/miekg/dns",
|
||||||
"github.com/namedotcom/go/namecom",
|
"github.com/namedotcom/go/namecom",
|
||||||
|
|
|
@ -7,9 +7,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edeckers/auroradnsclient"
|
"github.com/ldez/go-auroradns"
|
||||||
"github.com/edeckers/auroradnsclient/records"
|
|
||||||
"github.com/edeckers/auroradnsclient/zones"
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
"github.com/xenolf/lego/platform/config/env"
|
"github.com/xenolf/lego/platform/config/env"
|
||||||
)
|
)
|
||||||
|
@ -40,7 +38,7 @@ type DNSProvider struct {
|
||||||
recordIDs map[string]string
|
recordIDs map[string]string
|
||||||
recordIDsMu sync.Mutex
|
recordIDsMu sync.Mutex
|
||||||
config *Config
|
config *Config
|
||||||
client *auroradnsclient.AuroraDNSClient
|
client *auroradns.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for AuroraDNS.
|
// NewDNSProvider returns a DNSProvider instance configured for AuroraDNS.
|
||||||
|
@ -86,7 +84,12 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
config.BaseURL = defaultBaseURL
|
config.BaseURL = defaultBaseURL
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := auroradnsclient.NewAuroraDNSClient(config.BaseURL, config.UserID, config.Key)
|
tr, err := auroradns.NewTokenTransport(config.UserID, config.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("aurora: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := auroradns.NewClient(tr.Client(), auroradns.WithBaseURL(config.BaseURL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("aurora: %v", err)
|
return nil, fmt.Errorf("aurora: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -118,26 +121,25 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
|
||||||
authZone = acme.UnFqdn(authZone)
|
authZone = acme.UnFqdn(authZone)
|
||||||
|
|
||||||
zoneRecord, err := d.getZoneInformationByName(authZone)
|
zone, err := d.getZoneInformationByName(authZone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("aurora: could not create record: %v", err)
|
return fmt.Errorf("aurora: could not create record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqData :=
|
record := auroradns.Record{
|
||||||
records.CreateRecordRequest{
|
|
||||||
RecordType: "TXT",
|
RecordType: "TXT",
|
||||||
Name: subdomain,
|
Name: subdomain,
|
||||||
Content: value,
|
Content: value,
|
||||||
TTL: d.config.TTL,
|
TTL: d.config.TTL,
|
||||||
}
|
}
|
||||||
|
|
||||||
respData, err := d.client.CreateRecord(zoneRecord.ID, reqData)
|
newRecord, _, err := d.client.CreateRecord(zone.ID, record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("aurora: could not create record: %v", err)
|
return fmt.Errorf("aurora: could not create record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.recordIDsMu.Lock()
|
d.recordIDsMu.Lock()
|
||||||
d.recordIDs[fqdn] = respData.ID
|
d.recordIDs[fqdn] = newRecord.ID
|
||||||
d.recordIDsMu.Unlock()
|
d.recordIDsMu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -162,12 +164,12 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
|
||||||
authZone = acme.UnFqdn(authZone)
|
authZone = acme.UnFqdn(authZone)
|
||||||
|
|
||||||
zoneRecord, err := d.getZoneInformationByName(authZone)
|
zone, err := d.getZoneInformationByName(authZone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = d.client.RemoveRecord(zoneRecord.ID, recordID)
|
_, _, err = d.client.DeleteRecord(zone.ID, recordID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -185,10 +187,10 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
|
func (d *DNSProvider) getZoneInformationByName(name string) (auroradns.Zone, error) {
|
||||||
zs, err := d.client.GetZones()
|
zs, _, err := d.client.ListZones()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return zones.ZoneRecord{}, err
|
return auroradns.Zone{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, element := range zs {
|
for _, element := range zs {
|
||||||
|
@ -197,5 +199,5 @@ func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return zones.ZoneRecord{}, fmt.Errorf("could not find Zone record")
|
return auroradns.Zone{}, fmt.Errorf("could not find Zone record")
|
||||||
}
|
}
|
||||||
|
|
22
vendor/github.com/edeckers/auroradnsclient/client.go
generated
vendored
22
vendor/github.com/edeckers/auroradnsclient/client.go
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
package auroradnsclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/edeckers/auroradnsclient/requests"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AuroraDNSClient is a client for accessing the Aurora DNS API
|
|
||||||
type AuroraDNSClient struct {
|
|
||||||
requestor *requests.AuroraRequestor
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAuroraDNSClient instantiates a new client
|
|
||||||
func NewAuroraDNSClient(endpoint string, userID string, key string) (*AuroraDNSClient, error) {
|
|
||||||
requestor, err := requests.NewAuroraRequestor(endpoint, userID, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &AuroraDNSClient{
|
|
||||||
requestor: requestor,
|
|
||||||
}, nil
|
|
||||||
}
|
|
11
vendor/github.com/edeckers/auroradnsclient/errors.go
generated
vendored
11
vendor/github.com/edeckers/auroradnsclient/errors.go
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
package auroradnsclient
|
|
||||||
|
|
||||||
// AuroraDNSError describes the format of a generic AuroraDNS API error
|
|
||||||
type AuroraDNSError struct {
|
|
||||||
ErrorCode string `json:"error"`
|
|
||||||
Message string `json:"errormsg"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e AuroraDNSError) Error() string {
|
|
||||||
return e.Message
|
|
||||||
}
|
|
75
vendor/github.com/edeckers/auroradnsclient/records.go
generated
vendored
75
vendor/github.com/edeckers/auroradnsclient/records.go
generated
vendored
|
@ -1,75 +0,0 @@
|
||||||
package auroradnsclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/edeckers/auroradnsclient/records"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetRecords returns a list of all records in given zone
|
|
||||||
func (client *AuroraDNSClient) GetRecords(zoneID string) ([]records.GetRecordsResponse, error) {
|
|
||||||
logrus.Debugf("GetRecords(%s)", zoneID)
|
|
||||||
relativeURL := fmt.Sprintf("zones/%s/records", zoneID)
|
|
||||||
|
|
||||||
response, err := client.requestor.Request(relativeURL, "GET", []byte(""))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to receive records: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var respData []records.GetRecordsResponse
|
|
||||||
err = json.Unmarshal(response, &respData)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to unmarshall response: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return respData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRecord creates a new record in given zone
|
|
||||||
func (client *AuroraDNSClient) CreateRecord(zoneID string, data records.CreateRecordRequest) (*records.CreateRecordResponse, error) {
|
|
||||||
logrus.Debugf("CreateRecord(%s, %+v)", zoneID, data)
|
|
||||||
body, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to marshall request body: %s", err)
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
relativeURL := fmt.Sprintf("zones/%s/records", zoneID)
|
|
||||||
|
|
||||||
response, err := client.requestor.Request(relativeURL, "POST", body)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to create record: %s", err)
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var respData *records.CreateRecordResponse
|
|
||||||
err = json.Unmarshal(response, &respData)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to unmarshall response: %s", err)
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return respData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveRecord removes a record corresponding to a particular id in a given zone
|
|
||||||
func (client *AuroraDNSClient) RemoveRecord(zoneID string, recordID string) (*records.RemoveRecordResponse, error) {
|
|
||||||
logrus.Debugf("RemoveRecord(%s, %s)", zoneID, recordID)
|
|
||||||
relativeURL := fmt.Sprintf("zones/%s/records/%s", zoneID, recordID)
|
|
||||||
|
|
||||||
_, err := client.requestor.Request(relativeURL, "DELETE", nil)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to remove record: %s", err)
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &records.RemoveRecordResponse{}, nil
|
|
||||||
}
|
|
31
vendor/github.com/edeckers/auroradnsclient/records/datatypes.go
generated
vendored
31
vendor/github.com/edeckers/auroradnsclient/records/datatypes.go
generated
vendored
|
@ -1,31 +0,0 @@
|
||||||
package records
|
|
||||||
|
|
||||||
// CreateRecordRequest describes the json payload for creating a record
|
|
||||||
type CreateRecordRequest struct {
|
|
||||||
RecordType string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
TTL int `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRecordResponse describes the json response for creating a record
|
|
||||||
type CreateRecordResponse struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
RecordType string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
TTL int `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRecordsResponse describes the json response of a single record
|
|
||||||
type GetRecordsResponse struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
RecordType string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
TTL int `json:"ttl"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveRecordResponse describes the json response for removing a record
|
|
||||||
type RemoveRecordResponse struct {
|
|
||||||
}
|
|
19
vendor/github.com/edeckers/auroradnsclient/requests/errors/errors.go
generated
vendored
19
vendor/github.com/edeckers/auroradnsclient/requests/errors/errors.go
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
package errors
|
|
||||||
|
|
||||||
// BadRequest HTTP error wrapper
|
|
||||||
type BadRequest error
|
|
||||||
|
|
||||||
// Unauthorized HTTP error wrapper
|
|
||||||
type Unauthorized error
|
|
||||||
|
|
||||||
// Forbidden HTTP error wrapper
|
|
||||||
type Forbidden error
|
|
||||||
|
|
||||||
// NotFound HTTP error wrapper
|
|
||||||
type NotFound error
|
|
||||||
|
|
||||||
// ServerError HTTP error wrapper
|
|
||||||
type ServerError error
|
|
||||||
|
|
||||||
// InvalidStatusCodeError is used when none of the other types applies
|
|
||||||
type InvalidStatusCodeError error
|
|
124
vendor/github.com/edeckers/auroradnsclient/requests/requestor.go
generated
vendored
124
vendor/github.com/edeckers/auroradnsclient/requests/requestor.go
generated
vendored
|
@ -1,124 +0,0 @@
|
||||||
package requests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
request_errors "github.com/edeckers/auroradnsclient/requests/errors"
|
|
||||||
"github.com/edeckers/auroradnsclient/tokens"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AuroraRequestor performs actual requests to API
|
|
||||||
type AuroraRequestor struct {
|
|
||||||
endpoint string
|
|
||||||
userID string
|
|
||||||
key string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAuroraRequestor instantiates a new requestor
|
|
||||||
func NewAuroraRequestor(endpoint string, userID string, key string) (*AuroraRequestor, error) {
|
|
||||||
if endpoint == "" {
|
|
||||||
return nil, fmt.Errorf("Aurora endpoint missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if userID == "" || key == "" {
|
|
||||||
return nil, fmt.Errorf("Aurora credentials missing")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &AuroraRequestor{endpoint: endpoint, userID: userID, key: key}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (requestor *AuroraRequestor) buildRequest(relativeURL string, method string, body []byte) (*http.Request, error) {
|
|
||||||
url := fmt.Sprintf("%s/%s", requestor.endpoint, relativeURL)
|
|
||||||
|
|
||||||
request, err := http.NewRequest(method, url, bytes.NewReader(body))
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to build request: %s", err)
|
|
||||||
|
|
||||||
return request, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp := time.Now().UTC()
|
|
||||||
fmtTime := timestamp.Format("20060102T150405Z")
|
|
||||||
|
|
||||||
token := tokens.NewToken(requestor.userID, requestor.key, method, fmt.Sprintf("/%s", relativeURL), timestamp)
|
|
||||||
|
|
||||||
request.Header.Set("X-AuroraDNS-Date", fmtTime)
|
|
||||||
request.Header.Set("Authorization", fmt.Sprintf("AuroraDNSv1 %s", token))
|
|
||||||
|
|
||||||
request.Header.Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
rawRequest, err := httputil.DumpRequestOut(request, true)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to dump request: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf("Built request:\n%s", rawRequest)
|
|
||||||
|
|
||||||
return request, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (requestor *AuroraRequestor) testInvalidResponse(resp *http.Response, response []byte) ([]byte, error) {
|
|
||||||
if resp.StatusCode < 400 {
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Errorf("Received invalid status code %d:\n%s", resp.StatusCode, response)
|
|
||||||
|
|
||||||
content := errors.New(string(response))
|
|
||||||
|
|
||||||
statusCodeErrorMap := map[int]error{
|
|
||||||
400: request_errors.BadRequest(content),
|
|
||||||
401: request_errors.Unauthorized(content),
|
|
||||||
403: request_errors.Forbidden(content),
|
|
||||||
404: request_errors.NotFound(content),
|
|
||||||
500: request_errors.ServerError(content),
|
|
||||||
}
|
|
||||||
|
|
||||||
mappedError := statusCodeErrorMap[resp.StatusCode]
|
|
||||||
|
|
||||||
if mappedError == nil {
|
|
||||||
return nil, request_errors.InvalidStatusCodeError(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, mappedError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request builds and executues a request to the API
|
|
||||||
func (requestor *AuroraRequestor) Request(relativeURL string, method string, body []byte) ([]byte, error) {
|
|
||||||
req, err := requestor.buildRequest(relativeURL, method, body)
|
|
||||||
|
|
||||||
client := http.Client{Timeout: 30 * time.Second}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed request: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
rawResponse, err := httputil.DumpResponse(resp, true)
|
|
||||||
logrus.Debugf("Received raw response:\n%s", rawResponse)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to dump response: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to read response: %s", response)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err = requestor.testInvalidResponse(resp, response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
35
vendor/github.com/edeckers/auroradnsclient/tokens/generator.go
generated
vendored
35
vendor/github.com/edeckers/auroradnsclient/tokens/generator.go
generated
vendored
|
@ -1,35 +0,0 @@
|
||||||
package tokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewToken generates a token for accessing a specific method of the API
|
|
||||||
func NewToken(userID string, key string, method string, action string, timestamp time.Time) string {
|
|
||||||
fmtTime := timestamp.Format("20060102T150405Z")
|
|
||||||
logrus.Debugf("Built timestamp: %s", fmtTime)
|
|
||||||
|
|
||||||
message := strings.Join([]string{method, action, fmtTime}, "")
|
|
||||||
logrus.Debugf("Built message: %s", message)
|
|
||||||
|
|
||||||
signatureHmac := hmac.New(sha256.New, []byte(key))
|
|
||||||
|
|
||||||
signatureHmac.Write([]byte(message))
|
|
||||||
|
|
||||||
signature := base64.StdEncoding.EncodeToString([]byte(signatureHmac.Sum(nil)))
|
|
||||||
logrus.Debugf("Built signature: %s", signature)
|
|
||||||
|
|
||||||
userIDAndSignature := fmt.Sprintf("%s:%s", userID, signature)
|
|
||||||
|
|
||||||
token := base64.StdEncoding.EncodeToString([]byte(userIDAndSignature))
|
|
||||||
logrus.Debugf("Built token: %s", token)
|
|
||||||
|
|
||||||
return token
|
|
||||||
}
|
|
29
vendor/github.com/edeckers/auroradnsclient/zones.go
generated
vendored
29
vendor/github.com/edeckers/auroradnsclient/zones.go
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
package auroradnsclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/edeckers/auroradnsclient/zones"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetZones returns a list of all zones
|
|
||||||
func (client *AuroraDNSClient) GetZones() ([]zones.ZoneRecord, error) {
|
|
||||||
logrus.Debugf("GetZones")
|
|
||||||
response, err := client.requestor.Request("zones", "GET", []byte(""))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to get zones: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var respData []zones.ZoneRecord
|
|
||||||
err = json.Unmarshal(response, &respData)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Errorf("Failed to unmarshall response: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
logrus.Debugf("Unmarshalled response: %+v", respData)
|
|
||||||
return respData, nil
|
|
||||||
}
|
|
7
vendor/github.com/edeckers/auroradnsclient/zones/datatypes.go
generated
vendored
7
vendor/github.com/edeckers/auroradnsclient/zones/datatypes.go
generated
vendored
|
@ -1,7 +0,0 @@
|
||||||
package zones
|
|
||||||
|
|
||||||
// ZoneRecord describes the json format for a zone
|
|
||||||
type ZoneRecord struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
98
vendor/github.com/ldez/go-auroradns/auth.go
generated
vendored
Normal file
98
vendor/github.com/ldez/go-auroradns/auth.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
package auroradns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TokenTransport HTTP transport for API authentication
|
||||||
|
type TokenTransport struct {
|
||||||
|
userID string
|
||||||
|
key string
|
||||||
|
|
||||||
|
// Transport is the underlying HTTP transport to use when making requests.
|
||||||
|
// It will default to http.DefaultTransport if nil.
|
||||||
|
Transport http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTokenTransport Creates a new TokenTransport
|
||||||
|
func NewTokenTransport(userID, key string) (*TokenTransport, error) {
|
||||||
|
if userID == "" || key == "" {
|
||||||
|
return nil, fmt.Errorf("credentials missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &TokenTransport{userID: userID, key: key}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundTrip executes a single HTTP transaction
|
||||||
|
func (t *TokenTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
enrichedReq := &http.Request{}
|
||||||
|
*enrichedReq = *req
|
||||||
|
|
||||||
|
enrichedReq.Header = make(http.Header, len(req.Header))
|
||||||
|
for k, s := range req.Header {
|
||||||
|
enrichedReq.Header[k] = append([]string(nil), s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.userID != "" && t.key != "" {
|
||||||
|
timestamp := time.Now().UTC()
|
||||||
|
|
||||||
|
fmtTime := timestamp.Format("20060102T150405Z")
|
||||||
|
req.Header.Set("X-AuroraDNS-Date", fmtTime)
|
||||||
|
|
||||||
|
token, err := newToken(t.userID, t.key, req.Method, req.URL.Path, timestamp)
|
||||||
|
if err == nil {
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("AuroraDNSv1 %s", token))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.transport().RoundTrip(enrichedReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap Wrap a HTTP client Transport with the TokenTransport
|
||||||
|
func (t *TokenTransport) Wrap(client *http.Client) *http.Client {
|
||||||
|
backup := client.Transport
|
||||||
|
t.Transport = backup
|
||||||
|
client.Transport = t
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client Creates a new HTTP client
|
||||||
|
func (t *TokenTransport) Client() *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: t,
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TokenTransport) transport() http.RoundTripper {
|
||||||
|
if t.Transport != nil {
|
||||||
|
return t.Transport
|
||||||
|
}
|
||||||
|
return http.DefaultTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
// newToken generates a token for accessing a specific method of the API
|
||||||
|
func newToken(userID string, key string, method string, action string, timestamp time.Time) (string, error) {
|
||||||
|
fmtTime := timestamp.Format("20060102T150405Z")
|
||||||
|
message := strings.Join([]string{method, action, fmtTime}, "")
|
||||||
|
|
||||||
|
signatureHmac := hmac.New(sha256.New, []byte(key))
|
||||||
|
_, err := signatureHmac.Write([]byte(message))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
signature := base64.StdEncoding.EncodeToString(signatureHmac.Sum(nil))
|
||||||
|
|
||||||
|
userIDAndSignature := fmt.Sprintf("%s:%s", userID, signature)
|
||||||
|
|
||||||
|
token := base64.StdEncoding.EncodeToString([]byte(userIDAndSignature))
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
144
vendor/github.com/ldez/go-auroradns/client.go
generated
vendored
Normal file
144
vendor/github.com/ldez/go-auroradns/client.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
package auroradns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultBaseURL = "https://api.auroradns.eu"
|
||||||
|
|
||||||
|
const (
|
||||||
|
contentTypeHeader = "Content-Type"
|
||||||
|
contentTypeJSON = "application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrorResponse A representation of an API error message.
|
||||||
|
type ErrorResponse struct {
|
||||||
|
ErrorCode string `json:"error"`
|
||||||
|
Message string `json:"errormsg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ErrorResponse) Error() string {
|
||||||
|
return fmt.Sprintf("%s - %s", e.ErrorCode, e.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option Type of a client option
|
||||||
|
type Option func(*Client) error
|
||||||
|
|
||||||
|
// Client The API client
|
||||||
|
type Client struct {
|
||||||
|
baseURL *url.URL
|
||||||
|
UserAgent string
|
||||||
|
httpClient *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient Creates a new client
|
||||||
|
func NewClient(httpClient *http.Client, opts ...Option) (*Client, error) {
|
||||||
|
if httpClient == nil {
|
||||||
|
httpClient = http.DefaultClient
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL, _ := url.Parse(defaultBaseURL)
|
||||||
|
|
||||||
|
client := &Client{
|
||||||
|
baseURL: baseURL,
|
||||||
|
httpClient: httpClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
err := opt(client)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) newRequest(method, resource string, body io.Reader) (*http.Request, error) {
|
||||||
|
u, err := c.baseURL.Parse(resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, u.String(), body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set(contentTypeHeader, contentTypeJSON)
|
||||||
|
|
||||||
|
if c.UserAgent != "" {
|
||||||
|
req.Header.Set("User-Agent", c.UserAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) do(req *http.Request, v interface{}) (*http.Response, error) {
|
||||||
|
resp, err := c.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func() { _ = resp.Body.Close() }()
|
||||||
|
|
||||||
|
if err = checkResponse(resp); err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == nil {
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return resp, fmt.Errorf("failed to read body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(raw, v); err != nil {
|
||||||
|
return resp, fmt.Errorf("unmarshaling %T error: %v: %s", err, v, string(raw))
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkResponse(resp *http.Response) error {
|
||||||
|
if c := resp.StatusCode; 200 <= c && c <= 299 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err == nil && data != nil {
|
||||||
|
errorResponse := new(ErrorResponse)
|
||||||
|
err = json.Unmarshal(data, errorResponse)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshaling ErrorResponse error: %v: %s", err.Error(), string(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorResponse
|
||||||
|
}
|
||||||
|
defer func() { _ = resp.Body.Close() }()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBaseURL Allows to define a custom base URL
|
||||||
|
func WithBaseURL(rawBaseURL string) func(*Client) error {
|
||||||
|
return func(client *Client) error {
|
||||||
|
if len(rawBaseURL) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL, err := url.Parse(rawBaseURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client.baseURL = baseURL
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
91
vendor/github.com/ldez/go-auroradns/records.go
generated
vendored
Normal file
91
vendor/github.com/ldez/go-auroradns/records.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package auroradns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Record types
|
||||||
|
const (
|
||||||
|
RecordTypeA = "A"
|
||||||
|
RecordTypeAAAA = "AAAA"
|
||||||
|
RecordTypeCNAME = "CNAME"
|
||||||
|
RecordTypeMX = "MX"
|
||||||
|
RecordTypeNS = "NS"
|
||||||
|
RecordTypeSOA = "SOA"
|
||||||
|
RecordTypeSRV = "SRV"
|
||||||
|
RecordTypeTXT = "TXT"
|
||||||
|
RecordTypeDS = "DS"
|
||||||
|
RecordTypePTR = "PTR"
|
||||||
|
RecordTypeSSHFP = "SSHFP"
|
||||||
|
RecordTypeTLSA = "TLS"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Record a DNS record
|
||||||
|
type Record struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
RecordType string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
TTL int `json:"ttl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRecord Creates a new record.
|
||||||
|
func (c *Client) CreateRecord(zoneID string, record Record) (*Record, *http.Response, error) {
|
||||||
|
body, err := json.Marshal(record)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to marshall request body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource := fmt.Sprintf("/zones/%s/records", zoneID)
|
||||||
|
|
||||||
|
req, err := c.newRequest(http.MethodPost, resource, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newRecord := new(Record)
|
||||||
|
resp, err := c.do(req, newRecord)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRecord, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRecord Delete a record.
|
||||||
|
func (c *Client) DeleteRecord(zoneID string, recordID string) (bool, *http.Response, error) {
|
||||||
|
resource := fmt.Sprintf("/zones/%s/records/%s", zoneID, recordID)
|
||||||
|
|
||||||
|
req, err := c.newRequest(http.MethodDelete, resource, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRecords returns a list of all records in given zone
|
||||||
|
func (c *Client) ListRecords(zoneID string) ([]Record, *http.Response, error) {
|
||||||
|
resource := fmt.Sprintf("/zones/%s/records", zoneID)
|
||||||
|
|
||||||
|
req, err := c.newRequest(http.MethodGet, resource, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var records []Record
|
||||||
|
resp, err := c.do(req, &records)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return records, resp, nil
|
||||||
|
}
|
69
vendor/github.com/ldez/go-auroradns/zones.go
generated
vendored
Normal file
69
vendor/github.com/ldez/go-auroradns/zones.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package auroradns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Zone a DNS zone
|
||||||
|
type Zone struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateZone Creates a zone.
|
||||||
|
func (c *Client) CreateZone(domain string) (*Zone, *http.Response, error) {
|
||||||
|
body, err := json.Marshal(Zone{Name: domain})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to marshall request body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := c.newRequest(http.MethodPost, "/zones", bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zone := new(Zone)
|
||||||
|
resp, err := c.do(req, zone)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return zone, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteZone Delete a zone.
|
||||||
|
func (c *Client) DeleteZone(zoneID string) (bool, *http.Response, error) {
|
||||||
|
resource := fmt.Sprintf("/zones/%s", zoneID)
|
||||||
|
|
||||||
|
req, err := c.newRequest(http.MethodDelete, resource, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := c.do(req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, resp, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListZones returns a list of all zones.
|
||||||
|
func (c *Client) ListZones() ([]Zone, *http.Response, error) {
|
||||||
|
req, err := c.newRequest(http.MethodGet, "/zones", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var zones []Zone
|
||||||
|
resp, err := c.do(req, &zones)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return zones, resp, nil
|
||||||
|
}
|
Loading…
Reference in a new issue