mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-13 14:43:19 +00:00
cmd/k8s-operator,k8s-operator/api-proxy: move k8s proxy code to library (#15857)
The defaultEnv and defaultBool functions are copied over temporarily to minimise diff. This lays the ground work for having both the operator and the new k8s-proxy binary implement the API proxy Updates #13358 Change-Id: Ieacc79af64df2f13b27a18135517bb31c80a5a02 Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
@@ -840,9 +840,10 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
tailscale.com/ipn/store/kubestore from tailscale.com/cmd/k8s-operator+
|
||||
tailscale.com/ipn/store/mem from tailscale.com/ipn/ipnlocal+
|
||||
tailscale.com/k8s-operator from tailscale.com/cmd/k8s-operator
|
||||
tailscale.com/k8s-operator/api-proxy from tailscale.com/cmd/k8s-operator
|
||||
tailscale.com/k8s-operator/apis from tailscale.com/k8s-operator/apis/v1alpha1
|
||||
tailscale.com/k8s-operator/apis/v1alpha1 from tailscale.com/cmd/k8s-operator+
|
||||
tailscale.com/k8s-operator/sessionrecording from tailscale.com/cmd/k8s-operator
|
||||
tailscale.com/k8s-operator/sessionrecording from tailscale.com/k8s-operator/api-proxy
|
||||
tailscale.com/k8s-operator/sessionrecording/spdy from tailscale.com/k8s-operator/sessionrecording
|
||||
tailscale.com/k8s-operator/sessionrecording/tsrecorder from tailscale.com/k8s-operator/sessionrecording+
|
||||
tailscale.com/k8s-operator/sessionrecording/ws from tailscale.com/k8s-operator/sessionrecording
|
||||
@@ -945,7 +946,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
||||
tailscale.com/util/clientmetric from tailscale.com/cmd/k8s-operator+
|
||||
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
||||
tailscale.com/util/cmpver from tailscale.com/clientupdate+
|
||||
tailscale.com/util/ctxkey from tailscale.com/cmd/k8s-operator+
|
||||
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics+
|
||||
tailscale.com/util/dnsname from tailscale.com/appc+
|
||||
|
@@ -45,6 +45,7 @@ import (
|
||||
"tailscale.com/hostinfo"
|
||||
"tailscale.com/ipn"
|
||||
"tailscale.com/ipn/store/kubestore"
|
||||
apiproxy "tailscale.com/k8s-operator/api-proxy"
|
||||
tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
|
||||
"tailscale.com/kube/kubetypes"
|
||||
"tailscale.com/tsnet"
|
||||
@@ -102,8 +103,8 @@ func main() {
|
||||
// The operator can run either as a plain operator or it can
|
||||
// additionally act as api-server proxy
|
||||
// https://tailscale.com/kb/1236/kubernetes-operator/?q=kubernetes#accessing-the-kubernetes-control-plane-using-an-api-server-proxy.
|
||||
mode := parseAPIProxyMode()
|
||||
if mode == apiserverProxyModeDisabled {
|
||||
mode := apiproxy.ParseAPIProxyMode()
|
||||
if mode == apiproxy.APIServerProxyModeDisabled {
|
||||
hostinfo.SetApp(kubetypes.AppOperator)
|
||||
} else {
|
||||
hostinfo.SetApp(kubetypes.AppAPIServerProxy)
|
||||
@@ -112,7 +113,7 @@ func main() {
|
||||
s, tsc := initTSNet(zlog)
|
||||
defer s.Close()
|
||||
restConfig := config.GetConfigOrDie()
|
||||
maybeLaunchAPIServerProxy(zlog, restConfig, s, mode)
|
||||
apiproxy.MaybeLaunchAPIServerProxy(zlog, restConfig, s, mode)
|
||||
rOpts := reconcilerOpts{
|
||||
log: zlog,
|
||||
tsServer: s,
|
||||
|
8
k8s-operator/api-proxy/doc.go
Normal file
8
k8s-operator/api-proxy/doc.go
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !plan9
|
||||
|
||||
// Package apiproxy contains the Kubernetes API Proxy implementation used by
|
||||
// k8s-operator and k8s-proxy.
|
||||
package apiproxy
|
29
k8s-operator/api-proxy/env.go
Normal file
29
k8s-operator/api-proxy/env.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !plan9
|
||||
|
||||
package apiproxy
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"tailscale.com/types/opt"
|
||||
)
|
||||
|
||||
func defaultBool(envName string, defVal bool) bool {
|
||||
vs := os.Getenv(envName)
|
||||
if vs == "" {
|
||||
return defVal
|
||||
}
|
||||
v, _ := opt.Bool(vs).Get()
|
||||
return v
|
||||
}
|
||||
|
||||
func defaultEnv(envName, defVal string) string {
|
||||
v := os.Getenv(envName)
|
||||
if v == "" {
|
||||
return defVal
|
||||
}
|
||||
return v
|
||||
}
|
@@ -3,7 +3,7 @@
|
||||
|
||||
//go:build !plan9
|
||||
|
||||
package main
|
||||
package apiproxy
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
@@ -37,15 +37,15 @@ var (
|
||||
whoIsKey = ctxkey.New("", (*apitype.WhoIsResponse)(nil))
|
||||
)
|
||||
|
||||
type apiServerProxyMode int
|
||||
type APIServerProxyMode int
|
||||
|
||||
func (a apiServerProxyMode) String() string {
|
||||
func (a APIServerProxyMode) String() string {
|
||||
switch a {
|
||||
case apiserverProxyModeDisabled:
|
||||
case APIServerProxyModeDisabled:
|
||||
return "disabled"
|
||||
case apiserverProxyModeEnabled:
|
||||
case APIServerProxyModeEnabled:
|
||||
return "auth"
|
||||
case apiserverProxyModeNoAuth:
|
||||
case APIServerProxyModeNoAuth:
|
||||
return "noauth"
|
||||
default:
|
||||
return "unknown"
|
||||
@@ -53,12 +53,12 @@ func (a apiServerProxyMode) String() string {
|
||||
}
|
||||
|
||||
const (
|
||||
apiserverProxyModeDisabled apiServerProxyMode = iota
|
||||
apiserverProxyModeEnabled
|
||||
apiserverProxyModeNoAuth
|
||||
APIServerProxyModeDisabled APIServerProxyMode = iota
|
||||
APIServerProxyModeEnabled
|
||||
APIServerProxyModeNoAuth
|
||||
)
|
||||
|
||||
func parseAPIProxyMode() apiServerProxyMode {
|
||||
func ParseAPIProxyMode() APIServerProxyMode {
|
||||
haveAuthProxyEnv := os.Getenv("AUTH_PROXY") != ""
|
||||
haveAPIProxyEnv := os.Getenv("APISERVER_PROXY") != ""
|
||||
switch {
|
||||
@@ -67,34 +67,34 @@ func parseAPIProxyMode() apiServerProxyMode {
|
||||
case haveAuthProxyEnv:
|
||||
var authProxyEnv = defaultBool("AUTH_PROXY", false) // deprecated
|
||||
if authProxyEnv {
|
||||
return apiserverProxyModeEnabled
|
||||
return APIServerProxyModeEnabled
|
||||
}
|
||||
return apiserverProxyModeDisabled
|
||||
return APIServerProxyModeDisabled
|
||||
case haveAPIProxyEnv:
|
||||
var apiProxyEnv = defaultEnv("APISERVER_PROXY", "") // true, false or "noauth"
|
||||
switch apiProxyEnv {
|
||||
case "true":
|
||||
return apiserverProxyModeEnabled
|
||||
return APIServerProxyModeEnabled
|
||||
case "false", "":
|
||||
return apiserverProxyModeDisabled
|
||||
return APIServerProxyModeDisabled
|
||||
case "noauth":
|
||||
return apiserverProxyModeNoAuth
|
||||
return APIServerProxyModeNoAuth
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown APISERVER_PROXY value %q", apiProxyEnv))
|
||||
}
|
||||
}
|
||||
return apiserverProxyModeDisabled
|
||||
return APIServerProxyModeDisabled
|
||||
}
|
||||
|
||||
// maybeLaunchAPIServerProxy launches the auth proxy, which is a small HTTP server
|
||||
// that authenticates requests using the Tailscale LocalAPI and then proxies
|
||||
// them to the kube-apiserver.
|
||||
func maybeLaunchAPIServerProxy(zlog *zap.SugaredLogger, restConfig *rest.Config, s *tsnet.Server, mode apiServerProxyMode) {
|
||||
if mode == apiserverProxyModeDisabled {
|
||||
func MaybeLaunchAPIServerProxy(zlog *zap.SugaredLogger, restConfig *rest.Config, s *tsnet.Server, mode APIServerProxyMode) {
|
||||
if mode == APIServerProxyModeDisabled {
|
||||
return
|
||||
}
|
||||
startlog := zlog.Named("launchAPIProxy")
|
||||
if mode == apiserverProxyModeNoAuth {
|
||||
if mode == APIServerProxyModeNoAuth {
|
||||
restConfig = rest.AnonymousClientConfig(restConfig)
|
||||
}
|
||||
cfg, err := restConfig.TransportConfig()
|
||||
@@ -132,8 +132,8 @@ func maybeLaunchAPIServerProxy(zlog *zap.SugaredLogger, restConfig *rest.Config,
|
||||
// are passed through to the Kubernetes API.
|
||||
//
|
||||
// It never returns.
|
||||
func runAPIServerProxy(ts *tsnet.Server, rt http.RoundTripper, log *zap.SugaredLogger, mode apiServerProxyMode, host string) {
|
||||
if mode == apiserverProxyModeDisabled {
|
||||
func runAPIServerProxy(ts *tsnet.Server, rt http.RoundTripper, log *zap.SugaredLogger, mode APIServerProxyMode, host string) {
|
||||
if mode == APIServerProxyModeDisabled {
|
||||
return
|
||||
}
|
||||
ln, err := ts.Listen("tcp", ":443")
|
||||
@@ -192,7 +192,7 @@ type apiserverProxy struct {
|
||||
lc *local.Client
|
||||
rp *httputil.ReverseProxy
|
||||
|
||||
mode apiServerProxyMode
|
||||
mode APIServerProxyMode
|
||||
ts *tsnet.Server
|
||||
upstreamURL *url.URL
|
||||
}
|
||||
@@ -285,7 +285,7 @@ func (ap *apiserverProxy) execForProto(w http.ResponseWriter, r *http.Request, p
|
||||
func (h *apiserverProxy) addImpersonationHeadersAsRequired(r *http.Request) {
|
||||
r.URL.Scheme = h.upstreamURL.Scheme
|
||||
r.URL.Host = h.upstreamURL.Host
|
||||
if h.mode == apiserverProxyModeNoAuth {
|
||||
if h.mode == APIServerProxyModeNoAuth {
|
||||
// If we are not providing authentication, then we are just
|
||||
// proxying to the Kubernetes API, so we don't need to do
|
||||
// anything else.
|
@@ -3,7 +3,7 @@
|
||||
|
||||
//go:build !plan9
|
||||
|
||||
package main
|
||||
package apiproxy
|
||||
|
||||
import (
|
||||
"net/http"
|
Reference in New Issue
Block a user