summaryrefslogtreecommitdiffhomepage
path: root/ipn
diff options
context:
space:
mode:
authorIrbe Krumina <irbe@tailscale.com>2024-01-15 19:24:43 +0200
committerIrbe Krumina <irbe@tailscale.com>2024-01-15 19:24:43 +0200
commitbb98a50612b3bed05e1572b2fcc0f79dc0086ed2 (patch)
treef7ea38f76befdeef15ea3e5e927278c119ff8b20 /ipn
parent7100b6e72162d532efd10021e47b710fc10c9b64 (diff)
downloadtailscale-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.go1
-rw-r--r--ipn/ipn_view.go5
-rw-r--r--ipn/ipnlocal/serve.go26
-rw-r--r--ipn/serve.go7
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.