Skip to content

Commit

Permalink
Merge pull request #7446 from rancher-sandbox/remove-listener-only-mo…
Browse files Browse the repository at this point in the history
…de-guest-agent

Remove listener only mode guest agent
  • Loading branch information
mook-as authored Sep 11, 2024
2 parents 5443d1a + 0cd6df8 commit bbdd8ae
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 342 deletions.
3 changes: 2 additions & 1 deletion .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ Dlg
dlgbmp
dlicense
dmg
dnat
DNAT
dnf
dnsmasq
dockercfg
Expand Down Expand Up @@ -717,6 +717,7 @@ serveraddress
servernum
serviceaccount
servicemonitor
serviceapi
servicewatcher
setfattr
setproxy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ command=/usr/local/bin/rancher-desktop-guestagent
command_args="
${GUESTAGENT_ADMIN_INSTALL:+-adminInstall=${GUESTAGENT_ADMIN_INSTALL}}
${GUESTAGENT_KUBERNETES:+-kubernetes=${GUESTAGENT_KUBERNETES}}
${GUESTAGENT_IPTABLES:+-iptables=${GUESTAGENT_IPTABLES}}
${GUESTAGENT_DOCKER:+-docker=${GUESTAGENT_DOCKER}}
${GUESTAGENT_CONTAINERD:+-containerd=${GUESTAGENT_CONTAINERD}}
${GUESTAGENT_K8S_SVC_ADDR:+-k8sServiceListenerAddr=${GUESTAGENT_K8S_SVC_ADDR}}
Expand Down
23 changes: 0 additions & 23 deletions pkg/rancher-desktop/backend/k3sHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1119,29 +1119,6 @@ export default class K3sHelper extends events.EventEmitter {
}
}

/**
* Check if the given Kubernetes version requires the port forwarding fix
* (where we listen on a local port).
*
* @param version Kubernetes version; null if no Kubernetes will run.
*/
static requiresPortForwardingFix(version: semver.SemVer | undefined): boolean {
if (!version) {
// When Kubernetes is disabled, don't try to do NodePort forwarding.
return false;
}
switch (true) {
case version.major !== 1: return true;
case version.minor < 21: return false;
case version.minor === 21: return version.patch >= 12;
case version.minor === 22: return version.patch >= 10;
case version.minor === 23: return version.patch >= 7;
case version.minor >= 24: return true;
default:
throw new Error(`Unexpected Kubernetes version ${ version }`);
}
}

/**
* Helper for implementing KubernetesBackend.requiresRestartReasons
*/
Expand Down
3 changes: 0 additions & 3 deletions pkg/rancher-desktop/backend/wsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
} from './backend';
import BackendHelper from './backendHelper';
import { ContainerEngineClient, MobyClient, NerdctlClient } from './containerClient';
import K3sHelper from './k3sHelper';
import ProgressTracker, { getProgressErrorDescription } from './progressTracker';

import DEPENDENCY_VERSIONS from '@pkg/assets/dependencies.yaml';
Expand Down Expand Up @@ -786,14 +785,12 @@ export default class WSLBackend extends events.EventEmitter implements VMBackend

protected async installGuestAgent(kubeVersion: semver.SemVer | undefined, cfg: BackendSettings | undefined) {
const enableKubernetes = !!kubeVersion;
const iptables = enableKubernetes && !K3sHelper.requiresPortForwardingFix(kubeVersion);
const isAdminInstall = await this.getIsAdminInstall();

const guestAgentConfig: Record<string, string> = {
LOG_DIR: await this.wslify(paths.logs),
GUESTAGENT_ADMIN_INSTALL: isAdminInstall ? 'true' : 'false',
GUESTAGENT_KUBERNETES: enableKubernetes ? 'true' : 'false',
GUESTAGENT_IPTABLES: iptables.toString(), // only enable IPTABLES for older K8s
GUESTAGENT_CONTAINERD: cfg?.containerEngine.name === ContainerEngine.CONTAINERD ? 'true' : 'false',
GUESTAGENT_DOCKER: cfg?.containerEngine.name === ContainerEngine.MOBY ? 'true' : 'false',
GUESTAGENT_DEBUG: this.debug ? 'true' : 'false',
Expand Down
2 changes: 1 addition & 1 deletion src/go/guestagent/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ require (
github.com/docker/docker v24.0.1+incompatible
github.com/docker/go-connections v0.4.0
github.com/gogo/protobuf v1.3.2
github.com/lima-vm/lima v1.0.0-alpha.0
github.com/stretchr/testify v1.9.0
golang.org/x/sync v0.8.0
golang.org/x/sys v0.25.0
Expand Down Expand Up @@ -95,6 +94,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
Expand Down
2 changes: 0 additions & 2 deletions src/go/guestagent/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lima-vm/lima v1.0.0-alpha.0 h1:ytvyw0N3X7TLKH//D2rbM3IEnjYVcm0yH2cxlSIjE6M=
github.com/lima-vm/lima v1.0.0-alpha.0/go.mod h1:qonzb8JiUsTeuypJVmfzluU/wnN/tg+o2GeSubwzIiY=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
Expand Down
41 changes: 9 additions & 32 deletions src/go/guestagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/containerd"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/docker"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/forwarder"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/iptables"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/kube"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/tracker"
"github.com/rancher-sandbox/rancher-desktop/src/go/guestagent/pkg/types"
Expand All @@ -45,7 +44,6 @@ import (
var (
debug = flag.Bool("debug", false, "display debug output")
configPath = flag.String("kubeconfig", "/etc/rancher/k3s/k3s.yaml", "path to kubeconfig")
enableIptables = flag.Bool("iptables", true, "enable iptables scanning")
enableKubernetes = flag.Bool("kubernetes", false, "enable Kubernetes service forwarding")
enableDocker = flag.Bool("docker", false, "enable Docker event monitoring")
enableContainerd = flag.Bool("containerd", false, "enable Containerd event monitoring")
Expand All @@ -62,11 +60,10 @@ var (
)

const (
iptablesUpdateInterval = 3 * time.Second
socketInterval = 5 * time.Second
socketRetryTimeout = 2 * time.Minute
dockerSocketFile = "/var/run/docker.sock"
containerdSocketFile = "/run/k3s/containerd/containerd.sock"
socketInterval = 5 * time.Second
socketRetryTimeout = 2 * time.Minute
dockerSocketFile = "/var/run/docker.sock"
containerdSocketFile = "/run/k3s/containerd/containerd.sock"
)

func main() {
Expand Down Expand Up @@ -100,21 +97,19 @@ func main() {
}()

if !*enableContainerd &&
!*enableDocker &&
!*enableIptables {
log.Fatal("requires either -docker, -containerd or -iptables enabled.")
!*enableDocker {
log.Fatal("requires either -docker or -containerd enabled.")
}

if *enableContainerd &&
*enableDocker &&
*enableIptables {
log.Fatal("requires either -docker, -containerd or -iptables, not all.")
*enableDocker {
log.Fatal("requires either -docker or -containerd but not both.")
}

var portTracker tracker.Tracker

forwarder := forwarder.NewWSLProxyForwarder("/run/wsl-proxy.sock")
portTracker = tracker.NewAPITracker(forwarder, tracker.GatewayBaseURL, *tapIfaceIP, *adminInstall)
portTracker = tracker.NewAPITracker(ctx, forwarder, tracker.GatewayBaseURL, *tapIfaceIP, *adminInstall)
// Manually register the port for K8s API, we would
// only want to send this manual port mapping if both
// of the following conditions are met:
Expand Down Expand Up @@ -183,17 +178,10 @@ func main() {
"Valid options are 0.0.0.0 and 127.0.0.1.", *k8sServiceListenerAddr)
}

// listenerOnlyMode represents when iptables is enabled and privileged services
// and admin install are disabled; this typically indicates a non-admin installation
// of the legacy network, requiring listeners only. In listenerOnlyMode, we create
// TCP listeners on 127.0.0.1 to enable automatic port forwarding mechanisms,
// particularly in WSLv2 environments.
listenerOnlyMode := *enableIptables && !*adminInstall
// Watch for kube
err := kube.WatchForServices(ctx,
*configPath,
k8sServiceListenerIP,
listenerOnlyMode,
portTracker)
if err != nil {
return fmt.Errorf("error watching services: %w", err)
Expand All @@ -203,17 +191,6 @@ func main() {
})
}

if *enableIptables {
group.Go(func() error {
err := iptables.ForwardPorts(ctx, portTracker, iptablesUpdateInterval)
if err != nil {
return fmt.Errorf("error mapping ports: %w", err)
}

return nil
})
}

if err := group.Wait(); err != nil {
log.Fatal(err)
}
Expand Down
126 changes: 126 additions & 0 deletions src/go/guestagent/pkg/forwarder/serviceapi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
Copyright © 2024 SUSE LLC
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 forwarder

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"

"github.com/Masterminds/log-go"
"github.com/containers/gvisor-tap-vsock/pkg/types"
)

const (
exposeAPI = "/services/forwarder/expose"
unexposeAPI = "/services/forwarder/unexpose"
)

var (
ErrAPI = errors.New("error from API")
ErrExposeAPI = fmt.Errorf("error from %s API", exposeAPI)
ErrUnexposeAPI = fmt.Errorf("error from %s API", unexposeAPI)
)

// APIForwarder forwards the PortMappings to /services/forwarder/expose
// or /services/forwarder/unexpose that is host in the host-switch.
type APIForwarder struct {
baseURL string
httpClient *http.Client
}

// NewAPIForwarder returns a new instance of APIForwarder.
func NewAPIForwarder(baseURL string) *APIForwarder {
return &APIForwarder{
baseURL: baseURL,
httpClient: http.DefaultClient,
}
}

// Expose calls /services/forwarder/expose with a given portMappings.
func (a *APIForwarder) Expose(exposeReq *types.ExposeRequest) error {
bin, err := json.Marshal(exposeReq)
if err != nil {
return err
}

log.Debugf("sending a HTTP POST to %s API with expose request: %v", exposeAPI, exposeReq)
req, err := http.NewRequestWithContext(
context.Background(),
http.MethodPost,
a.urlBuilder(exposeAPI),
bytes.NewReader(bin))
if err != nil {
return err
}

res, err := a.httpClient.Do(req)
if err != nil {
return err
}

return verifyResponseBody(res)
}

// Unexpose calls /services/forwarder/unexpose with a given portMappings.
func (a *APIForwarder) Unexpose(unexposeReq *types.UnexposeRequest) error {
bin, err := json.Marshal(unexposeReq)
if err != nil {
return err
}

log.Debugf("sending a HTTP POST to %s API with unexpose request: %v", unexposeAPI, unexposeReq)
req, err := http.NewRequestWithContext(
context.Background(),
http.MethodPost,
a.urlBuilder(unexposeAPI),
bytes.NewReader(bin))
if err != nil {
return err
}

res, err := a.httpClient.Do(req)
if err != nil {
return err
}

return verifyResponseBody(res)
}

func (a *APIForwarder) urlBuilder(api string) string {
return a.baseURL + api
}

func verifyResponseBody(res *http.Response) error {
defer res.Body.Close()

if res.StatusCode != http.StatusOK {
apiResponse, readErr := io.ReadAll(res.Body)
if readErr != nil {
return fmt.Errorf("error while reading response body: %w", readErr)
}

errMsg := strings.TrimSpace(string(apiResponse))

return fmt.Errorf("%w: %s", ErrAPI, errMsg)
}

return nil
}
Loading

0 comments on commit bbdd8ae

Please sign in to comment.