Files
tailscale/appc/conn25.go
Fran Bull 247c67809b appc,feature/conn25: move functions to where they are used
The functions used to be used in ipn/ipnlocal but we changed that, so
the functions can be moved into feature/conn25 now.

Updates tailscale/corp#47250

Signed-off-by: Fran Bull <fran@tailscale.com>
2026-08-26 15:10:24 -07:00

47 lines
1.5 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package appc
import (
"fmt"
"strings"
"tailscale.com/tailcfg"
"tailscale.com/tailcfg/nodecap"
"tailscale.com/types/appctype"
"tailscale.com/types/dnstype"
)
const AppConnectorsExperimentalAttrName = "tailscale.com/app-connectors-experimental"
// DNSAddrScheme is the custom URI scheme used for conn25-managed split DNS
// entries to determine the destination at query time rather than configuration
// time.
const DNSAddrScheme = "tailscale-app"
func AppDNSRoutes(hasCap func(c nodecap.Cap) bool, self tailcfg.NodeView) map[string][]*dnstype.Resolver {
if !hasCap(AppConnectorsExperimentalAttrName) {
return nil
}
apps, err := tailcfg.UnmarshalNodeCapViewJSON[appctype.AppConnectorAttr](self.CapMap(), AppConnectorsExperimentalAttrName)
if err != nil {
return nil
}
appNamesByDomain := map[string]string{}
for _, app := range apps {
for _, domain := range app.Domains {
domain, _ = strings.CutPrefix(domain, "*.")
domain = strings.ToLower(domain)
// in the case of multiple apps specifying the same domain (which is misconfiguration
// that should be validated at point of input) last write wins.
appNamesByDomain[domain] = app.Name
}
}
m := make(map[string][]*dnstype.Resolver, len(appNamesByDomain))
for domain, appName := range appNamesByDomain {
m[domain] = []*dnstype.Resolver{{Addr: fmt.Sprintf("%s:%s", DNSAddrScheme, appName), UseWithExitNode: true}}
}
return m
}