mirror of
https://github.com/gravitational/teleport.git
synced 2026-11-04 02:21:02 +08:00
#36584 allowed routing to work for public addresses, however it used GetPublicAddr to retrieve the public address. types.Server can have multiple public addresses though which means routing was only ever considering the first public address defined. This updates the routing logic to use GetPublicAddrs so they are all considered.
247 lines
5.8 KiB
Go
247 lines
5.8 KiB
Go
// Copyright 2023 Gravitational, Inc
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package utils
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// NOTE: much of the details of the behavior of this type is tested in lib/proxy as part
|
|
// of the main router test coverage.
|
|
|
|
// TestSSHRouteMatcherHostnameMatching verifies the expected behavior of the custom ssh
|
|
// hostname matching logic.
|
|
func TestSSHRouteMatcherHostnameMatching(t *testing.T) {
|
|
tts := []struct {
|
|
desc string
|
|
principal string
|
|
target string
|
|
insensitive bool
|
|
match bool
|
|
}{
|
|
{
|
|
desc: "upper-eq",
|
|
principal: "Foo",
|
|
target: "Foo",
|
|
insensitive: true,
|
|
match: true,
|
|
},
|
|
{
|
|
desc: "lower-eq",
|
|
principal: "foo",
|
|
target: "foo",
|
|
insensitive: true,
|
|
match: true,
|
|
},
|
|
{
|
|
desc: "lower-target-match",
|
|
principal: "Foo",
|
|
target: "foo",
|
|
insensitive: true,
|
|
match: true,
|
|
},
|
|
{
|
|
desc: "upper-target-mismatch",
|
|
principal: "foo",
|
|
target: "Foo",
|
|
insensitive: true,
|
|
match: false,
|
|
},
|
|
{
|
|
desc: "upper-mismatch",
|
|
principal: "Foo",
|
|
target: "fOO",
|
|
insensitive: true,
|
|
match: false,
|
|
},
|
|
{
|
|
desc: "non-ascii-match",
|
|
principal: "🌲",
|
|
target: "🌲",
|
|
insensitive: true,
|
|
match: true,
|
|
},
|
|
{
|
|
desc: "non-ascii-mismatch",
|
|
principal: "🌲",
|
|
target: "🔥",
|
|
insensitive: true,
|
|
match: false,
|
|
},
|
|
{
|
|
desc: "sensitive-match",
|
|
principal: "Foo",
|
|
target: "Foo",
|
|
insensitive: false,
|
|
match: true,
|
|
},
|
|
{
|
|
desc: "sensitive-mismatch",
|
|
principal: "Foo",
|
|
target: "foo",
|
|
insensitive: false,
|
|
match: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tts {
|
|
matcher := NewSSHRouteMatcher(tt.target, "", tt.insensitive)
|
|
require.Equal(t, tt.match, matcher.routeToHostname(tt.principal), "desc=%q", tt.desc)
|
|
}
|
|
}
|
|
|
|
type mockRouteableServer struct {
|
|
name string
|
|
hostname string
|
|
addr string
|
|
useTunnel bool
|
|
publicAddr []string
|
|
}
|
|
|
|
func (m mockRouteableServer) GetName() string {
|
|
return m.name
|
|
}
|
|
|
|
func (m mockRouteableServer) GetHostname() string {
|
|
return m.hostname
|
|
}
|
|
|
|
func (m mockRouteableServer) GetAddr() string {
|
|
return m.addr
|
|
}
|
|
|
|
func (m mockRouteableServer) GetUseTunnel() bool {
|
|
return m.useTunnel
|
|
}
|
|
|
|
func (m mockRouteableServer) GetPublicAddrs() []string {
|
|
return m.publicAddr
|
|
}
|
|
|
|
func TestRouteToServer(t *testing.T) {
|
|
t.Parallel()
|
|
testUUID := uuid.NewString()
|
|
|
|
matchAddrServer := mockRouteableServer{
|
|
name: "test",
|
|
addr: "example.com:1111",
|
|
publicAddr: []string{"node:1234", "public.example.com:1111"},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
matcher SSHRouteMatcher
|
|
server RouteableServer
|
|
assert require.BoolAssertionFunc
|
|
}{
|
|
{
|
|
name: "no match",
|
|
matcher: NewSSHRouteMatcher(testUUID, "", true),
|
|
server: mockRouteableServer{
|
|
name: "test",
|
|
addr: "localhost",
|
|
hostname: "example.com",
|
|
publicAddr: []string{"example.com"},
|
|
},
|
|
assert: require.False,
|
|
},
|
|
{
|
|
name: "match by server name",
|
|
matcher: NewSSHRouteMatcher(testUUID, "", true),
|
|
server: mockRouteableServer{
|
|
name: testUUID,
|
|
addr: "localhost",
|
|
hostname: "example.com",
|
|
publicAddr: []string{"example.com"},
|
|
},
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "match by hostname over tunnel",
|
|
matcher: NewSSHRouteMatcher("example.com", "", true),
|
|
server: mockRouteableServer{
|
|
name: testUUID,
|
|
addr: "addr.example.com",
|
|
hostname: "example.com",
|
|
publicAddr: []string{"public.example.com"},
|
|
useTunnel: true,
|
|
},
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "mismatch hostname over tunnel",
|
|
matcher: NewSSHRouteMatcher("example.com", "", true),
|
|
server: mockRouteableServer{
|
|
name: testUUID,
|
|
addr: "example.com",
|
|
hostname: "fake.example.com",
|
|
publicAddr: []string{"example.com"},
|
|
useTunnel: true,
|
|
},
|
|
assert: require.False,
|
|
},
|
|
{
|
|
name: "match addr",
|
|
matcher: NewSSHRouteMatcher("example.com", "1111", true),
|
|
server: matchAddrServer,
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "match addr with empty port",
|
|
matcher: NewSSHRouteMatcher("example.com", "", true),
|
|
server: matchAddrServer,
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "mismatch addr with wrong port",
|
|
matcher: NewSSHRouteMatcher("example.com", "2222", true),
|
|
server: matchAddrServer,
|
|
assert: require.False,
|
|
},
|
|
{
|
|
name: "match first public addr",
|
|
matcher: NewSSHRouteMatcher("node", "1234", true),
|
|
server: matchAddrServer,
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "match second public addr",
|
|
matcher: NewSSHRouteMatcher("public.example.com", "1111", true),
|
|
server: matchAddrServer,
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "match public addr with empty port",
|
|
matcher: NewSSHRouteMatcher("public.example.com", "", true),
|
|
server: matchAddrServer,
|
|
assert: require.True,
|
|
},
|
|
{
|
|
name: "mismatch public addr with wrong port",
|
|
matcher: NewSSHRouteMatcher("public.example.com", "2222", true),
|
|
server: matchAddrServer,
|
|
assert: require.False,
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
tc.assert(t, tc.matcher.RouteToServer(tc.server))
|
|
})
|
|
}
|
|
}
|