mirror of
https://github.com/openziti/zrok.git
synced 2024-11-29 03:24:15 +01:00
Merge branch 'main' into snyk-upgrade-d8c6f5b4c55065b4ec64d776fcbd3a56
This commit is contained in:
commit
d2e8da8b2c
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,5 +1,23 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v0.4.33
|
||||||
|
|
||||||
|
CHANGE: Updated react-bootstrap to version 2.10.2.
|
||||||
|
|
||||||
|
CHANGE: Updated @mui/material to version 5.15.18.
|
||||||
|
|
||||||
|
## v0.4.32
|
||||||
|
|
||||||
|
FEATURE: New permission mode support for public frontends. Open permission mode frontends are available to all users in the service instance. Closed permission mode frontends reference the new `frontend_grants` table that can be used to control which accounts are allowed to create shares using that frontend. `zrok admin create frontend` now supports `--closed` flag to create closed permission mode frontends (https://github.com/openziti/zrok/issues/539)
|
||||||
|
|
||||||
|
FEATURE: New config `defaultFrontend` that specifies the default frontend to be used for an environment. Provides the default `--frontend` for `zrok share public` and `zrok reserve public` (https://github.com/openziti/zrok/issues/663)
|
||||||
|
|
||||||
|
FEATURE: Resource count limits now include `share_frontends` to limit the number of frontends that are allowed to make connections to a share (https://github.com/openziti/zrok/issues/650)
|
||||||
|
|
||||||
|
CHANGE: The frontend selection flag used by `zrok share public` and `zrok reserve public` has been changed from `--frontends` to `--frontend`
|
||||||
|
|
||||||
|
FIX: use controller config spec v4 in the Docker instance
|
||||||
|
|
||||||
## v0.4.31
|
## v0.4.31
|
||||||
|
|
||||||
FEATURE: New "limits classes" limits implementation (https://github.com/openziti/zrok/issues/606). This new feature allows for extensive limits customization on a per-user basis, with fallback to the global defaults in the controller configuration.
|
FEATURE: New "limits classes" limits implementation (https://github.com/openziti/zrok/issues/606). This new feature allows for extensive limits customization on a per-user basis, with fallback to the global defaults in the controller configuration.
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/openziti/zrok/environment"
|
"github.com/openziti/zrok/environment"
|
||||||
"github.com/openziti/zrok/rest_client_zrok/admin"
|
"github.com/openziti/zrok/rest_client_zrok/admin"
|
||||||
"github.com/openziti/zrok/rest_model_zrok"
|
"github.com/openziti/zrok/rest_model_zrok"
|
||||||
|
"github.com/openziti/zrok/sdk/golang/sdk"
|
||||||
"github.com/openziti/zrok/tui"
|
"github.com/openziti/zrok/tui"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -16,6 +17,7 @@ func init() {
|
|||||||
|
|
||||||
type adminCreateFrontendCommand struct {
|
type adminCreateFrontendCommand struct {
|
||||||
cmd *cobra.Command
|
cmd *cobra.Command
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAdminCreateFrontendCommand() *adminCreateFrontendCommand {
|
func newAdminCreateFrontendCommand() *adminCreateFrontendCommand {
|
||||||
@ -25,6 +27,7 @@ func newAdminCreateFrontendCommand() *adminCreateFrontendCommand {
|
|||||||
Args: cobra.ExactArgs(3),
|
Args: cobra.ExactArgs(3),
|
||||||
}
|
}
|
||||||
command := &adminCreateFrontendCommand{cmd: cmd}
|
command := &adminCreateFrontendCommand{cmd: cmd}
|
||||||
|
cmd.Flags().BoolVar(&command.closed, "closed", false, "Enabled closed permission mode")
|
||||||
cmd.Run = command.run
|
cmd.Run = command.run
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
@ -44,11 +47,16 @@ func (cmd *adminCreateFrontendCommand) run(_ *cobra.Command, args []string) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
permissionMode := sdk.OpenPermissionMode
|
||||||
|
if cmd.closed {
|
||||||
|
permissionMode = sdk.ClosedPermissionMode
|
||||||
|
}
|
||||||
req := admin.NewCreateFrontendParams()
|
req := admin.NewCreateFrontendParams()
|
||||||
req.Body = &rest_model_zrok.CreateFrontendRequest{
|
req.Body = &rest_model_zrok.CreateFrontendRequest{
|
||||||
ZID: zId,
|
ZID: zId,
|
||||||
PublicName: publicName,
|
PublicName: publicName,
|
||||||
URLTemplate: urlTemplate,
|
URLTemplate: urlTemplate,
|
||||||
|
PermissionMode: string(permissionMode),
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := zrok.Admin.CreateFrontend(req, mustGetAdminAuth())
|
resp, err := zrok.Admin.CreateFrontend(req, mustGetAdminAuth())
|
||||||
|
@ -40,6 +40,12 @@ func (cmd *configGetCommand) run(_ *cobra.Command, args []string) {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Println("apiEndpoint = <unset>")
|
fmt.Println("apiEndpoint = <unset>")
|
||||||
}
|
}
|
||||||
|
case "defaultFrontend":
|
||||||
|
if env.Config() != nil && env.Config().DefaultFrontend != "" {
|
||||||
|
fmt.Printf("defaultFrontend = %v\n", env.Config().DefaultFrontend)
|
||||||
|
} else {
|
||||||
|
fmt.Println("defaultFrontend = <unset>")
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fmt.Printf("unknown config name '%v'\n", configName)
|
fmt.Printf("unknown config name '%v'\n", configName)
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,20 @@ func (cmd *configSetCommand) run(_ *cobra.Command, args []string) {
|
|||||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "defaultFrontend":
|
||||||
|
if env.Config() == nil {
|
||||||
|
if err := env.SetConfig(&env_core.Config{DefaultFrontend: value}); err != nil {
|
||||||
|
tui.Error("unable to save config", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg := env.Config()
|
||||||
|
cfg.DefaultFrontend = value
|
||||||
|
if err := env.SetConfig(cfg); err != nil {
|
||||||
|
tui.Error("unable to save config", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("zrok configuration updated")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Printf("unknown config name '%v'\n", configName)
|
fmt.Printf("unknown config name '%v'\n", configName)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/openziti/zrok/environment"
|
"github.com/openziti/zrok/environment"
|
||||||
"github.com/openziti/zrok/environment/env_core"
|
|
||||||
"github.com/openziti/zrok/tui"
|
"github.com/openziti/zrok/tui"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"os"
|
"os"
|
||||||
@ -36,18 +35,25 @@ func (cmd *configUnsetCommand) run(_ *cobra.Command, args []string) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if env.Config() != nil {
|
||||||
|
cfg := env.Config()
|
||||||
switch configName {
|
switch configName {
|
||||||
case "apiEndpoint":
|
case "apiEndpoint":
|
||||||
if err := env.SetConfig(&env_core.Config{}); err != nil {
|
cfg.ApiEndpoint = ""
|
||||||
tui.Error("unable to save config", err)
|
|
||||||
}
|
|
||||||
fmt.Println("zrok configuration updated")
|
|
||||||
if env.IsEnabled() {
|
if env.IsEnabled() {
|
||||||
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
fmt.Printf("\n[%v]: because you have a %v-d environment, you won't see your config change until you run %v first!\n\n", tui.WarningLabel, tui.Code.Render("zrok enable"), tui.Code.Render("zrok disable"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "defaultFrontend":
|
||||||
|
cfg.DefaultFrontend = ""
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Printf("unknown config name '%v'\n", configName)
|
fmt.Printf("unknown config name '%v'\n", configName)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
if err := env.SetConfig(cfg); err != nil {
|
||||||
|
tui.Error("unable to save config", err)
|
||||||
|
}
|
||||||
|
fmt.Println("zrok configuration updated")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,13 @@ func newReserveCommand() *reserveCommand {
|
|||||||
Args: cobra.RangeArgs(1, 2),
|
Args: cobra.RangeArgs(1, 2),
|
||||||
}
|
}
|
||||||
command := &reserveCommand{cmd: cmd}
|
command := &reserveCommand{cmd: cmd}
|
||||||
|
defaultFrontends := []string{"public"}
|
||||||
|
if root, err := environment.LoadRoot(); err == nil {
|
||||||
|
defaultFrontend, _ := root.DefaultFrontend()
|
||||||
|
defaultFrontends = []string{defaultFrontend}
|
||||||
|
}
|
||||||
cmd.Flags().StringVarP(&command.uniqueName, "unique-name", "n", "", "A unique name for the reserved share (defaults to generated identifier)")
|
cmd.Flags().StringVarP(&command.uniqueName, "unique-name", "n", "", "A unique name for the reserved share (defaults to generated identifier)")
|
||||||
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
|
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontend", defaultFrontends, "Selected frontends to use for the share")
|
||||||
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode (public|private: proxy, web, caddy, drive) (private: tcpTunnel, udpTunnel, socks, vpn)")
|
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode (public|private: proxy, web, caddy, drive) (private: tcpTunnel, udpTunnel, socks, vpn)")
|
||||||
cmd.Flags().BoolVarP(&command.jsonOutput, "json-output", "j", false, "Emit JSON describing the created reserved share")
|
cmd.Flags().BoolVarP(&command.jsonOutput, "json-output", "j", false, "Emit JSON describing the created reserved share")
|
||||||
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
|
cmd.Flags().StringArrayVar(&command.basicAuth, "basic-auth", []string{}, "Basic authentication users (<username:password>,...)")
|
||||||
|
@ -45,7 +45,12 @@ func newSharePublicCommand() *sharePublicCommand {
|
|||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
}
|
}
|
||||||
command := &sharePublicCommand{cmd: cmd}
|
command := &sharePublicCommand{cmd: cmd}
|
||||||
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontends", []string{"public"}, "Selected frontends to use for the share")
|
defaultFrontends := []string{"public"}
|
||||||
|
if root, err := environment.LoadRoot(); err == nil {
|
||||||
|
defaultFrontend, _ := root.DefaultFrontend()
|
||||||
|
defaultFrontends = []string{defaultFrontend}
|
||||||
|
}
|
||||||
|
cmd.Flags().StringArrayVar(&command.frontendSelection, "frontend", defaultFrontends, "Selected frontends to use for the share")
|
||||||
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, caddy, drive}")
|
cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, caddy, drive}")
|
||||||
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
|
cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless")
|
||||||
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
|
cmd.Flags().BoolVar(&command.insecure, "insecure", false, "Enable insecure TLS certificate validation for <target>")
|
||||||
|
@ -48,8 +48,10 @@ func (cmd *statusCommand) run(_ *cobra.Command, _ []string) {
|
|||||||
t.SetOutputMirror(os.Stdout)
|
t.SetOutputMirror(os.Stdout)
|
||||||
t.SetStyle(table.StyleColoredDark)
|
t.SetStyle(table.StyleColoredDark)
|
||||||
t.AppendHeader(table.Row{"Config", "Value", "Source"})
|
t.AppendHeader(table.Row{"Config", "Value", "Source"})
|
||||||
apiEndpoint, from := env.ApiEndpoint()
|
apiEndpoint, apiEndpointFrom := env.ApiEndpoint()
|
||||||
t.AppendRow(table.Row{"apiEndpoint", apiEndpoint, from})
|
t.AppendRow(table.Row{"apiEndpoint", apiEndpoint, apiEndpointFrom})
|
||||||
|
defaultFrontend, defaultFrontendFrom := env.DefaultFrontend()
|
||||||
|
t.AppendRow(table.Row{"defaultFrontend", defaultFrontend, defaultFrontendFrom})
|
||||||
t.Render()
|
t.Render()
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n")
|
_, _ = fmt.Fprintf(os.Stderr, "\n")
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/go-openapi/runtime/middleware"
|
"github.com/go-openapi/runtime/middleware"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
"github.com/mattn/go-sqlite3"
|
"github.com/mattn/go-sqlite3"
|
||||||
@ -62,6 +61,7 @@ func (h *createFrontendHandler) Handle(params admin.CreateFrontendParams, princi
|
|||||||
PublicName: ¶ms.Body.PublicName,
|
PublicName: ¶ms.Body.PublicName,
|
||||||
UrlTemplate: ¶ms.Body.URLTemplate,
|
UrlTemplate: ¶ms.Body.URLTemplate,
|
||||||
Reserved: true,
|
Reserved: true,
|
||||||
|
PermissionMode: store.PermissionMode(params.Body.PermissionMode),
|
||||||
}
|
}
|
||||||
if _, err := str.CreateGlobalFrontend(fe, tx); err != nil {
|
if _, err := str.CreateGlobalFrontend(fe, tx); err != nil {
|
||||||
perr := &pq.Error{}
|
perr := &pq.Error{}
|
||||||
|
@ -163,32 +163,49 @@ func (a *Agent) CanAccessShare(shrId int, trx *sqlx.Tx) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if env.AccountId != nil {
|
if env.AccountId != nil {
|
||||||
|
if err := a.str.LimitCheckLock(*env.AccountId, trx); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
ul, err := a.getUserLimits(*env.AccountId, trx)
|
ul, err := a.getUserLimits(*env.AccountId, trx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ul.resource.IsGlobal() {
|
if scopedBwc, found := ul.scopes[sdk.BackendMode(shr.BackendMode)]; found {
|
||||||
if empty, err := a.str.IsBandwidthLimitJournalEmptyForGlobal(*env.AccountId, trx); err == nil && !empty {
|
latestScopedJe, err := a.isBandwidthClassLimitedForAccount(*env.AccountId, scopedBwc, trx)
|
||||||
lj, err := a.str.FindLatestBandwidthLimitJournalForGlobal(*env.AccountId, trx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if lj.Action == store.LimitLimitAction {
|
if latestScopedJe != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if empty, err := a.str.IsBandwidthLimitJournalEmptyForLimitClass(*env.AccountId, ul.resource.GetLimitClassId(), trx); err == nil && !empty {
|
for _, bwc := range ul.bandwidth {
|
||||||
lj, err := a.str.FindLatestBandwidthLimitJournalForLimitClass(*env.AccountId, ul.resource.GetLimitClassId(), trx)
|
latestJe, err := a.isBandwidthClassLimitedForAccount(*env.AccountId, bwc, trx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if lj.Action == store.LimitLimitAction {
|
if latestJe != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc := ul.resource
|
||||||
|
if scopeRc, found := ul.scopes[sdk.BackendMode(shr.BackendMode)]; found {
|
||||||
|
rc = scopeRc
|
||||||
|
}
|
||||||
|
if rc.GetShareFrontends() > store.Unlimited {
|
||||||
|
fes, err := a.str.FindFrontendsForPrivateShare(shr.Id, trx)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(fes)+1 > rc.GetShareFrontends() {
|
||||||
|
logrus.Infof("account '#%d' over frontends per share limit '%d'", *env.AccountId, rc.GetReservedShares())
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ type Config struct {
|
|||||||
Shares int
|
Shares int
|
||||||
ReservedShares int
|
ReservedShares int
|
||||||
UniqueNames int
|
UniqueNames int
|
||||||
|
ShareFrontends int
|
||||||
Bandwidth *BandwidthPerPeriod
|
Bandwidth *BandwidthPerPeriod
|
||||||
Cycle time.Duration
|
Cycle time.Duration
|
||||||
Enforcing bool
|
Enforcing bool
|
||||||
@ -49,6 +50,7 @@ func DefaultConfig() *Config {
|
|||||||
Shares: store.Unlimited,
|
Shares: store.Unlimited,
|
||||||
ReservedShares: store.Unlimited,
|
ReservedShares: store.Unlimited,
|
||||||
UniqueNames: store.Unlimited,
|
UniqueNames: store.Unlimited,
|
||||||
|
ShareFrontends: store.Unlimited,
|
||||||
Bandwidth: DefaultBandwidthPerPeriod(),
|
Bandwidth: DefaultBandwidthPerPeriod(),
|
||||||
Enforcing: false,
|
Enforcing: false,
|
||||||
Cycle: 15 * time.Minute,
|
Cycle: 15 * time.Minute,
|
||||||
|
@ -37,6 +37,10 @@ func (rcc *configResourceCountClass) GetUniqueNames() int {
|
|||||||
return rcc.cfg.UniqueNames
|
return rcc.cfg.UniqueNames
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rcc *configResourceCountClass) String() string {
|
func (rcc *configResourceCountClass) GetShareFrontends() int {
|
||||||
return fmt.Sprintf("Config<environments: %d, shares: %d, reservedShares: %d, uniqueNames: %d>", rcc.cfg.Environments, rcc.cfg.Shares, rcc.cfg.ReservedShares, rcc.cfg.UniqueNames)
|
return rcc.cfg.ShareFrontends
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcc *configResourceCountClass) String() string {
|
||||||
|
return fmt.Sprintf("Config<environments: %d, shares: %d, reservedShares: %d, uniqueNames: %d, share_frontends: %d>", rcc.cfg.Environments, rcc.cfg.Shares, rcc.cfg.ReservedShares, rcc.cfg.UniqueNames, rcc.cfg.ShareFrontends)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,6 @@ func (ul *userLimits) ignoreBackends(bwc store.BandwidthClass) map[sdk.BackendMo
|
|||||||
}
|
}
|
||||||
return ignoreBackends
|
return ignoreBackends
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) getUserLimits(acctId int, trx *sqlx.Tx) (*userLimits, error) {
|
func (a *Agent) getUserLimits(acctId int, trx *sqlx.Tx) (*userLimits, error) {
|
||||||
@ -85,7 +84,7 @@ func (a *Agent) isResourceCountClass(alc *store.LimitClass) bool {
|
|||||||
if alc.BackendMode != nil {
|
if alc.BackendMode != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if alc.Environments == store.Unlimited && alc.Shares == store.Unlimited && alc.ReservedShares == store.Unlimited && alc.UniqueNames == store.Unlimited {
|
if alc.Environments == store.Unlimited && alc.Shares == store.Unlimited && alc.ReservedShares == store.Unlimited && alc.UniqueNames == store.Unlimited && alc.ShareFrontends == store.Unlimited {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -95,7 +94,7 @@ func (a *Agent) isUnscopedBandwidthClass(alc *store.LimitClass) bool {
|
|||||||
if alc.BackendMode != nil {
|
if alc.BackendMode != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if alc.Environments > store.Unlimited || alc.Shares > store.Unlimited || alc.ReservedShares > store.Unlimited || alc.UniqueNames > store.Unlimited {
|
if alc.Environments > store.Unlimited || alc.Shares > store.Unlimited || alc.ReservedShares > store.Unlimited || alc.UniqueNames > store.Unlimited || alc.ShareFrontends > store.Unlimited {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if alc.PeriodMinutes < 1 {
|
if alc.PeriodMinutes < 1 {
|
||||||
|
@ -116,6 +116,17 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
|
|||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return share.NewShareNotFound()
|
return share.NewShareNotFound()
|
||||||
}
|
}
|
||||||
|
if sfe.PermissionMode == store.ClosedPermissionMode {
|
||||||
|
granted, err := str.IsFrontendGrantedToAccount(int(principal.ID), sfe.Id, trx)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
return share.NewShareInternalServerError()
|
||||||
|
}
|
||||||
|
if !granted {
|
||||||
|
logrus.Errorf("'%v' is not granted access to frontend '%v'", principal.Email, frontendSelection)
|
||||||
|
return share.NewShareNotFound()
|
||||||
|
}
|
||||||
|
}
|
||||||
if sfe != nil && sfe.UrlTemplate != nil {
|
if sfe != nil && sfe.UrlTemplate != nil {
|
||||||
frontendZIds = append(frontendZIds, sfe.ZId)
|
frontendZIds = append(frontendZIds, sfe.ZId)
|
||||||
frontendTemplates = append(frontendTemplates, *sfe.UrlTemplate)
|
frontendTemplates = append(frontendTemplates, *sfe.UrlTemplate)
|
||||||
|
@ -14,28 +14,28 @@ type Frontend struct {
|
|||||||
PublicName *string
|
PublicName *string
|
||||||
UrlTemplate *string
|
UrlTemplate *string
|
||||||
Reserved bool
|
Reserved bool
|
||||||
Deleted bool
|
PermissionMode PermissionMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (str *Store) CreateFrontend(envId int, f *Frontend, tx *sqlx.Tx) (int, error) {
|
func (str *Store) CreateFrontend(envId int, f *Frontend, tx *sqlx.Tx) (int, error) {
|
||||||
stmt, err := tx.Prepare("insert into frontends (environment_id, private_share_id, token, z_id, public_name, url_template, reserved) values ($1, $2, $3, $4, $5, $6, $7) returning id")
|
stmt, err := tx.Prepare("insert into frontends (environment_id, private_share_id, token, z_id, public_name, url_template, reserved, permission_mode) values ($1, $2, $3, $4, $5, $6, $7, $8) returning id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "error preparing frontends insert statement")
|
return 0, errors.Wrap(err, "error preparing frontends insert statement")
|
||||||
}
|
}
|
||||||
var id int
|
var id int
|
||||||
if err := stmt.QueryRow(envId, f.PrivateShareId, f.Token, f.ZId, f.PublicName, f.UrlTemplate, f.Reserved).Scan(&id); err != nil {
|
if err := stmt.QueryRow(envId, f.PrivateShareId, f.Token, f.ZId, f.PublicName, f.UrlTemplate, f.Reserved, f.PermissionMode).Scan(&id); err != nil {
|
||||||
return 0, errors.Wrap(err, "error executing frontends insert statement")
|
return 0, errors.Wrap(err, "error executing frontends insert statement")
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (str *Store) CreateGlobalFrontend(f *Frontend, tx *sqlx.Tx) (int, error) {
|
func (str *Store) CreateGlobalFrontend(f *Frontend, tx *sqlx.Tx) (int, error) {
|
||||||
stmt, err := tx.Prepare("insert into frontends (token, z_id, public_name, url_template, reserved) values ($1, $2, $3, $4, $5) returning id")
|
stmt, err := tx.Prepare("insert into frontends (token, z_id, public_name, url_template, reserved, permission_mode) values ($1, $2, $3, $4, $5, $6) returning id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "error preparing global frontends insert statement")
|
return 0, errors.Wrap(err, "error preparing global frontends insert statement")
|
||||||
}
|
}
|
||||||
var id int
|
var id int
|
||||||
if err := stmt.QueryRow(f.Token, f.ZId, f.PublicName, f.UrlTemplate, f.Reserved).Scan(&id); err != nil {
|
if err := stmt.QueryRow(f.Token, f.ZId, f.PublicName, f.UrlTemplate, f.Reserved, f.PermissionMode).Scan(&id); err != nil {
|
||||||
return 0, errors.Wrap(err, "error executing global frontends insert statement")
|
return 0, errors.Wrap(err, "error executing global frontends insert statement")
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
@ -122,12 +122,12 @@ func (str *Store) FindFrontendsForPrivateShare(shrId int, tx *sqlx.Tx) ([]*Front
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (str *Store) UpdateFrontend(fe *Frontend, tx *sqlx.Tx) error {
|
func (str *Store) UpdateFrontend(fe *Frontend, tx *sqlx.Tx) error {
|
||||||
sql := "update frontends set environment_id = $1, private_share_id = $2, token = $3, z_id = $4, public_name = $5, url_template = $6, reserved = $7, updated_at = current_timestamp where id = $8"
|
sql := "update frontends set environment_id = $1, private_share_id = $2, token = $3, z_id = $4, public_name = $5, url_template = $6, reserved = $7, permission_mode = $8, updated_at = current_timestamp where id = $9"
|
||||||
stmt, err := tx.Prepare(sql)
|
stmt, err := tx.Prepare(sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error preparing frontends update statement")
|
return errors.Wrap(err, "error preparing frontends update statement")
|
||||||
}
|
}
|
||||||
_, err = stmt.Exec(fe.EnvironmentId, fe.PrivateShareId, fe.Token, fe.ZId, fe.PublicName, fe.UrlTemplate, fe.Reserved, fe.Id)
|
_, err = stmt.Exec(fe.EnvironmentId, fe.PrivateShareId, fe.Token, fe.ZId, fe.PublicName, fe.UrlTemplate, fe.Reserved, fe.PermissionMode, fe.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error executing frontends update statement")
|
return errors.Wrap(err, "error executing frontends update statement")
|
||||||
}
|
}
|
||||||
|
18
controller/store/frontendGrant.go
Normal file
18
controller/store/frontendGrant.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (str *Store) IsFrontendGrantedToAccount(acctId, frontendId int, trx *sqlx.Tx) (bool, error) {
|
||||||
|
stmt, err := trx.Prepare("select count(0) from frontend_grants where account_id = $1 AND frontend_id = $2")
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "error preparing frontend_grants select statement")
|
||||||
|
}
|
||||||
|
var count int
|
||||||
|
if err := stmt.QueryRow(acctId, frontendId).Scan(&count); err != nil {
|
||||||
|
return false, errors.Wrap(err, "error querying frontend_grants count")
|
||||||
|
}
|
||||||
|
return count > 0, nil
|
||||||
|
}
|
@ -22,6 +22,7 @@ type ResourceCountClass interface {
|
|||||||
GetShares() int
|
GetShares() int
|
||||||
GetReservedShares() int
|
GetReservedShares() int
|
||||||
GetUniqueNames() int
|
GetUniqueNames() int
|
||||||
|
GetShareFrontends() int
|
||||||
}
|
}
|
||||||
|
|
||||||
type BandwidthClass interface {
|
type BandwidthClass interface {
|
||||||
@ -37,11 +38,13 @@ type BandwidthClass interface {
|
|||||||
|
|
||||||
type LimitClass struct {
|
type LimitClass struct {
|
||||||
Model
|
Model
|
||||||
|
Label *string
|
||||||
BackendMode *sdk.BackendMode
|
BackendMode *sdk.BackendMode
|
||||||
Environments int
|
Environments int
|
||||||
Shares int
|
Shares int
|
||||||
ReservedShares int
|
ReservedShares int
|
||||||
UniqueNames int
|
UniqueNames int
|
||||||
|
ShareFrontends int
|
||||||
PeriodMinutes int
|
PeriodMinutes int
|
||||||
RxBytes int64
|
RxBytes int64
|
||||||
TxBytes int64
|
TxBytes int64
|
||||||
@ -77,6 +80,10 @@ func (lc LimitClass) GetUniqueNames() int {
|
|||||||
return lc.UniqueNames
|
return lc.UniqueNames
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lc LimitClass) GetShareFrontends() int {
|
||||||
|
return lc.ShareFrontends
|
||||||
|
}
|
||||||
|
|
||||||
func (lc LimitClass) GetBackendMode() sdk.BackendMode {
|
func (lc LimitClass) GetBackendMode() sdk.BackendMode {
|
||||||
if lc.BackendMode == nil {
|
if lc.BackendMode == nil {
|
||||||
return ""
|
return ""
|
||||||
@ -105,7 +112,12 @@ func (lc LimitClass) GetLimitAction() LimitAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc LimitClass) String() string {
|
func (lc LimitClass) String() string {
|
||||||
out := fmt.Sprintf("LimitClass<#%d", lc.Id)
|
out := "LimitClass<"
|
||||||
|
if lc.Label != nil && *lc.Label != "" {
|
||||||
|
out += "'" + *lc.Label + "'"
|
||||||
|
} else {
|
||||||
|
out += fmt.Sprintf("#%d", lc.Id)
|
||||||
|
}
|
||||||
if lc.BackendMode != nil {
|
if lc.BackendMode != nil {
|
||||||
out += fmt.Sprintf(", backendMode: '%s'", *lc.BackendMode)
|
out += fmt.Sprintf(", backendMode: '%s'", *lc.BackendMode)
|
||||||
}
|
}
|
||||||
@ -121,6 +133,9 @@ func (lc LimitClass) String() string {
|
|||||||
if lc.UniqueNames > Unlimited {
|
if lc.UniqueNames > Unlimited {
|
||||||
out += fmt.Sprintf(", uniqueNames: %d", lc.UniqueNames)
|
out += fmt.Sprintf(", uniqueNames: %d", lc.UniqueNames)
|
||||||
}
|
}
|
||||||
|
if lc.ShareFrontends > Unlimited {
|
||||||
|
out += fmt.Sprintf(", shareFrontends: %d", lc.ShareFrontends)
|
||||||
|
}
|
||||||
if lc.RxBytes > Unlimited || lc.TxBytes > Unlimited || lc.TotalBytes > Unlimited {
|
if lc.RxBytes > Unlimited || lc.TxBytes > Unlimited || lc.TotalBytes > Unlimited {
|
||||||
out += fmt.Sprintf(", periodMinutes: %d", lc.PeriodMinutes)
|
out += fmt.Sprintf(", periodMinutes: %d", lc.PeriodMinutes)
|
||||||
}
|
}
|
||||||
@ -140,12 +155,12 @@ func (lc LimitClass) String() string {
|
|||||||
var _ BandwidthClass = (*LimitClass)(nil)
|
var _ BandwidthClass = (*LimitClass)(nil)
|
||||||
|
|
||||||
func (str *Store) CreateLimitClass(lc *LimitClass, trx *sqlx.Tx) (int, error) {
|
func (str *Store) CreateLimitClass(lc *LimitClass, trx *sqlx.Tx) (int, error) {
|
||||||
stmt, err := trx.Prepare("insert into limit_classes (backend_mode, environments, shares, reserved_shares, unique_names, period_minutes, rx_bytes, tx_bytes, total_bytes, limit_action) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) returning id")
|
stmt, err := trx.Prepare("insert into limit_classes (label, backend_mode, environments, shares, reserved_shares, unique_names, share_frontends, period_minutes, rx_bytes, tx_bytes, total_bytes, limit_action) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) returning id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "error preparing limit_classes insert statement")
|
return 0, errors.Wrap(err, "error preparing limit_classes insert statement")
|
||||||
}
|
}
|
||||||
var id int
|
var id int
|
||||||
if err := stmt.QueryRow(lc.BackendMode, lc.Environments, lc.Shares, lc.ReservedShares, lc.UniqueNames, lc.PeriodMinutes, lc.RxBytes, lc.TxBytes, lc.TotalBytes, lc.LimitAction).Scan(&id); err != nil {
|
if err := stmt.QueryRow(lc.Label, lc.BackendMode, lc.Environments, lc.Shares, lc.ReservedShares, lc.UniqueNames, lc.ShareFrontends, lc.PeriodMinutes, lc.RxBytes, lc.TxBytes, lc.TotalBytes, lc.LimitAction).Scan(&id); err != nil {
|
||||||
return 0, errors.Wrap(err, "error executing limit_classes insert statement")
|
return 0, errors.Wrap(err, "error executing limit_classes insert statement")
|
||||||
}
|
}
|
||||||
return id, nil
|
return id, nil
|
||||||
|
@ -7,14 +7,6 @@ const (
|
|||||||
WarningLimitAction LimitAction = "warning"
|
WarningLimitAction LimitAction = "warning"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LimitScope string
|
|
||||||
|
|
||||||
const (
|
|
||||||
AccountLimitScope LimitScope = "account"
|
|
||||||
EnvironmentLimitScope LimitScope = "environment"
|
|
||||||
ShareLimitScope LimitScope = "share"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PermissionMode string
|
type PermissionMode string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -18,7 +18,6 @@ type Share struct {
|
|||||||
Reserved bool
|
Reserved bool
|
||||||
UniqueName bool
|
UniqueName bool
|
||||||
PermissionMode PermissionMode
|
PermissionMode PermissionMode
|
||||||
Deleted bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (str *Store) CreateShare(envId int, shr *Share, tx *sqlx.Tx) (int, error) {
|
func (str *Store) CreateShare(envId int, shr *Share, tx *sqlx.Tx) (int, error) {
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table limit_classes add column share_frontends int not null default (-1);
|
@ -0,0 +1,17 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table frontends add column permission_mode permission_mode_type not null default('open');
|
||||||
|
|
||||||
|
create table frontend_grants (
|
||||||
|
id serial primary key,
|
||||||
|
|
||||||
|
account_id integer references accounts (id) not null,
|
||||||
|
frontend_id integer references frontends (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 frontend_grants_account_id_idx on frontend_grants (account_id);
|
||||||
|
create index frontend_grants_frontend_id_idx on frontend_grants (frontend_id);
|
@ -0,0 +1,3 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table limit_classes add column label varchar(32);
|
@ -0,0 +1,3 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table limit_classes add column share_frontends int not null default (-1);
|
17
controller/store/sql/sqlite3/027_v0_4_32_frontend_grants.sql
Normal file
17
controller/store/sql/sqlite3/027_v0_4_32_frontend_grants.sql
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table frontends add column permission_mode string not null default('open');
|
||||||
|
|
||||||
|
create table frontend_grants (
|
||||||
|
id integer primary key,
|
||||||
|
|
||||||
|
account_id integer references accounts (id) not null,
|
||||||
|
frontend_id integer references frontends (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 frontend_grants_account_id_idx on frontend_grants (account_id);
|
||||||
|
create index frontend_grants_frontend_id_idx on frontend_grants (frontend_id);
|
@ -0,0 +1,3 @@
|
|||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
alter table limit_classes add column label varchar(32);
|
@ -90,9 +90,9 @@ ZROK_OAUTH_GOOGLE_CLIENT_ID=abcd1234
|
|||||||
ZROK_OAUTH_GOOGLE_CLIENT_SECRET=abcd1234
|
ZROK_OAUTH_GOOGLE_CLIENT_SECRET=abcd1234
|
||||||
|
|
||||||
# zrok version, e.g., 1.0.0
|
# zrok version, e.g., 1.0.0
|
||||||
ZROK_IMAGE_TAG=latest
|
ZROK_CLI_TAG=latest
|
||||||
# ziti version, e.g., 1.0.0
|
# ziti version, e.g., 1.0.0
|
||||||
ZITI_IMAGE_TAG=latest
|
ZITI_CLI_TAG=latest
|
||||||
```
|
```
|
||||||
|
|
||||||
### Start the Docker Compose Project
|
### Start the Docker Compose Project
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# /___|_| \___/|_|\_\
|
# /___|_| \___/|_|\_\
|
||||||
# controller configuration
|
# controller configuration
|
||||||
|
|
||||||
v: 3
|
v: 4
|
||||||
admin:
|
admin:
|
||||||
# generate these admin tokens from a source of randomness, e.g.
|
# generate these admin tokens from a source of randomness, e.g.
|
||||||
# LC_ALL=C tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c32
|
# LC_ALL=C tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c32
|
||||||
|
@ -20,7 +20,7 @@ The limits agent is responsible for controlling the number of resources in use (
|
|||||||
|
|
||||||
### Types of Limits
|
### Types of Limits
|
||||||
|
|
||||||
Limits can be specified that control the number of environments, shares, reserved shares, and unique names that can be created by an account. Limits that control the allowed number of resources are called _resource count limits_.
|
Limits can be specified that control the number of environments, shares, reserved shares, unique names, and frontends per-share that can be created by an account. Limits that control the allowed number of resources are called _resource count limits_.
|
||||||
|
|
||||||
Limits can be specified to control the amount of data that can be transferred within a time period. Limits that control the amount of data that can be transferred are called _bandwidth limits_.
|
Limits can be specified to control the amount of data that can be transferred within a time period. Limits that control the amount of data that can be transferred are called _bandwidth limits_.
|
||||||
|
|
||||||
@ -40,6 +40,7 @@ limits:
|
|||||||
shares: -1
|
shares: -1
|
||||||
reserved_shares: -1
|
reserved_shares: -1
|
||||||
unique_names: -1
|
unique_names: -1
|
||||||
|
share_frontends: -1
|
||||||
bandwidth:
|
bandwidth:
|
||||||
period: 5m
|
period: 5m
|
||||||
warning:
|
warning:
|
||||||
@ -64,7 +65,7 @@ The `cycle` value controls how frequently the limits agent will evaluate enforce
|
|||||||
|
|
||||||
### Global Resouce Count Limits
|
### Global Resouce Count Limits
|
||||||
|
|
||||||
The `environments`, `shares`, `reserved_shares`, and `unique_names` specify the resource count limits, globally for the service instance.
|
The `environments`, `shares`, `reserved_shares`, `unique_names`, and `share_frontends` specify the resource count limits, globally for the service instance.
|
||||||
|
|
||||||
These resource counts will be applied to all users in the service instance by default.
|
These resource counts will be applied to all users in the service instance by default.
|
||||||
|
|
||||||
@ -91,11 +92,13 @@ Limit classes are created by creating a record in the `limit_classes` table in t
|
|||||||
```sql
|
```sql
|
||||||
CREATE TABLE public.limit_classes (
|
CREATE TABLE public.limit_classes (
|
||||||
id integer NOT NULL,
|
id integer NOT NULL,
|
||||||
|
label VARCHAR(32),
|
||||||
backend_mode public.backend_mode,
|
backend_mode public.backend_mode,
|
||||||
environments integer DEFAULT '-1'::integer NOT NULL,
|
environments integer DEFAULT '-1'::integer NOT NULL,
|
||||||
shares integer DEFAULT '-1'::integer NOT NULL,
|
shares integer DEFAULT '-1'::integer NOT NULL,
|
||||||
reserved_shares integer DEFAULT '-1'::integer NOT NULL,
|
reserved_shares integer DEFAULT '-1'::integer NOT NULL,
|
||||||
unique_names integer DEFAULT '-1'::integer NOT NULL,
|
unique_names integer DEFAULT '-1'::integer NOT NULL,
|
||||||
|
share_frontends integer DEFAULT '-1'::integer NOT NULL,
|
||||||
period_minutes integer DEFAULT 1440 NOT NULL,
|
period_minutes integer DEFAULT 1440 NOT NULL,
|
||||||
rx_bytes bigint DEFAULT '-1'::integer NOT NULL,
|
rx_bytes bigint DEFAULT '-1'::integer NOT NULL,
|
||||||
tx_bytes bigint DEFAULT '-1'::integer NOT NULL,
|
tx_bytes bigint DEFAULT '-1'::integer NOT NULL,
|
||||||
@ -130,7 +133,7 @@ Create a row in this table linking the `account_id` to the `limit_class_id` to a
|
|||||||
To support overriding the resource count limits defined in the global limits configuration, a site administrator can create a limit class by inserting a row into the `limit_classes` table structured like this:
|
To support overriding the resource count limits defined in the global limits configuration, a site administrator can create a limit class by inserting a row into the `limit_classes` table structured like this:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
insert into limit_classes (environments, shares, reserved_shares, unique_names) values (1, 1, 1, 1);
|
insert into limit_classes (environments, shares, reserved_shares, unique_names, share_frontends) values (1, 1, 1, 1, 1);
|
||||||
```
|
```
|
||||||
|
|
||||||
This creates a limit class that sets the `environments`, `shares`, `reserved_shares`, and `unique_names` all to `1`.
|
This creates a limit class that sets the `environments`, `shares`, `reserved_shares`, and `unique_names` all to `1`.
|
||||||
|
@ -124,6 +124,7 @@ func (t *FilesystemTarget) WriteStream(path string, stream io.Reader, mode os.Fi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
_, err = io.Copy(f, stream)
|
_, err = io.Copy(f, stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -13,6 +13,7 @@ type Root interface {
|
|||||||
|
|
||||||
Client() (*rest_client_zrok.Zrok, error)
|
Client() (*rest_client_zrok.Zrok, error)
|
||||||
ApiEndpoint() (string, string)
|
ApiEndpoint() (string, string)
|
||||||
|
DefaultFrontend() (string, string)
|
||||||
|
|
||||||
IsEnabled() bool
|
IsEnabled() bool
|
||||||
Environment() *Environment
|
Environment() *Environment
|
||||||
@ -35,6 +36,7 @@ type Environment struct {
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ApiEndpoint string
|
ApiEndpoint string
|
||||||
|
DefaultFrontend string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Metadata struct {
|
type Metadata struct {
|
||||||
|
@ -85,6 +85,24 @@ func (r *Root) ApiEndpoint() (string, string) {
|
|||||||
return apiEndpoint, from
|
return apiEndpoint, from
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Root) DefaultFrontend() (string, string) {
|
||||||
|
defaultFrontend := "public"
|
||||||
|
from := "binary"
|
||||||
|
|
||||||
|
if r.Config() != nil && r.Config().DefaultFrontend != "" {
|
||||||
|
defaultFrontend = r.Config().DefaultFrontend
|
||||||
|
from = "config"
|
||||||
|
}
|
||||||
|
|
||||||
|
env := os.Getenv("ZROK_DEFAULT_FRONTEND")
|
||||||
|
if env != "" {
|
||||||
|
defaultFrontend = env
|
||||||
|
from = "ZROK_DEFAULT_FRONTEND"
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultFrontend, from
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Root) Environment() *env_core.Environment {
|
func (r *Root) Environment() *env_core.Environment {
|
||||||
return r.env
|
return r.env
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,24 @@ func (r *Root) ApiEndpoint() (string, string) {
|
|||||||
return apiEndpoint, from
|
return apiEndpoint, from
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Root) DefaultFrontend() (string, string) {
|
||||||
|
defaultFrontend := "public"
|
||||||
|
from := "binary"
|
||||||
|
|
||||||
|
if r.Config() != nil && r.Config().DefaultFrontend != "" {
|
||||||
|
defaultFrontend = r.Config().DefaultFrontend
|
||||||
|
from = "config"
|
||||||
|
}
|
||||||
|
|
||||||
|
env := os.Getenv("ZROK_DEFAULT_FRONTEND")
|
||||||
|
if env != "" {
|
||||||
|
defaultFrontend = env
|
||||||
|
from = "ZROK_DEFAULT_FRONTEND"
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultFrontend, from
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Root) Environment() *env_core.Environment {
|
func (r *Root) Environment() *env_core.Environment {
|
||||||
return r.env
|
return r.env
|
||||||
}
|
}
|
||||||
|
@ -224,12 +224,13 @@ func loadConfig() (*env_core.Config, error) {
|
|||||||
}
|
}
|
||||||
out := &env_core.Config{
|
out := &env_core.Config{
|
||||||
ApiEndpoint: cfg.ApiEndpoint,
|
ApiEndpoint: cfg.ApiEndpoint,
|
||||||
|
DefaultFrontend: cfg.DefaultFrontend,
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveConfig(cfg *env_core.Config) error {
|
func saveConfig(cfg *env_core.Config) error {
|
||||||
in := &config{ApiEndpoint: cfg.ApiEndpoint}
|
in := &config{ApiEndpoint: cfg.ApiEndpoint, DefaultFrontend: cfg.DefaultFrontend}
|
||||||
data, err := json.MarshalIndent(in, "", " ")
|
data, err := json.MarshalIndent(in, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error marshaling config")
|
return errors.Wrap(err, "error marshaling config")
|
||||||
@ -324,6 +325,7 @@ type metadata struct {
|
|||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
ApiEndpoint string `json:"api_endpoint"`
|
ApiEndpoint string `json:"api_endpoint"`
|
||||||
|
DefaultFrontend string `json:"default_frontend"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type environment struct {
|
type environment struct {
|
||||||
|
@ -83,6 +83,7 @@ limits:
|
|||||||
shares: -1
|
shares: -1
|
||||||
reserved_shares: -1
|
reserved_shares: -1
|
||||||
unique_names: -1
|
unique_names: -1
|
||||||
|
share_frontends: -1
|
||||||
bandwidth:
|
bandwidth:
|
||||||
period: 5m
|
period: 5m
|
||||||
warning:
|
warning:
|
||||||
|
@ -7,9 +7,12 @@ package rest_model_zrok
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/go-openapi/errors"
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
"github.com/go-openapi/swag"
|
"github.com/go-openapi/swag"
|
||||||
|
"github.com/go-openapi/validate"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateFrontendRequest create frontend request
|
// CreateFrontendRequest create frontend request
|
||||||
@ -17,6 +20,10 @@ import (
|
|||||||
// swagger:model createFrontendRequest
|
// swagger:model createFrontendRequest
|
||||||
type CreateFrontendRequest struct {
|
type CreateFrontendRequest struct {
|
||||||
|
|
||||||
|
// permission mode
|
||||||
|
// Enum: [open closed]
|
||||||
|
PermissionMode string `json:"permissionMode,omitempty"`
|
||||||
|
|
||||||
// public name
|
// public name
|
||||||
PublicName string `json:"public_name,omitempty"`
|
PublicName string `json:"public_name,omitempty"`
|
||||||
|
|
||||||
@ -29,6 +36,57 @@ type CreateFrontendRequest struct {
|
|||||||
|
|
||||||
// Validate validates this create frontend request
|
// Validate validates this create frontend request
|
||||||
func (m *CreateFrontendRequest) Validate(formats strfmt.Registry) error {
|
func (m *CreateFrontendRequest) Validate(formats strfmt.Registry) error {
|
||||||
|
var res []error
|
||||||
|
|
||||||
|
if err := m.validatePermissionMode(formats); err != nil {
|
||||||
|
res = append(res, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res) > 0 {
|
||||||
|
return errors.CompositeValidationError(res...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var createFrontendRequestTypePermissionModePropEnum []interface{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var res []string
|
||||||
|
if err := json.Unmarshal([]byte(`["open","closed"]`), &res); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, v := range res {
|
||||||
|
createFrontendRequestTypePermissionModePropEnum = append(createFrontendRequestTypePermissionModePropEnum, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// CreateFrontendRequestPermissionModeOpen captures enum value "open"
|
||||||
|
CreateFrontendRequestPermissionModeOpen string = "open"
|
||||||
|
|
||||||
|
// CreateFrontendRequestPermissionModeClosed captures enum value "closed"
|
||||||
|
CreateFrontendRequestPermissionModeClosed string = "closed"
|
||||||
|
)
|
||||||
|
|
||||||
|
// prop value enum
|
||||||
|
func (m *CreateFrontendRequest) validatePermissionModeEnum(path, location string, value string) error {
|
||||||
|
if err := validate.EnumCase(path, location, value, createFrontendRequestTypePermissionModePropEnum, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CreateFrontendRequest) validatePermissionMode(formats strfmt.Registry) error {
|
||||||
|
if swag.IsZero(m.PermissionMode) { // not required
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// value enum
|
||||||
|
if err := m.validatePermissionModeEnum("permissionMode", "body", m.PermissionMode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1200,6 +1200,13 @@ func init() {
|
|||||||
"createFrontendRequest": {
|
"createFrontendRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"permissionMode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"open",
|
||||||
|
"closed"
|
||||||
|
]
|
||||||
|
},
|
||||||
"public_name": {
|
"public_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -2956,6 +2963,13 @@ func init() {
|
|||||||
"createFrontendRequest": {
|
"createFrontendRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"permissionMode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"open",
|
||||||
|
"closed"
|
||||||
|
]
|
||||||
|
},
|
||||||
"public_name": {
|
"public_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
7.4.0
|
7.6.0
|
||||||
|
@ -16,6 +16,7 @@ export class CreateFrontendRequest {
|
|||||||
'zId'?: string;
|
'zId'?: string;
|
||||||
'urlTemplate'?: string;
|
'urlTemplate'?: string;
|
||||||
'publicName'?: string;
|
'publicName'?: string;
|
||||||
|
'permissionMode'?: CreateFrontendRequest.PermissionModeEnum;
|
||||||
|
|
||||||
static discriminator: string | undefined = undefined;
|
static discriminator: string | undefined = undefined;
|
||||||
|
|
||||||
@ -34,6 +35,11 @@ export class CreateFrontendRequest {
|
|||||||
"name": "publicName",
|
"name": "publicName",
|
||||||
"baseName": "public_name",
|
"baseName": "public_name",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "permissionMode",
|
||||||
|
"baseName": "permissionMode",
|
||||||
|
"type": "CreateFrontendRequest.PermissionModeEnum"
|
||||||
} ];
|
} ];
|
||||||
|
|
||||||
static getAttributeTypeMap() {
|
static getAttributeTypeMap() {
|
||||||
@ -41,3 +47,9 @@ export class CreateFrontendRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace CreateFrontendRequest {
|
||||||
|
export enum PermissionModeEnum {
|
||||||
|
Open = <any> 'open',
|
||||||
|
Closed = <any> 'closed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -108,6 +108,7 @@ let primitives = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
let enumsMap: {[index: string]: any} = {
|
let enumsMap: {[index: string]: any} = {
|
||||||
|
"CreateFrontendRequest.PermissionModeEnum": CreateFrontendRequest.PermissionModeEnum,
|
||||||
"ShareRequest.ShareModeEnum": ShareRequest.ShareModeEnum,
|
"ShareRequest.ShareModeEnum": ShareRequest.ShareModeEnum,
|
||||||
"ShareRequest.BackendModeEnum": ShareRequest.BackendModeEnum,
|
"ShareRequest.BackendModeEnum": ShareRequest.BackendModeEnum,
|
||||||
"ShareRequest.OauthProviderEnum": ShareRequest.OauthProviderEnum,
|
"ShareRequest.OauthProviderEnum": ShareRequest.OauthProviderEnum,
|
||||||
|
@ -120,7 +120,8 @@ export namespace ShareRequest {
|
|||||||
UdpTunnel = <any> 'udpTunnel',
|
UdpTunnel = <any> 'udpTunnel',
|
||||||
Caddy = <any> 'caddy',
|
Caddy = <any> 'caddy',
|
||||||
Drive = <any> 'drive',
|
Drive = <any> 'drive',
|
||||||
Socks = <any> 'socks'
|
Socks = <any> 'socks',
|
||||||
|
Vpn = <any> 'vpn'
|
||||||
}
|
}
|
||||||
export enum OauthProviderEnum {
|
export enum OauthProviderEnum {
|
||||||
Github = <any> 'github',
|
Github = <any> 'github',
|
||||||
|
@ -30,20 +30,23 @@ class CreateFrontendRequest(object):
|
|||||||
swagger_types = {
|
swagger_types = {
|
||||||
'z_id': 'str',
|
'z_id': 'str',
|
||||||
'url_template': 'str',
|
'url_template': 'str',
|
||||||
'public_name': 'str'
|
'public_name': 'str',
|
||||||
|
'permission_mode': 'str'
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute_map = {
|
attribute_map = {
|
||||||
'z_id': 'zId',
|
'z_id': 'zId',
|
||||||
'url_template': 'url_template',
|
'url_template': 'url_template',
|
||||||
'public_name': 'public_name'
|
'public_name': 'public_name',
|
||||||
|
'permission_mode': 'permissionMode'
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, z_id=None, url_template=None, public_name=None): # noqa: E501
|
def __init__(self, z_id=None, url_template=None, public_name=None, permission_mode=None): # noqa: E501
|
||||||
"""CreateFrontendRequest - a model defined in Swagger""" # noqa: E501
|
"""CreateFrontendRequest - a model defined in Swagger""" # noqa: E501
|
||||||
self._z_id = None
|
self._z_id = None
|
||||||
self._url_template = None
|
self._url_template = None
|
||||||
self._public_name = None
|
self._public_name = None
|
||||||
|
self._permission_mode = None
|
||||||
self.discriminator = None
|
self.discriminator = None
|
||||||
if z_id is not None:
|
if z_id is not None:
|
||||||
self.z_id = z_id
|
self.z_id = z_id
|
||||||
@ -51,6 +54,8 @@ class CreateFrontendRequest(object):
|
|||||||
self.url_template = url_template
|
self.url_template = url_template
|
||||||
if public_name is not None:
|
if public_name is not None:
|
||||||
self.public_name = public_name
|
self.public_name = public_name
|
||||||
|
if permission_mode is not None:
|
||||||
|
self.permission_mode = permission_mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def z_id(self):
|
def z_id(self):
|
||||||
@ -115,6 +120,33 @@ class CreateFrontendRequest(object):
|
|||||||
|
|
||||||
self._public_name = public_name
|
self._public_name = public_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def permission_mode(self):
|
||||||
|
"""Gets the permission_mode of this CreateFrontendRequest. # noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
:return: The permission_mode of this CreateFrontendRequest. # noqa: E501
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return self._permission_mode
|
||||||
|
|
||||||
|
@permission_mode.setter
|
||||||
|
def permission_mode(self, permission_mode):
|
||||||
|
"""Sets the permission_mode of this CreateFrontendRequest.
|
||||||
|
|
||||||
|
|
||||||
|
:param permission_mode: The permission_mode of this CreateFrontendRequest. # noqa: E501
|
||||||
|
:type: str
|
||||||
|
"""
|
||||||
|
allowed_values = ["open", "closed"] # noqa: E501
|
||||||
|
if permission_mode not in allowed_values:
|
||||||
|
raise ValueError(
|
||||||
|
"Invalid value for `permission_mode` ({0}), must be one of {1}" # noqa: E501
|
||||||
|
.format(permission_mode, allowed_values)
|
||||||
|
)
|
||||||
|
|
||||||
|
self._permission_mode = permission_mode
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
"""Returns the model properties as a dict"""
|
"""Returns the model properties as a dict"""
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -766,6 +766,9 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
public_name:
|
public_name:
|
||||||
type: string
|
type: string
|
||||||
|
permissionMode:
|
||||||
|
type: string
|
||||||
|
enum: ["open", "closed"]
|
||||||
|
|
||||||
createFrontendResponse:
|
createFrontendResponse:
|
||||||
type: object
|
type: object
|
||||||
|
685
ui/package-lock.json
generated
685
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,14 +7,14 @@
|
|||||||
"@emotion/styled": "^11.10.4",
|
"@emotion/styled": "^11.10.4",
|
||||||
"@mdi/js": "^7.0.96",
|
"@mdi/js": "^7.0.96",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mui/material": "^5.10.4",
|
"@mui/material": "^5.15.18",
|
||||||
"bootstrap": "^5.2.3",
|
"bootstrap": "^5.2.3",
|
||||||
"dagre": "^0.8.5",
|
"dagre": "^0.8.5",
|
||||||
"eslint-config-react-app": "^7.0.1",
|
"eslint-config-react-app": "^7.0.1",
|
||||||
"humanize-duration": "^3.27.3",
|
"humanize-duration": "^3.27.3",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-bootstrap": "^2.7.0",
|
"react-bootstrap": "^2.10.2",
|
||||||
"react-data-table-component": "^7.5.2",
|
"react-data-table-component": "^7.5.2",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-force-graph": "^1.43.0",
|
"react-force-graph": "^1.43.0",
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
* @property {string} zId
|
* @property {string} zId
|
||||||
* @property {string} url_template
|
* @property {string} url_template
|
||||||
* @property {string} public_name
|
* @property {string} public_name
|
||||||
|
* @property {string} permissionMode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +14,7 @@ const ActionsTab = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"actions-tab"}>
|
<div className={"actions-tab"}>
|
||||||
<div id={"change-password"} style={{"padding-top": "10px"}}>
|
<div id={"change-password"} style={{"paddingTop": "10px"}}>
|
||||||
<h3>Change Password?</h3>
|
<h3>Change Password?</h3>
|
||||||
<p>Change the password used to log into the zrok web console.</p>
|
<p>Change the password used to log into the zrok web console.</p>
|
||||||
<Button variant={"danger"} onClick={openChangePasswordModal}>Change Password</Button>
|
<Button variant={"danger"} onClick={openChangePasswordModal}>Change Password</Button>
|
||||||
|
Loading…
Reference in New Issue
Block a user