Refactor the third-party connect backend functionality

This commit is contained in:
Dan Sosedoff 2017-09-21 01:21:26 -05:00
parent d175b0af34
commit 869fd8c6bc
3 changed files with 90 additions and 30 deletions

View File

@ -2,11 +2,8 @@ package api
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net/http"
neturl "net/url" neturl "net/url"
"strings" "strings"
"time" "time"
@ -74,27 +71,21 @@ func GetSessions(c *gin.Context) {
} }
func ConnectWithBackend(c *gin.Context) { func ConnectWithBackend(c *gin.Context) {
resp, err := http.PostForm(command.Opts.ConnectBackend, neturl.Values{ // Setup a new backend client
"resource": {c.Param("resource")}, backend := Backend{
"token": {command.Opts.ConnectToken}, Endpoint: command.Opts.ConnectBackend,
}) Token: command.Opts.ConnectToken,
PassHeaders: command.Opts.ConnectHeaders,
}
// Fetch connection credentials
cred, err := backend.FetchCredential(c.Param("resource"), c)
if err != nil { if err != nil {
c.JSON(400, err) c.JSON(400, Error{err.Error()})
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
c.JSON(400, Error{"Unable to fetch connection settings"})
return
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
c.JSON(400, err)
return return
} }
// Make the new session
sessionId, err := securerandom.Uuid() sessionId, err := securerandom.Uuid()
if err != nil { if err != nil {
c.JSON(400, Error{err.Error()}) c.JSON(400, Error{err.Error()})
@ -102,22 +93,15 @@ func ConnectWithBackend(c *gin.Context) {
} }
c.Request.Header.Add("x-session-id", sessionId) c.Request.Header.Add("x-session-id", sessionId)
config := struct { // Connect to the database
DatabaseUrl string `json:"database_url"` cl, err := client.NewFromUrl(cred.DatabaseUrl, nil)
}{}
if err := json.Unmarshal(data, &config); err != nil {
c.JSON(400, Error{err.Error()})
return
}
cl, err := client.NewFromUrl(config.DatabaseUrl, nil)
if err != nil { if err != nil {
c.JSON(400, Error{err.Error()}) c.JSON(400, Error{err.Error()})
return return
} }
cl.External = true cl.External = true
// Finalize session seetup
_, err = cl.Info() _, err = cl.Info()
if err == nil { if err == nil {
err = setClient(c, cl) err = setClient(c, cl)

75
pkg/api/backend.go Normal file
View File

@ -0,0 +1,75 @@
package api
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type Backend struct {
Endpoint string
Token string
PassHeaders string
}
type BackendRequest struct {
Resource string `json:"resource"`
Token string `json:"token"`
Headers map[string]string `json:"headers"`
}
type BackendCredential struct {
DatabaseUrl string `json:"database_url"`
}
func (be Backend) FetchCredential(resource string, c *gin.Context) (*BackendCredential, error) {
request := BackendRequest{
Resource: resource,
Token: be.Token,
Headers: map[string]string{},
}
for _, name := range strings.Split(be.PassHeaders, ",") {
request.Headers[strings.ToLower(name)] = c.Request.Header.Get(name)
}
body, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := http.Post(be.Endpoint, "application/json", bytes.NewReader(body))
if err != nil {
// Any connection-related issues will show up in the server log
log.Println("Unable to fetch backend credential:", err)
// We dont want to expose the url of the backend here, so reply with generic error
return nil, fmt.Errorf("Unable to connect to the auth backend")
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Got HTTP error %v from backend", resp.StatusCode)
}
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
cred := &BackendCredential{}
if err := json.Unmarshal(respBody, cred); err != nil {
return nil, err
}
if cred.DatabaseUrl == "" {
return nil, fmt.Errorf("Database url was not provided")
}
return cred, nil
}

View File

@ -32,6 +32,7 @@ type Options struct {
DisablePrettyJson bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export" default:"false"` DisablePrettyJson bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export" default:"false"`
ConnectBackend string `long:"connect-backend" description:"Enable database authentication through a third party backend"` ConnectBackend string `long:"connect-backend" description:"Enable database authentication through a third party backend"`
ConnectToken string `long:"connect-token" description:"Authentication token for the third-party connect backend"` ConnectToken string `long:"connect-token" description:"Authentication token for the third-party connect backend"`
ConnectHeaders string `long:"connect-headers" description:"List of headers to pass to the connect backend"`
} }
var Opts Options var Opts Options