basic unique name implementation (#123)

This commit is contained in:
Michael Quigley 2023-12-08 12:03:07 -05:00
parent ead350b442
commit f61b2c9086
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
9 changed files with 58 additions and 7 deletions

View File

@ -6,6 +6,7 @@ import (
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/openziti/zrok/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"slices"
@ -17,6 +18,7 @@ func init() {
}
type reserveCommand struct {
uniqueName string
basicAuth []string
frontendSelection []string
backendMode string
@ -34,6 +36,7 @@ func newReserveCommand() *reserveCommand {
Args: cobra.ExactArgs(2),
}
command := &reserveCommand{cmd: cmd}
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().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode (public|private: proxy, web, caddy, drive) (private: tcpTunnel, udpTunnel)")
cmd.Flags().BoolVarP(&command.jsonOutput, "json-output", "j", false, "Emit JSON describing the created reserved share")
@ -56,6 +59,10 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
tui.Error(fmt.Sprintf("invalid sharing mode for a %s share: %s", sdk.PublicShareMode, cmd.backendMode), nil)
}
if cmd.uniqueName != "" && !util.IsValidUniqueName(cmd.uniqueName) {
tui.Error("invalid unique name; must be lowercase alphanumeric, between 4 and 32 characters in length, screened for profanity", nil)
}
var target string
switch cmd.backendMode {
case "proxy":
@ -95,6 +102,7 @@ func (cmd *reserveCommand) run(_ *cobra.Command, args []string) {
req := &sdk.ShareRequest{
Reserved: true,
UniqueName: cmd.uniqueName,
BackendMode: sdk.BackendMode(cmd.backendMode),
ShareMode: shareMode,
BasicAuth: cmd.basicAuth,

View File

@ -8,6 +8,7 @@ import (
"github.com/openziti/zrok/rest_model_zrok"
"github.com/openziti/zrok/rest_server_zrok/operations/share"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -33,14 +34,14 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
found := false
for _, env := range envs {
if env.ZId == envZId {
logrus.Debugf("found identity '%v' for user '%v'", envZId, principal.Email)
logrus.Debugf("found identity '%v' for account '%v'", envZId, principal.Email)
envId = env.Id
found = true
break
}
}
if !found {
logrus.Errorf("environment '%v' not found for user '%v'", envZId, principal.Email)
logrus.Errorf("environment '%v' not found for account '%v'", envZId, principal.Email)
return share.NewShareUnauthorized()
}
} else {
@ -58,11 +59,21 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
logrus.Error(err)
return share.NewShareInternalServerError()
}
reserved := params.Body.Reserved
uniqueName := params.Body.UniqueName
shrToken, err := createShareToken()
if err != nil {
logrus.Error(err)
return share.NewShareInternalServerError()
}
if reserved && uniqueName != "" {
if !util.IsValidUniqueName(uniqueName) {
logrus.Errorf("invalid unique name '%v' for account '%v'", uniqueName, principal.Email)
return share.NewShareUnprocessableEntity()
}
shrToken = uniqueName
}
var shrZId string
var frontendEndpoints []string
@ -94,7 +105,6 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
}
case string(sdk.PrivateShareMode):
logrus.Info("doing private")
shrZId, frontendEndpoints, err = newPrivateResourceAllocator().allocate(envZId, shrToken, params, edge)
if err != nil {
logrus.Error(err)
@ -108,7 +118,6 @@ func (h *shareHandler) Handle(params share.ShareParams, principal *rest_model_zr
logrus.Debugf("allocated share '%v'", shrToken)
reserved := params.Body.Reserved
sshr := &store.Share{
ZId: shrZId,
Token: shrToken,

View File

@ -0,0 +1,7 @@
-- +migrate Up
-- remove the old unique index (which did not respect the deleted flag)
ALTER TABLE shares DROP CONSTRAINT shares_token_key;
-- add a new unique index which only constrains uniqueness for not-deleted rows
CREATE UNIQUE INDEX shares_token_idx ON shares(token) WHERE deleted is false;

3
go.mod
View File

@ -3,6 +3,7 @@ module github.com/openziti/zrok
go 1.20
require (
github.com/TwiN/go-away v1.6.12
github.com/caddyserver/caddy/v2 v2.7.5-0.20230829153420-ed8bb13c5df7
github.com/charmbracelet/bubbles v0.14.0
github.com/charmbracelet/bubbletea v0.23.1
@ -226,7 +227,7 @@ require (
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.10.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect

6
go.sum
View File

@ -114,6 +114,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/TwiN/go-away v1.6.12 h1:80AjDyeTjfQaSFYbALzRcDKMAmxKW0a5PoxwXKZlW2A=
github.com/TwiN/go-away v1.6.12/go.mod h1:MpvIC9Li3minq+CGgbgUDvQ9tDaeW35k5IXZrF9MVas=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@ -1792,8 +1794,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -22,6 +22,7 @@ const (
type ShareRequest struct {
Reserved bool
UniqueName string
BackendMode BackendMode
ShareMode ShareMode
Target string

View File

@ -26,6 +26,9 @@ func CreateShare(root env_core.Root, request *ShareRequest) (*Share, error) {
return nil, errors.Errorf("unknown share mode '%v'", request.ShareMode)
}
out.Body.Reserved = request.Reserved
if request.Reserved {
out.Body.UniqueName = request.UniqueName
}
if len(request.BasicAuth) > 0 {
out.Body.AuthScheme = string(Basic)

View File

@ -27,6 +27,8 @@ def CreateShare(root: Root, request: model.ShareRequest) -> model.Share:
if request.OauthProvider != "":
out.auth_scheme = model.AUTH_SCHEME_OAUTH
try:
zrok = root.Client()
except Exception as e:

18
util/uniqueName.go Normal file
View File

@ -0,0 +1,18 @@
package util
import (
goaway "github.com/TwiN/go-away"
"regexp"
)
// IsValidUniqueName ensures that the string represents a valid unique name. Lowercase alphanumeric only. 4-32 characters.
func IsValidUniqueName(uniqueName string) bool {
match, err := regexp.Match("^[a-z0-9]{4,32}$", []byte(uniqueName))
if err != nil {
return false
}
if match && goaway.IsProfane(uniqueName) {
return false
}
return match
}