diff options
| author | Irbe Krumina <irbe@tailscale.com> | 2024-01-15 19:24:43 +0200 |
|---|---|---|
| committer | Irbe Krumina <irbe@tailscale.com> | 2024-01-15 19:24:43 +0200 |
| commit | bb98a50612b3bed05e1572b2fcc0f79dc0086ed2 (patch) | |
| tree | f7ea38f76befdeef15ea3e5e927278c119ff8b20 /ipn | |
| parent | 7100b6e72162d532efd10021e47b710fc10c9b64 (diff) | |
| download | tailscale-irbekrm/byocerts.tar.xz tailscale-irbekrm/byocerts.zip | |
WIP: BYO TLS certs for Ingressirbekrm/byocerts
Signed-off-by: Irbe Krumina <irbe@tailscale.com>
Diffstat (limited to 'ipn')
| -rw-r--r-- | ipn/ipn_clone.go | 1 | ||||
| -rw-r--r-- | ipn/ipn_view.go | 5 | ||||
| -rw-r--r-- | ipn/ipnlocal/serve.go | 26 | ||||
| -rw-r--r-- | ipn/serve.go | 7 |
4 files changed, 39 insertions, 0 deletions
diff --git a/ipn/ipn_clone.go b/ipn/ipn_clone.go index 40cc44296..05bbe47d5 100644 --- a/ipn/ipn_clone.go +++ b/ipn/ipn_clone.go @@ -96,6 +96,7 @@ var _ServeConfigCloneNeedsRegeneration = ServeConfig(struct { AllowFunnel map[HostPort]bool Foreground map[string]*ServeConfig ETag string + KubeSecretCertStore *KubeSecretCertStore }{}) // Clone makes a deep copy of TCPPortHandler. diff --git a/ipn/ipn_view.go b/ipn/ipn_view.go index 18436867d..bb4672776 100644 --- a/ipn/ipn_view.go +++ b/ipn/ipn_view.go @@ -185,6 +185,10 @@ func (v ServeConfigView) AllowFunnel() views.Map[HostPort, bool] { return views.MapOf(v.ж.AllowFunnel) } +func (v ServeConfigView) KubeSecretCert() *KubeSecretCertStore { + return v.ж.KubeSecretCertStore +} + func (v ServeConfigView) Foreground() views.MapFn[string, *ServeConfig, ServeConfigView] { return views.MapFnOf(v.ж.Foreground, func(t *ServeConfig) ServeConfigView { return t.View() @@ -199,6 +203,7 @@ var _ServeConfigViewNeedsRegeneration = ServeConfig(struct { AllowFunnel map[HostPort]bool Foreground map[string]*ServeConfig ETag string + KubeSecretCertStore *KubeSecretCertStore }{}) // View returns a readonly view of TCPPortHandler. diff --git a/ipn/ipnlocal/serve.go b/ipn/ipnlocal/serve.go index c637a09be..58fa3c8d3 100644 --- a/ipn/ipnlocal/serve.go +++ b/ipn/ipnlocal/serve.go @@ -28,6 +28,7 @@ import ( "golang.org/x/net/http2" "tailscale.com/ipn" + "tailscale.com/kube" "tailscale.com/logtail/backoff" "tailscale.com/net/netutil" "tailscale.com/syncs" @@ -875,6 +876,31 @@ func (b *LocalBackend) getTLSServeCertForPort(port uint16) func(hi *tls.ClientHe ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() + if kubeSecret := b.serveConfig.KubeSecretCert(); kubeSecret != nil { + // TODO: initiate kube client once, maybe cache the certs somewhere too + c, err := kube.New() + if err != nil { + return nil, fmt.Errorf("error initalizing kube client: %v", err) + } + c.SetNS(kubeSecret.Namespace) + secret, err := c.GetSecret(ctx, kubeSecret.Name) + if err != nil { + return nil, fmt.Errorf("error getting certs secret: %v", err) + } + certBytes, ok := secret.Data["tls.crt"] + if !ok { + return nil, fmt.Errorf("secret does not contain tls.crt") + } + keyBytes, ok := secret.Data["tls.key"] + if !ok { + return nil, fmt.Errorf("secret data does not contain tls.key") + } + cert, err := tls.X509KeyPair(certBytes, keyBytes) + if err != nil { + return nil, fmt.Errorf("error creating TLS key pair: %w", err) + } + return &cert, nil + } pair, err := b.GetCertPEM(ctx, hi.ServerName) if err != nil { return nil, err diff --git a/ipn/serve.go b/ipn/serve.go index 84db09d1d..94bf06b10 100644 --- a/ipn/serve.go +++ b/ipn/serve.go @@ -50,6 +50,13 @@ type ServeConfig struct { // GetServeConfig request and is translated to an If-Match header // during a SetServeConfig request. ETag string `json:"-"` + // Reference to a Kubernetes Secret that contains TLS certs for serve + KubeSecretCertStore *KubeSecretCertStore `json:",omitempty"` +} + +type KubeSecretCertStore struct { + Name string `json:",omitempty"` + Namespace string `json:",omitempty"` } // HostPort is an SNI name and port number, joined by a colon. |
