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:
Jeff Carr 2023-12-29 21:14:36 -06:00
parent 867b69f555
commit ec5cbbe203
7 changed files with 306 additions and 24 deletions

View File

@ -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

View File

@ -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 {

57
cloudflare/create.go Normal file
View File

@ -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
}

64
cloudflare/delete.go Normal file
View File

@ -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
}

View File

@ -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
View File

@ -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)

View File

@ -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)