From e3f4eb33feb254ff852e6b30d292b8d172ed19ad Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 28 Jul 2022 14:32:49 -0400 Subject: [PATCH] authenticate remaining api endpoints (#11) --- cmd/zrok/http.go | 15 ++++++++--- controller/tunnel.go | 3 ++- controller/untunnel.go | 3 ++- rest_client_zrok/tunnel/tunnel_client.go | 10 +++++--- rest_server_zrok/embedded_spec.go | 20 +++++++++++++++ rest_server_zrok/operations/tunnel/tunnel.go | 25 +++++++++++++++---- .../operations/tunnel/untunnel.go | 25 +++++++++++++++---- rest_server_zrok/operations/zrok_api.go | 4 +-- specs/zrok.yml | 4 +++ 9 files changed, 87 insertions(+), 22 deletions(-) diff --git a/cmd/zrok/http.go b/cmd/zrok/http.go index 544846ea..48edf193 100644 --- a/cmd/zrok/http.go +++ b/cmd/zrok/http.go @@ -1,6 +1,8 @@ package main import ( + "github.com/go-openapi/runtime" + httptransport "github.com/go-openapi/runtime/client" "github.com/openziti-test-kitchen/zrok/http" "github.com/openziti-test-kitchen/zrok/rest_client_zrok" "github.com/openziti-test-kitchen/zrok/rest_client_zrok/tunnel" @@ -33,14 +35,19 @@ func handleHttp(_ *cobra.Command, args []string) { if err != nil { panic(err) } + token, err := zrokdir.ReadToken() + if err != nil { + panic(err) + } zrok := newZrokClient() + auth := httptransport.APIKeyAuth("X-TOKEN", "header", token) req := tunnel.NewTunnelParams() req.Body = &rest_model_zrok.TunnelRequest{ Endpoint: cfg.EndpointAddress, Identity: id, } - resp, err := zrok.Tunnel.Tunnel(req) + resp, err := zrok.Tunnel.Tunnel(req, auth) if err != nil { panic(err) } @@ -50,7 +57,7 @@ func handleHttp(_ *cobra.Command, args []string) { signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c - cleanupHttp(cfg, zrok) + cleanupHttp(cfg, zrok, auth) os.Exit(1) }() @@ -59,13 +66,13 @@ func handleHttp(_ *cobra.Command, args []string) { } } -func cleanupHttp(cfg *http.Config, zrok *rest_client_zrok.Zrok) { +func cleanupHttp(cfg *http.Config, zrok *rest_client_zrok.Zrok, auth runtime.ClientAuthInfoWriter) { logrus.Infof("shutting down '%v'", cfg.Service) req := tunnel.NewUntunnelParams() req.Body = &rest_model_zrok.UntunnelRequest{ Service: cfg.Service, } - if _, err := zrok.Tunnel.Untunnel(req); err == nil { + if _, err := zrok.Tunnel.Untunnel(req, auth); err == nil { logrus.Infof("shutdown complete") } else { logrus.Errorf("error shutting down: %v", err) diff --git a/controller/tunnel.go b/controller/tunnel.go index 5bfac6cd..960af0d1 100644 --- a/controller/tunnel.go +++ b/controller/tunnel.go @@ -16,7 +16,8 @@ import ( "time" ) -func tunnelHandler(params tunnel.TunnelParams) middleware.Responder { +func tunnelHandler(params tunnel.TunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { + logrus.Infof("tunneling for '%v' (%v)", principal.Username, principal.Token) edge, err := edgeClient() if err != nil { logrus.Error(err) diff --git a/controller/untunnel.go b/controller/untunnel.go index ee8f0d66..3c5a8d36 100644 --- a/controller/untunnel.go +++ b/controller/untunnel.go @@ -15,7 +15,8 @@ import ( "time" ) -func untunnelHandler(params tunnel.UntunnelParams) middleware.Responder { +func untunnelHandler(params tunnel.UntunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { + logrus.Infof("untunneling for '%v' (%v)", principal.Username, principal.Token) edge, err := edgeClient() if err != nil { logrus.Error(err) diff --git a/rest_client_zrok/tunnel/tunnel_client.go b/rest_client_zrok/tunnel/tunnel_client.go index 0ddbd213..b91a139b 100644 --- a/rest_client_zrok/tunnel/tunnel_client.go +++ b/rest_client_zrok/tunnel/tunnel_client.go @@ -30,9 +30,9 @@ type ClientOption func(*runtime.ClientOperation) // ClientService is the interface for Client methods type ClientService interface { - Tunnel(params *TunnelParams, opts ...ClientOption) (*TunnelCreated, error) + Tunnel(params *TunnelParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*TunnelCreated, error) - Untunnel(params *UntunnelParams, opts ...ClientOption) (*UntunnelOK, error) + Untunnel(params *UntunnelParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UntunnelOK, error) SetTransport(transport runtime.ClientTransport) } @@ -40,7 +40,7 @@ type ClientService interface { /* Tunnel tunnel API */ -func (a *Client) Tunnel(params *TunnelParams, opts ...ClientOption) (*TunnelCreated, error) { +func (a *Client) Tunnel(params *TunnelParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*TunnelCreated, error) { // TODO: Validate the params before sending if params == nil { params = NewTunnelParams() @@ -54,6 +54,7 @@ func (a *Client) Tunnel(params *TunnelParams, opts ...ClientOption) (*TunnelCrea Schemes: []string{"http"}, Params: params, Reader: &TunnelReader{formats: a.formats}, + AuthInfo: authInfo, Context: params.Context, Client: params.HTTPClient, } @@ -78,7 +79,7 @@ func (a *Client) Tunnel(params *TunnelParams, opts ...ClientOption) (*TunnelCrea /* Untunnel untunnel API */ -func (a *Client) Untunnel(params *UntunnelParams, opts ...ClientOption) (*UntunnelOK, error) { +func (a *Client) Untunnel(params *UntunnelParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UntunnelOK, error) { // TODO: Validate the params before sending if params == nil { params = NewUntunnelParams() @@ -92,6 +93,7 @@ func (a *Client) Untunnel(params *UntunnelParams, opts ...ClientOption) (*Untunn Schemes: []string{"http"}, Params: params, Reader: &UntunnelReader{formats: a.formats}, + AuthInfo: authInfo, Context: params.Context, Client: params.HTTPClient, } diff --git a/rest_server_zrok/embedded_spec.go b/rest_server_zrok/embedded_spec.go index 47d4d012..2f2e896f 100644 --- a/rest_server_zrok/embedded_spec.go +++ b/rest_server_zrok/embedded_spec.go @@ -106,6 +106,11 @@ func init() { }, "/tunnel": { "post": { + "security": [ + { + "key": [] + } + ], "tags": [ "tunnel" ], @@ -137,6 +142,11 @@ func init() { }, "/untunnel": { "delete": { + "security": [ + { + "key": [] + } + ], "tags": [ "tunnel" ], @@ -356,6 +366,11 @@ func init() { }, "/tunnel": { "post": { + "security": [ + { + "key": [] + } + ], "tags": [ "tunnel" ], @@ -387,6 +402,11 @@ func init() { }, "/untunnel": { "delete": { + "security": [ + { + "key": [] + } + ], "tags": [ "tunnel" ], diff --git a/rest_server_zrok/operations/tunnel/tunnel.go b/rest_server_zrok/operations/tunnel/tunnel.go index 587451b9..ccafd0cd 100644 --- a/rest_server_zrok/operations/tunnel/tunnel.go +++ b/rest_server_zrok/operations/tunnel/tunnel.go @@ -9,19 +9,21 @@ import ( "net/http" "github.com/go-openapi/runtime/middleware" + + "github.com/openziti-test-kitchen/zrok/rest_model_zrok" ) // TunnelHandlerFunc turns a function with the right signature into a tunnel handler -type TunnelHandlerFunc func(TunnelParams) middleware.Responder +type TunnelHandlerFunc func(TunnelParams, *rest_model_zrok.Principal) middleware.Responder // Handle executing the request and returning a response -func (fn TunnelHandlerFunc) Handle(params TunnelParams) middleware.Responder { - return fn(params) +func (fn TunnelHandlerFunc) Handle(params TunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { + return fn(params, principal) } // TunnelHandler interface for that can handle valid tunnel params type TunnelHandler interface { - Handle(TunnelParams) middleware.Responder + Handle(TunnelParams, *rest_model_zrok.Principal) middleware.Responder } // NewTunnel creates a new http.Handler for the tunnel operation @@ -45,12 +47,25 @@ func (o *Tunnel) ServeHTTP(rw http.ResponseWriter, r *http.Request) { *r = *rCtx } var Params = NewTunnelParams() + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + *r = *aCtx + } + var principal *rest_model_zrok.Principal + if uprinc != nil { + principal = uprinc.(*rest_model_zrok.Principal) // this is really a rest_model_zrok.Principal, I promise + } + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params o.Context.Respond(rw, r, route.Produces, route, err) return } - res := o.Handler.Handle(Params) // actually handle the request + res := o.Handler.Handle(Params, principal) // actually handle the request o.Context.Respond(rw, r, route.Produces, route, res) } diff --git a/rest_server_zrok/operations/tunnel/untunnel.go b/rest_server_zrok/operations/tunnel/untunnel.go index f0ed59cc..1c4f73df 100644 --- a/rest_server_zrok/operations/tunnel/untunnel.go +++ b/rest_server_zrok/operations/tunnel/untunnel.go @@ -9,19 +9,21 @@ import ( "net/http" "github.com/go-openapi/runtime/middleware" + + "github.com/openziti-test-kitchen/zrok/rest_model_zrok" ) // UntunnelHandlerFunc turns a function with the right signature into a untunnel handler -type UntunnelHandlerFunc func(UntunnelParams) middleware.Responder +type UntunnelHandlerFunc func(UntunnelParams, *rest_model_zrok.Principal) middleware.Responder // Handle executing the request and returning a response -func (fn UntunnelHandlerFunc) Handle(params UntunnelParams) middleware.Responder { - return fn(params) +func (fn UntunnelHandlerFunc) Handle(params UntunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { + return fn(params, principal) } // UntunnelHandler interface for that can handle valid untunnel params type UntunnelHandler interface { - Handle(UntunnelParams) middleware.Responder + Handle(UntunnelParams, *rest_model_zrok.Principal) middleware.Responder } // NewUntunnel creates a new http.Handler for the untunnel operation @@ -45,12 +47,25 @@ func (o *Untunnel) ServeHTTP(rw http.ResponseWriter, r *http.Request) { *r = *rCtx } var Params = NewUntunnelParams() + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + *r = *aCtx + } + var principal *rest_model_zrok.Principal + if uprinc != nil { + principal = uprinc.(*rest_model_zrok.Principal) // this is really a rest_model_zrok.Principal, I promise + } + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params o.Context.Respond(rw, r, route.Produces, route, err) return } - res := o.Handler.Handle(Params) // actually handle the request + res := o.Handler.Handle(Params, principal) // actually handle the request o.Context.Respond(rw, r, route.Produces, route, res) } diff --git a/rest_server_zrok/operations/zrok_api.go b/rest_server_zrok/operations/zrok_api.go index fdd680f1..99fdc953 100644 --- a/rest_server_zrok/operations/zrok_api.go +++ b/rest_server_zrok/operations/zrok_api.go @@ -53,10 +53,10 @@ func NewZrokAPI(spec *loads.Document) *ZrokAPI { IdentityEnableHandler: identity.EnableHandlerFunc(func(params identity.EnableParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation identity.Enable has not yet been implemented") }), - TunnelTunnelHandler: tunnel.TunnelHandlerFunc(func(params tunnel.TunnelParams) middleware.Responder { + TunnelTunnelHandler: tunnel.TunnelHandlerFunc(func(params tunnel.TunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation tunnel.Tunnel has not yet been implemented") }), - TunnelUntunnelHandler: tunnel.UntunnelHandlerFunc(func(params tunnel.UntunnelParams) middleware.Responder { + TunnelUntunnelHandler: tunnel.UntunnelHandlerFunc(func(params tunnel.UntunnelParams, principal *rest_model_zrok.Principal) middleware.Responder { return middleware.NotImplemented("operation tunnel.Untunnel has not yet been implemented") }), MetadataVersionHandler: metadata.VersionHandlerFunc(func(params metadata.VersionParams) middleware.Responder { diff --git a/specs/zrok.yml b/specs/zrok.yml index 7552efe2..587781ae 100644 --- a/specs/zrok.yml +++ b/specs/zrok.yml @@ -57,6 +57,8 @@ paths: post: tags: - tunnel + security: + - key: [] operationId: tunnel parameters: - name: body @@ -76,6 +78,8 @@ paths: delete: tags: - tunnel + security: + - key: [] operationId: untunnel parameters: - name: body