ipn/store: add support for stores to hook into a custom dialer

For stores like k8s secrets we need to dial out to the k8s API as though Tailscale
wasn't running. The issue currently only manifests when you try to use an exit node
while running inside a k8s cluster and are trying to use Kubernetes secrets as the
backing store.

This doesn't address cmd/containerboot, which I'll do in a follow up.

Updates #7695

Signed-off-by: Maisem Ali <maisem@tailscale.com>
pull/7737/head
Maisem Ali 2 years ago committed by Maisem Ali
parent 2b00d6922f
commit e0d291ab8a

@ -276,6 +276,9 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, store ipn.StateStor
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sds, ok := store.(ipn.StateStoreDialerSetter); ok {
sds.SetDialer(dialer.SystemDial)
}
hi := hostinfo.New() hi := hostinfo.New()
logf.JSON(1, "Hostinfo", hi) logf.JSON(1, "Hostinfo", hi)

@ -4,8 +4,10 @@
package ipn package ipn
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"net"
"strconv" "strconv"
) )
@ -72,6 +74,12 @@ type StateStore interface {
WriteState(id StateKey, bs []byte) error WriteState(id StateKey, bs []byte) error
} }
// StateStoreDialerSetter is an optional interface that StateStores
// can implement to allow the caller to set a custom dialer.
type StateStoreDialerSetter interface {
SetDialer(d func(ctx context.Context, network, address string) (net.Conn, error))
}
// ReadStoreInt reads an integer from a StateStore. // ReadStoreInt reads an integer from a StateStore.
func ReadStoreInt(store StateStore, id StateKey) (int64, error) { func ReadStoreInt(store StateStore, id StateKey) (int64, error) {
v, err := store.ReadState(id) v, err := store.ReadState(id)

@ -7,6 +7,7 @@ package kubestore
import ( import (
"context" "context"
"net"
"strings" "strings"
"time" "time"
@ -33,6 +34,10 @@ func New(_ logger.Logf, secretName string) (*Store, error) {
}, nil }, nil
} }
func (s *Store) SetDialer(d func(ctx context.Context, network, address string) (net.Conn, error)) {
s.client.SetDialer(d)
}
func (s *Store) String() string { return "kube.Store" } func (s *Store) String() string { return "kube.Store" }
// ReadState implements the StateStore interface. // ReadState implements the StateStore interface.

@ -15,6 +15,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -90,6 +91,12 @@ func (c *Client) SetURL(url string) {
c.url = url c.url = url
} }
// SetDialer sets the dialer to use when establishing a connection
// to the Kubernetes API server.
func (c *Client) SetDialer(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) {
c.client.Transport.(*http.Transport).DialContext = dialer
}
func (c *Client) expireToken() { func (c *Client) expireToken() {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()

Loading…
Cancel
Save