tailcfg,types/netmap: add (visible) Services to SelfNode Caps (#19335)
Updates #40052 Signed-off-by: Adriano Sela Aviles <adriano@tailscale.com>
This commit is contained in:
committed by
GitHub
parent
674f866ecc
commit
4fcce6000d
@@ -2447,6 +2447,18 @@ type Oauth2Token struct {
|
|||||||
// These are also referred to as "Node Attributes" in the ACL policy file.
|
// These are also referred to as "Node Attributes" in the ACL policy file.
|
||||||
type NodeCapability string
|
type NodeCapability string
|
||||||
|
|
||||||
|
// NodeCapabilityPrefix is a prefix for [NodeCapMap] keys that share a common
|
||||||
|
// namespace, where each entry represents a distinct named instance (e.g. one
|
||||||
|
// per service). The full key is formed by concatenating the prefix with the
|
||||||
|
// instance name.
|
||||||
|
type NodeCapabilityPrefix string
|
||||||
|
|
||||||
|
// ToAttribute returns the full [NodeCapability] key for the given value under
|
||||||
|
// this prefix, of the form prefix+value.
|
||||||
|
func (p NodeCapabilityPrefix) ToAttribute(value string) NodeCapability {
|
||||||
|
return NodeCapability(string(p) + value)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CapabilityFileSharing NodeCapability = "https://tailscale.com/cap/file-sharing"
|
CapabilityFileSharing NodeCapability = "https://tailscale.com/cap/file-sharing"
|
||||||
CapabilityAdmin NodeCapability = "https://tailscale.com/cap/is-admin"
|
CapabilityAdmin NodeCapability = "https://tailscale.com/cap/is-admin"
|
||||||
@@ -2780,6 +2792,14 @@ const (
|
|||||||
NodeAttrCacheNetworkMaps NodeCapability = "cache-network-maps"
|
NodeAttrCacheNetworkMaps NodeCapability = "cache-network-maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NodeAttrPrefixServices is the prefix for per-service [NodeCapMap]
|
||||||
|
// entries describing Services visible (accessible) to this node. The full
|
||||||
|
// key for a service named "svc:foo" is NodeAttrPrefixServices+"foo".
|
||||||
|
// Each value under such a key is of type [ServiceDetails].
|
||||||
|
NodeAttrPrefixServices NodeCapabilityPrefix = "services/"
|
||||||
|
)
|
||||||
|
|
||||||
// SetDNSRequest is a request to add a DNS record.
|
// SetDNSRequest is a request to add a DNS record.
|
||||||
//
|
//
|
||||||
// This is used to let tailscaled clients complete their ACME DNS-01 challenges
|
// This is used to let tailscaled clients complete their ACME DNS-01 challenges
|
||||||
@@ -3318,6 +3338,19 @@ const LBHeader = "Ts-Lb"
|
|||||||
// this client is hosting can be ignored.
|
// this client is hosting can be ignored.
|
||||||
type ServiceIPMappings map[ServiceName][]netip.Addr
|
type ServiceIPMappings map[ServiceName][]netip.Addr
|
||||||
|
|
||||||
|
// ServiceDetails describes a Service visible to this node.
|
||||||
|
// It is the value type stored under [NodeAttrPrefixServices]+serviceName keys in [NodeCapMap].
|
||||||
|
type ServiceDetails struct {
|
||||||
|
// Name is the name of the Service, of the form "svc:dns-label".
|
||||||
|
Name ServiceName
|
||||||
|
|
||||||
|
// Addrs are the IP addresses (IPv4 and IPv6) assigned to this Service.
|
||||||
|
Addrs []netip.Addr `json:",omitempty"`
|
||||||
|
|
||||||
|
// Ports are the protocol/port combinations the Service accepts.
|
||||||
|
Ports []ProtoPortRange `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ClientAuditAction represents an auditable action that a client can report to the
|
// ClientAuditAction represents an auditable action that a client can report to the
|
||||||
// control plane. These actions must correspond to the supported actions
|
// control plane. These actions must correspond to the supported actions
|
||||||
// in the control plane.
|
// in the control plane.
|
||||||
|
|||||||
@@ -146,6 +146,27 @@ func (nm *NetworkMap) GetIPVIPServiceMap() IPServiceMappings {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Services returns the Services visible (accessible) to this node,
|
||||||
|
// decoded from [tailcfg.NodeAttrPrefixServices]+serviceName entries in the
|
||||||
|
// self node's CapMap. Returns nil if nm is nil or SelfNode is invalid.
|
||||||
|
func (nm *NetworkMap) Services() map[tailcfg.ServiceName]tailcfg.ServiceDetails {
|
||||||
|
if nm == nil || !nm.SelfNode.Valid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
result := make(map[tailcfg.ServiceName]tailcfg.ServiceDetails)
|
||||||
|
for cap := range nm.SelfNode.CapMap().All() {
|
||||||
|
if !strings.HasPrefix(string(cap), string(tailcfg.NodeAttrPrefixServices)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
svcs, err := tailcfg.UnmarshalNodeCapViewJSON[tailcfg.ServiceDetails](nm.SelfNode.CapMap(), cap)
|
||||||
|
if err != nil || len(svcs) < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result[svcs[0].Name] = svcs[0]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// SelfNodeOrZero returns the self node, or a zero value if nm is nil.
|
// SelfNodeOrZero returns the self node, or a zero value if nm is nil.
|
||||||
func (nm *NetworkMap) SelfNodeOrZero() tailcfg.NodeView {
|
func (nm *NetworkMap) SelfNodeOrZero() tailcfg.NodeView {
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user