Skip to content

Commit

Permalink
Merge pull request #479 from openziti/vanity_share_tokens
Browse files Browse the repository at this point in the history
Unique Names (Vanity Share Tokens) (#123)
  • Loading branch information
michaelquigley committed Dec 11, 2023
2 parents 7c56800 + 4f45715 commit 444b456
Show file tree
Hide file tree
Showing 58 changed files with 747 additions and 44 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,11 @@
# CHANGELOG

## v0.4.19

FEATURE: Reserved shares now support unique names ("vanity tokens"). This allows for the creation of reserved shares with identifiable names rather than generated share tokens. Includes basic support for profanity checking (https://github.com/openziti/zrok/issues/401)

CHANGE: The Python SDK has been updated to properly support the "reserved" flag on the `ShareRequest` passed to `CreateShare`

## v0.4.18

FEATURE: Python SDK added. Can be found on [pypi](https://test.pypi.org/project/zrok-sdk). `pastebin` example illustrates basic SDK usage (see `sdk/python/examples/README.md` for details) (https://github.com/openziti/zrok/issues/401)
Expand Down
8 changes: 8 additions & 0 deletions cmd/zrok/reserve.go
Expand Up @@ -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"
Expand All @@ -17,6 +18,7 @@ func init() {
}

type reserveCommand struct {
uniqueName string
basicAuth []string
frontendSelection []string
backendMode string
Expand All @@ -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")
Expand All @@ -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":
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 13 additions & 4 deletions controller/share.go
Expand Up @@ -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"
)
Expand All @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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,
Expand Down
@@ -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;
@@ -0,0 +1,55 @@
-- +migrate Up

alter table shares rename to shares_old;
create table shares (
id integer primary key,
environment_id integer constraint fk_environments_shares references environments on delete cascade,
z_id string not null unique,
token string not null,
share_mode string not null,
backend_mode string not null,
frontend_selection string,
frontend_endpoint string,
backend_proxy_endpoint string,
reserved boolean not null default(false),
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),

constraint chk_z_id check (z_id <> ''),
constraint chk_token check (token <> ''),
constraint chk_share_mode check (share_mode == 'public' or share_mode == 'private'),
constraint chk_backend_mode check (backend_mode == 'proxy' or backend_mode == 'web' or backend_mode == 'tcpTunnel' or backend_mode == 'udpTunnel' or backend_mode == 'caddy' or backend_mode == 'drive')
);
CREATE UNIQUE INDEX shares_token_idx ON shares(token) WHERE deleted is false;
insert into shares select * from shares_old;
drop table shares_old;

alter table frontends rename to frontends_old;
create table frontends (
id integer primary key,
environment_id integer references environments(id),
token varchar(32) not null unique,
z_id varchar(32) not null,
public_name varchar(64) unique,
url_template varchar(1024),
reserved boolean not null default(false),
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),
private_share_id integer references shares(id)
);
insert into frontends select * from frontends_old;
drop table frontends_old;

alter table share_limit_journal rename to share_limit_journal_old;
create table share_limit_journal (
id integer primary key,
share_id integer references shares(id),
rx_bytes bigint not null,
tx_bytes bigint not null,
action limit_action_type 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'))
);
insert into share_limit_journal select * from share_limit_journal_old;
drop table share_limit_journal_old;
3 changes: 2 additions & 1 deletion go.mod
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down
22 changes: 21 additions & 1 deletion rest_client_zrok/account/invite_responses.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion rest_client_zrok/account/login_responses.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion rest_client_zrok/account/register_responses.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 444b456

Please sign in to comment.