tsnet: fix TLS-terminated-TCP test

Signed-off-by: Harry Harpham <harry@tailscale.com>
hwh33/tsnet-services-support
Harry Harpham 3 weeks ago
parent 0bb60fe2ad
commit 95318b7cb4
No known key found for this signature in database

@ -314,9 +314,9 @@ func (b *LocalBackend) getCertStore() (certStore, error) {
// certificate registration.
//
// Certificates will be served based on the subject name or subject alternative
// names (SANs) in the certificate. If this backend should serve certificates
// names (SANs) in the certificates. If this backend should serve certificates
// for hostnames like foo.tail-scale.ts.net or test-service.tail-scale.ts.net,
// then those names need to appear in the subject name or SAN.
// then those names need to appear as a subject name or SAN.
func (b *LocalBackend) SetCertsForTest(certs ...TLSCertKeyPair) {
testenv.AssertInTest()
m := map[string]TLSCertKeyPair{}

@ -50,6 +50,7 @@ func main() {
}
defer ln.Close()
// TODO: provide access to FQDN from listener and use that instead
fmt.Printf("Listening on https://%v\n", tailcfg.AsServiceName(*svcName).WithoutPrefix())
err = http.Serve(ln, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

@ -14,6 +14,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"errors"
"flag"
"fmt"
@ -37,10 +38,12 @@ import (
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"golang.org/x/net/proxy"
"tailscale.com/client/local"
"tailscale.com/cmd/testwrapper/flakytest"
"tailscale.com/internal/client/tailscale"
"tailscale.com/ipn"
"tailscale.com/ipn/ipnlocal"
"tailscale.com/ipn/store/mem"
"tailscale.com/net/netns"
"tailscale.com/tailcfg"
@ -747,11 +750,15 @@ func TestFunnel(t *testing.T) {
func TestListenService(t *testing.T) {
tests := []struct {
name string
opts ServiceOption
opts []ServiceOption
}{
{
name: "basic_TCP_service",
},
{
name: "TLS_terminated_TCP",
opts: []ServiceOption{ServiceOptionTerminateTLS()},
},
// TODO:
// Success cases:
// - TLS-terminated-TCP
@ -771,6 +778,9 @@ func TestListenService(t *testing.T) {
// - start a Service listener from host
// - dial Service from peer client
// - try to have a conversation
//
// This ends up also testing the Service forwarding logic in
// LocalBackend, but that's useful too.
t.Run(tt.name, func(t *testing.T) {
ctx := t.Context()
@ -779,9 +789,11 @@ func TestListenService(t *testing.T) {
serviceClient, _, _ := startServer(t, ctx, controlURL, "service-client")
const serviceName = tailcfg.ServiceName("svc:foo")
const servicePort uint16 = 80
const servicePort uint16 = 99
const serviceVIP = "100.11.22.33"
serviceFQDN := serviceName.WithoutPrefix() + "." + control.MagicDNSDomain
// == Set up necessary state in our mock ==
// The Service host must have the 'service-host' capability, which
@ -803,6 +815,23 @@ func TestListenService(t *testing.T) {
serviceHostNode.Tags = append(serviceHostNode.Tags, "some-tag")
control.UpdateNode(serviceHostNode)
// Configure a certificate for the Service domain (in production,
// the local backend would use an ACME client to obtain a cert).
// This is only used when serving over TLS.
cert := must.Get(testCertRoot.getCert(&tls.ClientHelloInfo{
ServerName: serviceFQDN,
}))
serviceHost.lb.SetCertsForTest(ipnlocal.TLSCertKeyPair{
CertPEM: pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Certificate[0],
}),
KeyPEM: pem.EncodeToMemory(&pem.Block{
Type: "PRIVATE KEY",
Bytes: must.Get(x509.MarshalPKCS8PrivateKey(cert.PrivateKey)),
}),
})
// The service client must accept routes advertised by other nodes
// (RouteAll is equivalent to --accept-routes).
must.Get(serviceClient.localClient.EditPrefs(ctx, &ipn.MaskedPrefs{
@ -815,7 +844,7 @@ func TestListenService(t *testing.T) {
// == Done setting up mock state ==
// Start a Service listener.
ln := must.Get(serviceHost.ListenService(serviceName.String(), servicePort))
ln := must.Get(serviceHost.ListenService(serviceName.String(), servicePort, tt.opts...))
defer ln.Close()
// Accept the first connection on ln and echo back what we receive.
@ -835,6 +864,15 @@ func TestListenService(t *testing.T) {
conn := must.Get(serviceClient.Dial(ctx, "tcp", target))
defer conn.Close()
for _, opt := range tt.opts {
if _, ok := opt.(serviceOptionTerminateTLS); ok {
conn = tls.Client(conn, &tls.Config{
ServerName: serviceFQDN,
RootCAs: testCertRoot.Pool(),
})
}
}
msg := "hello, Service"
buf := make([]byte, 1024)
if _, err := conn.Write([]byte(msg)); err != nil {

@ -838,6 +838,9 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key.
CapMap: capMap,
Capabilities: slices.Collect(maps.Keys(capMap)),
}
if s.MagicDNSDomain != "" {
node.Name = node.Name + "." + s.MagicDNSDomain
}
s.nodes[nk] = node
}
requireAuth := s.RequireAuth
@ -1261,9 +1264,7 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse,
dns := s.DNSConfig
if dns != nil && s.MagicDNSDomain != "" {
dns = dns.Clone()
dns.CertDomains = []string{
node.Hostinfo.Hostname() + "." + s.MagicDNSDomain,
}
dns.CertDomains = append(dns.CertDomains, node.Hostinfo.Hostname()+"."+s.MagicDNSDomain)
}
res = &tailcfg.MapResponse{

Loading…
Cancel
Save