Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,3 +799,9 @@ const (
// the upgraded connection should be handled by the ALPN handler.
WebAPIConnUpgradeTypeALPN = "alpn"
)

const (
// KubeLegacyProxySuffix is the suffix used for legacy proxy services when
// generating their names Server names.
KubeLegacyProxySuffix = "-proxy_service"
)
14 changes: 12 additions & 2 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1167,12 +1167,22 @@ func (a *ServerWithRoles) KeepAliveServer(ctx context.Context, handle types.Keep
return trace.AccessDenied("access denied")
}
} else { // DELETE IN 13.0. Legacy kubeservice server is heartbeating back.
if serverName != handle.Name {
name := handle.Name
// legacy kube proxy server is heartbeating kubernetes clusters
// with the server name suffixed with "-proxy_service".
// To compare the server name with the name in the heartbeat
// we need to remove the suffix.
if a.hasBuiltinRole(types.RoleProxy) {
name = strings.TrimSuffix(name, teleport.KubeLegacyProxySuffix)
}
if name != serverName {
return trace.AccessDenied("access denied")
}
}

if !a.hasBuiltinRole(types.RoleKube) {
// Legacy kube proxy can heartbeat kube servers from the proxy itself so
// we need to check if the host has the Kube or Proxy role.
if !a.hasBuiltinRole(types.RoleKube, types.RoleProxy) {
return trace.AccessDenied("access denied")
}
if err := a.action(apidefaults.Namespace, types.KindKubeServer, types.VerbUpdate); err != nil {
Expand Down
91 changes: 90 additions & 1 deletion lib/auth/auth_with_roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3272,7 +3272,6 @@ func TestListResources_SearchAsRoles(t *testing.T) {
}
})
}

}

func TestGetAndList_WindowsDesktops(t *testing.T) {
Expand Down Expand Up @@ -4697,3 +4696,93 @@ func createSnowflakeSessionTestUsers(t *testing.T, authServer *Server) (string,
require.NoError(t, err)
return "alice", "bob", "admin"
}

func TestKubeKeepAliveServer(t *testing.T) {
t.Parallel()
srv := newTestTLSServer(t)
domainName, err := srv.Auth().GetDomainName()
require.NoError(t, err)

tests := map[string]struct {
builtInRole types.SystemRole
assertErr require.ErrorAssertionFunc
}{
"as kube service": {
builtInRole: types.RoleKube,
assertErr: require.NoError,
},
"as legacy proxy service": {
builtInRole: types.RoleProxy,
assertErr: require.NoError,
},
"as database service": {
builtInRole: types.RoleDatabase,
assertErr: require.Error,
},
}
for name, test := range tests {
test := test
t.Run(name, func(t *testing.T) {
t.Parallel()
hostID := uuid.New().String()
// Create a kubernetes cluster.
kube, err := types.NewKubernetesClusterV3(
types.Metadata{
Name: "kube",
Namespace: defaults.Namespace,
},
types.KubernetesClusterSpecV3{},
)
require.NoError(t, err)
// Create a kubernetes server.
// If the built-in role is proxy, the server name should be
// kube-proxy_service
serverName := "kube"
if test.builtInRole == types.RoleProxy {
serverName += teleport.KubeLegacyProxySuffix
}
kubeServer, err := types.NewKubernetesServerV3(
types.Metadata{
Name: serverName,
Namespace: defaults.Namespace,
},
types.KubernetesServerSpecV3{
Cluster: kube,
HostID: hostID,
},
)
require.NoError(t, err)
// Upsert the kubernetes server into the backend.
_, err = srv.Auth().UpsertKubernetesServer(context.Background(), kubeServer)
require.NoError(t, err)

// Create a built-in role.
authContext, err := contextForBuiltinRole(
BuiltinRole{
Role: test.builtInRole,
Username: fmt.Sprintf("%s.%s", hostID, domainName),
},
types.DefaultSessionRecordingConfig(),
)
require.NoError(t, err)

// Create a server with the built-in role.
srv := ServerWithRoles{
authServer: srv.Auth(),
context: *authContext,
}
// Keep alive the server.
err = srv.KeepAliveServer(context.Background(),
types.KeepAlive{
Type: types.KeepAlive_KUBERNETES,
Expires: time.Now().Add(5 * time.Minute),
Name: serverName,
Namespace: defaults.Namespace,
HostID: hostID,
},
)
test.assertErr(t, err)
},
)
}
}
2 changes: 1 addition & 1 deletion lib/kube/proxy/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ func (t *TLSServer) getServerInfo(name string) (types.Resource, error) {
// Note: we *don't* want to add suffix for kubernetes_service!
// This breaks reverse tunnel routing, which uses server.Name.
if t.KubeServiceType != KubeService {
name += "-proxy_service"
name += teleport.KubeLegacyProxySuffix
}

srv, err := types.NewKubernetesServerV3(
Expand Down