From ed1b30aa2ceb323f2b3fb6ca275e27babc2e7f55 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Mon, 22 Jul 2024 12:34:42 -0400 Subject: [PATCH 01/17] proxy components naming (#704) --- endpoints/proxy/backend.go | 2 +- endpoints/proxy/frontend.go | 2 +- endpoints/publicProxy/http.go | 4 ++-- util/proxy.go | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/endpoints/proxy/backend.go b/endpoints/proxy/backend.go index 1aef09e9..9a22ce00 100644 --- a/endpoints/proxy/backend.go +++ b/endpoints/proxy/backend.go @@ -52,7 +52,7 @@ func NewBackend(cfg *BackendConfig) (*Backend, error) { return nil, err } - handler := util.NewProxyHandler(proxy) + handler := util.NewRequestsWrapper(proxy) return &Backend{ cfg: cfg, listener: listener, diff --git a/endpoints/proxy/frontend.go b/endpoints/proxy/frontend.go index bd31b36b..9660270e 100644 --- a/endpoints/proxy/frontend.go +++ b/endpoints/proxy/frontend.go @@ -68,7 +68,7 @@ func NewFrontend(cfg *FrontendConfig) (*Frontend, error) { } proxy.Transport = zTransport - handler := authHandler(cfg.ShrToken, util.NewProxyHandler(proxy), "zrok", cfg, zCtx) + handler := authHandler(cfg.ShrToken, util.NewRequestsWrapper(proxy), "zrok", cfg, zCtx) return &Frontend{ cfg: cfg, zCtx: zCtx, diff --git a/endpoints/publicProxy/http.go b/endpoints/publicProxy/http.go index 60fc4438..f32736bb 100644 --- a/endpoints/publicProxy/http.go +++ b/endpoints/publicProxy/http.go @@ -73,7 +73,7 @@ func NewHTTP(cfg *Config) (*HttpFrontend, error) { if err := configureOauthHandlers(context.Background(), cfg, cfg.Tls != nil); err != nil { return nil, err } - handler := authHandler(util.NewProxyHandler(proxy), cfg, key, zCtx) + handler := shareHandler(util.NewRequestsWrapper(proxy), cfg, key, zCtx) return &HttpFrontend{ cfg: cfg, zCtx: zCtx, @@ -151,7 +151,7 @@ func hostTargetReverseProxy(cfg *Config, ctx ziti.Context) *httputil.ReverseProx return &httputil.ReverseProxy{Director: director} } -func authHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Context) http.HandlerFunc { +func shareHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Context) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { shrToken := resolveService(pcfg.HostMatch, r.Host) if shrToken != "" { diff --git a/util/proxy.go b/util/proxy.go index 8991fecd..a585a603 100644 --- a/util/proxy.go +++ b/util/proxy.go @@ -6,13 +6,13 @@ import ( "sync/atomic" ) -type proxyHandler struct { +type requestsWrapper struct { proxy *httputil.ReverseProxy requests int32 } -func NewProxyHandler(proxy *httputil.ReverseProxy) *proxyHandler { - handler := &proxyHandler{proxy: proxy} +func NewRequestsWrapper(proxy *httputil.ReverseProxy) *requestsWrapper { + handler := &requestsWrapper{proxy: proxy} director := proxy.Director proxy.Director = func(req *http.Request) { @@ -23,10 +23,10 @@ func NewProxyHandler(proxy *httputil.ReverseProxy) *proxyHandler { return handler } -func (self *proxyHandler) Requests() int32 { +func (self *requestsWrapper) Requests() int32 { return atomic.LoadInt32(&self.requests) } -func (self *proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (self *requestsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) { self.proxy.ServeHTTP(w, r) } From b7423ca59ec7c88afc14f88ad38e5d48e087cf63 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Tue, 23 Jul 2024 13:39:17 -0400 Subject: [PATCH 02/17] minimum viable interstitial (#704) --- endpoints/publicProxy/http.go | 10 +++++++++ endpoints/publicProxy/interstitialUi/embed.go | 6 ++++++ .../publicProxy/interstitialUi/handler.go | 21 +++++++++++++++++++ .../publicProxy/interstitialUi/index.html | 13 ++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 endpoints/publicProxy/interstitialUi/embed.go create mode 100644 endpoints/publicProxy/interstitialUi/handler.go create mode 100644 endpoints/publicProxy/interstitialUi/index.html diff --git a/endpoints/publicProxy/http.go b/endpoints/publicProxy/http.go index f32736bb..2787c62a 100644 --- a/endpoints/publicProxy/http.go +++ b/endpoints/publicProxy/http.go @@ -9,6 +9,7 @@ import ( "github.com/openziti/sdk-golang/ziti" "github.com/openziti/zrok/endpoints" "github.com/openziti/zrok/endpoints/publicProxy/healthUi" + "github.com/openziti/zrok/endpoints/publicProxy/interstitialUi" "github.com/openziti/zrok/endpoints/publicProxy/notFoundUi" "github.com/openziti/zrok/endpoints/publicProxy/unauthorizedUi" "github.com/openziti/zrok/environment" @@ -157,6 +158,15 @@ func shareHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Conte if shrToken != "" { if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found { if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found { + + ignore := r.Header.Get("zrok_interstitial") + _, zrokOkErr := r.Cookie("zrok_interstitial") + if ignore == "" && zrokOkErr != nil { + logrus.Infof("forcing interstitial for: %v", r.URL) + interstitialUi.WriteInterstitialAnnounce(w) + return + } + if scheme, found := cfg["auth_scheme"]; found { switch scheme { case string(sdk.None): diff --git a/endpoints/publicProxy/interstitialUi/embed.go b/endpoints/publicProxy/interstitialUi/embed.go new file mode 100644 index 00000000..e95039ab --- /dev/null +++ b/endpoints/publicProxy/interstitialUi/embed.go @@ -0,0 +1,6 @@ +package interstitialUi + +import "embed" + +//go:embed index.html +var FS embed.FS diff --git a/endpoints/publicProxy/interstitialUi/handler.go b/endpoints/publicProxy/interstitialUi/handler.go new file mode 100644 index 00000000..98bd5dbc --- /dev/null +++ b/endpoints/publicProxy/interstitialUi/handler.go @@ -0,0 +1,21 @@ +package interstitialUi + +import ( + "github.com/sirupsen/logrus" + "net/http" +) + +func WriteInterstitialAnnounce(w http.ResponseWriter) { + if data, err := FS.ReadFile("index.html"); err == nil { + w.WriteHeader(http.StatusOK) + n, err := w.Write(data) + if n != len(data) { + logrus.Errorf("short write") + return + } + if err != nil { + logrus.Error(err) + return + } + } +} diff --git a/endpoints/publicProxy/interstitialUi/index.html b/endpoints/publicProxy/interstitialUi/index.html new file mode 100644 index 00000000..d2b014d2 --- /dev/null +++ b/endpoints/publicProxy/interstitialUi/index.html @@ -0,0 +1,13 @@ + + + + +

this is a zrok share!

+ + + \ No newline at end of file From 2e3d6a627f92611c3750c47cc87fc82d41b41af7 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 10:43:22 -0400 Subject: [PATCH 03/17] frontend config for interstitial enable/disable; zrok.proxy.v1 support for interstitial enablement (#704) --- endpoints/publicProxy/config.go | 18 ++++++++++-------- endpoints/publicProxy/http.go | 17 ++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/endpoints/publicProxy/config.go b/endpoints/publicProxy/config.go index 54710c0b..cac3da35 100644 --- a/endpoints/publicProxy/config.go +++ b/endpoints/publicProxy/config.go @@ -12,12 +12,13 @@ import ( const V = 3 type Config struct { - V int - Identity string - Address string - HostMatch string - Oauth *OauthConfig - Tls *endpoints.TlsConfig + V int + Identity string + Address string + HostMatch string + Interstitial bool + Oauth *OauthConfig + Tls *endpoints.TlsConfig } type OauthConfig struct { @@ -45,8 +46,9 @@ type OauthProviderConfig struct { func DefaultConfig() *Config { return &Config{ - Identity: "public", - Address: "0.0.0.0:8080", + Identity: "public", + Address: "0.0.0.0:8080", + Interstitial: false, } } diff --git a/endpoints/publicProxy/http.go b/endpoints/publicProxy/http.go index 2787c62a..d4083724 100644 --- a/endpoints/publicProxy/http.go +++ b/endpoints/publicProxy/http.go @@ -158,13 +158,16 @@ func shareHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Conte if shrToken != "" { if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found { if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found { - - ignore := r.Header.Get("zrok_interstitial") - _, zrokOkErr := r.Cookie("zrok_interstitial") - if ignore == "" && zrokOkErr != nil { - logrus.Infof("forcing interstitial for: %v", r.URL) - interstitialUi.WriteInterstitialAnnounce(w) - return + if pcfg.Interstitial { + if _, istlFound := cfg["interstitial"]; istlFound { + skip := r.Header.Get("skip_zrok_interstitial") + _, zrokOkErr := r.Cookie("zrok_interstitial") + if skip == "" && zrokOkErr != nil { + logrus.Debugf("forcing interstitial for '%v'", r.URL) + interstitialUi.WriteInterstitialAnnounce(w) + return + } + } } if scheme, found := cfg["auth_scheme"]; found { From 2755422a29bb2ee013b8b47e4cdfbdbcfae1af7d Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 10:47:12 -0400 Subject: [PATCH 04/17] iteration (#704) --- endpoints/publicProxy/http.go | 16 +++++++++------- sdk/golang/sdk/config.go | 11 +++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/endpoints/publicProxy/http.go b/endpoints/publicProxy/http.go index d4083724..5e3ba4e8 100644 --- a/endpoints/publicProxy/http.go +++ b/endpoints/publicProxy/http.go @@ -159,13 +159,15 @@ func shareHandler(handler http.Handler, pcfg *Config, key []byte, ctx ziti.Conte if svc, found := endpoints.GetRefreshedService(shrToken, ctx); found { if cfg, found := svc.Config[sdk.ZrokProxyConfig]; found { if pcfg.Interstitial { - if _, istlFound := cfg["interstitial"]; istlFound { - skip := r.Header.Get("skip_zrok_interstitial") - _, zrokOkErr := r.Cookie("zrok_interstitial") - if skip == "" && zrokOkErr != nil { - logrus.Debugf("forcing interstitial for '%v'", r.URL) - interstitialUi.WriteInterstitialAnnounce(w) - return + if v, istlFound := cfg["interstitial"]; istlFound { + if istlEnabled, ok := v.(bool); ok && istlEnabled { + skip := r.Header.Get("skip_zrok_interstitial") + _, zrokOkErr := r.Cookie("zrok_interstitial") + if skip == "" && zrokOkErr != nil { + logrus.Debugf("forcing interstitial for '%v'", r.URL) + interstitialUi.WriteInterstitialAnnounce(w) + return + } } } } diff --git a/sdk/golang/sdk/config.go b/sdk/golang/sdk/config.go index 38748e78..e07000bb 100644 --- a/sdk/golang/sdk/config.go +++ b/sdk/golang/sdk/config.go @@ -1,13 +1,16 @@ package sdk -import "github.com/pkg/errors" +import ( + "github.com/pkg/errors" +) const ZrokProxyConfig = "zrok.proxy.v1" type FrontendConfig struct { - AuthScheme AuthScheme `json:"auth_scheme"` - BasicAuth *BasicAuthConfig `json:"basic_auth"` - OauthAuth *OauthConfig `json:"oauth"` + Interstitial bool `json:"interstitial"` + AuthScheme AuthScheme `json:"auth_scheme"` + BasicAuth *BasicAuthConfig `json:"basic_auth"` + OauthAuth *OauthConfig `json:"oauth"` } type BasicAuthConfig struct { From 275666c2b23f3e8d8b80752e258d0c0a3090e649 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 11:16:36 -0400 Subject: [PATCH 05/17] skip_interstitial_grants sql structure (#704) --- controller/store/skipInterstitialGrant.go | 18 ++++++++++++++++++ .../029_v0_4_36_skip_interstitial_grants.sql | 13 +++++++++++++ .../029_v0_4_36_skip_interstitial_grants.sql | 13 +++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 controller/store/skipInterstitialGrant.go create mode 100644 controller/store/sql/postgresql/029_v0_4_36_skip_interstitial_grants.sql create mode 100644 controller/store/sql/sqlite3/029_v0_4_36_skip_interstitial_grants.sql diff --git a/controller/store/skipInterstitialGrant.go b/controller/store/skipInterstitialGrant.go new file mode 100644 index 00000000..2ec2d80a --- /dev/null +++ b/controller/store/skipInterstitialGrant.go @@ -0,0 +1,18 @@ +package store + +import ( + "github.com/jmoiron/sqlx" + "github.com/pkg/errors" +) + +func (str *Store) IsAccountGrantedSkipInterstitial(acctId int, trx *sqlx.Tx) (bool, error) { + stmt, err := trx.Prepare("select count(0) from skip_interstitial_grants where account_id = $1") + if err != nil { + return false, errors.Wrap(err, "error preparing skip_interstitial_grants select statement") + } + var count int + if err := stmt.QueryRow(acctId).Scan(&count); err != nil { + return false, errors.Wrap(err, "error querying skip_interstitial_grants count") + } + return count > 0, nil +} diff --git a/controller/store/sql/postgresql/029_v0_4_36_skip_interstitial_grants.sql b/controller/store/sql/postgresql/029_v0_4_36_skip_interstitial_grants.sql new file mode 100644 index 00000000..a57782dc --- /dev/null +++ b/controller/store/sql/postgresql/029_v0_4_36_skip_interstitial_grants.sql @@ -0,0 +1,13 @@ +-- +migrate Up + +create table skip_interstitial_grants ( + id serial primary key, + + account_id integer references accounts (id) not null, + + created_at timestamptz not null default(current_timestamp), + updated_at timestamptz not null default(current_timestamp), + deleted boolean not null default(false) +); + +create index skip_interstitial_grants_id_idx on skip_interstitial_grants (account_id); \ No newline at end of file diff --git a/controller/store/sql/sqlite3/029_v0_4_36_skip_interstitial_grants.sql b/controller/store/sql/sqlite3/029_v0_4_36_skip_interstitial_grants.sql new file mode 100644 index 00000000..a2fbf464 --- /dev/null +++ b/controller/store/sql/sqlite3/029_v0_4_36_skip_interstitial_grants.sql @@ -0,0 +1,13 @@ +-- +migrate Up + +create table skip_interstitial_grants ( + id integer primary key, + + account_id integer references accounts (id) not null, + + created_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), + updated_at datetime not null default(strftime('%Y-%m-%d %H:%M:%f', 'now')), + deleted boolean not null default(false) +); + +create index skip_interstitial_grants_id_idx on skip_interstitial_grants (account_id); \ No newline at end of file From d593232cf67f3f17b6203647320233c7823d4278 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 11:28:20 -0400 Subject: [PATCH 06/17] wire skip interstitial into public share config (#704) --- controller/share.go | 7 ++++++- controller/sharePublic.go | 3 ++- controller/zrokEdgeSdk/config.go | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/controller/share.go b/controller/share.go index b5dc286b..21d018bc 100644 --- a/controller/share.go +++ b/controller/share.go @@ -133,7 +133,12 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr logrus.Infof("added frontend selection '%v' with ziti identity '%v' for share '%v'", frontendSelection, sfe.ZId, shrToken) } } - shrZId, frontendEndpoints, err = newPublicResourceAllocator().allocate(envZId, shrToken, frontendZIds, frontendTemplates, params, edge) + skipInterstitial, err := str.IsAccountGrantedSkipInterstitial(int(principal.ID), trx) + if err != nil { + logrus.Errorf("error checking skip interstitial for account '%v': %v", principal.Email, err) + return share.NewShareInternalServerError() + } + shrZId, frontendEndpoints, err = newPublicResourceAllocator().allocate(envZId, shrToken, frontendZIds, frontendTemplates, params, !skipInterstitial, edge) if err != nil { logrus.Error(err) return share.NewShareInternalServerError() diff --git a/controller/sharePublic.go b/controller/sharePublic.go index 58539e8b..335b9b24 100644 --- a/controller/sharePublic.go +++ b/controller/sharePublic.go @@ -13,7 +13,7 @@ func newPublicResourceAllocator() *publicResourceAllocator { return &publicResourceAllocator{} } -func (a *publicResourceAllocator) allocate(envZId, shrToken string, frontendZIds, frontendTemplates []string, params share.ShareParams, edge *rest_management_api_client.ZitiEdgeManagement) (shrZId string, frontendEndpoints []string, err error) { +func (a *publicResourceAllocator) allocate(envZId, shrToken string, frontendZIds, frontendTemplates []string, params share.ShareParams, interstitial bool, edge *rest_management_api_client.ZitiEdgeManagement) (shrZId string, frontendEndpoints []string, err error) { var authUsers []*sdk.AuthUserConfig for _, authUser := range params.Body.AuthUsers { authUsers = append(authUsers, &sdk.AuthUserConfig{Username: authUser.Username, Password: authUser.Password}) @@ -23,6 +23,7 @@ func (a *publicResourceAllocator) allocate(envZId, shrToken string, frontendZIds return "", nil, err } options := &zrokEdgeSdk.FrontendOptions{ + Interstitial: interstitial, AuthScheme: authScheme, BasicAuthUsers: authUsers, Oauth: &sdk.OauthConfig{ diff --git a/controller/zrokEdgeSdk/config.go b/controller/zrokEdgeSdk/config.go index c164814e..d58f32ee 100644 --- a/controller/zrokEdgeSdk/config.go +++ b/controller/zrokEdgeSdk/config.go @@ -12,6 +12,7 @@ import ( ) type FrontendOptions struct { + Interstitial bool AuthScheme sdk.AuthScheme BasicAuthUsers []*sdk.AuthUserConfig Oauth *sdk.OauthConfig @@ -19,7 +20,8 @@ type FrontendOptions struct { func CreateConfig(cfgTypeZId, envZId, shrToken string, options *FrontendOptions, edge *rest_management_api_client.ZitiEdgeManagement) (cfgZId string, err error) { cfg := &sdk.FrontendConfig{ - AuthScheme: options.AuthScheme, + Interstitial: options.Interstitial, + AuthScheme: options.AuthScheme, } if cfg.AuthScheme == sdk.Basic { cfg.BasicAuth = &sdk.BasicAuthConfig{} From 23a9be0a408583f0898208a077cbe0a891fd1809 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 14:09:06 -0400 Subject: [PATCH 07/17] interim interstitial page layout (#704) --- .../publicProxy/interstitialUi/index.html | 210 +++++++++++++++++- 1 file changed, 206 insertions(+), 4 deletions(-) diff --git a/endpoints/publicProxy/interstitialUi/index.html b/endpoints/publicProxy/interstitialUi/index.html index d2b014d2..45f454a7 100644 --- a/endpoints/publicProxy/interstitialUi/index.html +++ b/endpoints/publicProxy/interstitialUi/index.html @@ -1,13 +1,215 @@ + + + + + + + + + zrok + + + +
+ - -

this is a zrok share!

- - +
+
+

You are about to visit a zrok share served at:

+

+ +
    +
  • This share is made available for free through zrok.
  • +
  • You should only visit this shared website if you trust whoever sent you the link.
  • +
  • Be careful about disclosing any personal or financial information like passwords, phone numbers, or credit cards.
  • +
+ + +
+
+

Are you the owner of this zrok share?

+

+ We display this page to prevent abuse of zrok shares. Visitors to your share will only see it once. +

+ +

To remove this page:

+
    +
  • If you are using the global zrok service at zrok.io, you can upgrade to any paid account to have this + page removed.
  • +
  • If you are using a zrok instance hosted elsewhere, contact the administrator of your instance for + options to have this page removed.
  • +
  • If you are operating a self-hosted zrok instance, see the documentation for configuration options + to remove the interstitial page.
  • +
+
+
+
+ + \ No newline at end of file From 607ba8b69e3e79da85279672cb2084d6855106fa Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Wed, 24 Jul 2024 14:23:18 -0400 Subject: [PATCH 08/17] samesite; expiration; path (#704) --- endpoints/publicProxy/interstitialUi/index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/endpoints/publicProxy/interstitialUi/index.html b/endpoints/publicProxy/interstitialUi/index.html index 45f454a7..936d87c4 100644 --- a/endpoints/publicProxy/interstitialUi/index.html +++ b/endpoints/publicProxy/interstitialUi/index.html @@ -173,7 +173,8 @@ From c3cf0f866845c99f489328eef40fd405f21112d2 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:02:03 -0400 Subject: [PATCH 09/17] responsive, updated interstitial layout (#704) --- .../publicProxy/interstitialUi/index.html | 340 ++++++++++-------- 1 file changed, 187 insertions(+), 153 deletions(-) diff --git a/endpoints/publicProxy/interstitialUi/index.html b/endpoints/publicProxy/interstitialUi/index.html index 936d87c4..82270dfc 100644 --- a/endpoints/publicProxy/interstitialUi/index.html +++ b/endpoints/publicProxy/interstitialUi/index.html @@ -4,39 +4,22 @@ - + + zrok -
-