add multi instance support

This commit is contained in:
2025-03-26 13:47:05 +01:00
parent 3dc275d7e3
commit 546b08039f
7 changed files with 170 additions and 73 deletions

View File

@@ -106,10 +106,10 @@ func (j JSONInput) String() string {
}
// SetDefaults modify the input by setting the right default parameters
func (ja JSONArray) SetDefaults(p *PowerDNS) JSONArray {
func (ja JSONArray) SetDefaults(h *HTTPServer) JSONArray {
for i, j := range ja {
if j.Params.TTL == 0 {
ja[i].Params.TTL = p.DefaultTTL
ja[i].Params.TTL = h.findDNSInstance(j.Params.Name).DefaultTTL
}
}
return ja
@@ -136,7 +136,8 @@ func (ja JSONArray) Run(h *HTTPServer, user string, wasArray, textOnly bool) str
continue
}
listResult = append(listResult, JSONRPCNewError(-32000, j.ID, last.Error))
h.dns.LogDebug(last.Error)
h.findDNSInstance(j.Params.Name).LogDebug(last.Error)
if !j.Params.IgnoreError {
break
}
@@ -162,23 +163,31 @@ func (j *JSONInput) Run(h *HTTPServer, user string) []*JSONRPCResult {
if err := j.Normalize(); err != nil {
return append(ret, j.JSONRPCResult("", "", err))
}
d := h.findDNSInstance(j.Params.Name)
switch j.Method {
// list is a spacial case, it doesn't imply a DNSQuery() object
case "list":
result, err := h.dns.ListZones(j.Params.Name)
// we apply the acl after the fact for the list method
result = j.FilterList(result)
var err error
total := DNSZones{}
for _, dns := range h.dnsInstances {
result, err := dns.dns.ListZones(j.Params.Name)
// we apply the acl after the fact for the list method
result = j.FilterList(result)
if err == nil && len(result) == 0 {
err = errors.New("Unknown domain")
if err == nil && len(result) == 0 {
err = errors.New("Unknown domain")
}
total = append(total, result...)
}
res := j.JSONRPCResult(result.List("\n"), "", err)
for i := range result {
res.Raw = append(res.Raw, result[i].Name)
res := j.JSONRPCResult(total.List("\n"), "", err)
for i := range total {
res.Raw = append(res.Raw, total[i].Name)
}
return append(ret, res)
case "domain":
parentName, err := h.dns.GetDomain(j.Params.Name)
parentName, err := d.GetDomain(j.Params.Name)
res := j.JSONRPCResult(parentName, "", err)
res.Raw = append(res.Raw, parentName)
return append(ret, res)
@@ -212,7 +221,7 @@ func (j *JSONInput) Run(h *HTTPServer, user string) []*JSONRPCResult {
ret = append(ret, result)
continue
}
code, _, err := h.dns.Execute(act)
code, _, err := d.Execute(act)
switch {
case err == nil && code == 204:
result.Result = "Command Successfull"
@@ -277,15 +286,17 @@ func (j *JSONInput) Normalize() error {
// pdns. It can change the content of j to force dry run mode
func (j *JSONInput) DNSQueries(h *HTTPServer) ([]*DNSQuery, error) {
var err error
d := h.findDNSInstance(j.Params.Name)
switch j.Method {
case "search":
result, err := h.dns.Search(j.Params.Name)
result, err := d.Search(j.Params.Name)
// we apply the acl after the fact for the search method
result = j.FilterSearch(result)
j.Params.DryRun = true
return []*DNSQuery{result.DNSQuery()}, err
case "dump":
result, err := h.dns.Zone(j.Params.Name)
result, err := d.Zone(j.Params.Name)
j.Params.DryRun = true
return []*DNSQuery{result}, err
case "newzone":
@@ -297,13 +308,13 @@ func (j *JSONInput) DNSQueries(h *HTTPServer) ([]*DNSQuery, error) {
return append(otherActions, newZone.TransformIntoDNSQuery()), nil
}
result := &DNSQuery{}
code, _, err := h.dns.ExecuteZone(newZone, result)
code, _, err := d.ExecuteZone(newZone, result)
if err == nil && code != 201 {
err = fmt.Errorf("The return code was %d for the creation of zone %s", code, j.Params.Name)
}
return append(otherActions, result), err
}
current, err := h.dns.GetRecord(j.Params.Name, j.Method, j.ignoreBadDomain)
current, err := d.GetRecord(j.Params.Name, j.Method, j.ignoreBadDomain)
if err != nil {
return nil, err
}
@@ -371,7 +382,8 @@ func (j *JSONInput) DNSQueriesNS(h *HTTPServer, current *DNSQuery) ([]*DNSQuery,
if trimPoint(j.Params.Name) == trimPoint(current.Domain) {
return nil, fmt.Errorf("You cannot change the NS of a local zone")
}
subZone, err := h.dns.Zone(j.Params.Name)
d := h.findDNSInstance(j.Params.Name)
subZone, err := d.Zone(j.Params.Name)
if err != nil {
return nil, err
}
@@ -443,7 +455,8 @@ func (j *JSONInput) DNSQueriesTTL(current *DNSQuery) ([]*DNSQuery, error) {
// DNSQueriesA is the DNSQueries method for the A and AAAA commands
// it checks the command is legal, and can make reverse DNS changes if needed
func (j *JSONInput) DNSQueriesA(h *HTTPServer, forward *DNSQuery) ([]*DNSQuery, error) {
reverse, err := h.dns.GetReverse(j.Params.Value, j.Method == "a")
d := h.findDNSInstance(j.Params.Name)
reverse, err := d.GetReverse(j.Params.Value, j.Method == "a")
if err != nil {
return nil, err
}
@@ -458,13 +471,14 @@ func (j *JSONInput) DNSQueriesA(h *HTTPServer, forward *DNSQuery) ([]*DNSQuery,
forward.ChangeValue(j.Params.Name, j.Params.Value, j.Method, false, askForReverse)
return []*DNSQuery{forward}, nil
}
actions, err := h.dns.ReverseChanges(forward, j.Params.Value)
actions, err := d.ReverseChanges(forward, j.Params.Value)
forward.ChangeValue(j.Params.Name, j.Params.Value, j.Method, true, askForReverse)
return append(actions, forward), err
}
// DNSQueriesDelete is the DNSQueries method for the Delete command
func (j *JSONInput) DNSQueriesDelete(h *HTTPServer, current *DNSQuery) ([]*DNSQuery, error) {
d := h.findDNSInstance(j.Params.Name)
reverses, useful, err := current.SplitDeletionQuery(j.Params.Name, j.Params.Value)
if err != nil {
return nil, err
@@ -477,7 +491,7 @@ func (j *JSONInput) DNSQueriesDelete(h *HTTPServer, current *DNSQuery) ([]*DNSQu
ret := []*DNSQuery{current}
// add the reverse changes if needed
for _, r := range reverses {
parentName, err := h.dns.GetDomain(r.Name)
parentName, err := d.GetDomain(r.Name)
if err != nil {
return nil, err
}
@@ -486,7 +500,7 @@ func (j *JSONInput) DNSQueriesDelete(h *HTTPServer, current *DNSQuery) ([]*DNSQu
continue
}
ip := ptrToIP(r.Name)
if h.dns.IsUsed(ip, j.Params.Name, []string{"A", "AAAA"}) {
if d.IsUsed(ip, j.Params.Name, []string{"A", "AAAA"}) {
message := "Reverse issue : %s is the reverse for %s and will be removed\n"
message += "But other records are pointing to %s as well. Please cleanup first\n"
return ret, fmt.Errorf(message, j.Params.Name, ip, ip)
@@ -497,12 +511,13 @@ func (j *JSONInput) DNSQueriesDelete(h *HTTPServer, current *DNSQuery) ([]*DNSQu
// CheckPTR validates that the query is a valid PTR
func (j *JSONInput) CheckPTR(h *HTTPServer) error {
d := h.findDNSInstance(j.Params.Name)
ip := ptrToIP(j.Params.Name)
if ip == "" {
return fmt.Errorf("%s is not a valid PTR", j.Params.Name)
}
target := &DNSQuery{}
if err := h.dns.CanCreate(j.Params.Value, true, target); err != nil || target.Len() == 0 {
if err := d.CanCreate(j.Params.Value, true, target); err != nil || target.Len() == 0 {
return err
}
for _, rec := range target.RRSets[0].Records {
@@ -515,11 +530,12 @@ func (j *JSONInput) CheckPTR(h *HTTPServer) error {
// CheckSRV validates that the query is a valid SRV
func (j *JSONInput) CheckSRV(h *HTTPServer) error {
d := h.findDNSInstance(j.Params.Name)
name := validSRV(j.Params.Value)
if name == "" {
return fmt.Errorf("%s is not a valid SRV", j.Params.Value)
}
return h.dns.CanCreate(name, false, nil)
return d.CanCreate(name, false, nil)
}
// CheckCAA validates that the query is a valid CAA
@@ -535,10 +551,11 @@ func (j *JSONInput) CheckCAA() error {
// CheckMX validates that the query is a valid MX
func (j *JSONInput) CheckMX(h *HTTPServer) error {
name := validMX(j.Params.Value)
d := h.findDNSInstance(j.Params.Name)
if name == "" {
return fmt.Errorf("%s is not a valid MX", j.Params.Value)
}
return h.dns.CanCreate(name, true, nil)
return d.CanCreate(name, true, nil)
}
// CheckCNAME validates that the query is a valid CNAME
@@ -550,7 +567,8 @@ func (j *JSONInput) CheckCNAME(h *HTTPServer) error {
if !validName(j.Params.Value, false) {
return fmt.Errorf("%s is not a valid DNS Name", j.Params.Value)
}
return h.dns.CanCreate(j.Params.Value, false, nil)
d := h.findDNSInstance(j.Params.Name)
return d.CanCreate(j.Params.Value, false, nil)
}
// NewZone create a new zone in the DNS.
@@ -565,10 +583,11 @@ func (j *JSONInput) NewZone(h *HTTPServer) (z *DNSZone, otherActions []*DNSQuery
if soa == "" {
soa = fmt.Sprintf("%s hostmaster.%s 0 28800 7200 604800 86400", nameServers[0], j.Params.Name)
}
parentName, zoneErr := h.dns.GetDomain(j.Params.Name)
dns := h.findDNSInstance(j.Params.Name)
parentName, zoneErr := dns.GetDomain(j.Params.Name)
parentName = trimPoint(parentName)
z, err = h.dns.NewZone(j.Params.Name, zoneType, soa, j.user, j.Params.Comment,
z, err = dns.NewZone(j.Params.Name, zoneType, soa, j.user, j.Params.Comment,
j.Params.TTL, nameServers, autoInc)
if err != nil {
return nil, nil, err
@@ -589,7 +608,7 @@ func (j *JSONInput) NewZone(h *HTTPServer) (z *DNSZone, otherActions []*DNSQuery
entry.Params.Name = fmt.Sprintf("%s.%s", d.Params.Name, j.Params.Name)
}
if err := entry.Normalize(); err != nil {
h.dns.LogDebug(err)
dns.LogDebug(err)
continue
}
actions, err := entry.DNSQueries(h)
@@ -605,14 +624,14 @@ func (j *JSONInput) NewZone(h *HTTPServer) (z *DNSZone, otherActions []*DNSQuery
return
}
// we must create the NS records in the parent zone too
glue, err := h.dns.SetNameServers(j.Params.Name, parentName, nameServers)
glue, err := dns.SetNameServers(j.Params.Name, parentName, nameServers)
if err != nil {
return nil, nil, err
}
otherActions = append(otherActions, glue)
// check if there are records in the parent zone
records, err := h.dns.Zone(j.Params.Name)
records, err := dns.Zone(j.Params.Name)
if err != nil {
err = nil
return
@@ -622,7 +641,7 @@ func (j *JSONInput) NewZone(h *HTTPServer) (z *DNSZone, otherActions []*DNSQuery
z.AddEntries(records)
// and delete them in the parent
delete, err := h.dns.Zone(j.Params.Name)
delete, err := dns.Zone(j.Params.Name)
if err != nil {
return nil, nil, err
}
@@ -677,16 +696,16 @@ func (j *JSONInput) FilterList(z []*DNSZone) []*DNSZone {
}
// ParsejsonRPCRequest read the payload of the query and put it in the structure
func ParsejsonRPCRequest(s []byte, d *PowerDNS) (JSONArray, bool, error) {
func ParsejsonRPCRequest(s []byte, h *HTTPServer) (JSONArray, bool, error) {
var inSimple *JSONInput
var inArray JSONArray
if json.Unmarshal(s, &inArray); len(inArray) > 0 {
return inArray.SetDefaults(d), true, nil
return inArray.SetDefaults(h), true, nil
}
if err := json.Unmarshal(s, &inSimple); err != nil {
return nil, false, err
}
return JSONArray{inSimple}.SetDefaults(d), false, nil
return JSONArray{inSimple}.SetDefaults(h), false, nil
}
func isDryRun(j JSONArray) bool {