summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cloudflare/api.go4
-rw-r--r--cloudflare/create.go57
-rw-r--r--cloudflare/delete.go64
-rw-r--r--cloudflare/http.go85
-rw-r--r--gui.go11
-rw-r--r--hostnameStatus.go107
7 files changed, 306 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index 4d3db8e..40a1d91 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
run: build
# ./control-panel-dns >/tmp/witgui.log.stderr 2>&1
- ./control-panel-dns
+ ./control-panel-dns --gui-debug
install:
go install -v go.wit.com/control-panel-dns@latest
diff --git a/cloudflare/api.go b/cloudflare/api.go
index 293857f..41ddae6 100644
--- a/cloudflare/api.go
+++ b/cloudflare/api.go
@@ -99,7 +99,7 @@ func SetRow(dnsRow *RRT) {
}
func GetZonefile(c *ConfigT) *DNSRecords {
- var url = cloudflareURL + c.ZoneID + "/dns_records/"
+ var url = cloudflareURL + c.ZoneID + "/dns_records/?per_page=100"
log.Println("getZonefile()", c.Domain, url)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
@@ -162,7 +162,7 @@ func makeJSON(dnsRow *RRT) string {
// https://api.cloudflare.com/client/v4/zones
func GetZones(auth, email string) *DNSRecords {
- var url = "https://api.cloudflare.com/client/v4/zones"
+ var url = "https://api.cloudflare.com/client/v4/zones?per_page=100"
log.Println("getZones()", url)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
diff --git a/cloudflare/create.go b/cloudflare/create.go
new file mode 100644
index 0000000..5d75b0c
--- /dev/null
+++ b/cloudflare/create.go
@@ -0,0 +1,57 @@
+/*
+ This will attempt to create a RR in a DNS zone file.
+
+ Create("wit.com", "test.wit.com", "1.1.1.1"
+*/
+
+package cloudflare
+
+import (
+ "os"
+
+ "go.wit.com/log"
+)
+
+func Create(zone string, hostname string, value string) bool {
+ log.Info("cloudflare.Create() START", zone, hostname, value)
+ key := os.Getenv("CF_API_KEY")
+ email := os.Getenv("CF_API_EMAIL")
+
+ if (key == "") {
+ log.Warn("cloudflare.Create() MISSING environment variable CF_API_KEY")
+ return false
+ }
+ if (email == "") {
+ log.Warn("cloudflare.Create() MISSING environment variable CF_API_EMAIL")
+ return false
+ }
+
+ GetZones(key, email)
+ var z *ConfigT
+ for d, v := range Config {
+ log.Info("cloudflare.Create() zone =", d, "value =", v)
+ if (zone == d) {
+ z = Config[zone]
+ log.Info("cloudflare.Create() FOUND ZONE", zone, "ID =", z.ZoneID)
+ }
+ }
+ if (z == nil) {
+ log.Warn("cloudflare.Create() COULD NOT FIND ZONE", zone)
+ return false
+ }
+ log.Info("cloudflare.Create() FOUND ZONE", z)
+
+ // make a json record to send on port 80 to cloudflare
+ var data string
+ data = `{"content": "` + value + `", `
+ data += `"name": "` + hostname + `", `
+ data += `"type": "AAAA", `
+ data += `"ttl": "1", `
+ data += `"comment": "WIT DNS Control Panel"`
+ data += `}`
+
+ result := doCurlCreate(key, email, z.ZoneID, data)
+ pretty, _ := FormatJSON(result)
+ log.Info("cloudflare.Create() result =", pretty)
+ return true
+}
diff --git a/cloudflare/delete.go b/cloudflare/delete.go
new file mode 100644
index 0000000..aa59105
--- /dev/null
+++ b/cloudflare/delete.go
@@ -0,0 +1,64 @@
+/*
+ This will attempt to delete a RR in a DNS zone file.
+
+ Delete("wit.com", "test.wit.com", "1.1.1.1"
+*/
+
+package cloudflare
+
+import (
+ "os"
+
+ "go.wit.com/log"
+)
+
+func Delete(zone string, hostname string, value string) bool {
+ // CFdialog.emailNode.SetText(os.Getenv("CF_API_EMAIL"))
+ // CFdialog.apiNode.SetText(os.Getenv("CF_API_KEY"))
+
+ log.Info("cloudflare.Delete() START", zone, hostname, value)
+ key := os.Getenv("CF_API_KEY")
+ email := os.Getenv("CF_API_EMAIL")
+
+ if (key == "") {
+ log.Warn("cloudflare.Delete() MISSING environment variable CF_API_KEY")
+ return false
+ }
+ if (email == "") {
+ log.Warn("cloudflare.Delete() MISSING environment variable CF_API_EMAIL")
+ return false
+ }
+
+ GetZones(key, email)
+ var z *ConfigT
+ for d, v := range Config {
+ log.Info("cloudflare.Delete() zone =", d, "value =", v)
+ if (zone == d) {
+ z = Config[zone]
+ log.Info("cloudflare.Delete() FOUND ZONE", zone, "ID =", z.ZoneID)
+ }
+ }
+ if (z == nil) {
+ log.Warn("cloudflare.Delete() COULD NOT FIND ZONE", zone)
+ return false
+ }
+ log.Info("cloudflare.Delete() FOUND ZONE", z)
+
+ records := GetZonefile(z)
+ for i, record := range records.Result {
+ if (record.Name == hostname) {
+ log.Info("cloudflare.Delete() FOUND hostname:", i, record.ID, record.Type, record.Name, record.Content)
+ }
+ if (record.Content == value) {
+ log.Info("cloudflare.Delete() FOUND CONTENT:", i, record.ID, record.Type, record.Name, record.Content)
+ log.Info("cloudflare.Delete() DO THE ACTUAL cloudflare DELETE here")
+ result := doCurlDelete(key, email, z.ZoneID, record.ID)
+ pretty, _ := FormatJSON(result)
+ log.Info("cloudflare.Delete() result =", pretty)
+ return true
+ }
+ }
+
+ log.Info("cloudflare.Delete() NEVER FOUND cloudflare value:", value)
+ return false
+}
diff --git a/cloudflare/http.go b/cloudflare/http.go
index 1917c8b..f976b96 100644
--- a/cloudflare/http.go
+++ b/cloudflare/http.go
@@ -2,10 +2,11 @@
package cloudflare
import (
- "log"
"io/ioutil"
"net/http"
"bytes"
+
+ "go.wit.com/log"
)
/*
@@ -26,6 +27,88 @@ curl --request POST \
}'
*/
+func doCurlDelete(auth string, email string, zoneId string, rrId string) string {
+ var err error
+ var req *http.Request
+
+ if zoneId == "" {
+ log.Warn("doCurlDelete() zoneId == nil")
+ return ""
+ }
+
+ if rrId == "" {
+ log.Warn("doCurlDelete() rrId == nil")
+ return ""
+ }
+
+ data := []byte("")
+
+ url := "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/dns_records/" + rrId
+
+ req, err = http.NewRequest(http.MethodDelete, url, bytes.NewBuffer(data))
+
+ // Set headers
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("X-Auth-Key", auth)
+ req.Header.Set("X-Auth-Email", email)
+
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ log.Println(err)
+ return ""
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ log.Println(err)
+ return ""
+ }
+
+ return string(body)
+}
+
+func doCurlCreate(auth string, email string, zoneId string, data string) string {
+ var err error
+ var req *http.Request
+
+ if zoneId == "" {
+ log.Warn("doCurlDelete() zoneId == nil")
+ return ""
+ }
+
+ url := "https://api.cloudflare.com/client/v4/zones/" + zoneId + "/dns_records/"
+
+ log.Info("doCurlCreate() POST url =", url)
+ log.Info("doCurlCreate() POST Auth =", auth)
+ log.Info("doCurlCreate() POST Email =", email)
+ log.Info("doCurlCreate() POST data =", data)
+
+ req, err = http.NewRequest(http.MethodPost, url, bytes.NewBuffer( []byte(data) ))
+
+ // Set headers
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("X-Auth-Key", auth)
+ req.Header.Set("X-Auth-Email", email)
+
+ client := &http.Client{}
+ resp, err := client.Do(req)
+ if err != nil {
+ log.Println(err)
+ return ""
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ log.Println(err)
+ return ""
+ }
+
+ return string(body)
+}
+
func doCurl(method string, rr *RRT) string {
var err error
var req *http.Request
diff --git a/gui.go b/gui.go
index abc0485..18ab3dc 100644
--- a/gui.go
+++ b/gui.go
@@ -2,7 +2,6 @@
package main
import (
- "fmt"
"time"
"os"
"os/user"
@@ -85,16 +84,6 @@ func debugTab(title string) {
g2 = tab.NewGroup("Real Stuff")
- g2.NewButton("gui.DebugWindow()", func () {
- gui.DebugWindow()
- })
-
- g2.NewButton("Load 'gocui'", func () {
- // this set the xterm and mate-terminal window title. maybe works generally?
- fmt.Println("\033]0;" + title + "blah \007")
- myGui.LoadToolkit("gocui")
- })
-
g2.NewButton("Network Interfaces", func () {
for i, t := range me.ifmap {
log.Println("name =", t.iface.Name)
diff --git a/hostnameStatus.go b/hostnameStatus.go
index 8afa9a2..f8ada99 100644
--- a/hostnameStatus.go
+++ b/hostnameStatus.go
@@ -15,6 +15,7 @@ import (
"go.wit.com/log"
"go.wit.com/gui"
"go.wit.com/gui/gadgets"
+ "go.wit.com/control-panel-dns/cloudflare"
)
type hostnameStatus struct {
@@ -25,21 +26,31 @@ type hostnameStatus struct {
window *gui.Node
+ // Primary Directives
status *gadgets.OneLiner
summary *gadgets.OneLiner
- speed *gadgets.OneLiner
- speedActual *gadgets.OneLiner
-
- dnsA *gadgets.OneLiner
- dnsAAAA *gadgets.OneLiner
- dnsAPI *gadgets.OneLiner
-
statusIPv4 *gadgets.OneLiner
statusIPv6 *gadgets.OneLiner
// Details Group
+ hostShort *gadgets.OneLiner
+ domainname *gadgets.OneLiner
+
+ // what the current IP address your network has given you
currentIPv4 *gadgets.OneLiner
currentIPv6 *gadgets.OneLiner
+
+ // what the DNS servers have
+ dnsA *gadgets.OneLiner
+ dnsAAAA *gadgets.OneLiner
+ dnsAPI *gadgets.OneLiner
+
+ speed *gadgets.OneLiner
+ speedActual *gadgets.OneLiner
+
+ // Actions
+ dnsValue *gui.Node
+ dnsAction *gui.Node
}
func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
@@ -69,23 +80,79 @@ func NewHostnameStatusWindow(p *gui.Node) *hostnameStatus {
group = box.NewGroup("Details")
grid = group.NewGrid("LookupDetails", 2, 2)
+ hs.hostShort = gadgets.NewOneLiner(grid, "hostname -s")
+ hs.domainname = gadgets.NewOneLiner(grid, "domain name")
hs.currentIPv4 = gadgets.NewOneLiner(grid, "Current IPv4")
hs.currentIPv6 = gadgets.NewOneLiner(grid, "Current IPv6")
hs.dnsAPI = gadgets.NewOneLiner(grid, "dns API provider").Set("unknown")
hs.dnsA = gadgets.NewOneLiner(grid, "dns IPv4 resource records").Set("unknown")
hs.dnsAAAA = gadgets.NewOneLiner(grid, "dns IPv6 resource records").Set("unknown")
+
hs.speed = gadgets.NewOneLiner(grid, "speed").Set("unknown")
hs.speedActual = gadgets.NewOneLiner(grid, "actual").Set("unknown")
group.Pad()
grid.Pad()
+ group = box.NewGroup("Actions")
+ grid = group.NewGrid("LookupDetails", 2, 2)
+
+ hs.dnsValue = grid.NewLabel("3.4.5.6")
+ hs.dnsAction = grid.NewButton("CHECK", func () {
+ log.Info("should", hs.dnsAction.S, "here for", hs.dnsValue.S)
+ if (hs.dnsAction.S == "DELETE") {
+ hs.deleteDNSrecord(hs.dnsValue.S)
+ }
+ if (hs.dnsAction.S == "CREATE") {
+ hs.createDNSrecord(hs.dnsValue.S)
+ }
+ })
+
+ group.Pad()
+ grid.Pad()
+
hs.hidden = false
hs.ready = true
return hs
}
+func (hs *hostnameStatus) Domain() string {
+ if ! hs.Ready() {return ""}
+ return hs.domainname.Get()
+}
+
+func (hs *hostnameStatus) API() string {
+ if ! hs.Ready() {return ""}
+ return hs.dnsAPI.Get()
+}
+
+func (hs *hostnameStatus) deleteDNSrecord(value string) bool {
+ log.Info("deleteDNSrecord() START for", value)
+ log.Info("deleteDNSrecord() hostname =", me.hostname)
+ log.Info("deleteDNSrecord() domain =", hs.Domain())
+ log.Info("deleteDNSrecord() DNS API Provider =", hs.API())
+
+ if (hs.API() == "cloudflare") {
+ log.Info("deleteDNSrecord() Try to delete via cloudflare")
+ return cloudflare.Delete(hs.Domain(), me.hostname, value)
+ }
+ return false
+}
+
+func (hs *hostnameStatus) createDNSrecord(value string) bool {
+ log.Info("createDNSrecord() START for", value)
+ log.Info("createDNSrecord() hostname =", me.hostname)
+ log.Info("createDNSrecord() domain =", hs.Domain())
+ log.Info("createDNSrecord() DNS API Provider =", hs.API())
+
+ if (hs.API() == "cloudflare") {
+ log.Info("createDNSrecord() Try to delete via cloudflare")
+ return cloudflare.Create(hs.Domain(), me.hostname, value)
+ }
+ return false
+}
+
func (hs *hostnameStatus) Update() {
log.Info("hostnameStatus() Update() START")
if hs == nil {
@@ -174,23 +241,45 @@ func (hs *hostnameStatus) set(a any, s string) {
os.Exit(0)
}
+// figure out if I'm missing any IPv6 address in DNS
+func (hs *hostnameStatus) missingAAAA() bool {
+ var aaaa []string
+ aaaa = dhcpAAAA()
+ for _, s := range aaaa {
+ debug(LogNet, "my actual AAAA = ",s)
+ hs.dnsValue.SetText(s)
+ hs.dnsAction.SetText("CREATE")
+ return true
+ }
+
+ return false
+}
+
func (hs *hostnameStatus) updateStatus() {
var s string
var vals []string
log.Info("updateStatus() START")
if ! hs.Ready() { return }
+ hs.hostShort.Set(me.hostshort.S)
+ hs.domainname.Set(me.domainname.S)
+
vals = lookupDoH(hs.hostname, "AAAA")
- log.Println("IPv6 Addresses for ", hs.hostname, "=", vals)
+ log.Println("DNS IPv6 Addresses for ", hs.hostname, "=", vals)
if len(vals) == 0 {
s = "(none)"
- hs.setIPv6("NEED VPN")
+ hs.setIPv6("Check for real IPv6 addresses here")
+ if hs.missingAAAA() {
+ hs.setIPv6("Add the missing IPv6 address")
+ }
} else {
for _, addr := range vals {
log.Println(addr)
s += addr + " (DELETE)"
hs.setIPv6("NEEDS DELETE")
+ hs.dnsValue.SetText(addr)
+ hs.dnsAction.SetText("DELETE")
}
}
hs.set(hs.dnsAAAA, s)