diff --git a/cmd/converge/converge.go b/cmd/converge/converge.go index a057524..531f4c2 100644 --- a/cmd/converge/converge.go +++ b/cmd/converge/converge.go @@ -27,9 +27,10 @@ func parsePublicId(path string) (publicId string, _ error) { return matches[1], nil } -func catchAllHandler(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/docs", http.StatusFound) - return +func catchAllHandler(contextPath string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, contextPath+"/docs", http.StatusFound) + } } func printHelp(msg string) { @@ -48,8 +49,13 @@ func printHelp(msg string) { "an embedded SSH server to provide interactive access to the end-user. This works\n" + "both on linux and on windows.\n" + "\n" + - "-s : directory where static content of converge is placed\n" + - "-d : directory where downloads of converge are placed\n" + "Options\n" + + "-s : directory where static content of converge is placed\n" + + "-d : directory where downloads of converge are placed\n" + + "-c : by default all content is served at /. Use this option to specify\n" + + " a different context path. For instance to host converge at a base\n" + + " URL of https://example.com/converge, specify /converg (and without\n" + + " trailing slash. " fmt.Fprintln(os.Stderr, helpText) os.Exit(1) } @@ -58,6 +64,7 @@ func main() { downloaddir := "." staticdir := "../static" + contextpath := "" args := os.Args[1:] for len(args) > 0 && strings.HasPrefix(args[0], "-") { @@ -74,6 +81,12 @@ func main() { } staticdir = args[1] args = args[1:] + case "-c": + if len(args) <= 1 { + printHelp("The -c option expects an argument") + } + contextpath = args[1] + args = args[1:] default: printHelp("Unknown option " + args[0]) } @@ -162,7 +175,6 @@ func main() { // TODO remove, simulate contextpath - contextpath := "" http.HandleFunc(contextpath+"/agent/", registrationService.Handle) http.HandleFunc(contextpath+"/client/", clientService.Handle) http.HandleFunc(contextpath+"/ws/sessions", sessionService.Handle) @@ -176,11 +188,7 @@ func main() { // TODO remove for testing contextpath - catchAllHandler2 := func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, contextpath+"/docs", http.StatusFound) - return - } - http.HandleFunc(contextpath+"/", catchAllHandler2) + http.HandleFunc(contextpath+"/", catchAllHandler(contextpath)) // create usage generator http.HandleFunc(contextpath+"/usage", generateCLIExammple) diff --git a/cmd/converge/convergeaccess.go b/cmd/converge/convergeaccess.go index f69407f..5cb1160 100644 --- a/cmd/converge/convergeaccess.go +++ b/cmd/converge/convergeaccess.go @@ -3,11 +3,23 @@ package main import ( "converge/pkg/models" "converge/pkg/server/converge" + "log" "net/http" + "regexp" "strings" ) func getConvergeAccess(r *http.Request, sshRemoteUser string) models.ConvergeAccess { + + pattern := regexp.MustCompile("^(.*)/usage$") + matches := pattern.FindStringSubmatch(r.URL.Path) + contextPath := "" + if len(matches) != 2 { + log.Printf("Cannot determine context path for %s, assumming it is empty", r.URL.Path) + } else { + contextPath = matches[1] + } + secure := "" if r.TLS == nil { secure = "" @@ -27,9 +39,10 @@ func getConvergeAccess(r *http.Request, sshRemoteUser string) models.ConvergeAcc if err != nil { panic(err) } + baseUrl := strings.ReplaceAll(r.Host+contextPath, "//", "/") return models.ConvergeAccess{ Secure: secure, - HostPort: r.Host, + BaseUrl: baseUrl, Location: location, Username: sshRemoteUser, } diff --git a/cmd/templaterender/render.go b/cmd/templaterender/render.go index 3ea7024..55b0bf9 100644 --- a/cmd/templaterender/render.go +++ b/cmd/templaterender/render.go @@ -39,7 +39,7 @@ func main() { access := models.ConvergeAccess{ Secure: "s", - HostPort: "example.com", + BaseUrl: "example.com", Location: netherlands, Username: "converge", } diff --git a/pkg/models/convergeaccess.go b/pkg/models/convergeaccess.go index 007c321..3c5e2d1 100644 --- a/pkg/models/convergeaccess.go +++ b/pkg/models/convergeaccess.go @@ -5,7 +5,7 @@ import "time" type ConvergeAccess struct { // 's" when secure, "" otherwise Secure string - HostPort string + BaseUrl string Location *time.Location Username string } diff --git a/pkg/server/templates/usage.templ b/pkg/server/templates/usage.templ index 5a5e65d..51e9f4d 100644 --- a/pkg/server/templates/usage.templ +++ b/pkg/server/templates/usage.templ @@ -13,23 +13,23 @@ templ AgentUsage(access models.ConvergeAccess, usageInputs UsageInputs) { if usageInputs.RemoteShells[BASH] {
{addSshKeys(BASH, usageInputs.SshKeys)}
-        curl --fail-with-body http{access.Secure}://{access.HostPort}/downloads/agent > agent{`
+        curl --fail-with-body http{access.Secure}://{access.BaseUrl}/downloads/agent > agent{`
         chmod 755 agent
-        `}./agent --id {usageInputs.Id} ws{access.Secure}://{access.HostPort}{`
+        `}./agent --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl}{`
         rm -f agent
         `}
} if usageInputs.RemoteShells[CMD] {
{addSshKeys(CMD, usageInputs.SshKeys)}
-        curl --fail-with-body http{access.Secure}://{access.HostPort}/downloads/agent.exe > agent.exe{`
-        `}agent --id {usageInputs.Id} ws{access.Secure}://{access.HostPort}{`
+        curl --fail-with-body http{access.Secure}://{access.BaseUrl}/downloads/agent.exe > agent.exe{`
+        `}agent --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl}{`
         del agent.exe
         `}
} if usageInputs.RemoteShells[POWERSHELL] {
{addSshKeys(POWERSHELL, usageInputs.SshKeys)}
-        curl --fail-with-body http{access.Secure}://{access.HostPort}/downloads/agent.exe > agent.exe{`
-        `}agent --id {usageInputs.Id} ws{access.Secure}://{access.HostPort}{`
+        curl --fail-with-body http{access.Secure}://{access.BaseUrl}/downloads/agent.exe > agent.exe{`
+        `}agent --id {usageInputs.Id} ws{access.Secure}://{access.BaseUrl}{`
         del agent.exe
         `}
} @@ -55,8 +55,8 @@ templ AgentUsage(access models.ConvergeAccess, usageInputs UsageInputs) {

{`
-          `}ssh -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.HostPort}/client/{usageInputs.Id}"  { access.Username }{"@localhost"}   {`
-          `}sftp -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.HostPort}/client/{usageInputs.Id}" { access.Username }{"@localhost"}   {`
+          `}ssh -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}"  { access.Username }{"@localhost"}   {`
+          `}sftp -oServerAliveInterval=10 -oProxyCommand="wsproxy ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}" { access.Username }{"@localhost"}   {`
           `}

This requires the wsproxy utility which is available in the @@ -79,8 +79,8 @@ templ AgentUsage(access models.ConvergeAccess, usageInputs UsageInputs) { using:

{`
-         `}tcptows ws{access.Secure}://{access.HostPort}/client/{usageInputs.Id}   {`
-         `}tcptows ws{access.Secure}://{access.HostPort}/client/{usageInputs.Id}   {`
+         `}tcptows ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}   {`
+         `}tcptows ws{access.Secure}://{access.BaseUrl}/client/{usageInputs.Id}   {`
          `}

Working with the agent