123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- package handlers
- import (
- "bufio"
- "byom-infra-api/config"
- "encoding/json"
- "fmt"
- "log"
- "math/rand"
- "net/http"
- "os"
- "regexp"
- "strings"
- "github.com/gorilla/mux"
- )
- type DNSRecord struct {
- FieldType string `json:"fieldType"`
- SubDomain string `json:"subDomain"`
- Target string `json:"target"`
- TTL int `json:"ttl"`
- }
- type DNSHandler struct {
- Zone string
- }
- func NewDNSHandler() *DNSHandler {
- zone, exists := config.GetConfig("dns_zone")
- log.Printf("DNS Handler initialized - zone = %s (exists: %v)\n", zone, exists)
- return &DNSHandler{
- Zone: zone,
- }
- }
- // generateRandomWord generates a random 6-letter word from /usr/share/dict/words
- func (h *DNSHandler) generateRandomWord() (string, error) {
- file, err := os.Open("/usr/share/dict/words")
- if err != nil {
- return "", err
- }
- defer file.Close()
- var words []string
- scanner := bufio.NewScanner(file)
- regex := regexp.MustCompile(`^[a-zA-Z]{6}$`)
- for scanner.Scan() {
- word := strings.ToLower(scanner.Text())
- if regex.MatchString(word) {
- words = append(words, word)
- }
- }
- if len(words) == 0 {
- return "", fmt.Errorf("no suitable words found")
- }
- return words[rand.Intn(len(words))], nil
- }
- // CreateDNSRecord handles the creation of a new DNS record
- func (h *DNSHandler) CreateDNSRecord(w http.ResponseWriter, r *http.Request) {
- log.Printf("Handling POST request for new DNS record from %s", r.RemoteAddr)
- // Parse request body for target IP
- var request struct {
- Target string `json:"target"`
- }
- if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
- log.Printf("Error decoding request body: %v", err)
- http.Error(w, "Invalid request body", http.StatusBadRequest)
- return
- }
- // Generate random subdomain
- word1, err := h.generateRandomWord()
- if err != nil {
- log.Printf("Error generating first word: %v", err)
- http.Error(w, "Failed to generate subdomain", http.StatusInternalServerError)
- return
- }
- word2, err := h.generateRandomWord()
- if err != nil {
- log.Printf("Error generating second word: %v", err)
- http.Error(w, "Failed to generate subdomain", http.StatusInternalServerError)
- return
- }
- // Create DNS record
- record := DNSRecord{
- FieldType: "A",
- SubDomain: word1 + "-" + word2,
- Target: request.Target,
- TTL: 0,
- }
- var response DNSRecord
- err = config.OVHClient.Post("/domain/zone/"+h.Zone+"/record", record, &response)
- if err != nil {
- log.Printf("Error creating DNS record: %v", err)
- http.Error(w, "Failed to create DNS record: "+err.Error(), http.StatusInternalServerError)
- return
- }
- // Refresh the zone
- err = h.refreshZone()
- if err != nil {
- log.Printf("Warning: zone refresh failed: %v", err)
- }
- log.Printf("Successfully created DNS record: %s.%s", response.SubDomain, h.Zone)
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
- if err := json.NewEncoder(w).Encode(response); err != nil {
- log.Printf("Error encoding response: %v", err)
- http.Error(w, "Failed to encode response", http.StatusInternalServerError)
- return
- }
- }
- // DeleteDNSRecord handles the deletion of a DNS record
- func (h *DNSHandler) DeleteDNSRecord(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- recordID := vars["id"]
- log.Printf("Handling DELETE request for DNS record: %s from %s", recordID, r.RemoteAddr)
- err := config.OVHClient.Delete("/domain/zone/"+h.Zone+"/record/"+recordID, nil)
- if err != nil {
- log.Printf("Error deleting DNS record %s: %v", recordID, err)
- http.Error(w, "Failed to delete DNS record: "+err.Error(), http.StatusInternalServerError)
- return
- }
- // Refresh the zone
- err = h.refreshZone()
- if err != nil {
- log.Printf("Warning: zone refresh failed: %v", err)
- }
- log.Printf("Successfully deleted DNS record: %s", recordID)
- w.WriteHeader(http.StatusNoContent)
- }
- // refreshZone refreshes the DNS zone
- func (h *DNSHandler) refreshZone() error {
- return config.OVHClient.Post("/domain/zone/"+h.Zone+"/refresh", nil, nil)
- }
- // ListDNSRecords handles listing all A records in the DNS zone
- func (h *DNSHandler) ListDNSRecords(w http.ResponseWriter, r *http.Request) {
- log.Printf("Handling GET request for DNS records from %s", r.RemoteAddr)
- //log.Printf("Loading DNS Zone : %s", h.Zone)
- var recordIDs []int
- err := config.OVHClient.Get("/domain/zone/"+h.Zone+"/record", &recordIDs)
- if err != nil {
- log.Printf("Error getting DNS record IDs: %v", err)
- http.Error(w, "Failed to get DNS records: "+err.Error(), http.StatusInternalServerError)
- return
- }
- var records []DNSRecord
- for _, id := range recordIDs {
- var record DNSRecord
- err := config.OVHClient.Get(fmt.Sprintf("/domain/zone/%s/record/%d", h.Zone, id), &record)
- if err != nil {
- log.Printf("Error getting DNS record %d: %v", id, err)
- continue
- }
- // Only include A records
- if record.FieldType == "A" {
- records = append(records, record)
- }
- }
- w.Header().Set("Content-Type", "application/json")
- if err := json.NewEncoder(w).Encode(records); err != nil {
- log.Printf("Error encoding response: %v", err)
- http.Error(w, "Failed to encode response", http.StatusInternalServerError)
- return
- }
- }
- // GetDNSRecordID retrieves the record ID for a specific subdomain
- func (h *DNSHandler) GetDNSRecordID(w http.ResponseWriter, r *http.Request) {
- vars := mux.Vars(r)
- subdomain := vars["subdomain"]
- log.Printf("Handling GET request for DNS record ID with subdomain: %s from %s", subdomain, r.RemoteAddr)
- // Get all record IDs
- var recordIDs []int
- err := config.OVHClient.Get("/domain/zone/"+h.Zone+"/record", &recordIDs)
- if err != nil {
- log.Printf("Error getting DNS record IDs: %v", err)
- http.Error(w, "Failed to get DNS records: "+err.Error(), http.StatusInternalServerError)
- return
- }
- // Search through records to find matching subdomain
- for _, id := range recordIDs {
- var record DNSRecord
- err := config.OVHClient.Get(fmt.Sprintf("/domain/zone/%s/record/%d", h.Zone, id), &record)
- if err != nil {
- log.Printf("Error getting DNS record %d: %v", id, err)
- continue
- }
- if record.FieldType == "A" && record.SubDomain == subdomain {
- response := struct {
- ID int `json:"id"`
- }{
- ID: id,
- }
- w.Header().Set("Content-Type", "application/json")
- if err := json.NewEncoder(w).Encode(response); err != nil {
- log.Printf("Error encoding response: %v", err)
- http.Error(w, "Failed to encode response", http.StatusInternalServerError)
- return
- }
- return
- }
- }
- // If we get here, no matching record was found
- http.Error(w, "Record not found", http.StatusNotFound)
- }
|