Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tags are now case-sensitive, describe account lists tags associated with the account #668

Merged
merged 2 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions cmd/describer.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,7 @@ func AddStandardClaimInfo(table *tablewriter.Table, claims jwt.Claims) {
}
tags = ac.Tags
}
if acc, ok := claims.(*jwt.ActivationClaims); ok {
if acc.IssuerAccount != "" {
issuer = acc.IssuerAccount
}
if acc, ok := claims.(*jwt.AccountClaims); ok {
tags = acc.Tags
}
if uc, ok := claims.(*jwt.UserClaims); ok {
Expand Down
1 change: 1 addition & 0 deletions cmd/editaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func createEditAccount() *cobra.Command {
return RunAction(cmd, args, params)
},
}
cmd.Flags().BoolVarP(&params.strictTags, "strict-tags", "", false, "allow tags to be case-sensitive, default false")
cmd.Flags().StringSliceVarP(&params.tags, "tag", "", nil, "add tags for user - comma separated list or option can be specified multiple times")
cmd.Flags().StringSliceVarP(&params.rmTags, "rm-tag", "", nil, "remove tag - comma separated list or option can be specified multiple times")
params.conns = -1
Expand Down
41 changes: 33 additions & 8 deletions cmd/editaccount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func Test_EditAccount(t *testing.T) {
{createEditAccount(), []string{"edit", "account"}, nil, []string{"specify an edit option"}, true},
{createEditAccount(), []string{"edit", "account", "--info-url", "http://foo/bar"}, nil, []string{"changed info url to"}, false},
{createEditAccount(), []string{"edit", "account", "--description", "my account is about this"}, nil, []string{"changed description to"}, false},
{createEditAccount(), []string{"edit", "account", "--tag", "A", "--name", "A"}, nil, []string{"edited account \"A\""}, false},
{createEditAccount(), []string{"edit", "account", "--tag", "a", "--name", "A"}, nil, []string{"edited account \"A\""}, false},
}

tests.Run(t, "root", "edit")
Expand All @@ -60,7 +60,7 @@ func Test_EditAccount_Tag(t *testing.T) {
defer ts.Done(t)

ts.AddAccount(t, "A")
_, _, err := ExecuteCmd(createEditAccount(), "--tag", "A,B,C")
_, _, err := ExecuteCmd(createEditAccount(), "--tag", "a,b,c")
require.NoError(t, err)

ac, err := ts.Store.ReadAccountClaim("A")
Expand All @@ -75,17 +75,17 @@ func Test_EditAccount_RmTag(t *testing.T) {
defer ts.Done(t)

ts.AddAccount(t, "A")
_, _, err := ExecuteCmd(createEditAccount(), "--tag", "A,B,C")
_, _, err := ExecuteCmd(createEditAccount(), "--tag", "A,B,C", "--strict-tags")
require.NoError(t, err)

_, _, err = ExecuteCmd(createEditAccount(), "--rm-tag", "A,B")
_, _, err = ExecuteCmd(createEditAccount(), "--rm-tag", "A,B", "--strict-tags")
require.NoError(t, err)

ac, err := ts.Store.ReadAccountClaim("A")
require.NoError(t, err)

require.Len(t, ac.Tags, 1)
require.ElementsMatch(t, ac.Tags, []string{"c"})
require.ElementsMatch(t, ac.Tags, []string{"C"})
}

func Test_EditAccount_Times(t *testing.T) {
Expand Down Expand Up @@ -380,17 +380,17 @@ func Test_EditSysAccount(t *testing.T) {
for idx, n := range jsOptions {
flag := fmt.Sprintf("--%s", n)
if idx > 0 {
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "A", flag, "1")
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "a", flag, "1")
require.Error(t, err)
require.Contains(t, err.Error(), flag)
} else {
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "A", flag)
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "a", flag)
require.Error(t, err)
require.Contains(t, err.Error(), flag)
}
}
// defaults are removed automatically
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "A")
_, _, err = ExecuteCmd(createEditAccount(), "SYS", "--tag", "a")
require.NoError(t, err)
}

Expand Down Expand Up @@ -524,3 +524,28 @@ func Test_EnableTierNoOtherFlag(t *testing.T) {
require.Error(t, err)
require.Equal(t, "rm-js-tier is exclusive of all other js options", err.Error())
}

func TestEditAccountStrictTags(t *testing.T) {
ts := NewTestStore(t, "O")
defer ts.Done(t)

ts.AddAccount(t, "A")

_, _, err := ExecuteCmd(createEditAccount(), "--tag", "a")
require.NoError(t, err)

_, _, err = ExecuteCmd(createEditAccount(), "--rm-tag", "A")
require.Error(t, err)
require.Contains(t, err.Error(), "--rm-tag \"A\" is not lowercased")

_, _, err = ExecuteCmd(createEditAccount(), "--rm-tag", "A", "--strict-tags")
require.Error(t, err)
require.Contains(t, err.Error(), "unable to remove tag: \"A\" - not found")

_, _, err = ExecuteCmd(createEditAccount(), "--tag", "A", "--strict-tags")
require.NoError(t, err)

uc, err := ts.Store.ReadAccountClaim("A")
require.NoError(t, err)
require.True(t, uc.Tags.Equals(&jwt.TagList{"A", "a"}))
}
1 change: 1 addition & 0 deletions cmd/editoperator.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func createEditOperatorCmd() *cobra.Command {
}
params.signingKeys.BindFlags("sk", "", nkeys.PrefixByteOperator, cmd)
cmd.Flags().StringSliceVarP(&params.rmSigningKeys, "rm-sk", "", nil, "remove signing key - comma separated list or option can be specified multiple times")
cmd.Flags().BoolVarP(&params.strictTags, "strict-tags", "", false, "allow tags to be case-sensitive, default false")
cmd.Flags().StringSliceVarP(&params.tags, "tag", "", nil, "add tags for user - comma separated list or option can be specified multiple times")
cmd.Flags().StringSliceVarP(&params.rmTags, "rm-tag", "", nil, "remove tag - comma separated list or option can be specified multiple times")
cmd.Flags().StringVarP(&params.asu, "account-jwt-server-url", "u", "", "set account jwt server url for nsc sync (only http/https or nats service (nats/tls/ws/wss) urls supported if updating with nsc)")
Expand Down
28 changes: 27 additions & 1 deletion cmd/editoperator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func Test_EditOperator(t *testing.T) {
{createEditOperatorCmd(), []string{"edit", "operator", "--sk"}, nil, []string{"flag needs an argument"}, true},
{createEditOperatorCmd(), []string{"edit", "operator", "--sk", "SAADOZRUTPZS6LIXS6CSSSW5GXY3DNMQMSDTVWHQNHQTIBPGNSADSMBPEU"}, nil, []string{"invalid operator signing key"}, true},
{createEditOperatorCmd(), []string{"edit", "operator", "--sk", "OBMWGGURAFWMH3AFDX65TVIH4ZYSL7UKZ3LOH2ZRWIAU7PGZ3IJNR6W5"}, nil, []string{"edited operator"}, false},
{createEditOperatorCmd(), []string{"edit", "operator", "--tag", "O", "--start", "2019-04-13", "--expiry", "2050-01-01"}, nil, []string{"edited operator"}, false},
{createEditOperatorCmd(), []string{"edit", "operator", "--tag", "o", "--start", "2019-04-13", "--expiry", "2050-01-01"}, nil, []string{"edited operator"}, false},
{createEditOperatorCmd(), []string{"edit", "operator", "--require-signing-keys"}, nil, []string{"needs to be issued with a signing key first"}, true},
}

Expand Down Expand Up @@ -420,3 +420,29 @@ func Test_CannotSetRequireSKWithoutSK(t *testing.T) {
require.False(t, oc.StrictSigningKeyUsage)
require.Empty(t, oc.SigningKeys)
}

func TestEditOperatorStrictTags(t *testing.T) {
ts := NewTestStore(t, "O")
defer ts.Done(t)

_, _, err := ExecuteCmd(createEditOperatorCmd(), "--tag", "A")
require.Error(t, err)

_, _, err = ExecuteCmd(createEditOperatorCmd(), "--tag", "a")
require.NoError(t, err)

_, _, err = ExecuteCmd(createEditOperatorCmd(), "--rm-tag", "A")
require.Error(t, err)
require.Contains(t, err.Error(), "--rm-tag \"A\" is not lowercased")

_, _, err = ExecuteCmd(createEditOperatorCmd(), "--rm-tag", "A", "--strict-tags")
require.Error(t, err)
require.Contains(t, err.Error(), "unable to remove tag: \"A\" - not found")

_, _, err = ExecuteCmd(createEditOperatorCmd(), "--tag", "A", "--strict-tags")
require.NoError(t, err)

oc, err := ts.Store.ReadOperatorClaim()
require.NoError(t, err)
require.True(t, oc.Tags.Equals(&jwt.TagList{"A", "a"}))
}
1 change: 1 addition & 0 deletions cmd/edituser.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ nsc edit user --name <n> --rm-response-perms
return RunAction(cmd, args, &params)
},
}
cmd.Flags().BoolVarP(&params.strictTags, "strict-tags", "", false, "allow tags to be case-sensitive, default false")
cmd.Flags().StringSliceVarP(&params.tags, "tag", "", nil, "add tags for user - comma separated list or option can be specified multiple times")
cmd.Flags().StringSliceVarP(&params.rmTags, "rm-tag", "", nil, "remove tag - comma separated list or option can be specified multiple times")
cmd.Flags().StringVarP(&params.name, "name", "n", "", "user name")
Expand Down
44 changes: 36 additions & 8 deletions cmd/edituser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
package cmd

import (
"github.com/nats-io/nsc/v2/cmd/store"
"strings"
"testing"
"time"

"github.com/nats-io/nsc/v2/cmd/store"

"github.com/nats-io/nkeys"

cli "github.com/nats-io/cliprompts/v2"
Expand All @@ -38,12 +39,13 @@ func Test_EditUser(t *testing.T) {

tests := CmdTests{
{createEditUserCmd(), []string{"edit", "user"}, nil, []string{"specify an edit option"}, true},
{createEditUserCmd(), []string{"edit", "user", "--tag", "A", "--account", "A"}, nil, []string{"edited user \"a\""}, false},
{createEditUserCmd(), []string{"edit", "user", "--tag", "A", "--account", "A"}, nil, []string{"--tag \"A\" is not lowercased"}, true},
{createEditUserCmd(), []string{"edit", "user", "--tag", "a", "--account", "A"}, nil, []string{"edited user \"a\""}, false},
{createEditUserCmd(), []string{"edit", "user", "--conn-type", "MQTT", "--rm-conn-type", "LEAFNODE", "--account", "A"}, nil, []string{"added connection type MQTT", "added connection type MQTT"}, false},
{createEditUserCmd(), []string{"edit", "user", "--conn-type", "LEAFNODE_WS", "--account", "A"}, nil, []string{"added connection type LEAFNODE_WS"}, false},
{createEditUserCmd(), []string{"edit", "user", "--conn-type", "MQTT_WS", "--account", "A"}, nil, []string{"added connection type MQTT_WS"}, false},
{createEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B"}, nil, []string{"user name is required"}, true},
{createEditUserCmd(), []string{"edit", "user", "--tag", "B", "--account", "B", "--name", "bb"}, nil, []string{"edited user \"bb\""}, false},
{createEditUserCmd(), []string{"edit", "user", "--tag", "b", "--account", "B"}, nil, []string{"user name is required"}, true},
{createEditUserCmd(), []string{"edit", "user", "--tag", "b", "--account", "B", "--name", "bb"}, nil, []string{"edited user \"bb\""}, false},
}

tests.Run(t, "root", "edit")
Expand Down Expand Up @@ -107,25 +109,25 @@ func Test_EditUser_Tag(t *testing.T) {
defer ts.Done(t)

ts.AddUser(t, "A", "a")
_, _, err := ExecuteCmd(createEditUserCmd(), "--tag", "A,B,C")
_, _, err := ExecuteCmd(createEditUserCmd(), "--tag", "A,B,C", "--strict-tags")
require.NoError(t, err)

cc, err := ts.Store.ReadUserClaim("A", "a")
require.NoError(t, err)
require.NotNil(t, cc)

require.Len(t, cc.Tags, 3)
require.ElementsMatch(t, cc.Tags, []string{"a", "b", "c"})
require.ElementsMatch(t, cc.Tags, []string{"A", "B", "C"})

_, _, err = ExecuteCmd(createEditUserCmd(), "--rm-tag", "A,B")
_, _, err = ExecuteCmd(createEditUserCmd(), "--rm-tag", "A,B", "--strict-tags")
require.NoError(t, err)

cc, err = ts.Store.ReadUserClaim("A", "a")
require.NoError(t, err)
require.NotNil(t, cc)

require.Len(t, cc.Tags, 1)
require.ElementsMatch(t, cc.Tags, []string{"c"})
require.ElementsMatch(t, cc.Tags, []string{"C"})

}

Expand Down Expand Up @@ -595,3 +597,29 @@ func Test_EditUserConnectionDeleteCase(t *testing.T) {
require.NoError(t, err)
require.Len(t, claim.AllowedConnectionTypes, 0)
}

func TestEditUserStrictTags(t *testing.T) {
ts := NewTestStore(t, "O")
defer ts.Done(t)

ts.AddAccount(t, "A")
ts.AddUser(t, "A", "U")

_, _, err := ExecuteCmd(createEditUserCmd(), "--tag", "a")
require.NoError(t, err)

_, _, err = ExecuteCmd(createEditUserCmd(), "--rm-tag", "A")
require.Error(t, err)
require.Contains(t, err.Error(), "--rm-tag \"A\" is not lowercased")

_, _, err = ExecuteCmd(createEditUserCmd(), "--rm-tag", "A", "--strict-tags")
require.Error(t, err)
require.Contains(t, err.Error(), "unable to remove tag: \"A\" - not found")

_, _, err = ExecuteCmd(createEditUserCmd(), "--tag", "A", "--strict-tags")
require.NoError(t, err)

uc, err := ts.Store.ReadUserClaim("A", "U")
require.NoError(t, err)
require.True(t, uc.Tags.Equals(&jwt.TagList{"A", "a"}))
}
30 changes: 25 additions & 5 deletions cmd/genericclaimparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ import (
// GenericClaimsParams - TimeParams and tags
type GenericClaimsParams struct {
TimeParams
tags []string
rmTags []string
tags []string
rmTags []string
strictTags bool
}

func (sp *GenericClaimsParams) Edit(current []string) error {
Expand Down Expand Up @@ -100,6 +101,21 @@ func (sp *GenericClaimsParams) Valid() error {
if err := sp.TimeParams.Validate(); err != nil {
return err
}
if !sp.strictTags {
for _, t := range sp.tags {
tt := strings.ToLower(t)
if t != tt {
return fmt.Errorf("--tag %q is not lowercased, specify option --strict-tags to honor non-lowercased values", t)
}
}
for _, t := range sp.rmTags {
tt := strings.ToLower(t)
if t != tt {
return fmt.Errorf("--rm-tag %q is not lowercased, specify option --strict-tags", t)
}
}
}

return nil
}

Expand Down Expand Up @@ -145,15 +161,19 @@ func (sp *GenericClaimsParams) Run(ctx ActionCtx, claim jwt.Claims, r *store.Rep
}

tags.Add(sp.tags...)
tags.Remove(sp.rmTags...)
if err := tags.Remove(sp.rmTags...); err != nil {
return err
}
sort.Strings(*tags)

if r != nil {
for _, t := range sp.tags {
r.AddOK("added tag %q", strings.ToLower(t))
t = strings.TrimSpace(t)
r.AddOK("added tag %q", t)
}
for _, t := range sp.rmTags {
r.AddOK("removed tag %q", strings.ToLower(t))
t = strings.TrimSpace(t)
r.AddOK("removed tag %q", t)
}
}
return nil
Expand Down
7 changes: 4 additions & 3 deletions cmd/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func Test_SyncOK(t *testing.T) {
ts.AddAccount(t, "A")

// edit the jwt
_, _, err = ExecuteCmd(createEditAccount(), "--tag", "A")
_, _, err = ExecuteCmd(createEditAccount(), "--tag", "A", "--strict-tags")
require.NoError(t, err)

// sync the store
Expand All @@ -50,7 +50,8 @@ func Test_SyncOK(t *testing.T) {
// verify the tag was stored
ac, err := ts.Store.ReadAccountClaim("A")
require.NoError(t, err)
require.Contains(t, ac.Tags, "a")
require.Contains(t, ac.Tags, "A")
require.True(t, ac.Tags.Contains("A"))
}

func Test_SyncNoURL(t *testing.T) {
Expand Down Expand Up @@ -120,7 +121,7 @@ func Test_SyncManualServer(t *testing.T) {
ts.AddAccount(t, "A")

// edit the jwt
_, _, err = ExecuteCmd(createEditAccount(), "--tag", "A")
_, _, err = ExecuteCmd(createEditAccount(), "--tag", "a")
require.NoError(t, err)

// sync the store
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/nats-io/cliprompts/v2 v2.0.0-20231014115920-801ca035562a
github.com/nats-io/jsm.go v0.1.2
github.com/nats-io/jwt/v2 v2.6.0
github.com/nats-io/jwt/v2 v2.6.1-0.20240917143920-d3fa85bd725f
github.com/nats-io/nats-server/v2 v2.10.18
github.com/nats-io/nats.go v1.37.0
github.com/nats-io/nkeys v0.4.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ github.com/nats-io/cliprompts/v2 v2.0.0-20231014115920-801ca035562a h1:28qvB6peS
github.com/nats-io/cliprompts/v2 v2.0.0-20231014115920-801ca035562a/go.mod h1:oweZn7AeaVJYKlNHfCIhznJVsdySLSng55vfuINE/d0=
github.com/nats-io/jsm.go v0.1.2 h1:T4Fq88a03sPAPWYwrOLQ85oanYsC2Bs6517rUiWBMpQ=
github.com/nats-io/jsm.go v0.1.2/go.mod h1:tnubE70CAKi5TNfQiq6XHFqWTuSIe1H7X4sDwfq6ZK8=
github.com/nats-io/jwt/v2 v2.6.0 h1:yXoBTdEotZw3NujMT+Nnu1UPNlFWdKQ3d0JJF/+pJag=
github.com/nats-io/jwt/v2 v2.6.0/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A=
github.com/nats-io/jwt/v2 v2.6.1-0.20240917143920-d3fa85bd725f h1:izYA+fDsvJ71/nlCRmaDFPEhVpmumWx0aSNE00b+00I=
github.com/nats-io/jwt/v2 v2.6.1-0.20240917143920-d3fa85bd725f/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A=
github.com/nats-io/nats-server/v2 v2.10.18 h1:tRdZmBuWKVAFYtayqlBB2BuCHNGAQPvoQIXOKwU3WSM=
github.com/nats-io/nats-server/v2 v2.10.18/go.mod h1:97Qyg7YydD8blKlR8yBsUlPlWyZKjA7Bp5cl3MUE9K8=
github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE=
Expand Down
Loading