Ctrl K
ComunidadGuías…

internal/server/acme_dns_resolvers_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: Apache-2.0

package server

import (
	"path/filepath"
	"reflect"
	"testing"

	appdb "github.com/X4Applegate/caddyui/internal/db"
	"github.com/X4Applegate/caddyui/internal/dns"
	"github.com/X4Applegate/caddyui/internal/models"
)

func TestParsePlainDNSServers(t *testing.T) {
	tests := []struct {
		name string
		raw  string
		want []string
	}{
		{"blank", "", nil},
		{"whitespace", "   ", nil},
		{"single ip with port", "1.1.1.1:53", []string{"1.1.1.1:53"}},
		{"single ip default port", "1.1.1.1", []string{"1.1.1.1:53"}},
		{"comma list mixed ports", "1.1.1.1, 8.8.8.8:5353", []string{"1.1.1.1:53", "8.8.8.8:5353"}},
		{"newline list", "1.1.1.1\n8.8.8.8", []string{"1.1.1.1:53", "8.8.8.8:53"}},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := parsePlainDNSServers(tc.raw)
			if !reflect.DeepEqual(got, tc.want) {
				t.Fatalf("servers = %#v, want %#v", got, tc.want)
			}
		})
	}
}

// issue #116: an admin-configured ACME DNS-01 resolver list must be emitted
// into every DNS-01 automation policy's challenges.dns.resolvers, so Caddy
// checks TXT-record propagation against those servers instead of the
// container's default resolver (the split-horizon DNS failure mode).
func TestBuildDNSAutomationPoliciesIncludesACMEResolvers(t *testing.T) {
	conn, err := appdb.Open(filepath.Join(t.TempDir(), "caddyui.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { _ = conn.Close() })
	for key, value := range map[string]string{
		settingRoute53AccessKeyID:     "AKIAEXAMPLE",
		settingRoute53SecretAccessKey: "secret",
		settingACMEDNSResolvers:       "1.1.1.1, 8.8.8.8:5353",
	} {
		if err := models.SetSetting(conn, key, value); err != nil {
			t.Fatal(err)
		}
	}
	s := &Server{DB: conn}
	policies := s.buildDNSAutomationPolicies([]models.ProxyHost{
		{Domains: "split.example.com", Enabled: true, SSLEnabled: true, DNSProvider: dns.Route53, DNSZoneID: "ZSPLIT"},
	}, nil, nil, nil)
	if len(policies) != 1 {
		t.Fatalf("policies = %d, want 1", len(policies))
	}
	issuers := policies[0]["issuers"].([]any)
	challenge := issuers[0].(map[string]any)["challenges"].(map[string]any)["dns"].(map[string]any)
	want := []any{"1.1.1.1:53", "8.8.8.8:5353"}
	if got, _ := challenge["resolvers"].([]any); !reflect.DeepEqual(got, want) {
		t.Fatalf("resolvers = %#v, want %#v", got, want)
	}
}

// Without the setting, Caddy's challenges.dns config must carry no resolvers
// key at all — not an empty list — so Caddy's own default resolver applies.
func TestBuildDNSAutomationPoliciesOmitsResolversWhenUnset(t *testing.T) {
	conn, err := appdb.Open(filepath.Join(t.TempDir(), "caddyui.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { _ = conn.Close() })
	for key, value := range map[string]string{
		settingRoute53AccessKeyID:     "AKIAEXAMPLE",
		settingRoute53SecretAccessKey: "secret",
	} {
		if err := models.SetSetting(conn, key, value); err != nil {
			t.Fatal(err)
		}
	}
	s := &Server{DB: conn}
	policies := s.buildDNSAutomationPolicies([]models.ProxyHost{
		{Domains: "default.example.com", Enabled: true, SSLEnabled: true, DNSProvider: dns.Route53, DNSZoneID: "ZDEFAULT"},
	}, nil, nil, nil)
	if len(policies) != 1 {
		t.Fatalf("policies = %d, want 1", len(policies))
	}
	issuers := policies[0]["issuers"].([]any)
	challenge := issuers[0].(map[string]any)["challenges"].(map[string]any)["dns"].(map[string]any)
	if _, exists := challenge["resolvers"]; exists {
		t.Fatalf("resolvers = %#v, want key absent", challenge["resolvers"])
	}
}