mirror of
https://github.com/siderolabs/talos.git
synced 2025-10-11 15:41:11 +02:00
Don't allow worker nodes to act as apid routers: * don't try to issue client certificate for apid on worker nodes * if worker nodes receives incoming connections with `--nodes` set to one of the local addresses of the nodd, it routes the request to itself without proxying Second point allows using `talosctl -e worker -n worker` to connect directly to the worker if the connection from the control plane is not available for some reason. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package director
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/cosi-project/runtime/pkg/resource"
|
|
"github.com/cosi-project/runtime/pkg/state"
|
|
|
|
"github.com/talos-systems/talos/pkg/machinery/resources/network"
|
|
)
|
|
|
|
// LocalAddressProvider provides local address information.
|
|
type LocalAddressProvider interface {
|
|
IsLocalTarget(string) bool
|
|
}
|
|
|
|
// localAddressProvider watches and keeps track of the local node addresses.
|
|
type localAddressProvider struct {
|
|
mu sync.Mutex
|
|
|
|
localAddresses map[string]struct{}
|
|
localHostnames map[string]struct{}
|
|
}
|
|
|
|
// NewLocalAddressProvider initializes and returns a new LocalAddressProvider.
|
|
func NewLocalAddressProvider(st state.State) (*localAddressProvider, error) {
|
|
p := &localAddressProvider{}
|
|
|
|
evCh := make(chan state.Event)
|
|
|
|
if err := st.Watch(context.Background(), resource.NewMetadata(network.NamespaceName, network.NodeAddressType, network.NodeAddressCurrentID, resource.VersionUndefined), evCh); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := st.Watch(context.Background(), resource.NewMetadata(network.NamespaceName, network.HostnameStatusType, network.HostnameID, resource.VersionUndefined), evCh); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
go p.watch(evCh)
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (p *localAddressProvider) watch(evCh <-chan state.Event) {
|
|
for ev := range evCh {
|
|
if ev.Type == state.Destroyed {
|
|
// shouldn't happen
|
|
continue
|
|
}
|
|
|
|
switch r := ev.Resource.(type) {
|
|
case *network.NodeAddress:
|
|
p.mu.Lock()
|
|
|
|
p.localAddresses = make(map[string]struct{}, len(r.TypedSpec().Addresses))
|
|
|
|
for _, addr := range r.TypedSpec().Addresses {
|
|
p.localAddresses[addr.Addr().String()] = struct{}{}
|
|
}
|
|
|
|
p.mu.Unlock()
|
|
case *network.HostnameStatus:
|
|
p.mu.Lock()
|
|
|
|
p.localHostnames = make(map[string]struct{}, 2)
|
|
|
|
p.localHostnames[r.TypedSpec().Hostname] = struct{}{}
|
|
p.localHostnames[r.TypedSpec().FQDN()] = struct{}{}
|
|
|
|
p.mu.Unlock()
|
|
}
|
|
}
|
|
}
|
|
|
|
// IsLocalTarget returns true if the address (hostname) is local.
|
|
func (p *localAddressProvider) IsLocalTarget(target string) bool {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
|
|
_, ok1 := p.localAddresses[target]
|
|
_, ok2 := p.localHostnames[target]
|
|
|
|
return ok1 || ok2
|
|
}
|