added a real IPv6 record
first time deleting cloudflare AAAA record can find wit.com on cloudflare ready to add cloudflare.Delete() remove code since --gui-debug works Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
867b69f555
commit
ec5cbbe203
2
Makefile
2
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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
11
gui.go
11
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue