Skip to content

Commit 8439999

Browse files
authored
Add SSH support to tyger-proxy (#290)
1 parent 6b5b4aa commit 8439999

File tree

26 files changed

+927
-267
lines changed

26 files changed

+927
-267
lines changed

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,13 @@ start-docs-website:
194194

195195
generate-ca-certificates:
196196
scripts/generate-ca-certificates.sh cli/internal/client/ca-certificates.pem
197+
198+
199+
start-proxy: install-cli
200+
tyger-proxy start -f <($(MAKE) get-proxy-config)
201+
202+
run-proxy: install-cli
203+
tyger-proxy run -f <($(MAKE) get-proxy-config)
204+
205+
kill-proxy:
206+
killall -s SIGINT tyger-proxy

Makefile.cloud

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,6 @@ get-proxy-config:
256256
$${auth_parameters}
257257
"
258258

259-
start-proxy: install-cli
260-
tyger-proxy start -f <($(MAKE) get-proxy-config)
261-
262-
kill-proxy:
263-
killall tyger-proxy
264-
265259
connect-db: set-context
266260
helm_values=$$(helm get values -n ${HELM_NAMESPACE} ${HELM_RELEASE} -o json || true)
267261

cli/cmd/tyger-proxy/main.go

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"io"
10+
"net/url"
1011
"os"
1112
"path"
1213
"path/filepath"
@@ -133,45 +134,71 @@ func readProxyOptions(optionsFilePath string, options *tygerproxy.ProxyOptions)
133134
return errors.New("serverUrl must be specified")
134135
}
135136

136-
if options.ManagedIdentity {
137-
if options.ServicePrincipal != "" {
138-
return errors.New("servicePrincipal cannot be specified when using managed identity")
137+
parsedUrl, err := url.Parse(options.ServerUrl)
138+
if err != nil {
139+
return fmt.Errorf("invalid serverUrl: %v", err)
140+
}
141+
142+
if parsedUrl.Scheme == "ssh" || parsedUrl.Scheme == "http+unix" {
143+
if options.ManagedIdentity {
144+
return errors.New("managedIdentity cannot be specified when using SSH or Unix socket connection")
139145
}
140-
if options.CertificatePath != "" {
141-
return errors.New("certificatePath cannot be specified when using managed identity")
146+
if options.GitHub {
147+
return errors.New("github cannot be specified when using SSH or Unix socket connection")
142148
}
143-
if options.CertificateThumbprint != "" {
144-
return errors.New("certificateThumbprint cannot be specified when using managed identity")
145-
}
146-
} else if options.GitHub {
147149
if options.ServicePrincipal != "" {
148-
return errors.New("servicePrincipal cannot be specified when using GitHub authentication")
150+
return errors.New("servicePrincipal cannot be specified when using SSH or Unix socket connection")
149151
}
150152
if options.CertificatePath != "" {
151-
return errors.New("certificatePath cannot be specified when using GitHub authentication")
153+
return errors.New("certificatePath cannot be specified when using SSH or Unix socket connection")
152154
}
153155
if options.CertificateThumbprint != "" {
154-
return errors.New("certificateThumbprint cannot be specified when using GitHub authentication")
156+
return errors.New("certificateThumbprint cannot be specified when using SSH or Unix socket connection")
155157
}
156-
} else {
157-
if options.ServicePrincipal == "" {
158-
return errors.New("if both managedIdentity and github are both not true, servicePrincipal must be specified in the options file")
158+
if options.TargetFederatedIdentity != "" {
159+
return errors.New("targetFederatedIdentity cannot be specified when using SSH or Unix socket connection")
159160
}
160-
161-
if runtime.GOOS == "windows" {
162-
if options.CertificatePath == "" && options.CertificateThumbprint == "" {
163-
return errors.New("either certificatePath or certificateThumbprint must be specified in the options file")
161+
} else {
162+
if options.ManagedIdentity {
163+
if options.ServicePrincipal != "" {
164+
return errors.New("servicePrincipal cannot be specified when using managed identity")
164165
}
166+
if options.CertificatePath != "" {
167+
return errors.New("certificatePath cannot be specified when using managed identity")
168+
}
169+
if options.CertificateThumbprint != "" {
170+
return errors.New("certificateThumbprint cannot be specified when using managed identity")
171+
}
172+
} else if options.GitHub {
173+
if options.ServicePrincipal != "" {
174+
return errors.New("servicePrincipal cannot be specified when using GitHub authentication")
175+
}
176+
if options.CertificatePath != "" {
177+
return errors.New("certificatePath cannot be specified when using GitHub authentication")
178+
}
179+
if options.CertificateThumbprint != "" {
180+
return errors.New("certificateThumbprint cannot be specified when using GitHub authentication")
181+
}
182+
} else {
183+
if options.ServicePrincipal == "" {
184+
return errors.New("if both managedIdentity and github are both not true, servicePrincipal must be specified in the options file")
185+
}
186+
187+
if runtime.GOOS == "windows" {
188+
if options.CertificatePath == "" && options.CertificateThumbprint == "" {
189+
return errors.New("either certificatePath or certificateThumbprint must be specified in the options file")
190+
}
165191

166-
if options.CertificatePath != "" && options.CertificateThumbprint != "" {
167-
return errors.New("certificatePath and certificateThumbprint cannot both be specified")
192+
if options.CertificatePath != "" && options.CertificateThumbprint != "" {
193+
return errors.New("certificatePath and certificateThumbprint cannot both be specified")
194+
}
195+
} else if options.CertificatePath == "" {
196+
return errors.New("certificatePath must be specified in the options file")
168197
}
169-
} else if options.CertificatePath == "" {
170-
return errors.New("certificatePath must be specified in the options file")
171-
}
172198

173-
if options.TargetFederatedIdentity != "" {
174-
return errors.New("targetFederatedIdentity cannot be specified when using service principal authentication")
199+
if options.TargetFederatedIdentity != "" {
200+
return errors.New("targetFederatedIdentity cannot be specified when using service principal authentication")
201+
}
175202
}
176203
}
177204

cli/cmd/tyger-proxy/proxyrun.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
package main
55

66
import (
7+
"context"
78
"io"
89
"os"
10+
"os/signal"
911
"path"
1012
"path/filepath"
13+
"syscall"
1114

1215
"github.com/microsoft/tyger/cli/internal/controlplane"
1316
"github.com/microsoft/tyger/cli/internal/logging"
@@ -66,12 +69,19 @@ func newProxyRunCommand(optionsFilePath *string, options *tygerproxy.ProxyOption
6669
log.Info().Str("path", logFile.Name()).Msg("Logging to file")
6770
}
6871

69-
client, err := controlplane.Login(cmd.Context(), options.LoginConfig)
72+
// Set up signal handling for graceful shutdown
73+
ctx, cancel := context.WithCancel(cmd.Context())
74+
defer cancel()
75+
76+
sigChan := make(chan os.Signal, 1)
77+
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
78+
79+
client, serviceMetadata, err := controlplane.Login(ctx, options.LoginConfig)
7080
if err != nil {
7181
log.Fatal().Err(err).Msg("login failed")
7282
}
7383

74-
_, err = tygerproxy.RunProxy(cmd.Context(), client, options, log.Logger)
84+
closeProxy, err := tygerproxy.RunProxy(ctx, client, options, serviceMetadata, log.Logger)
7585
if err != nil {
7686
if err == tygerproxy.ErrProxyAlreadyRunning {
7787
log.Info().Int("port", options.Port).Msg("A proxy is already running at this address.")
@@ -83,8 +93,21 @@ func newProxyRunCommand(optionsFilePath *string, options *tygerproxy.ProxyOption
8393

8494
log.Info().Int("port", options.Port).Msg(proxyIsListeningMessage)
8595

86-
// wait indefinitely
87-
<-(make(chan any))
96+
// Wait for shutdown signal
97+
sig := <-sigChan
98+
log.Info().Str("signal", sig.String()).Msg("Received shutdown signal, cleaning up...")
99+
100+
// Cancel context to trigger cleanup of SSH tunnels and other resources
101+
cancel()
102+
103+
// Close the proxy
104+
if closeProxy != nil {
105+
if err := closeProxy(); err != nil {
106+
log.Warn().Err(err).Msg("Error closing proxy")
107+
}
108+
}
109+
110+
log.Info().Msg("Proxy shutdown complete")
88111
},
89112
}
90113

cli/integrationtest/expected_openapi_spec.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,12 @@ components:
11111111
items:
11121112
type: string
11131113
nullable: true
1114+
storageEndpoints:
1115+
type: array
1116+
items:
1117+
type: string
1118+
format: uri
1119+
nullable: true
11141120
additionalProperties: false
11151121
Socket:
11161122
type: object

0 commit comments

Comments
 (0)