Simplify client creation API

Previously it was RESTful and required both a user and client
name in order to PUT new clients. Now this information is taken
from the token if possible (user is always available, client name
may not be) and a simple POST /clients endpoint is provided.
This commit is contained in:
Anders Pitman 2022-02-17 14:40:17 -07:00
parent 4ca1b5959d
commit 0eab8db4d6
3 changed files with 57 additions and 6 deletions

51
api.go
View File

@ -29,6 +29,7 @@ func NewApi(config *Config, db *Database, auth *Auth, tunMan *TunnelManager) *Ap
mux.Handle("/tunnels", http.StripPrefix("/tunnels", http.HandlerFunc(api.handleTunnels)))
mux.Handle("/users/", http.StripPrefix("/users", http.HandlerFunc(api.handleUsers)))
mux.Handle("/tokens/", http.StripPrefix("/tokens", http.HandlerFunc(api.handleTokens)))
mux.Handle("/clients/", http.StripPrefix("/clients", http.HandlerFunc(api.handleClients)))
return api
}
@ -244,6 +245,56 @@ func (a *Api) handleTokens(w http.ResponseWriter, r *http.Request) {
}
}
func (a *Api) handleClients(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
token, err := extractToken("access_token", r)
if err != nil {
w.WriteHeader(401)
w.Write([]byte("No token provided"))
return
}
tokenData, exists := a.db.GetTokenData(token)
if !exists {
w.WriteHeader(403)
w.Write([]byte("Not authorized"))
return
}
clientName := r.Form.Get("client-name")
if clientName == "" {
clientName = tokenData.Client
if tokenData.Client == "" {
w.WriteHeader(400)
w.Write([]byte("Missing client-name parameter"))
return
} else {
clientName = tokenData.Client
}
}
if tokenData.Client != "" && tokenData.Client != clientName {
w.WriteHeader(403)
io.WriteString(w, "Token does not have proper permissions")
return
}
switch r.Method {
case "POST":
err := a.SetClient(tokenData, r.Form, tokenData.Owner, clientName)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
}
default:
w.WriteHeader(405)
w.Write([]byte(err.Error()))
}
}
func (a *Api) GetTunnel(tokenData TokenData, params url.Values) (Tunnel, error) {
domain := params.Get("domain")
if domain == "" {

View File

@ -115,8 +115,12 @@ func NewClient(config *ClientConfig) (*Client, error) {
func (c *Client) Run(ctx context.Context) error {
url := fmt.Sprintf("https://%s/api/users/%s/clients/%s", c.server, c.user, c.clientName)
clientReq, err := http.NewRequest("PUT", url, nil)
url := fmt.Sprintf("https://%s/api/clients/?client-name=%s", c.server, c.clientName)
if c.user != "" {
url = url + "&user=" + c.user
}
clientReq, err := http.NewRequest("POST", url, nil)
if err != nil {
return errors.New(fmt.Sprintf("Failed to create request for URL %s", url))
}

View File

@ -67,10 +67,6 @@ func main() {
fail("-token is required")
}
if *name == "" {
fail("-client-name is required")
}
config := &boringproxy.ClientConfig{
ServerAddr: *server,
Token: *token,