Now displaying agent number instead of id.
Passing timezone to server side for rendering of time stamps Configuration of preferred shells.
This commit is contained in:
		
							parent
							
								
									4c52fb0f12
								
							
						
					
					
						commit
						2e12d0a9fd
					
				| @ -174,7 +174,11 @@ func printHelp(msg string) { | ||||
| 		"--warning-time:     advance warning time before sessio ends\n" + | ||||
| 		"--expiry-time:      expiry time of the session\n" + | ||||
| 		"--check-interval:   interval at which expiry is checked\n" + | ||||
| 		"-insecure:          allow invalid certificates\n" | ||||
| 		"--insecure:         allow invalid certificates\n" + | ||||
| 		"--shells:           comma-separated list of shells to add to the front of theshell search path\n" + | ||||
| 		"                    (e.g. 'zsh,sh'). If the shell name contains a slash,then the path must exist:\n" + | ||||
| 		"                    either relative to the agent's current directory or absolute. Otherwise it is looekd\n" + | ||||
| 		"                    up in the system search path. " | ||||
| 
 | ||||
| 	fmt.Fprintln(os.Stderr, helpText) | ||||
| 	os.Exit(1) | ||||
| @ -211,8 +215,14 @@ func main() { | ||||
| 	agentExpriryTime := 10 * time.Minute | ||||
| 	tickerInterval := 60 * time.Second | ||||
| 	insecure := false | ||||
| 	shells := []string{"bash", "sh", "ash", "ksh", "zsh", "fish", "tcsh", "csh"} | ||||
| 	if runtime.GOOS == "windows" { | ||||
| 		shells = []string{"powershell", "bash"} | ||||
| 	} | ||||
| 
 | ||||
| 	args := os.Args[1:] | ||||
| 	additionalShells := []string{} | ||||
| 	commaSeparated := "" | ||||
| 	for len(args) > 0 && strings.HasPrefix(args[0], "-") { | ||||
| 		val := "" | ||||
| 		switch args[0] { | ||||
| @ -228,12 +238,17 @@ func main() { | ||||
| 			tickerInterval, args = parseDuration(args, val) | ||||
| 		case "--insecure": | ||||
| 			insecure = true | ||||
| 		case "--shells": | ||||
| 			commaSeparated, args = getArg(args) | ||||
| 			additionalShells = append(additionalShells, strings.Split(commaSeparated, ",")...) | ||||
| 		default: | ||||
| 			printHelp("Unknown option " + args[0]) | ||||
| 		} | ||||
| 		args = args[1:] | ||||
| 	} | ||||
| 
 | ||||
| 	shells = append(additionalShells, shells...) | ||||
| 
 | ||||
| 	id = getId(id) | ||||
| 
 | ||||
| 	if len(args) != 1 { | ||||
| @ -266,7 +281,7 @@ func main() { | ||||
| 	wsConn := websocketutil.NewWebSocketConn(conn, false) | ||||
| 	defer wsConn.Close() | ||||
| 
 | ||||
| 	shell := chooseShell() | ||||
| 	shell := chooseShell(shells) | ||||
| 	serverInfo, err := comms.AgentInitialization(wsConn, comms.NewAgentInfo(shell)) | ||||
| 	if err != nil { | ||||
| 		log.Printf("ERROR: %v", err) | ||||
| @ -355,14 +370,9 @@ func setupAuthentication(commChannel comms.CommChannel, | ||||
| 	return passwordHandler, authorizedKeys | ||||
| } | ||||
| 
 | ||||
| func chooseShell() string { | ||||
| func chooseShell(shells []string) string { | ||||
| 	log.Printf("Shell search path is %v", shells) | ||||
| 	var err error | ||||
| 
 | ||||
| 	shells := []string{"bash", "sh", "ash", "ksh", "zsh", "fish", "tcsh", "csh"} | ||||
| 	if runtime.GOOS == "windows" { | ||||
| 		shells = []string{"powershell", "bash"} | ||||
| 	} | ||||
| 
 | ||||
| 	shell := "" | ||||
| 	for _, candidate := range shells { | ||||
| 		shell, err = exec.LookPath(candidate) | ||||
|  | ||||
| @ -61,8 +61,9 @@ func main() { | ||||
| 
 | ||||
| 		state := models.State{} | ||||
| 		agent := models.Agent{ | ||||
| 			PublicId:  "id", | ||||
| 			StartTime: time.Now().In(japan), | ||||
| 			PublicId:    "id", | ||||
| 			GeneratedId: "100", | ||||
| 			StartTime:   time.Now().In(japan), | ||||
| 			AgentInfo: comms.AgentInfo{ | ||||
| 				Username: "ci", | ||||
| 				Hostname: "container123", | ||||
| @ -75,6 +76,7 @@ func main() { | ||||
| 		state.Agents = append(state.Agents, agent) | ||||
| 		client := models.Client{ | ||||
| 			PublicId:    "c1", | ||||
| 			AgentId:     "100", | ||||
| 			ClientId:    3, | ||||
| 			StartTime:   time.Now().In(japan), | ||||
| 			SessionType: "sftp", | ||||
|  | ||||
| @ -6,8 +6,9 @@ import ( | ||||
| ) | ||||
| 
 | ||||
| type Agent struct { | ||||
| 	PublicId  string | ||||
| 	StartTime time.Time | ||||
| 	PublicId    string | ||||
| 	GeneratedId string | ||||
| 	StartTime   time.Time | ||||
| 
 | ||||
| 	AgentInfo  comms.AgentInfo | ||||
| 	ExpiryTime time.Time | ||||
|  | ||||
| @ -6,6 +6,7 @@ import ( | ||||
| 
 | ||||
| type Client struct { | ||||
| 	PublicId    string | ||||
| 	AgentId     string | ||||
| 	ClientId    int | ||||
| 	StartTime   time.Time | ||||
| 	SessionType string | ||||
|  | ||||
| @ -21,6 +21,7 @@ type AgentConnection struct { | ||||
| 	commChannel comms.CommChannel | ||||
| } | ||||
| 
 | ||||
| var agentIdGenerator = concurrency.NewAtomicCounter() | ||||
| var clientIdGenerator = concurrency.NewAtomicCounter() | ||||
| 
 | ||||
| type ClientConnection struct { | ||||
| @ -32,19 +33,21 @@ type ClientConnection struct { | ||||
| func NewAgent(commChannel comms.CommChannel, publicId string, agentInfo comms.AgentInfo) *AgentConnection { | ||||
| 	return &AgentConnection{ | ||||
| 		Agent: models.Agent{ | ||||
| 			PublicId:  publicId, | ||||
| 			StartTime: time.Now(), | ||||
| 			AgentInfo: agentInfo, | ||||
| 			PublicId:    publicId, | ||||
| 			GeneratedId: strconv.Itoa(agentIdGenerator.IncrementAndGet()), | ||||
| 			StartTime:   time.Now(), | ||||
| 			AgentInfo:   agentInfo, | ||||
| 		}, | ||||
| 		commChannel: commChannel, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func NewClient(publicId string, clientConn iowrappers2.ReadWriteAddrCloser, | ||||
| func NewClient(publicId string, agentId string, clientConn iowrappers2.ReadWriteAddrCloser, | ||||
| 	agentConn net.Conn) *ClientConnection { | ||||
| 	return &ClientConnection{ | ||||
| 		Client: models.Client{ | ||||
| 			PublicId:  publicId, | ||||
| 			AgentId:   agentId, | ||||
| 			ClientId:  clientIdGenerator.IncrementAndGet(), | ||||
| 			StartTime: time.Now(), | ||||
| 		}, | ||||
| @ -197,7 +200,7 @@ func (admin *Admin) addClient(publicId string, clientConn iowrappers2.ReadWriteA | ||||
| 
 | ||||
| 	log.Println("Sending connection information to agent") | ||||
| 
 | ||||
| 	client := NewClient(publicId, clientConn, agentConn) | ||||
| 	client := NewClient(publicId, agent.GeneratedId, clientConn, agentConn) | ||||
| 
 | ||||
| 	// Before using this connection for SSH we use it to send client metadata to the
 | ||||
| 	// agent
 | ||||
|  | ||||
| @ -59,20 +59,14 @@ func (sessions *WebSessions) NewSession(wsConnection net.Conn) *WebSession { | ||||
| } | ||||
| 
 | ||||
| func GetUserLocation(r *http.Request) (*time.Location, error) { | ||||
| 	// Try to get timezone from a custom header
 | ||||
| 	tzName := r.Header.Get("X-Timezone") | ||||
| 
 | ||||
| 	// If not found in header, try to get from query parameter
 | ||||
| 	tzName := r.URL.Query().Get("timezone") | ||||
| 	if tzName == "" { | ||||
| 		tzName = r.URL.Query().Get("tz") | ||||
| 		tzName = r.Header.Get("X-Timezone") | ||||
| 	} | ||||
| 
 | ||||
| 	// If still not found, default to UTC
 | ||||
| 	//log.Println("GetUserLocation: timezone ", tzName)
 | ||||
| 	if tzName == "" { | ||||
| 		tzName = "UTC" | ||||
| 	} | ||||
| 
 | ||||
| 	// Load the location
 | ||||
| 	return time.LoadLocation(tzName) | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -24,15 +24,36 @@ templ BasePage(tab int) { | ||||
|         <title>Converge</title> | ||||
|     </head> | ||||
|     <body> | ||||
|     <script> | ||||
|     <!-- script> | ||||
|     htmx.logAll(); | ||||
|     </script --> | ||||
|     <script> | ||||
|         function getTimezone() { | ||||
|             return Intl.DateTimeFormat().resolvedOptions().timeZone; | ||||
|         } | ||||
|         if (!window.originalWebSocket) { | ||||
|             console.log("timezone override for websockets") | ||||
|             window.originalWebSocket = htmx.createWebSocket | ||||
|             htmx.createWebSocket = function(url) { | ||||
|                 let modifiedUrl = url + "?timezone=" + getTimezone() | ||||
|                 return window.originalWebSocket(modifiedUrl) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         document.body.addEventListener( | ||||
|             "htmx:configRequest", | ||||
|             function(evt) { | ||||
|                 console.log("Adding timezone to htmx request headers"); | ||||
|                 evt.detail.headers["X-Timezone"] = getTimezone(); | ||||
|             } | ||||
|         ); | ||||
|     </script> | ||||
| 
 | ||||
| 
 | ||||
|     <script src="../static/js/bootstrap.bundle.min.js" | ||||
|             crossorigin="anonymous"></script> | ||||
| 
 | ||||
|     <div class="container-fluid"> | ||||
|     <div class="container-fluid" hx-boost="true"> | ||||
|         <div class="row"> | ||||
|             <div class="col"> | ||||
|                 <nav class="navbar navbar-expand-sm navbar-light bg-light"> | ||||
|  | ||||
| @ -45,7 +45,7 @@ templ State(state *models.State, location *time.Location) { | ||||
|            </thead> | ||||
|    for _, agent := range state.Agents { | ||||
|            <tr> | ||||
|                <td>{agent.PublicId}</td> | ||||
|                <td>{agent.GeneratedId}</td> | ||||
|                <td>{agent.StartTime.In(location).Format(time.DateTime)}</td> | ||||
|                <td>{agent.ExpiryTime.In(location).Format(time.DateTime)}</td> | ||||
|                <td>{agent.AgentInfo.Username}</td> | ||||
| @ -75,7 +75,7 @@ templ State(state *models.State, location *time.Location) { | ||||
|               </thead> | ||||
|    for _, client := range state.Clients { | ||||
|               <tr> | ||||
|                   <td>{client.PublicId}</td> | ||||
|                   <td>{client.AgentId}</td> | ||||
|                   <td>{strconv.Itoa(client.ClientId)}</td> | ||||
|                   <td>{client.StartTime.In(location).Format(time.DateTime)}</td> | ||||
|                   <td>{client.SessionType}</td> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user