249 lines
7.3 KiB
Go
249 lines
7.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type CloudFlareClient struct {
|
|
apiToken string
|
|
email string
|
|
|
|
httpClient http.Client
|
|
}
|
|
|
|
func NewCloudFlareClient(ApiToken string, UserEmail string) *CloudFlareClient {
|
|
c := CloudFlareClient{
|
|
apiToken: ApiToken,
|
|
email: UserEmail,
|
|
}
|
|
c.httpClient = http.Client{}
|
|
|
|
return &c
|
|
}
|
|
|
|
type listDomainZones struct {
|
|
Result []struct {
|
|
ID string `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Status string `json:"status,omitempty"`
|
|
Paused bool `json:"paused,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
DevelopmentMode int `json:"development_mode,omitempty"`
|
|
NameServers []string `json:"name_servers,omitempty"`
|
|
OriginalNameServers []string `json:"original_name_servers,omitempty"`
|
|
OriginalRegistrar string `json:"original_registrar,omitempty"`
|
|
OriginalDnshost interface{} `json:"original_dnshost,omitempty"`
|
|
ModifiedOn time.Time `json:"modified_on,omitempty"`
|
|
CreatedOn time.Time `json:"created_on,omitempty"`
|
|
ActivatedOn time.Time `json:"activated_on,omitempty"`
|
|
Meta struct {
|
|
Step int `json:"step,omitempty"`
|
|
CustomCertificateQuota int `json:"custom_certificate_quota,omitempty"`
|
|
PageRuleQuota int `json:"page_rule_quota,omitempty"`
|
|
PhishingDetected bool `json:"phishing_detected,omitempty"`
|
|
MultipleRailgunsAllowed bool `json:"multiple_railguns_allowed,omitempty"`
|
|
} `json:"meta,omitempty"`
|
|
Owner struct {
|
|
ID string `json:"id,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Email string `json:"email,omitempty"`
|
|
} `json:"owner,omitempty"`
|
|
Account struct {
|
|
ID string `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
} `json:"account,omitempty"`
|
|
Tenant struct {
|
|
ID interface{} `json:"id,omitempty"`
|
|
Name interface{} `json:"name,omitempty"`
|
|
} `json:"tenant,omitempty"`
|
|
TenantUnit struct {
|
|
ID interface{} `json:"id,omitempty"`
|
|
} `json:"tenant_unit,omitempty"`
|
|
Permissions []string `json:"permissions,omitempty"`
|
|
Plan struct {
|
|
ID string `json:"id,omitempty"`
|
|
Name string `json:"name,omitempty"`
|
|
Price int `json:"price,omitempty"`
|
|
Currency string `json:"currency,omitempty"`
|
|
Frequency string `json:"frequency,omitempty"`
|
|
IsSubscribed bool `json:"is_subscribed,omitempty"`
|
|
CanSubscribe bool `json:"can_subscribe,omitempty"`
|
|
LegacyID string `json:"legacy_id,omitempty"`
|
|
LegacyDiscount bool `json:"legacy_discount,omitempty"`
|
|
ExternallyManaged bool `json:"externally_managed,omitempty"`
|
|
} `json:"plan,omitempty"`
|
|
} `json:"result,omitempty"`
|
|
ResultInfo struct {
|
|
Page int `json:"page,omitempty"`
|
|
PerPage int `json:"per_page,omitempty"`
|
|
TotalPages int `json:"total_pages,omitempty"`
|
|
Count int `json:"count,omitempty"`
|
|
TotalCount int `json:"total_count,omitempty"`
|
|
} `json:"result_info,omitempty"`
|
|
Success bool `json:"success,omitempty"`
|
|
Errors []interface{} `json:"errors,omitempty"`
|
|
Messages []interface{} `json:"messages,omitempty"`
|
|
}
|
|
|
|
// Lists out all the zones bound to an ac
|
|
//
|
|
// https://api.cloudflare.com/#zone-list-zones
|
|
func (c *CloudFlareClient) GetDomainByName(domain string) (*listDomainZones, error) {
|
|
var items listDomainZones
|
|
uri := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones?name=%v", domain)
|
|
|
|
req, err := http.NewRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return &items, err
|
|
}
|
|
req.Header.Set("X-Auth-Email", c.email)
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", c.apiToken))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return &items, err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return &items, ErrInvalidStatusCode
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return &items, ErrWasNotJson
|
|
}
|
|
//log.Print(string(body))
|
|
err = json.Unmarshal(body, &items)
|
|
if err != nil {
|
|
return &items, ErrFailedToDecodeJson
|
|
}
|
|
|
|
if !items.Success {
|
|
log.Println("Failed to find the requested domain on Cloudflare.")
|
|
return &items, ErrDomainNotFound
|
|
}
|
|
|
|
return &items, nil
|
|
}
|
|
|
|
type DnsDetails struct {
|
|
Success bool `json:"success"`
|
|
Errors []interface{} `json:"errors"`
|
|
Messages []interface{} `json:"messages"`
|
|
Result []struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
Name string `json:"name"`
|
|
Content string `json:"content"`
|
|
Proxiable bool `json:"proxiable"`
|
|
Proxied bool `json:"proxied"`
|
|
TTL int `json:"ttl"`
|
|
Locked bool `json:"locked"`
|
|
ZoneID string `json:"zone_id"`
|
|
ZoneName string `json:"zone_name"`
|
|
CreatedOn time.Time `json:"created_on"`
|
|
ModifiedOn time.Time `json:"modified_on"`
|
|
Data struct {
|
|
} `json:"data"`
|
|
Meta struct {
|
|
AutoAdded bool `json:"auto_added"`
|
|
Source string `json:"source"`
|
|
} `json:"meta"`
|
|
} `json:"result"`
|
|
}
|
|
|
|
func (c *CloudFlareClient) GetDnsEntriesByDomain(DomainId string, Host string, Domain string) (*DnsDetails, error) {
|
|
var items DnsDetails
|
|
name := fmt.Sprintf("%v.%v", Host, Domain)
|
|
uri := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%v/dns_records?name=%v", DomainId, name)
|
|
|
|
req, err := http.NewRequest("GET", uri, nil)
|
|
if err != nil {
|
|
return &items, err
|
|
}
|
|
req.Header.Set("X-Auth-Email", c.email)
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", c.apiToken))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return &items, err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return &items, ErrInvalidStatusCode
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return &items, ErrWasNotJson
|
|
}
|
|
err = json.Unmarshal(body, &items)
|
|
if err != nil {
|
|
return &items, ErrFailedToDecodeJson
|
|
}
|
|
|
|
if !items.Success {
|
|
log.Println("Failed to find the requested domain on Cloudflare.")
|
|
return &items, ErrDomainNotFound
|
|
}
|
|
|
|
return &items, nil
|
|
}
|
|
|
|
type dnsUpdate struct {
|
|
Type string `json:"type"`
|
|
Name string `json:"name"`
|
|
Content string `json:"content"`
|
|
Ttl int `json:"ttl"`
|
|
Proxied bool `json:"proxied"`
|
|
}
|
|
|
|
func (c *CloudFlareClient) UpdateDnsEntry(DomainId string, DnsDetails *DnsDetails, NewIpAddress string) error {
|
|
param := dnsUpdate{
|
|
Type: DnsDetails.Result[0].Type,
|
|
Name: DnsDetails.Result[0].Name,
|
|
Content: NewIpAddress,
|
|
Ttl: DnsDetails.Result[0].TTL,
|
|
Proxied: DnsDetails.Result[0].Proxied,
|
|
}
|
|
|
|
endpoint := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%v/dns_records/%v", DomainId, DnsDetails.Result[0].ID)
|
|
|
|
body, err := json.Marshal(param)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req, err := http.NewRequest("PATCH", endpoint, bytes.NewBuffer(body))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("X-Auth-Email", c.email)
|
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", c.apiToken))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := c.httpClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
log.Println(resp.Status)
|
|
return errors.New("failed to update the IP address")
|
|
}
|
|
|
|
log.Println("IP Address request was sent and no errors reported.")
|
|
return nil
|
|
}
|