[Adding] support for JS MaxBytesRequired

Signed-off-by: Matthias Hanel <mh@synadia.com>
This commit is contained in:
Matthias Hanel
2022-01-12 21:56:05 -05:00
parent 08ff14a24e
commit 78bbcd791f
8 changed files with 65 additions and 16 deletions

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/golang/protobuf v1.4.2 // indirect github.com/golang/protobuf v1.4.2 // indirect
github.com/klauspost/compress v1.13.4 github.com/klauspost/compress v1.13.4
github.com/minio/highwayhash v1.0.1 github.com/minio/highwayhash v1.0.1
github.com/nats-io/jwt/v2 v2.2.0 github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296
github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc
github.com/nats-io/nkeys v0.3.0 github.com/nats-io/nkeys v0.3.0
github.com/nats-io/nuid v1.0.1 github.com/nats-io/nuid v1.0.1

4
go.sum
View File

@@ -14,8 +14,8 @@ github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEE
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/nats-io/jwt/v2 v2.2.0 h1:Yg/4WFK6vsqMudRg91eBb7Dh6XeVcDMPHycDE8CfltE= github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 h1:vU9tpM3apjYlLLeY23zRWJ9Zktr5jp+mloR942LEOpY=
github.com/nats-io/jwt/v2 v2.2.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc h1:SHr4MUUZJ/fAC0uSm2OzWOJYsHpapmR86mpw7q1qPXU= github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc h1:SHr4MUUZJ/fAC0uSm2OzWOJYsHpapmR86mpw7q1qPXU=
github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=

View File

@@ -3195,10 +3195,11 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim
if ac.Limits.JetStreamLimits.DiskStorage != 0 || ac.Limits.JetStreamLimits.MemoryStorage != 0 { if ac.Limits.JetStreamLimits.DiskStorage != 0 || ac.Limits.JetStreamLimits.MemoryStorage != 0 {
// JetStreamAccountLimits and jwt.JetStreamLimits use same value for unlimited // JetStreamAccountLimits and jwt.JetStreamLimits use same value for unlimited
a.jsLimits = &JetStreamAccountLimits{ a.jsLimits = &JetStreamAccountLimits{
MaxMemory: ac.Limits.JetStreamLimits.MemoryStorage, MaxMemory: ac.Limits.JetStreamLimits.MemoryStorage,
MaxStore: ac.Limits.JetStreamLimits.DiskStorage, MaxStore: ac.Limits.JetStreamLimits.DiskStorage,
MaxStreams: int(ac.Limits.JetStreamLimits.Streams), MaxStreams: int(ac.Limits.JetStreamLimits.Streams),
MaxConsumers: int(ac.Limits.JetStreamLimits.Consumer), MaxConsumers: int(ac.Limits.JetStreamLimits.Consumer),
MaxBytesRequired: ac.Limits.JetStreamLimits.MaxBytesRequired,
} }
} else if a.jsLimits != nil { } else if a.jsLimits != nil {
// covers failed update followed by disable // covers failed update followed by disable

View File

@@ -4259,7 +4259,7 @@ func TestJWTJetStreamLimits(t *testing.T) {
sysKp.Seed() sysKp.Seed()
sysCreds := genCredsFile(t, sysUserJwt, sysUSeed) sysCreds := genCredsFile(t, sysUserJwt, sysUSeed)
// limits to apply and check // limits to apply and check
limits1 := jwt.JetStreamLimits{MemoryStorage: 1024 * 1024, DiskStorage: 2048 * 1024, Streams: 1, Consumer: 2} limits1 := jwt.JetStreamLimits{MemoryStorage: 1024 * 1024, DiskStorage: 2048 * 1024, Streams: 1, Consumer: 2, MaxBytesRequired: true}
// has valid limits that would fail when incorrectly applied twice // has valid limits that would fail when incorrectly applied twice
limits2 := jwt.JetStreamLimits{MemoryStorage: 4096 * 1024, DiskStorage: 8192 * 1024, Streams: 3, Consumer: 4} limits2 := jwt.JetStreamLimits{MemoryStorage: 4096 * 1024, DiskStorage: 8192 * 1024, Streams: 3, Consumer: 4}
// limits exceeding actual configured value of DiskStorage // limits exceeding actual configured value of DiskStorage

View File

@@ -51,15 +51,16 @@ func (n *NatsLimits) IsUnlimited() bool {
} }
type JetStreamLimits struct { type JetStreamLimits struct {
MemoryStorage int64 `json:"mem_storage,omitempty"` // Max number of bytes stored in memory across all streams. (0 means disabled) MemoryStorage int64 `json:"mem_storage,omitempty"` // Max number of bytes stored in memory across all streams. (0 means disabled)
DiskStorage int64 `json:"disk_storage,omitempty"` // Max number of bytes stored on disk across all streams. (0 means disabled) DiskStorage int64 `json:"disk_storage,omitempty"` // Max number of bytes stored on disk across all streams. (0 means disabled)
Streams int64 `json:"streams,omitempty"` // Max number of streams Streams int64 `json:"streams,omitempty"` // Max number of streams
Consumer int64 `json:"consumer,omitempty"` // Max number of consumer Consumer int64 `json:"consumer,omitempty"` // Max number of consumers
MaxBytesRequired bool `json:"max_bytes_required,omitempty"` // Max bytes required by all Streams
} }
// IsUnlimited returns true if all limits are unlimited // IsUnlimited returns true if all limits are unlimited
func (j *JetStreamLimits) IsUnlimited() bool { func (j *JetStreamLimits) IsUnlimited() bool {
return *j == JetStreamLimits{NoLimit, NoLimit, NoLimit, NoLimit} return *j == JetStreamLimits{NoLimit, NoLimit, NoLimit, NoLimit, false}
} }
// OperatorLimits are used to limit access by an account // OperatorLimits are used to limit access by an account
@@ -188,7 +189,7 @@ func NewAccountClaims(subject string) *AccountClaims {
c.Limits = OperatorLimits{ c.Limits = OperatorLimits{
NatsLimits{NoLimit, NoLimit, NoLimit}, NatsLimits{NoLimit, NoLimit, NoLimit},
AccountLimits{NoLimit, NoLimit, true, NoLimit, NoLimit}, AccountLimits{NoLimit, NoLimit, true, NoLimit, NoLimit},
JetStreamLimits{0, 0, 0, 0}} JetStreamLimits{0, 0, 0, 0, false}}
c.Subject = subject c.Subject = subject
c.Mappings = Mapping{} c.Mappings = Mapping{}
return c return c

View File

@@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/nats-io/nkeys" "github.com/nats-io/nkeys"
) )
@@ -216,3 +217,49 @@ func ParseDecoratedUserNKey(contents []byte) (nkeys.KeyPair, error) {
} }
return kp, nil return kp, nil
} }
// IssueUserJWT takes an account scoped signing key, account id, and use public key (and optionally a user's name, an expiration duration and tags) and returns a valid signed JWT.
// The scopedSigningKey, is a mandatory account scoped signing nkey pair to sign the generated jwt (note that it _must_ be a signing key attached to the account (and a _scoped_ signing key), not the account's private (seed) key).
// The accountId, is a mandatory public account nkey. Will return error when not set or not account nkey.
// The publicUserKey, is a mandatory public user nkey. Will return error when not set or not user nkey.
// The name, is an optional human-readable name. When absent, default to publicUserKey.
// The expirationDuration, is an optional but recommended duration, when the generated jwt needs to expire. If not set, JWT will not expire.
// The tags, is an optional list of tags to be included in the JWT.
//
// Returns:
// string, resulting jwt.
// error, when issues arose.
func IssueUserJWT(scopedSigningKey nkeys.KeyPair, accountId string, publicUserKey string, name string, expirationDuration time.Duration, tags ...string) (string, error) {
if !nkeys.IsValidPublicAccountKey(accountId) {
return "", errors.New("issueUserJWT requires an account key for the accountId parameter, but got " + nkeys.Prefix(accountId).String())
}
if !nkeys.IsValidPublicUserKey(publicUserKey) {
return "", errors.New("issueUserJWT requires an account key for the publicUserKey parameter, but got " + nkeys.Prefix(publicUserKey).String())
}
claim := NewUserClaims(publicUserKey)
claim.SetScoped(true)
if expirationDuration != 0 {
claim.Expires = time.Now().Add(expirationDuration).UTC().Unix()
}
claim.IssuerAccount = accountId
if name != "" {
claim.Name = name
} else {
claim.Name = publicUserKey
}
claim.Subject = publicUserKey
claim.Tags = tags
encoded, err := claim.Encode(scopedSigningKey)
if err != nil {
return "", errors.New("err encoding claim " + err.Error())
}
return encoded, nil
}

View File

@@ -73,7 +73,7 @@ func (oa v1AccountClaims) migrateV1() (*AccountClaims, error) {
a.Account.Exports = oa.v1NatsAccount.Exports a.Account.Exports = oa.v1NatsAccount.Exports
a.Account.Limits.AccountLimits = oa.v1NatsAccount.Limits.AccountLimits a.Account.Limits.AccountLimits = oa.v1NatsAccount.Limits.AccountLimits
a.Account.Limits.NatsLimits = oa.v1NatsAccount.Limits.NatsLimits a.Account.Limits.NatsLimits = oa.v1NatsAccount.Limits.NatsLimits
a.Account.Limits.JetStreamLimits = JetStreamLimits{0, 0, 0, 0} a.Account.Limits.JetStreamLimits = JetStreamLimits{0, 0, 0, 0, false}
a.Account.SigningKeys = make(SigningKeys) a.Account.SigningKeys = make(SigningKeys)
for _, v := range oa.SigningKeys { for _, v := range oa.SigningKeys {
a.Account.SigningKeys.Add(v) a.Account.SigningKeys.Add(v)

2
vendor/modules.txt vendored
View File

@@ -6,7 +6,7 @@ github.com/klauspost/compress/s2
# github.com/minio/highwayhash v1.0.1 # github.com/minio/highwayhash v1.0.1
## explicit ## explicit
github.com/minio/highwayhash github.com/minio/highwayhash
# github.com/nats-io/jwt/v2 v2.2.0 # github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296
## explicit ## explicit
github.com/nats-io/jwt/v2 github.com/nats-io/jwt/v2
# github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc # github.com/nats-io/nats.go v1.13.1-0.20211122170419-d7c1d78a50fc