Skip to content

Commit

Permalink
feat: Support multiple username and password for login.
Browse files Browse the repository at this point in the history
  • Loading branch information
liqiang-fit2cloud committed Aug 23, 2022
1 parent d44ffa4 commit a098904
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 41 deletions.
53 changes: 27 additions & 26 deletions gotty/GOTTY_USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,33 @@ By default, GoTTY starts a web server at port 8080. Open the URL on your web bro
## Options

```
--address value, -a value IP address to listen (default: "0.0.0.0") [$GOTTY_ADDRESS]
--port value, -p value Port number to liten (default: "8080") [$GOTTY_PORT]
--permit-write, -w Permit clients to write to the TTY (BE CAREFUL) [$GOTTY_PERMIT_WRITE]
--credential value, -c value Credential for Basic Authentication (ex: user:pass, default disabled) [$GOTTY_CREDENTIAL]
--random-url, -r Add a random string to the URL [$GOTTY_RANDOM_URL]
--random-url-length value Random URL length (default: 8) [$GOTTY_RANDOM_URL_LENGTH]
--tls, -t Enable TLS/SSL [$GOTTY_TLS]
--tls-crt value TLS/SSL certificate file path (default: "~/.gotty.crt") [$GOTTY_TLS_CRT]
--tls-key value TLS/SSL key file path (default: "~/.gotty.key") [$GOTTY_TLS_KEY]
--tls-ca-crt value TLS/SSL CA certificate file for client certifications (default: "~/.gotty.ca.crt") [$GOTTY_TLS_CA_CRT]
--index value Custom index.html file [$GOTTY_INDEX]
--title-format value Title format of browser window (default: "{{ .command }}@{{ .hostname }}") [$GOTTY_TITLE_FORMAT]
--reconnect Enable reconnection [$GOTTY_RECONNECT]
--reconnect-time value Time to reconnect (default: 10) [$GOTTY_RECONNECT_TIME]
--max-connection value Maximum connection to gotty (default: 0) [$GOTTY_MAX_CONNECTION]
--once Accept only one client and exit on disconnection [$GOTTY_ONCE]
--timeout value Timeout seconds for waiting a client(0 to disable) (default: 0) [$GOTTY_TIMEOUT]
--permit-arguments Permit clients to send command line arguments in URL (e.g. http://example.com:8080/?arg=AAA&arg=BBB) [$GOTTY_PERMIT_ARGUMENTS]
--width value Static width of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_WIDTH]
--height value Static height of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_HEIGHT]
--ws-origin value A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default [$GOTTY_WS_ORIGIN]
--term value Terminal name to use on the browser, one of xterm or hterm. (default: "xterm") [$GOTTY_TERM]
--close-signal value Signal sent to the command process when gotty close it (default: SIGHUP) (default: 1) [$GOTTY_CLOSE_SIGNAL]
--close-timeout value Time in seconds to force kill process after client is disconnected (default: -1) (default: -1) [$GOTTY_CLOSE_TIMEOUT]
--config value Config file path (default: "~/.gotty") [$GOTTY_CONFIG]
--version, -v print the version
--address value, -a value IP address to listen (default: "0.0.0.0") [$GOTTY_ADDRESS]
--port value, -p value Port number to liten (default: "8080") [$GOTTY_PORT]
--permit-write, -w Permit clients to write to the TTY (BE CAREFUL) [$GOTTY_PERMIT_WRITE]
--credential value, -c value Credential for Basic Authentication (ex: user:pass, default disabled) [$GOTTY_CREDENTIAL]
--credential-file value, -c value Credential file for Basic Authentication [$GOTTY_CREDENTIAL_FILE]
--random-url, -r Add a random string to the URL [$GOTTY_RANDOM_URL]
--random-url-length value Random URL length (default: 8) [$GOTTY_RANDOM_URL_LENGTH]
--tls, -t Enable TLS/SSL [$GOTTY_TLS]
--tls-crt value TLS/SSL certificate file path (default: "~/.gotty.crt") [$GOTTY_TLS_CRT]
--tls-key value TLS/SSL key file path (default: "~/.gotty.key") [$GOTTY_TLS_KEY]
--tls-ca-crt value TLS/SSL CA certificate file for client certifications (default: "~/.gotty.ca.crt") [$GOTTY_TLS_CA_CRT]
--index value Custom index.html file [$GOTTY_INDEX]
--title-format value Title format of browser window (default: "{{ .command }}@{{ .hostname }}") [$GOTTY_TITLE_FORMAT]
--reconnect Enable reconnection [$GOTTY_RECONNECT]
--reconnect-time value Time to reconnect (default: 10) [$GOTTY_RECONNECT_TIME]
--max-connection value Maximum connection to gotty (default: 0) [$GOTTY_MAX_CONNECTION]
--once Accept only one client and exit on disconnection [$GOTTY_ONCE]
--timeout value Timeout seconds for waiting a client(0 to disable) (default: 0) [$GOTTY_TIMEOUT]
--permit-arguments Permit clients to send command line arguments in URL (e.g. http://example.com:8080/?arg=AAA&arg=BBB) [$GOTTY_PERMIT_ARGUMENTS]
--width value Static width of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_WIDTH]
--height value Static height of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_HEIGHT]
--ws-origin value A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default [$GOTTY_WS_ORIGIN]
--term value Terminal name to use on the browser, one of xterm or hterm. (default: "xterm") [$GOTTY_TERM]
--close-signal value Signal sent to the command process when gotty close it (default: SIGHUP) (default: 1) [$GOTTY_CLOSE_SIGNAL]
--close-timeout value Time in seconds to force kill process after client is disconnected (default: -1) (default: -1) [$GOTTY_CLOSE_TIMEOUT]
--config value Config file path (default: "~/.gotty") [$GOTTY_CONFIG]
--version, -v print the version
```

### Config File
Expand Down
2 changes: 1 addition & 1 deletion gotty/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func main() {

utils.ApplyFlags(cliFlags, flagMappings, c, appOptions, backendOptions, redisOptions)

appOptions.EnableBasicAuth = c.IsSet("credential")
appOptions.EnableBasicAuth = c.IsSet("credential") || c.IsSet("credential-file")
appOptions.EnableTLSClientAuth = c.IsSet("tls-ca-crt")

err = appOptions.Validate()
Expand Down
16 changes: 3 additions & 13 deletions gotty/server/middleware.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package server

import (
"encoding/base64"
"log"
"net/http"
"strings"
)
Expand All @@ -23,7 +21,7 @@ func (server *Server) wrapHeaders(handler http.Handler) http.Handler {
})
}

func (server *Server) wrapBasicAuth(handler http.Handler, credential string) http.Handler {
func (server *Server) wrapBasicAuth(handler http.Handler, basicCredentialMap map[string]string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := strings.SplitN(r.Header.Get("Authorization"), " ", 2)

Expand All @@ -32,20 +30,12 @@ func (server *Server) wrapBasicAuth(handler http.Handler, credential string) htt
http.Error(w, "Bad Request", http.StatusUnauthorized)
return
}

payload, err := base64.StdEncoding.DecodeString(token[1])
if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}

if credential != string(payload) {
_, ok := basicCredentialMap[token[1]]
if !ok {
w.Header().Set("WWW-Authenticate", `Basic realm="GoTTY"`)
http.Error(w, "authorization failed", http.StatusUnauthorized)
return
}

log.Printf("Basic Authentication Succeeded: %s", r.RemoteAddr)
handler.ServeHTTP(w, r)
})
}
1 change: 1 addition & 0 deletions gotty/server/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Options struct {
PermitWrite bool `hcl:"permit_write" flagName:"permit-write" flagSName:"w" flagDescribe:"Permit clients to write to the TTY (BE CAREFUL)" default:"false"`
EnableBasicAuth bool `hcl:"enable_basic_auth" default:"false"`
Credential string `hcl:"credential" flagName:"credential" flagSName:"c" flagDescribe:"Credential for Basic Authentication (ex: user:pass, default disabled)" default:""`
CredentialFile string `hcl:"credential_file" flagName:"credential-file" flagSName:"cf" flagDescribe:"Credential File for Basic Authentication" default:""`
EnableRandomUrl bool `hcl:"enable_random_url" flagName:"random-url" flagSName:"r" flagDescribe:"Add a random string to the URL" default:"false"`
RandomUrlLength int `hcl:"random_url_length" flagName:"random-url-length" flagDescribe:"Random URL length" default:"8"`
EnableTLS bool `hcl:"enable_tls" flagName:"tls" flagSName:"t" flagDescribe:"Enable TLS/SSL" default:"false"`
Expand Down
31 changes: 30 additions & 1 deletion gotty/server/server.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package server

import (
"bufio"
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"html/template"
"log"
"net"
Expand Down Expand Up @@ -235,7 +237,34 @@ func (server *Server) setupHandlers(ctx context.Context, cancel context.CancelFu

if server.options.EnableBasicAuth {
log.Printf("Using Basic Authentication")
siteHandler = server.wrapBasicAuth(siteHandler, server.options.Credential)
basicCredentialMap := make(map[string]string)
if server.options.Credential != "" {
basicCredentialMap[base64.StdEncoding.EncodeToString([]byte(server.options.Credential))] = server.options.Credential
}
if server.options.CredentialFile != "" {
file, err := os.Open(server.options.CredentialFile)
if err != nil {
log.Printf("Ubable to open credential file " + server.options.CredentialFile)
panic(err)
}
fileInfo, _ := file.Stat()
if fileInfo.Size() > 10*1024*1024 {
panic("Credential file size exceeds 10M, too big to open.")
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if len(line) > 1024 {
log.Printf("Too long to read, ignore this line.")
log.Printf(line)
continue
}
if line != "" {
basicCredentialMap[base64.StdEncoding.EncodeToString([]byte(line))] = line
}
}
}
siteHandler = server.wrapBasicAuth(siteHandler, basicCredentialMap)
}

withGz := gziphandler.GzipHandler(server.wrapHeaders(siteHandler))
Expand Down

0 comments on commit a098904

Please sign in to comment.