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 1aef09e97..9a22ce004 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 bd31b36b4..9660270ed 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 60fc44384..f32736bbf 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 8991fecd8..a585a6037 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 f32736bbf..2787c62aa 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 000000000..e95039ab8 --- /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 000000000..98bd5dbc3 --- /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 000000000..d2b014d2c --- /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 54710c0ba..cac3da354 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 2787c62aa..d4083724d 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 d4083724d..5e3ba4e81 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 38748e785..e07000bbb 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 000000000..2ec2d80ae --- /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 000000000..a57782dce --- /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 000000000..a2fbf4641 --- /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 b5dc286b7..21d018bcd 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 58539e8b3..335b9b24b 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 c164814e8..d58f32eeb 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 d2b014d2c..45f454a70 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 45f454a70..936d87c48 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 | 336 ++++++++++-------- 1 file changed, 185 insertions(+), 151 deletions(-) diff --git a/endpoints/publicProxy/interstitialUi/index.html b/endpoints/publicProxy/interstitialUi/index.html index 936d87c48..82270dfcf 100644 --- a/endpoints/publicProxy/interstitialUi/index.html +++ b/endpoints/publicProxy/interstitialUi/index.html @@ -4,39 +4,22 @@ - + + zrok -
- - -
-
-

You are about to visit a zrok share served at:

-

+ document.cookie = 'zrok_interstitial = 1; expires=${e}; path=/; SameSite=None'; + window.location.reload(); + } + +
+
+
+
+

You are about to visit a zrok share located 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.
  • -
+
    +
  • This share is made available for free through zrok.
  • +
  • You should only visit this share 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. -

+ +
+
+
+
+

Non-interactive clients:

+
    +
  • This warning can be bypassed by setting the skip_zrok_interstitial HTTP + header with any value set.
  • +
+
+
+
+
+

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.
  • -
+

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 e0b467fab0c20c866d81a6e7fea88cc8d1a4cec0 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:37:20 -0400 Subject: [PATCH 10/17] skip interstitial on drive shares (#704) --- controller/share.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/controller/share.go b/controller/share.go index 21d018bcd..b43088d13 100644 --- a/controller/share.go +++ b/controller/share.go @@ -133,10 +133,15 @@ 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) } } - 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() + var skipInterstitial bool + if backendMode != sdk.DriveBackendMode { + 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() + } + } else { + skipInterstitial = true } shrZId, frontendEndpoints, err = newPublicResourceAllocator().allocate(envZId, shrToken, frontendZIds, frontendTemplates, params, !skipInterstitial, edge) if err != nil { From 3e42d32a503ea82112ed1166f2e228eded6283a3 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:37:43 -0400 Subject: [PATCH 11/17] docs draft (#704) --- docs/guides/self-hosting/interstitial-page.md | 51 ++++++++++++++++++ docs/images/zrok_interstitial_rendezvous.png | Bin 0 -> 28840 bytes etc/frontend.yml | 5 ++ 3 files changed, 56 insertions(+) create mode 100644 docs/guides/self-hosting/interstitial-page.md create mode 100644 docs/images/zrok_interstitial_rendezvous.png diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md new file mode 100644 index 000000000..fbad01e94 --- /dev/null +++ b/docs/guides/self-hosting/interstitial-page.md @@ -0,0 +1,51 @@ +--- +title: Interstitial Page Configuration +sidebar_label: Interstitial Pages +sidebar_position: 18 +--- + +On large zrok installations that support open registration and shared public frontends, abuse can become an issue. In order to mitigate phishing and other similar forms of abuse, zrok offers an interstitial page that announces to the visiting user that the share is hosted through zrok, and probably isn't their financial institution. + +Interstitial pages can be enabled on a per-frontend basis, allowing the interstitial to be enabled on shared public frontends, but not private, closed frontends. The interstitial page requirement can also be overridden on a per-account basis, allowing shares created by specific accounts to bypass the interstitial requirement on frontends that enable it. + +By default, if you do not specifically enable interstitial pages, then your self-hosted service instance will not offer them. + +Let's take a look at how the interstitial pages mechanism works: + +![zrok_interstitial_rendezvous](../../images/zrok_interstitial_rendezvous.png) + +Every zrok share has a _config_ recorded in the underlying OpenZiti network. The config is of type `zrok.proxy.v1`. The frontend uses the information in this config to understand the disposition of the share. The config can contain an `interstitial: true` setting. If the config has this setting, and the frontend is configured to enable interstitial pages, then end users accessing the share will receive the interstitial page on first visit. + +By default the zrok controller will record `interstitial: true` in the share config _unless_ a row is present in the `skip_interstitial_grants` table in the underlying database. The `skip_interstitial_grants` table is a basic SQL structure that allows inserting a row per account. + +``` +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) +); +``` + +If an account has a row present in this table when creating a share, then the controller will write `interstitial: false` into the config for the share, which will bypass the interstitial regardless of frontend configuration. + +The frontend config looks like this: + +``` +# Setting the `interstitial` setting to `true` will allow this frontend +# to offer interstitial pages if they are configured on the share by the +# controller. +# +#interstitial: true +``` + +Simply setting `interstitial: true` in the controller config will allow the configured frontend to offer interstitial pages. + +## Bypassing the Interstitial + +End users can offer an HTTP header of `skip_zrok_interstitial`, set to any value to bypass the interstitial page. Setting this header means that the user most likely understands what a zrok share is and will hopefully not fall for a phishing attack. + +This header is especially useful for API clients (like `curl`). \ No newline at end of file diff --git a/docs/images/zrok_interstitial_rendezvous.png b/docs/images/zrok_interstitial_rendezvous.png new file mode 100644 index 0000000000000000000000000000000000000000..4830af0d22def81aff5281c0c9b2884462b78021 GIT binary patch literal 28840 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 literal 0 HcmV?d00001 diff --git a/etc/frontend.yml b/etc/frontend.yml index ad90a9ffd..7ea7e8616 100644 --- a/etc/frontend.yml +++ b/etc/frontend.yml @@ -10,6 +10,11 @@ v: 3 # #host_match: zrok.io +# Setting the `interstitial` setting to `true` will allow this frontend to offer interstitial pages if they are +# configured on the share by the controller. +# +#interstitial: true + # The OAuth configuration is used when enabling OAuth authentication with your public frontend. # #oauth: From 8ed89d3400dfb01221b1d65158c201435411ece3 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:43:42 -0400 Subject: [PATCH 12/17] doc update (#704) --- docs/guides/self-hosting/interstitial-page.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md index fbad01e94..a32a04f30 100644 --- a/docs/guides/self-hosting/interstitial-page.md +++ b/docs/guides/self-hosting/interstitial-page.md @@ -6,17 +6,19 @@ sidebar_position: 18 On large zrok installations that support open registration and shared public frontends, abuse can become an issue. In order to mitigate phishing and other similar forms of abuse, zrok offers an interstitial page that announces to the visiting user that the share is hosted through zrok, and probably isn't their financial institution. -Interstitial pages can be enabled on a per-frontend basis, allowing the interstitial to be enabled on shared public frontends, but not private, closed frontends. The interstitial page requirement can also be overridden on a per-account basis, allowing shares created by specific accounts to bypass the interstitial requirement on frontends that enable it. +Interstitial pages can be enabled on a per-frontend basis. This allows the interstitial to be enabled on open public frontends, but not closed public frontends (closed public frontends require a grant to use). + +The interstitial page requirement can also be overridden on a per-account basis, allowing shares created by specific accounts to bypass the interstitial requirement on frontends that enable it. This facilitates building infrastructure that grants trusted users additional privileges. By default, if you do not specifically enable interstitial pages, then your self-hosted service instance will not offer them. -Let's take a look at how the interstitial pages mechanism works: +Let's take a look at how the interstitial pages mechanism works. The following diagram shows the share configuration rendezvous made between the zrok controller and a zrok frontend: ![zrok_interstitial_rendezvous](../../images/zrok_interstitial_rendezvous.png) Every zrok share has a _config_ recorded in the underlying OpenZiti network. The config is of type `zrok.proxy.v1`. The frontend uses the information in this config to understand the disposition of the share. The config can contain an `interstitial: true` setting. If the config has this setting, and the frontend is configured to enable interstitial pages, then end users accessing the share will receive the interstitial page on first visit. -By default the zrok controller will record `interstitial: true` in the share config _unless_ a row is present in the `skip_interstitial_grants` table in the underlying database. The `skip_interstitial_grants` table is a basic SQL structure that allows inserting a row per account. +By default the zrok controller will record `interstitial: true` in the share config _unless_ a row is present in the `skip_interstitial_grants` table in the underlying database for the account creating the share. The `skip_interstitial_grants` table is a basic SQL structure that allows inserting a row per account. ``` create table skip_interstitial_grants ( @@ -30,9 +32,9 @@ create table skip_interstitial_grants ( ); ``` -If an account has a row present in this table when creating a share, then the controller will write `interstitial: false` into the config for the share, which will bypass the interstitial regardless of frontend configuration. +If an account has a row present in this table when creating a share, then the controller will write `interstitial: false` into the config for the share, which will bypass the interstitial regardless of frontend configuration. The `skip_interstitial_grants` controls what the zrok controller will store in the share config when creating the share. -The frontend config looks like this: +The frontend configuration controls what the frontend will do with the share config it finds in OpenZiti. The new stanza looks like this: ``` # Setting the `interstitial` setting to `true` will allow this frontend @@ -42,7 +44,7 @@ The frontend config looks like this: #interstitial: true ``` -Simply setting `interstitial: true` in the controller config will allow the configured frontend to offer interstitial pages. +Simply setting `interstitial: true` in the controller config will allow the configured frontend to offer an interstitial page if the share config enables the interstitial page for that share. ## Bypassing the Interstitial From 7d3079a3f2dd7461f55fc6a76cefb8093850efff Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:45:39 -0400 Subject: [PATCH 13/17] docs (#704) --- docs/guides/self-hosting/interstitial-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md index a32a04f30..217bc0799 100644 --- a/docs/guides/self-hosting/interstitial-page.md +++ b/docs/guides/self-hosting/interstitial-page.md @@ -10,7 +10,7 @@ Interstitial pages can be enabled on a per-frontend basis. This allows the inter The interstitial page requirement can also be overridden on a per-account basis, allowing shares created by specific accounts to bypass the interstitial requirement on frontends that enable it. This facilitates building infrastructure that grants trusted users additional privileges. -By default, if you do not specifically enable interstitial pages, then your self-hosted service instance will not offer them. +By default, if you do not specifically enable interstitial pages on a public frontend, then your self-hosted service instance will not offer them. Let's take a look at how the interstitial pages mechanism works. The following diagram shows the share configuration rendezvous made between the zrok controller and a zrok frontend: From ace8bae54f47b37ce08ce9ee228c825c84be2b52 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:49:50 -0400 Subject: [PATCH 14/17] docs (#704) --- docs/guides/self-hosting/interstitial-page.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md index 217bc0799..054eee766 100644 --- a/docs/guides/self-hosting/interstitial-page.md +++ b/docs/guides/self-hosting/interstitial-page.md @@ -6,7 +6,7 @@ sidebar_position: 18 On large zrok installations that support open registration and shared public frontends, abuse can become an issue. In order to mitigate phishing and other similar forms of abuse, zrok offers an interstitial page that announces to the visiting user that the share is hosted through zrok, and probably isn't their financial institution. -Interstitial pages can be enabled on a per-frontend basis. This allows the interstitial to be enabled on open public frontends, but not closed public frontends (closed public frontends require a grant to use). +Interstitial pages can be enabled on a per-frontend basis. This allows the interstitial to be enabled on open public frontends but not closed public frontends (closed public frontends require a grant to use). The interstitial page requirement can also be overridden on a per-account basis, allowing shares created by specific accounts to bypass the interstitial requirement on frontends that enable it. This facilitates building infrastructure that grants trusted users additional privileges. @@ -48,6 +48,10 @@ Simply setting `interstitial: true` in the controller config will allow the conf ## Bypassing the Interstitial +The interstitial page will be presented unless the client shows up with a `zrok_interstitial` cookie. When the user is presented with the interstitial page, there is a button they can click which sets the necessary cookie and allows them to visit the site. The cookie is set to expire in one week. + End users can offer an HTTP header of `skip_zrok_interstitial`, set to any value to bypass the interstitial page. Setting this header means that the user most likely understands what a zrok share is and will hopefully not fall for a phishing attack. -This header is especially useful for API clients (like `curl`). \ No newline at end of file +The `skip_zrok_interstitial` header is especially useful for API clients (like `curl`) and other types of non-interactive clients. + +The `drive` backend mode does not currently support `GET` requests and cannot be accessed with a conventional web browser, so it bypasses the interstitial page requirement. \ No newline at end of file From 6da6cbc4c6d73aa6c5641adc4042af767db03d21 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 11:50:25 -0400 Subject: [PATCH 15/17] lint (#704) --- docs/guides/self-hosting/interstitial-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md index 054eee766..aaafda803 100644 --- a/docs/guides/self-hosting/interstitial-page.md +++ b/docs/guides/self-hosting/interstitial-page.md @@ -1,5 +1,5 @@ --- -title: Interstitial Page Configuration +title: Interstitial Pages sidebar_label: Interstitial Pages sidebar_position: 18 --- From 55605aad772f4a5b1f050e5b568765d30d2041e2 Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 12:53:24 -0400 Subject: [PATCH 16/17] changelog (#704) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 498491801..72d26e1fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## v0.4.36 +FEATURE: New interstitial pages that can be enabled per-frontend, and disabled per-account (https://github.com/openziti/zrok/issues/704) + CHANGE: Enable `"declaration": true` in `tsconfig.json` for Node SDK. ## v0.4.35 From e41eea770426247846c10666572b84400afb595b Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 25 Jul 2024 13:52:15 -0400 Subject: [PATCH 17/17] typo (#704) --- docs/guides/self-hosting/interstitial-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/self-hosting/interstitial-page.md b/docs/guides/self-hosting/interstitial-page.md index aaafda803..31de66647 100644 --- a/docs/guides/self-hosting/interstitial-page.md +++ b/docs/guides/self-hosting/interstitial-page.md @@ -44,7 +44,7 @@ The frontend configuration controls what the frontend will do with the share con #interstitial: true ``` -Simply setting `interstitial: true` in the controller config will allow the configured frontend to offer an interstitial page if the share config enables the interstitial page for that share. +Simply setting `interstitial: true` in the frontend config will allow the configured frontend to offer an interstitial page if the share config enables the interstitial page for that share. ## Bypassing the Interstitial