Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#47037 - Create Remote Dialer Proxy #90

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
13 changes: 13 additions & 0 deletions Dockerfile.proxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.23 AS builder
WORKDIR /app

COPY go.mod .
COPY go.sum .
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 go build -o proxy ./cmd/proxy

FROM scratch
COPY --from=builder /app/proxy .
CMD ["./proxy"]
93 changes: 93 additions & 0 deletions cmd/proxy/deployment.yaml
joshmeranda marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#FIXME This is temporary file. This should be converted into Helm Charts in the charts repo.

apiVersion: apps/v1
kind: Deployment
metadata:
name: remotedialer-proxy
namespace: cattle-system
labels:
app: remotedialer-proxy
spec:
replicas: 1
selector:
matchLabels:
app: remotedialer-proxy
template:
metadata:
labels:
app: remotedialer-proxy
spec:
containers:
- name: remotedialer-proxy
image: rancher/remotedialer-proxy:latest
imagePullPolicy: IfNotPresent
env:
- name: TLS_NAME
value: "remotedialer-proxy"
- name: CA_NAME
value: "remotedialer-proxy-ca"
- name: CERT_CA_NAMESPACE
value: "cattle-system"
- name: CERT_CA_NAME
value: "remotedialer-proxy-cert"
- name: SECRET
value: "secret" # X-Tunnel-ID header secret
- name: PROXY_PORT
value: "6666" # The proxy TCP port for kube-apiserver traffic
- name: PEER_PORT
value: "8888" # The port used to connect to the special "imperative API" server behind the remotedialer
- name: HTTPS_PORT
value: "8443" # The dynamiclistener HTTPS port for /connect
ports:
- containerPort: 6666
name: proxy
- containerPort: 8443
name: https
- containerPort: 8888
name: peer

---
apiVersion: v1
kind: Service
metadata:
name: remotedialer-proxy
namespace: cattle-system
labels:
app: remotedialer-proxy
spec:
type: ClusterIP
selector:
app: remotedialer-proxy
ports:
- name: proxy
port: 6666
targetPort: proxy
- name: https
port: 8443
targetPort: https

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: remotedialer-proxy-secret-access
namespace: cattle-system
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["secrets"] # We need to read secrets
verbs: ["get", "list", "watch", "create", "delete"] # Allowed verbs
joshmeranda marked this conversation as resolved.
Show resolved Hide resolved

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: remotedialer-proxy-secret-access-binding
namespace: cattle-system
subjects:
- kind: ServiceAccount
name: default # The service account name
namespace: cattle-system # The same namespace as the SA
roleRef:
kind: Role
name: remotedialer-proxy-secret-access
apiGroup: rbac.authorization.k8s.io
30 changes: 30 additions & 0 deletions cmd/proxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"github.com/sirupsen/logrus"
"k8s.io/client-go/rest"

"github.com/rancher/lasso/pkg/log"
"github.com/rancher/remotedialer/proxy"
)

func main() {
logrus.Info("Starting Remote Dialer Proxy")

cfg, err := proxy.ConfigFromEnvironment()
if err != nil {
logrus.Fatalf("fatal configuration error: %v", err)
}

// Initializing Wrangler
joshmeranda marked this conversation as resolved.
Show resolved Hide resolved
restConfig, err := rest.InClusterConfig()
if err != nil {
log.Errorf("failed to get in-cluster config: %w", err)
joshmeranda marked this conversation as resolved.
Show resolved Hide resolved
return
}

err = proxy.Start(cfg, restConfig)
if err != nil {
logrus.Fatal(err)
}
}
13 changes: 13 additions & 0 deletions examples/fakek8s/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.23 as builder
WORKDIR /app
COPY go.mod .
RUN go mod download
COPY . .
RUN go build -o /app/tcp-client main.go

FROM debian:bookworm-slim
joshmeranda marked this conversation as resolved.
Show resolved Hide resolved
COPY --from=builder /app/tcp-client .

RUN ls .

CMD ["./tcp-client"]
28 changes: 28 additions & 0 deletions examples/fakek8s/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: fakek8s-deployment
namespace: cattle-system
labels:
app: fakek8s
spec:
replicas: 1
selector:
matchLabels:
app: fakek8s
template:
metadata:
labels:
app: fakek8s
spec:
containers:
- name: fakek8s
image: rancher/fakek8s:latest
imagePullPolicy: IfNotPresent
env:
- name: TARGET_HOST
value: "remotedialer-proxy.cattle-system.svc.cluster.local"
- name: TARGET_PORT
value: "6666"
- name: SEND_INTERVAL
value: "1"
3 changes: 3 additions & 0 deletions examples/fakek8s/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module dummy/fakek8s

go 1.23
113 changes: 113 additions & 0 deletions examples/fakek8s/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package main

import (
"context"
"fmt"
"net"
"os"
"os/signal"
"strconv"
"syscall"
"time"
)

var (
targetHost = "remotedialer-proxy.cattle-system.svc.cluster.local"
targetPort = 6666
retryDelay = 5 * time.Second
)

func init() {
if host, ok := os.LookupEnv("TARGET_HOST"); ok {
targetHost = host
}

if portStr, ok := os.LookupEnv("TARGET_PORT"); ok {
if p, err := strconv.Atoi(portStr); err != nil {
fmt.Printf("Could not parse TARGET_PORT=%q: %v. Using default %d.\n",
portStr, err, targetPort)
} else {
targetPort = p
}
}

if intervalStr, ok := os.LookupEnv("SEND_INTERVAL"); ok {
if i, err := strconv.Atoi(intervalStr); err != nil {
fmt.Printf("Could not parse SEND_INTERVAL=%q: %v. Using default %v.\n",
intervalStr, err, retryDelay)
} else {
retryDelay = time.Duration(i) * time.Second
}
}
}

func echoHandler(ctx context.Context, conn net.Conn) {
defer conn.Close()
go func() {
<-ctx.Done()
fmt.Println("echoHandler: context canceled; closing connection.")
_ = conn.Close()
}()

buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
if err != nil {
fmt.Printf("Connection closed or error occurred: %v\n", err)
return
}

fmt.Println("Received from Server:", string(buffer[:n]))

// Echo back the received data
if _, err := conn.Write(buffer[:n]); err != nil {
fmt.Printf("Error sending data back: %v\n", err)
return
}

fmt.Println("Sent back to Server:", string(buffer[:n]))
}
}

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("main: received shutdown signal; canceling context...")
cancel()
}()

for {
select {
case <-ctx.Done():
fmt.Println("main: context canceled; exiting dial loop.")
return
default:
}

fmt.Printf("Attempting to connect to %s:%d...\n", targetHost, targetPort)

conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", targetHost, targetPort))
if err != nil {
fmt.Printf("Failed to connect: %v. Retrying in %v...\n", err, retryDelay)
time.Sleep(retryDelay)
continue
}

fmt.Println("Connected to the server.")

// Send a welcome message
welcomeMessage := "Hello, server! Client has connected.\nPlease type any word and hit enter:"
if _, err = conn.Write([]byte(welcomeMessage)); err != nil {
fmt.Printf("Error sending welcome message: %v\n", err)
conn.Close()
continue
}

echoHandler(ctx, conn)
}
}
Loading