From 75e1bd77bac4e84b42937b9b16e120eb46bc66ec Mon Sep 17 00:00:00 2001
From: Erik Brakkee
Date: Sat, 3 Aug 2024 23:10:57 +0200
Subject: [PATCH] Alternative contextpath is now supported. This will simplify
hosting in cases where you have no control over DNS but only over one domain.
---
cmd/converge/converge.go | 30 +++++++++++++++++++-----------
cmd/converge/convergeaccess.go | 15 ++++++++++++++-
cmd/templaterender/render.go | 2 +-
pkg/models/convergeaccess.go | 2 +-
pkg/server/templates/usage.templ | 20 ++++++++++----------
5 files changed, 45 insertions(+), 24 deletions(-)
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