Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation when connecting Kubernetes endpoints #94

Merged
merged 2 commits into from
Nov 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/jetstream/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,17 @@ func (p *portalProxy) DoLoginToCNSI(c echo.Context, cnsiGUID string, systemShare
"Error occurred: %s", err)
}

// Validate the connection - some endpoints may want to validate that the connected endpoint
err = endpointPlugin.Validate(userID, cnsiRecord, *tokenRecord)
if err != nil {
// Clear the token
p.ClearCNSIToken(cnsiRecord, userID)
return nil, interfaces.NewHTTPShadowError(
http.StatusBadRequest,
"Could not connect to the endpoint",
"Could not connect to the endpoint: %s", err)
}

resp := &interfaces.LoginRes{
Account: userID,
TokenExpiry: tokenRecord.TokenExpiry,
Expand Down Expand Up @@ -583,18 +594,24 @@ func (p *portalProxy) logoutOfCNSI(c echo.Context) error {
userGUID = tokens.SystemSharedUserGuid
}

// Clear the token
return p.ClearCNSIToken(cnsiRecord, userGUID)
}

// Clear the CNSI token
func (p *portalProxy) ClearCNSIToken(cnsiRecord interfaces.CNSIRecord, userGUID string) error {
// If cnsi is cf AND cf is auto-register only clear the entry
p.Config.AutoRegisterCFUrl = strings.TrimRight(p.Config.AutoRegisterCFUrl, "/")
if cnsiRecord.CNSIType == "cf" && p.GetConfig().AutoRegisterCFUrl == cnsiRecord.APIEndpoint.String() {
log.Debug("Setting token record as disconnected")

tokenRecord := p.InitEndpointTokenRecord(0, "cleared_token", "cleared_token", true)
if err := p.setCNSITokenRecord(cnsiGUID, userGUID, tokenRecord); err != nil {
if err := p.setCNSITokenRecord(cnsiRecord.GUID, userGUID, tokenRecord); err != nil {
return fmt.Errorf("Unable to clear token: %s", err)
}
} else {
log.Debug("Deleting Token")
if err := p.deleteCNSIToken(cnsiGUID, userGUID); err != nil {
if err := p.deleteCNSIToken(cnsiRecord.GUID, userGUID); err != nil {
return fmt.Errorf("Unable to delete token: %s", err)
}
}
Expand Down
25 changes: 25 additions & 0 deletions src/jetstream/passthrough.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,31 @@ func (p *portalProxy) DoProxyRequest(requests []interfaces.ProxyRequestInfo) (ma
return responses, nil
}

// Convenience helper for a single request
func (p *portalProxy) DoProxySingleRequest(cnsiGUID, userGUID, method, requestUrl string) (*interfaces.CNSIRequest, error) {
requests := make([]interfaces.ProxyRequestInfo, 0)

proxyURL, err := url.Parse(requestUrl)
if err != nil {
return nil, err
}

req := interfaces.ProxyRequestInfo{}
req.UserGUID = userGUID
req.ResultGUID = "REQ_" + cnsiGUID
req.EndpointGUID = cnsiGUID
req.Method = method
req.URI = proxyURL
requests = append(requests, req)

responses, err := p.DoProxyRequest(requests)
if err != nil {
return nil, err
}

return responses[req.ResultGUID], err
}

func (p *portalProxy) SendProxiedResponse(c echo.Context, responses map[string]*interfaces.CNSIRequest) error {
shouldPassthrough := "true" == c.Request().Header().Get("x-cap-passthrough")

Expand Down
4 changes: 4 additions & 0 deletions src/jetstream/plugins/caasp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (m *CaaspSpecification) Register(echoContext echo.Context) error {
return m.portalProxy.RegisterEndpoint(echoContext, m.Info)
}

func (m *CaaspSpecification) Validate(userGUID string, cnsiRecord interfaces.CNSIRecord, tokenRecord interfaces.TokenRecord) error {
return nil
}

func (m *CaaspSpecification) Connect(ec echo.Context, cnsiRecord interfaces.CNSIRecord, userId string) (*interfaces.TokenRecord, bool, error) {
log.Debug("Caasp Connect...")

Expand Down
4 changes: 4 additions & 0 deletions src/jetstream/plugins/cloudfoundry/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func (c *CloudFoundrySpecification) Register(echoContext echo.Context) error {
return c.portalProxy.RegisterEndpoint(echoContext, c.Info)
}

func (c *CloudFoundrySpecification) Validate(userGUID string, cnsiRecord interfaces.CNSIRecord, tokenRecord interfaces.TokenRecord) error {
return nil
}

func (c *CloudFoundrySpecification) Connect(ec echo.Context, cnsiRecord interfaces.CNSIRecord, userId string) (*interfaces.TokenRecord, bool, error) {
log.Info("CloudFoundry Connect...")

Expand Down
13 changes: 13 additions & 0 deletions src/jetstream/plugins/kubernetes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ func (c *KubernetesSpecification) Register(echoContext echo.Context) error {
return c.portalProxy.RegisterEndpoint(echoContext, c.Info)
}

func (c *KubernetesSpecification) Validate(userGUID string, cnsiRecord interfaces.CNSIRecord, tokenRecord interfaces.TokenRecord) error {
response, err := c.portalProxy.DoProxySingleRequest(cnsiRecord.GUID, userGUID, "GET", "api/v1/pods?limit=1")
if err != nil {
return err
}

if response.StatusCode >= 400 {
return errors.New("Unable to connect to endpoint")
}

return nil
}

func (c *KubernetesSpecification) Connect(ec echo.Context, cnsiRecord interfaces.CNSIRecord, userId string) (*interfaces.TokenRecord, bool, error) {
log.Debug("Kubernetes Connect...")

Expand Down
4 changes: 4 additions & 0 deletions src/jetstream/plugins/metrics/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ func (m *MetricsSpecification) Register(echoContext echo.Context) error {
return m.portalProxy.RegisterEndpoint(echoContext, m.Info)
}

func (m *MetricsSpecification) Validate(userGUID string, cnsiRecord interfaces.CNSIRecord, tokenRecord interfaces.TokenRecord) error {
return nil
}

func (m *MetricsSpecification) Connect(ec echo.Context, cnsiRecord interfaces.CNSIRecord, userId string) (*interfaces.TokenRecord, bool, error) {
log.Debug("Metrics Connect...")

Expand Down
1 change: 1 addition & 0 deletions src/jetstream/repository/interfaces/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type EndpointPlugin interface {
GetType() string
Register(echoContext echo.Context) error
Connect(echoContext echo.Context, cnsiRecord CNSIRecord, userId string) (*TokenRecord, bool, error)
Validate(userGUID string, cnsiRecord CNSIRecord, tokenRecord TokenRecord) error
UpdateMetadata(info *Info, userGUID string, echoContext echo.Context)
}

Expand Down
1 change: 1 addition & 0 deletions src/jetstream/repository/interfaces/portal_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type PortalProxy interface {
// Proxy API requests
ProxyRequest(c echo.Context, uri *url.URL) (map[string]*CNSIRequest, error)
DoProxyRequest(requests []ProxyRequestInfo) (map[string]*CNSIRequest, error)
DoProxySingleRequest(cnsiGUID, userGUID, method, requestUrl string) (*CNSIRequest, error)
SendProxiedResponse(c echo.Context, responses map[string]*CNSIRequest) error

AddAuthProvider(name string, provider AuthProvider)
Expand Down