Initial commit.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.vscode
|
||||
build
|
124
netbox-dns-updater.go
Normal file
124
netbox-dns-updater.go
Normal file
@ -0,0 +1,124 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IPAddress struct {
|
||||
Address string `json:"address"`
|
||||
DNSName string `json:"dns_name"`
|
||||
}
|
||||
|
||||
type NetBoxResponse struct {
|
||||
Results []IPAddress `json:"results"`
|
||||
}
|
||||
|
||||
func FetchNetboxIPAddresses(apiURL, token string) ([]IPAddress, error) {
|
||||
req, err := http.NewRequest("GET", apiURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Accept", "application/json; indent=2")
|
||||
req.Header.Set("Authorization", "Token "+token)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("unexpected status: %s, body: %s", resp.Status, string(body))
|
||||
}
|
||||
|
||||
var nbResp NetBoxResponse
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
if err := decoder.Decode(&nbResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Filter out entries with empty DNSName and strip CIDR from Address
|
||||
var filtered []IPAddress
|
||||
for _, ip := range nbResp.Results {
|
||||
if ip.DNSName != "" {
|
||||
ip.Address = strings.Split(ip.Address, "/")[0]
|
||||
filtered = append(filtered, ip)
|
||||
}
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func CreateDnsMasqConfig() {
|
||||
token := os.Getenv("NETBOX_TOKEN")
|
||||
if token == "" {
|
||||
home := os.Getenv("HOME")
|
||||
paths := []string{
|
||||
home + "/.netbox/token",
|
||||
"/etc/netbox/token",
|
||||
}
|
||||
for _, path := range paths {
|
||||
data, err := os.ReadFile(path)
|
||||
if err == nil {
|
||||
token = strings.TrimSpace(string(data))
|
||||
break
|
||||
}
|
||||
}
|
||||
if token == "" {
|
||||
log.Fatal("NETBOX_TOKEN not set and no token file found")
|
||||
}
|
||||
}
|
||||
apiURL := "https://netbox.koszewscy.waw.pl/api/ipam/ip-addresses/"
|
||||
ips, err := FetchNetboxIPAddresses(apiURL, token)
|
||||
if err != nil {
|
||||
log.Fatalf("Error fetching IP addresses: %v", err)
|
||||
}
|
||||
|
||||
dir := "/etc/dnsmasq.d"
|
||||
if stat, err := os.Stat(dir); err == nil && stat.IsDir() {
|
||||
file, err := os.Create(dir + "/netbox.conf")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create netbox.conf: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
for _, ip := range ips {
|
||||
fmt.Fprintf(file, "address=/%s/%s\n", ip.DNSName, ip.Address)
|
||||
}
|
||||
} else {
|
||||
for _, ip := range ips {
|
||||
fmt.Printf("address=/%s/%s\n", ip.DNSName, ip.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
listenAddr := flag.String("listen", ":8080", "address and port to listen on (e.g. :8080 or 127.0.0.1:8080)")
|
||||
flag.Parse()
|
||||
|
||||
http.HandleFunc("/update-dnsmasq", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
w.Write([]byte("Method not allowed"))
|
||||
return
|
||||
}
|
||||
CreateDnsMasqConfig()
|
||||
cmd := exec.Command("systemctl", "restart", "dnsmasq.service")
|
||||
if err := cmd.Run(); err != nil {
|
||||
log.Printf("Failed to restart dnsmasq.service: %v", err)
|
||||
w.Write([]byte("\nWarning: Failed to restart dnsmasq.service.\n"))
|
||||
}
|
||||
w.Write([]byte("DNSMasq config updated."))
|
||||
})
|
||||
log.Printf("Starting web service on %s...", *listenAddr)
|
||||
if err := http.ListenAndServe(*listenAddr, nil); err != nil {
|
||||
log.Fatalf("Failed to start server: %v", err)
|
||||
}
|
||||
}
|
13
netbox-dns-updater.service
Normal file
13
netbox-dns-updater.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=NetBox DNSMasq Updater Web Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/netbox-dns-updater -listen=:8080
|
||||
Restart=on-failure
|
||||
User=nobody
|
||||
Group=nogroup
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
17
query-netbox.sh
Normal file
17
query-netbox.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /root/.netbox-token
|
||||
|
||||
# Build DNS data file from NetBox
|
||||
curl -s \
|
||||
-H "Accept: application/json; indent=2" \
|
||||
-H "Authorization: Token $NETBOX_TOKEN" \
|
||||
"https://netbox.koszewscy.waw.pl/api/ipam/ip-addresses/" | \
|
||||
jq -r '.results[] | select(.dns_name!="") | [(.address | split("/"))[0], .dns_name] | @tsv' | \
|
||||
while read ip name
|
||||
do
|
||||
echo "address=/$name/$ip"
|
||||
done > /etc/dnsmasq.d/netbox.conf
|
||||
|
||||
# Restart the DNSMasq service
|
||||
systemctl restart dnsmasq.service
|
Reference in New Issue
Block a user