From cf6fcda75c6f1130b85a83358f2e083afb570979 Mon Sep 17 00:00:00 2001 From: Matthias Hanel Date: Mon, 18 May 2020 12:48:38 -0400 Subject: [PATCH] Added default_permissions to accounts and account jwt Signed-off-by: Matthias Hanel --- go.mod | 7 +- go.sum | 49 +--------- server/accounts.go | 46 ++++++---- server/accounts_test.go | 2 +- server/config_check_test.go | 4 +- server/opts.go | 89 +++++++++++-------- server/opts_test.go | 78 ++++++++++++---- .../nats-io/jwt/v2/account_claims.go | 14 +-- vendor/github.com/nats-io/jwt/v2/exports.go | 32 +++++-- vendor/github.com/nats-io/jwt/v2/go.mod | 2 +- vendor/github.com/nats-io/jwt/v2/go.sum | 16 +--- vendor/modules.txt | 11 +-- 12 files changed, 188 insertions(+), 162 deletions(-) diff --git a/go.mod b/go.mod index 0f350d71..96c06cb0 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,13 @@ module github.com/nats-io/nats-server/v2 -go 1.14 - require ( github.com/minio/highwayhash v1.0.0 - github.com/nats-io/jwt/v2 v2.0.0-20200601202241-430770d434ee + github.com/nats-io/jwt/v2 v2.0.0-20200602193336-473d698956ed github.com/nats-io/nats.go v1.10.1-0.20200601214746-e93e18d0ed6f github.com/nats-io/nkeys v0.2.0 github.com/nats-io/nuid v1.0.1 golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 - google.golang.org/protobuf v1.24.0 // indirect ) + +go 1.13 diff --git a/go.sum b/go.sum index 4d07e887..b5e683be 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,10 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= @@ -26,8 +14,8 @@ github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5 github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7 h1:RnGotxlghqR5D2KDAu4TyuLqyjuylOsJiAFhXvMvQIc= github.com/nats-io/jwt v0.3.3-0.20200519195258-f2bf5ce574c7/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= -github.com/nats-io/jwt/v2 v2.0.0-20200601202241-430770d434ee h1:MTaoV13IU9JY5VgSTHmFZNPlLfY7HQuKARk21cj1J/w= -github.com/nats-io/jwt/v2 v2.0.0-20200601202241-430770d434ee/go.mod h1:mOCQTs5xlE5oOb1sTYB5bNGb7HPgZaz7/kK9F9xKGBY= +github.com/nats-io/jwt/v2 v2.0.0-20200602193336-473d698956ed h1:nnV8Mw23aNwNpKuQWuVBEuAqyBOEY21hLWKpVdNr6dQ= +github.com/nats-io/jwt/v2 v2.0.0-20200602193336-473d698956ed/go.mod h1:vs+ZEjP+XKy8szkBmQwCB7RjYdIlMaPsFPs4VdS4bTQ= github.com/nats-io/nats-server/v2 v2.1.8-0.20200524125952-51ebd92a9093/go.mod h1:rQnBf2Rv4P9adtAs/Ti6LfFmVtFG6HLhl/H7cVshcJU= github.com/nats-io/nats-server/v2 v2.1.8-0.20200601203034-f8d6dd992b71/go.mod h1:Nan/1L5Sa1JRW+Thm4HNYcIDcVRFc5zK9OpSZeI2kk4= github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= @@ -40,54 +28,23 @@ github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM= github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/accounts.go b/server/accounts.go index baf4534a..2b66ef2a 100644 --- a/server/accounts.go +++ b/server/accounts.go @@ -65,14 +65,15 @@ type Account struct { js *jsAccount jsLimits *JetStreamAccountLimits limits - expired bool - signingKeys []string - srv *Server // server this account is registered with (possibly nil) - lds string // loop detection subject for leaf nodes - siReply []byte // service reply prefix, will form wildcard subscription. - prand *rand.Rand - eventIds *nuid.NUID - eventIdsMu sync.Mutex + expired bool + signingKeys []string + srv *Server // server this account is registered with (possibly nil) + lds string // loop detection subject for leaf nodes + siReply []byte // service reply prefix, will form wildcard subscription. + prand *rand.Rand + eventIds *nuid.NUID + eventIdsMu sync.Mutex + defaultPerms *Permissions } // Account based limits. @@ -2450,6 +2451,7 @@ func (s *Server) UpdateAccountClaims(a *Account, ac *jwt.AccountClaims) { a.usersRevoked[pk] = t } } + a.defaultPerms = buildPermissionsFromJwt(&ac.DefaultPermissions) a.mu.Unlock() clients := gatherClients() @@ -2518,16 +2520,13 @@ func (s *Server) buildInternalAccount(ac *jwt.AccountClaims) *Account { return acc } -// Helper to build internal NKeyUser. -func buildInternalNkeyUser(uc *jwt.UserClaims, acc *Account) *NkeyUser { - nu := &NkeyUser{Nkey: uc.Subject, Account: acc} - if uc.IssuerAccount != "" { - nu.SigningKey = uc.Issuer +// Helper to build Permissions from jwt.Permissions +// or return nil if none were specified +func buildPermissionsFromJwt(uc *jwt.Permissions) *Permissions { + if uc == nil { + return nil } - - // Now check for permissions. var p *Permissions - if len(uc.Pub.Allow) > 0 || len(uc.Pub.Deny) > 0 { if p == nil { p = &Permissions{} @@ -2554,6 +2553,21 @@ func buildInternalNkeyUser(uc *jwt.UserClaims, acc *Account) *NkeyUser { } validateResponsePermissions(p) } + return p +} + +// Helper to build internal NKeyUser. +func buildInternalNkeyUser(uc *jwt.UserClaims, acc *Account) *NkeyUser { + nu := &NkeyUser{Nkey: uc.Subject, Account: acc} + if uc.IssuerAccount != "" { + nu.SigningKey = uc.Issuer + } + + // Now check for permissions. + var p = buildPermissionsFromJwt(&uc.Permissions) + if p == nil && acc.defaultPerms != nil { + p = acc.defaultPerms.clone() + } nu.Permissions = p return nu } diff --git a/server/accounts_test.go b/server/accounts_test.go index 45280bb7..24fa0fb9 100644 --- a/server/accounts_test.go +++ b/server/accounts_test.go @@ -390,7 +390,7 @@ func TestAccountParseConfigDuplicateUsers(t *testing.T) { func TestAccountParseConfigImportsExports(t *testing.T) { opts, err := ProcessConfigFile("./configs/accounts.conf") if err != nil { - t.Fatal(err) + t.Fatal("parsing failed: ", err) } if la := len(opts.Accounts); la != 3 { t.Fatalf("Expected to see 3 accounts in opts, got %d", la) diff --git a/server/config_check_test.go b/server/config_check_test.go index 0485c613..db0d8107 100644 --- a/server/config_check_test.go +++ b/server/config_check_test.go @@ -750,8 +750,8 @@ func TestConfigCheck(t *testing.T) { http_port = 8222 `, err: errors.New(`Duplicate user "foo" detected`), - errorLine: 6, - errorPos: 21, + errorLine: 5, + errorPos: 19, }, { name: "when accounts block imports are not a list", diff --git a/server/opts.go b/server/opts.go index d555a553..588d476a 100644 --- a/server/opts.go +++ b/server/opts.go @@ -1788,6 +1788,10 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er *errors = append(*errors, err) continue } + var ( + users []*User + nkeyUsr []*NkeyUser + ) acc := NewAccount(aname) opts.Accounts = append(opts.Accounts, acc) @@ -1825,32 +1829,19 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er continue } case "users": - nkeys, users, err := parseUsers(mv, opts, errors, warnings) + var err error + nkeyUsr, users, err = parseUsers(mv, opts, errors, warnings) if err != nil { *errors = append(*errors, err) continue } - for _, u := range users { - if _, ok := uorn[u.Username]; ok { - err := &configErr{tk, fmt.Sprintf("Duplicate user %q detected", u.Username)} - *errors = append(*errors, err) - continue - } - uorn[u.Username] = struct{}{} - u.Account = acc + case "default_permissions": + permissions, err := parseUserPermissions(tk, errors, warnings) + if err != nil { + *errors = append(*errors, err) + continue } - opts.Users = append(opts.Users, users...) - - for _, u := range nkeys { - if _, ok := uorn[u.Nkey]; ok { - err := &configErr{tk, fmt.Sprintf("Duplicate nkey %q detected", u.Nkey)} - *errors = append(*errors, err) - continue - } - uorn[u.Nkey] = struct{}{} - u.Account = acc - } - opts.Nkeys = append(opts.Nkeys, nkeys...) + acc.defaultPerms = permissions default: if !tk.IsUsedVariable() { err := &unknownConfigFieldErr{ @@ -1863,6 +1854,27 @@ func parseAccounts(v interface{}, opts *Options, errors *[]error, warnings *[]er } } } + applyDefaultPermissions(users, nkeyUsr, acc.defaultPerms) + for _, u := range nkeyUsr { + if _, ok := uorn[u.Nkey]; ok { + err := &configErr{tk, fmt.Sprintf("Duplicate nkey %q detected", u.Nkey)} + *errors = append(*errors, err) + continue + } + uorn[u.Nkey] = struct{}{} + u.Account = acc + } + opts.Nkeys = append(opts.Nkeys, nkeyUsr...) + for _, u := range users { + if _, ok := uorn[u.Username]; ok { + err := &configErr{tk, fmt.Sprintf("Duplicate user %q detected", u.Username)} + *errors = append(*errors, err) + continue + } + uorn[u.Username] = struct{}{} + u.Account = acc + } + opts.Users = append(opts.Users, users...) } } lt = tk @@ -2447,6 +2459,23 @@ func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*impo return curStream, curService, nil } +// Apply permission defaults to users/nkeyuser that don't have their own. +func applyDefaultPermissions(users []*User, nkeys []*NkeyUser, defaultP *Permissions) { + if defaultP == nil { + return + } + for _, user := range users { + if user.Permissions == nil { + user.Permissions = defaultP + } + } + for _, user := range nkeys { + if user.Permissions == nil { + user.Permissions = defaultP + } + } +} + // Helper function to parse Authorization configs. func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings *[]error) (*authorization, error) { var ( @@ -2505,23 +2534,7 @@ func parseAuthorization(v interface{}, opts *Options, errors *[]error, warnings continue } - // Now check for permission defaults with multiple users, etc. - if auth.defaultPermissions != nil { - if auth.users != nil { - for _, user := range auth.users { - if user.Permissions == nil { - user.Permissions = auth.defaultPermissions - } - } - } - if auth.nkeys != nil { - for _, user := range auth.nkeys { - if user.Permissions == nil { - user.Permissions = auth.defaultPermissions - } - } - } - } + applyDefaultPermissions(auth.users, auth.nkeys, auth.defaultPermissions) } return auth, nil } diff --git a/server/opts_test.go b/server/opts_test.go index 913a01c5..00140da7 100644 --- a/server/opts_test.go +++ b/server/opts_test.go @@ -901,7 +901,29 @@ func TestNkeyUsersDefaultPermissionsConfig(t *testing.T) { } } ] - }`)) + } + accounts { + A { + default_permissions = { + publish = "foo" + } + users = [ + { user: "accuser", password: "pwd"} + { user: "accother", password: "pwd", + permissions = { + subscribe = "bar" + } + } + { nkey: "UC4YEYJHYKTU4LHROX7UEKEIO5RP5OUWDYXELHWXZOQHZYXHUD44LCRS" } + { nkey: "UDLSDF4UY3YW7JJQCYE6T2D4KFDCH6RGF3R65KHK247G3POJPI27VMQ3", + permissions = { + subscribe = "bar" + } + } + ] + } + } + `)) checkPerms := func(permsDef *Permissions, permsNonDef *Permissions) { if permsDef.Publish.Allow[0] != "foo" { t.Fatal("Publish allow foo missing") @@ -918,26 +940,48 @@ func TestNkeyUsersDefaultPermissionsConfig(t *testing.T) { if err != nil { t.Fatalf("Received an error reading config file: %v", err) } - if lu := len(opts.Users); lu != 2 { - t.Fatalf("Expected 2 nkey users, got %d", lu) + + findUsers := func(u1, u2 string) (found []*User) { + find := []string{u1, u2} + for _, f := range find { + for _, u := range opts.Users { + if u.Username == f { + found = append(found, u) + break + } + } + } + return } - userDefault := opts.Users[0] - userNonDef := opts.Users[1] - if !strings.HasPrefix(userDefault.Username, "user") { - userDefault = opts.Users[1] - userNonDef = opts.Users[0] + + findNkeyUsers := func(nk1, nk2 string) (found []*NkeyUser) { + find := []string{nk1, nk2} + for _, f := range find { + for _, u := range opts.Nkeys { + if strings.HasPrefix(u.Nkey, f) { + found = append(found, u) + break + } + } + } + return } - checkPerms(userDefault.Permissions, userNonDef.Permissions) - if lu := len(opts.Nkeys); lu != 2 { - t.Fatalf("Expected 2 nkey users, got %d", lu) + + if lu := len(opts.Users); lu != 4 { + t.Fatalf("Expected 4 nkey users, got %d", lu) } - nkeyDefault := opts.Nkeys[0] - nkeyNonDef := opts.Nkeys[1] - if !strings.HasPrefix(nkeyDefault.Nkey, "UDK") { - nkeyDefault = opts.Nkeys[1] - nkeyNonDef = opts.Nkeys[0] + foundU := findUsers("user", "other") + checkPerms(foundU[0].Permissions, foundU[1].Permissions) + foundU = findUsers("accuser", "accother") + checkPerms(foundU[0].Permissions, foundU[1].Permissions) + + if lu := len(opts.Nkeys); lu != 4 { + t.Fatalf("Expected 4 nkey users, got %d", lu) } - checkPerms(nkeyDefault.Permissions, nkeyNonDef.Permissions) + foundNk := findNkeyUsers("UDK", "UA3") + checkPerms(foundNk[0].Permissions, foundNk[1].Permissions) + foundNk = findNkeyUsers("UC4", "UDL") + checkPerms(foundNk[0].Permissions, foundNk[1].Permissions) } func TestNkeyUsersWithPermsConfig(t *testing.T) { diff --git a/vendor/github.com/nats-io/jwt/v2/account_claims.go b/vendor/github.com/nats-io/jwt/v2/account_claims.go index b54c8fa8..e878efe5 100644 --- a/vendor/github.com/nats-io/jwt/v2/account_claims.go +++ b/vendor/github.com/nats-io/jwt/v2/account_claims.go @@ -55,12 +55,13 @@ func (o *OperatorLimits) Validate(_ *ValidationResults) { // Account holds account specific claims data type Account struct { - Imports Imports `json:"imports,omitempty"` - Exports Exports `json:"exports,omitempty"` - Identities []Identity `json:"identity,omitempty"` - Limits OperatorLimits `json:"limits,omitempty"` - SigningKeys StringList `json:"signing_keys,omitempty"` - Revocations RevocationList `json:"revocations,omitempty"` + Imports Imports `json:"imports,omitempty"` + Exports Exports `json:"exports,omitempty"` + Identities []Identity `json:"identity,omitempty"` + Limits OperatorLimits `json:"limits,omitempty"` + SigningKeys StringList `json:"signing_keys,omitempty"` + Revocations RevocationList `json:"revocations,omitempty"` + DefaultPermissions Permissions `json:"default_permissions,omitempty"` GenericFields } @@ -69,6 +70,7 @@ func (a *Account) Validate(acct *AccountClaims, vr *ValidationResults) { a.Imports.Validate(acct.Subject, vr) a.Exports.Validate(vr) a.Limits.Validate(vr) + a.DefaultPermissions.Validate(vr) for _, i := range a.Identities { i.Validate(vr) diff --git a/vendor/github.com/nats-io/jwt/v2/exports.go b/vendor/github.com/nats-io/jwt/v2/exports.go index f1f1bea7..43853f0d 100644 --- a/vendor/github.com/nats-io/jwt/v2/exports.go +++ b/vendor/github.com/nats-io/jwt/v2/exports.go @@ -17,6 +17,7 @@ package jwt import ( "fmt" + "strings" "time" ) @@ -71,13 +72,14 @@ func (sl *ServiceLatency) Validate(vr *ValidationResults) { // Export represents a single export type Export struct { - Name string `json:"name,omitempty"` - Subject Subject `json:"subject,omitempty"` - Type ExportType `json:"type,omitempty"` - TokenReq bool `json:"token_req,omitempty"` - Revocations RevocationList `json:"revocations,omitempty"` - ResponseType ResponseType `json:"response_type,omitempty"` - Latency *ServiceLatency `json:"service_latency,omitempty"` + Name string `json:"name,omitempty"` + Subject Subject `json:"subject,omitempty"` + Type ExportType `json:"type,omitempty"` + TokenReq bool `json:"token_req,omitempty"` + Revocations RevocationList `json:"revocations,omitempty"` + ResponseType ResponseType `json:"response_type,omitempty"` + Latency *ServiceLatency `json:"service_latency,omitempty"` + AccountTokenPosition uint `json:"account_token_position,omitempty"` } // IsService returns true if an export is for a service @@ -124,6 +126,22 @@ func (e *Export) Validate(vr *ValidationResults) { e.Latency.Validate(vr) } e.Subject.Validate(vr) + if e.AccountTokenPosition > 0 { + if !e.Subject.HasWildCards() { + vr.AddError("Account Token Position can only be used with wildcard subjects: %s", e.Subject) + } else { + subj := string(e.Subject) + token := strings.Split(subj, ".") + tkCnt := uint(len(token)) + if e.AccountTokenPosition > tkCnt { + vr.AddError("Account Token Position %d exceeds length of subject '%s'", + e.AccountTokenPosition, e.Subject) + } else if tk := token[e.AccountTokenPosition-1]; tk != "*" { + vr.AddError("Account Token Position %d matches '%s' but must match a * in: %s", + e.AccountTokenPosition, tk, e.Subject) + } + } + } } // Revoke enters a revocation by publickey using time.Now(). diff --git a/vendor/github.com/nats-io/jwt/v2/go.mod b/vendor/github.com/nats-io/jwt/v2/go.mod index 9a2c5a3b..420392a3 100644 --- a/vendor/github.com/nats-io/jwt/v2/go.mod +++ b/vendor/github.com/nats-io/jwt/v2/go.mod @@ -2,7 +2,7 @@ module github.com/nats-io/jwt/v2 require ( github.com/nats-io/jwt v0.3.2 - github.com/nats-io/nkeys v0.1.4 + github.com/nats-io/nkeys v0.2.0 ) replace github.com/nats-io/jwt v0.3.2 => ../ diff --git a/vendor/github.com/nats-io/jwt/v2/go.sum b/vendor/github.com/nats-io/jwt/v2/go.sum index eed6be47..05ef1fb0 100644 --- a/vendor/github.com/nats-io/jwt/v2/go.sum +++ b/vendor/github.com/nats-io/jwt/v2/go.sum @@ -1,13 +1,5 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA= -github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/nats-io/nkeys v0.2.0 h1:WXKF7diOaPU9cJdLD7nuzwasQy9vT1tBqzXZZf3AMJM= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -15,7 +7,3 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/modules.txt b/vendor/modules.txt index 3935c216..f99068cb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,33 +1,24 @@ # github.com/minio/highwayhash v1.0.0 -## explicit github.com/minio/highwayhash -# github.com/nats-io/jwt/v2 v2.0.0-20200601202241-430770d434ee -## explicit +# github.com/nats-io/jwt/v2 v2.0.0-20200602193336-473d698956ed github.com/nats-io/jwt/v2 # github.com/nats-io/nats.go v1.10.1-0.20200601214746-e93e18d0ed6f -## explicit github.com/nats-io/nats.go github.com/nats-io/nats.go/encoders/builtin github.com/nats-io/nats.go/util # github.com/nats-io/nkeys v0.2.0 -## explicit github.com/nats-io/nkeys # github.com/nats-io/nuid v1.0.1 -## explicit github.com/nats-io/nuid # golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 -## explicit golang.org/x/crypto/bcrypt golang.org/x/crypto/blowfish golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 # golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 -## explicit golang.org/x/sys/cpu golang.org/x/sys/windows golang.org/x/sys/windows/registry golang.org/x/sys/windows/svc golang.org/x/sys/windows/svc/eventlog golang.org/x/sys/windows/svc/mgr -# google.golang.org/protobuf v1.24.0 -## explicit