mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-02 03:38:42 -07:00
Add in user JWT support for ResponsePermissions
Signed-off-by: Derek Collison <derek@nats.io>
This commit is contained in:
5
go.mod
5
go.mod
@@ -1,11 +1,10 @@
|
|||||||
module github.com/nats-io/nats-server/v2
|
module github.com/nats-io/nats-server/v2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.3.2 // indirect
|
github.com/nats-io/jwt v0.2.13-0.20190726194050-829b612a49c3
|
||||||
github.com/nats-io/jwt v0.2.8
|
|
||||||
github.com/nats-io/nats.go v1.8.1
|
github.com/nats-io/nats.go v1.8.1
|
||||||
github.com/nats-io/nkeys v0.1.0
|
github.com/nats-io/nkeys v0.1.0
|
||||||
github.com/nats-io/nuid v1.0.1
|
github.com/nats-io/nuid v1.0.1
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e
|
||||||
)
|
)
|
||||||
|
|||||||
11
go.sum
11
go.sum
@@ -1,10 +1,7 @@
|
|||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/nats-io/jwt v0.2.13-0.20190726194050-829b612a49c3 h1:5vVSRJhjWOTv/TeJX1NUGuDYbZkfcWTu/97AHlsC02o=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/nats-io/jwt v0.2.13-0.20190726194050-829b612a49c3/go.mod h1:mQxQ0uHQ9FhEVPIcTSKwx2lqZEpXWWcCgA7R6NrWvvY=
|
||||||
github.com/nats-io/jwt v0.2.8 h1:PXr0mRjPCPX4cXsdfHcsqoplrNXnKOD+g2yHoh9qy1I=
|
|
||||||
github.com/nats-io/jwt v0.2.8/go.mod h1:mQxQ0uHQ9FhEVPIcTSKwx2lqZEpXWWcCgA7R6NrWvvY=
|
|
||||||
github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ=
|
github.com/nats-io/nats.go v1.8.1 h1:6lF/f1/NN6kzUDBz6pyvQDEXO39jqXcWRLu/tKjtOUQ=
|
||||||
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
|
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
|
||||||
github.com/nats-io/nkeys v0.0.2 h1:+qM7QpgXnvDDixitZtQUBDY9w/s9mu1ghS+JIbsrx6M=
|
|
||||||
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
|
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
|
||||||
github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
|
github.com/nats-io/nkeys v0.1.0 h1:qMd4+pRHgdr1nAClu+2h/2a5F2TmKcCzjCDazVgRoX4=
|
||||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
@@ -16,8 +13,6 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49N
|
|||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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 h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|||||||
@@ -586,8 +586,9 @@ func (a *Account) AddStreamExport(subject string, accounts []*Account) error {
|
|||||||
func (a *Account) checkStreamImportAuthorized(account *Account, subject string, imClaim *jwt.Import) bool {
|
func (a *Account) checkStreamImportAuthorized(account *Account, subject string, imClaim *jwt.Import) bool {
|
||||||
// Find the subject in the exports list.
|
// Find the subject in the exports list.
|
||||||
a.mu.RLock()
|
a.mu.RLock()
|
||||||
defer a.mu.RUnlock()
|
auth := a.checkStreamImportAuthorizedNoLock(account, subject, imClaim)
|
||||||
return a.checkStreamImportAuthorizedNoLock(account, subject, imClaim)
|
a.mu.RUnlock()
|
||||||
|
return auth
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Account) checkStreamImportAuthorizedNoLock(account *Account, subject string, imClaim *jwt.Import) bool {
|
func (a *Account) checkStreamImportAuthorizedNoLock(account *Account, subject string, imClaim *jwt.Import) bool {
|
||||||
@@ -1165,6 +1166,19 @@ func buildInternalNkeyUser(uc *jwt.UserClaims, acc *Account) *NkeyUser {
|
|||||||
p.Subscribe.Allow = uc.Sub.Allow
|
p.Subscribe.Allow = uc.Sub.Allow
|
||||||
p.Subscribe.Deny = uc.Sub.Deny
|
p.Subscribe.Deny = uc.Sub.Deny
|
||||||
}
|
}
|
||||||
|
if uc.Resp != nil {
|
||||||
|
if p == nil {
|
||||||
|
p = &Permissions{Publish: &SubjectPermission{}}
|
||||||
|
}
|
||||||
|
if p.Publish.Allow == nil {
|
||||||
|
// We turn off the blanket allow statement.
|
||||||
|
p.Publish.Allow = []string{}
|
||||||
|
}
|
||||||
|
p.Response = &ResponsePermission{
|
||||||
|
MaxMsgs: uc.Resp.MaxMsgs,
|
||||||
|
Expires: uc.Resp.Expires,
|
||||||
|
}
|
||||||
|
}
|
||||||
nu.Permissions = p
|
nu.Permissions = p
|
||||||
return nu
|
return nu
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,6 +370,78 @@ func TestJWTUserPermissionClaims(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJWTUserResponsePermissionClaims(t *testing.T) {
|
||||||
|
okp, _ := nkeys.FromSeed(oSeed)
|
||||||
|
|
||||||
|
nkp, _ := nkeys.CreateUser()
|
||||||
|
pub, _ := nkp.PublicKey()
|
||||||
|
nuc := jwt.NewUserClaims(pub)
|
||||||
|
nuc.Permissions.Resp = &jwt.ResponsePermission{
|
||||||
|
MaxMsgs: 22,
|
||||||
|
Expires: 100 * time.Millisecond,
|
||||||
|
}
|
||||||
|
|
||||||
|
akp, _ := nkeys.FromSeed(aSeed)
|
||||||
|
apub, _ := akp.PublicKey()
|
||||||
|
nac := jwt.NewAccountClaims(apub)
|
||||||
|
ajwt, err := nac.Encode(okp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error generating account JWT: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt, err := nuc.Encode(akp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error generating user JWT: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := opTrustBasicSetup()
|
||||||
|
defer s.Shutdown()
|
||||||
|
buildMemAccResolver(s)
|
||||||
|
addAccountToMemResolver(s, apub, ajwt)
|
||||||
|
|
||||||
|
c, cr, l := newClientForServer(s)
|
||||||
|
|
||||||
|
// Sign Nonce
|
||||||
|
var info nonceInfo
|
||||||
|
json.Unmarshal([]byte(l[5:]), &info)
|
||||||
|
sigraw, _ := nkp.Sign([]byte(info.Nonce))
|
||||||
|
sig := base64.RawURLEncoding.EncodeToString(sigraw)
|
||||||
|
|
||||||
|
// PING needed to flush the +OK/-ERR to us.
|
||||||
|
// This should fail too since no account resolver is defined.
|
||||||
|
cs := fmt.Sprintf("CONNECT {\"jwt\":%q,\"sig\":\"%s\",\"verbose\":true,\"pedantic\":true}\r\nPING\r\n", jwt, sig)
|
||||||
|
go c.parse([]byte(cs))
|
||||||
|
l, _ = cr.ReadString('\n')
|
||||||
|
if !strings.HasPrefix(l, "+OK") {
|
||||||
|
t.Fatalf("Expected an OK, got: %v", l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check client to make sure permissions transferred.
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
if c.perms == nil {
|
||||||
|
t.Fatalf("Expected client permissions to be set")
|
||||||
|
}
|
||||||
|
if c.perms.pub.allow == nil {
|
||||||
|
t.Fatalf("Expected client perms for pub allow to be non-nil")
|
||||||
|
}
|
||||||
|
if lpa := c.perms.pub.allow.Count(); lpa != 0 {
|
||||||
|
t.Fatalf("Expected 0 publish allow subjects, got %d", lpa)
|
||||||
|
}
|
||||||
|
if c.perms.resp == nil {
|
||||||
|
t.Fatalf("Expected client perms for response permissions to be non-nil")
|
||||||
|
}
|
||||||
|
if c.perms.resp.MaxMsgs != nuc.Permissions.Resp.MaxMsgs {
|
||||||
|
t.Fatalf("Expected client perms for response permissions MaxMsgs to be same as jwt: %d vs %d",
|
||||||
|
c.perms.resp.MaxMsgs, nuc.Permissions.Resp.MaxMsgs)
|
||||||
|
}
|
||||||
|
if c.perms.resp.Expires != nuc.Permissions.Resp.Expires {
|
||||||
|
t.Fatalf("Expected client perms for response permissions Expires to be same as jwt: %v vs %v",
|
||||||
|
c.perms.resp.Expires, nuc.Permissions.Resp.Expires)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestJWTAccountExpired(t *testing.T) {
|
func TestJWTAccountExpired(t *testing.T) {
|
||||||
s := opTrustBasicSetup()
|
s := opTrustBasicSetup()
|
||||||
defer s.Shutdown()
|
defer s.Shutdown()
|
||||||
|
|||||||
5
vendor/github.com/nats-io/jwt/ReleaseNotes.md
generated
vendored
Normal file
5
vendor/github.com/nats-io/jwt/ReleaseNotes.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Release Notes
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
* Removed revocation claims in favor of timestamp-based revocation maps in account and export claims.
|
||||||
38
vendor/github.com/nats-io/jwt/account_claims.go
generated
vendored
38
vendor/github.com/nats-io/jwt/account_claims.go
generated
vendored
@@ -17,11 +17,12 @@ package jwt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/nats-io/nkeys"
|
"github.com/nats-io/nkeys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Signifies no limit.
|
// NoLimit is used to indicate a limit field is unlimited in value.
|
||||||
const NoLimit = -1
|
const NoLimit = -1
|
||||||
|
|
||||||
// OperatorLimits are used to limit access by an account
|
// OperatorLimits are used to limit access by an account
|
||||||
@@ -58,6 +59,7 @@ type Account struct {
|
|||||||
Identities []Identity `json:"identity,omitempty"`
|
Identities []Identity `json:"identity,omitempty"`
|
||||||
Limits OperatorLimits `json:"limits,omitempty"`
|
Limits OperatorLimits `json:"limits,omitempty"`
|
||||||
SigningKeys StringList `json:"signing_keys,omitempty"`
|
SigningKeys StringList `json:"signing_keys,omitempty"`
|
||||||
|
Revocations RevocationList `json:"revocations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks if the account is valid, based on the wrapper
|
// Validate checks if the account is valid, based on the wrapper
|
||||||
@@ -127,7 +129,7 @@ func (a *AccountClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a.ClaimsData.Type = AccountClaim
|
a.ClaimsData.Type = AccountClaim
|
||||||
return a.ClaimsData.encode(pair, a)
|
return a.ClaimsData.Encode(pair, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeAccountClaims decodes account claims from a JWT string
|
// DecodeAccountClaims decodes account claims from a JWT string
|
||||||
@@ -184,3 +186,35 @@ func (a *AccountClaims) DidSign(op Claims) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Revoke enters a revocation by publickey using time.Now().
|
||||||
|
func (a *AccountClaims) Revoke(pubKey string) {
|
||||||
|
a.RevokeAt(pubKey, time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeAt enters a revocation by publickey and timestamp into this export
|
||||||
|
// If there is already a revocation for this public key that is newer, it is kept.
|
||||||
|
func (a *AccountClaims) RevokeAt(pubKey string, timestamp time.Time) {
|
||||||
|
if a.Revocations == nil {
|
||||||
|
a.Revocations = RevocationList{}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.Revocations.Revoke(pubKey, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearRevocation removes any revocation for the public key
|
||||||
|
func (a *AccountClaims) ClearRevocation(pubKey string) {
|
||||||
|
a.Revocations.ClearRevocation(pubKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than
|
||||||
|
// the one passed in. Generally this method is called with time.Now() but other time's can
|
||||||
|
// be used for testing.
|
||||||
|
func (a *AccountClaims) IsRevokedAt(pubKey string, timestamp time.Time) bool {
|
||||||
|
return a.Revocations.IsRevoked(pubKey, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRevoked checks if the public key is in the revoked list with time.Now()
|
||||||
|
func (a *AccountClaims) IsRevoked(pubKey string) bool {
|
||||||
|
return a.Revocations.IsRevoked(pubKey, time.Now())
|
||||||
|
}
|
||||||
|
|||||||
2
vendor/github.com/nats-io/jwt/activation_claims.go
generated
vendored
2
vendor/github.com/nats-io/jwt/activation_claims.go
generated
vendored
@@ -83,7 +83,7 @@ func (a *ActivationClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
return "", errors.New("expected subject to be an account")
|
return "", errors.New("expected subject to be an account")
|
||||||
}
|
}
|
||||||
a.ClaimsData.Type = ActivationClaim
|
a.ClaimsData.Type = ActivationClaim
|
||||||
return a.ClaimsData.encode(pair, a)
|
return a.ClaimsData.Encode(pair, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeActivationClaims tries to create an activation claim from a JWT string
|
// DecodeActivationClaims tries to create an activation claim from a JWT string
|
||||||
|
|||||||
8
vendor/github.com/nats-io/jwt/claims.go
generated
vendored
8
vendor/github.com/nats-io/jwt/claims.go
generated
vendored
@@ -44,8 +44,6 @@ const (
|
|||||||
ClusterClaim = "cluster"
|
ClusterClaim = "cluster"
|
||||||
//OperatorClaim is the type of an operator JWT
|
//OperatorClaim is the type of an operator JWT
|
||||||
OperatorClaim = "operator"
|
OperatorClaim = "operator"
|
||||||
//RevocationClaim is the type of an revocation JWT
|
|
||||||
RevocationClaim = "revocation"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Claims is a JWT claims
|
// Claims is a JWT claims
|
||||||
@@ -180,9 +178,9 @@ func (c *ClaimsData) hash() (string, error) {
|
|||||||
return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(h.Sum(nil)), nil
|
return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(h.Sum(nil)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode encodes a claim into a JWT token. The claim is signed with the
|
// Encode encodes a claim into a JWT token. The claim is signed with the
|
||||||
// provided nkey's private key
|
// provided nkey's private key
|
||||||
func (c *ClaimsData) encode(kp nkeys.KeyPair, payload Claims) (string, error) {
|
func (c *ClaimsData) Encode(kp nkeys.KeyPair, payload Claims) (string, error) {
|
||||||
return c.doEncode(&Header{TokenTypeJwt, AlgorithmNkey}, kp, payload)
|
return c.doEncode(&Header{TokenTypeJwt, AlgorithmNkey}, kp, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +239,7 @@ func (c *ClaimsData) IsSelfSigned() bool {
|
|||||||
// Decode takes a JWT string decodes it and validates it
|
// Decode takes a JWT string decodes it and validates it
|
||||||
// and return the embedded Claims. If the token header
|
// and return the embedded Claims. If the token header
|
||||||
// doesn't match the expected algorithm, or the claim is
|
// doesn't match the expected algorithm, or the claim is
|
||||||
// not valid or verification fails an error is returned
|
// not valid or verification fails an error is returned.
|
||||||
func Decode(token string, target Claims) error {
|
func Decode(token string, target Claims) error {
|
||||||
// must have 3 chunks
|
// must have 3 chunks
|
||||||
chunks := strings.Split(token, ".")
|
chunks := strings.Split(token, ".")
|
||||||
|
|||||||
2
vendor/github.com/nats-io/jwt/cluster_claims.go
generated
vendored
2
vendor/github.com/nats-io/jwt/cluster_claims.go
generated
vendored
@@ -56,7 +56,7 @@ func (c *ClusterClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
return "", errors.New("expected subject to be a cluster public key")
|
return "", errors.New("expected subject to be a cluster public key")
|
||||||
}
|
}
|
||||||
c.ClaimsData.Type = ClusterClaim
|
c.ClaimsData.Type = ClusterClaim
|
||||||
return c.ClaimsData.encode(pair, c)
|
return c.ClaimsData.Encode(pair, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeClusterClaims tries to parse cluster claims from a JWT string
|
// DecodeClusterClaims tries to parse cluster claims from a JWT string
|
||||||
|
|||||||
196
vendor/github.com/nats-io/jwt/creds_utils.go
generated
vendored
Normal file
196
vendor/github.com/nats-io/jwt/creds_utils.go
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecorateJWT returns a decorated JWT that describes the kind of JWT
|
||||||
|
func DecorateJWT(jwtString string) ([]byte, error) {
|
||||||
|
gc, err := DecodeGeneric(jwtString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return formatJwt(string(gc.Type), jwtString)
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatJwt(kind string, jwtString string) ([]byte, error) {
|
||||||
|
templ := `-----BEGIN NATS %s JWT-----
|
||||||
|
%s
|
||||||
|
------END NATS %s JWT------
|
||||||
|
`
|
||||||
|
w := bytes.NewBuffer(nil)
|
||||||
|
kind = strings.ToUpper(kind)
|
||||||
|
_, err := fmt.Fprintf(w, templ, kind, jwtString, kind)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return w.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecorateSeed(seed []byte) ([]byte, error) {
|
||||||
|
w := bytes.NewBuffer(nil)
|
||||||
|
ts := bytes.TrimSpace(seed)
|
||||||
|
pre := string(ts[0:2])
|
||||||
|
kind := ""
|
||||||
|
switch pre {
|
||||||
|
case "SU":
|
||||||
|
kind = "USER"
|
||||||
|
case "SA":
|
||||||
|
kind = "ACCOUNT"
|
||||||
|
case "SO":
|
||||||
|
kind = "OPERATOR"
|
||||||
|
default:
|
||||||
|
return nil, errors.New("seed is not an operator, account or user seed")
|
||||||
|
}
|
||||||
|
header := `************************* IMPORTANT *************************
|
||||||
|
NKEY Seed printed below can be used to sign and prove identity.
|
||||||
|
NKEYs are sensitive and should be treated as secrets.
|
||||||
|
-----BEGIN %s NKEY SEED-----
|
||||||
|
`
|
||||||
|
_, err := fmt.Fprintf(w, header, kind)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
w.Write(ts)
|
||||||
|
|
||||||
|
footer := `
|
||||||
|
------END %s NKEY SEED------
|
||||||
|
*************************************************************
|
||||||
|
`
|
||||||
|
_, err = fmt.Fprintf(w, footer, kind)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return w.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var userConfigRE = regexp.MustCompile(`\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))`)
|
||||||
|
|
||||||
|
// An user config file looks like this:
|
||||||
|
// -----BEGIN NATS USER JWT-----
|
||||||
|
// eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5...
|
||||||
|
// ------END NATS USER JWT------
|
||||||
|
//
|
||||||
|
// ************************* IMPORTANT *************************
|
||||||
|
// NKEY Seed printed below can be used sign and prove identity.
|
||||||
|
// NKEYs are sensitive and should be treated as secrets.
|
||||||
|
//
|
||||||
|
// -----BEGIN USER NKEY SEED-----
|
||||||
|
// SUAIO3FHUX5PNV2LQIIP7TZ3N4L7TX3W53MQGEIVYFIGA635OZCKEYHFLM
|
||||||
|
// ------END USER NKEY SEED------
|
||||||
|
|
||||||
|
// FormatUserConfig returns a decorated file with a decorated JWT and decorated seed
|
||||||
|
func FormatUserConfig(jwtString string, seed []byte) ([]byte, error) {
|
||||||
|
gc, err := DecodeGeneric(jwtString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if gc.Type != UserClaim {
|
||||||
|
return nil, fmt.Errorf("%q cannot be serialized as a user config", string(gc.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
w := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
jd, err := formatJwt(string(gc.Type), jwtString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = w.Write(jd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.HasPrefix(bytes.TrimSpace(seed), []byte("SU")) {
|
||||||
|
return nil, fmt.Errorf("nkey seed is not an user seed")
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := DecorateSeed(seed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = w.Write(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDecoratedJWT(contents []byte) (string, error) {
|
||||||
|
defer wipeSlice(contents)
|
||||||
|
|
||||||
|
items := userConfigRE.FindAllSubmatch(contents, -1)
|
||||||
|
if len(items) == 0 {
|
||||||
|
return string(contents), nil
|
||||||
|
}
|
||||||
|
// First result should be the user JWT.
|
||||||
|
// We copy here so that if the file contained a seed file too we wipe appropriately.
|
||||||
|
raw := items[0][1]
|
||||||
|
tmp := make([]byte, len(raw))
|
||||||
|
copy(tmp, raw)
|
||||||
|
return string(tmp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDecoratedNKey(contents []byte) (nkeys.KeyPair, error) {
|
||||||
|
var seed []byte
|
||||||
|
defer wipeSlice(contents)
|
||||||
|
|
||||||
|
items := userConfigRE.FindAllSubmatch(contents, -1)
|
||||||
|
if len(items) > 1 {
|
||||||
|
seed = items[1][1]
|
||||||
|
} else {
|
||||||
|
lines := bytes.Split(contents, []byte("\n"))
|
||||||
|
for _, line := range lines {
|
||||||
|
if bytes.HasPrefix(bytes.TrimSpace(line), []byte("SO")) ||
|
||||||
|
bytes.HasPrefix(bytes.TrimSpace(line), []byte("SA")) ||
|
||||||
|
bytes.HasPrefix(bytes.TrimSpace(line), []byte("SU")) {
|
||||||
|
seed = line
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if seed == nil {
|
||||||
|
return nil, errors.New("no nkey seed found")
|
||||||
|
}
|
||||||
|
if !bytes.HasPrefix(seed, []byte("SO")) &&
|
||||||
|
!bytes.HasPrefix(seed, []byte("SA")) &&
|
||||||
|
!bytes.HasPrefix(seed, []byte("SU")) {
|
||||||
|
return nil, errors.New("doesn't contain a seed nkey")
|
||||||
|
}
|
||||||
|
kp, err := nkeys.FromSeed(seed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return kp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDecoratedUserNKey(contents []byte) (nkeys.KeyPair, error) {
|
||||||
|
nk, err := ParseDecoratedNKey(contents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
seed, err := nk.Seed()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.HasPrefix(seed, []byte("SU")) {
|
||||||
|
return nil, errors.New("doesn't contain an user seed nkey")
|
||||||
|
}
|
||||||
|
kp, err := nkeys.FromSeed(seed)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return kp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just wipe slice with 'x', for clearing contents of nkey seed file.
|
||||||
|
func wipeSlice(buf []byte) {
|
||||||
|
for i := range buf {
|
||||||
|
buf[i] = 'x'
|
||||||
|
}
|
||||||
|
}
|
||||||
42
vendor/github.com/nats-io/jwt/exports.go
generated
vendored
42
vendor/github.com/nats-io/jwt/exports.go
generated
vendored
@@ -17,14 +17,16 @@ package jwt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Export represents a single export
|
// Export represents a single export
|
||||||
type Export struct {
|
type Export struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Subject Subject `json:"subject,omitempty"`
|
Subject Subject `json:"subject,omitempty"`
|
||||||
Type ExportType `json:"type,omitempty"`
|
Type ExportType `json:"type,omitempty"`
|
||||||
TokenReq bool `json:"token_req,omitempty"`
|
TokenReq bool `json:"token_req,omitempty"`
|
||||||
|
Revocations RevocationList `json:"revocations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsService returns true if an export is for a service
|
// IsService returns true if an export is for a service
|
||||||
@@ -45,6 +47,38 @@ func (e *Export) Validate(vr *ValidationResults) {
|
|||||||
e.Subject.Validate(vr)
|
e.Subject.Validate(vr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Revoke enters a revocation by publickey using time.Now().
|
||||||
|
func (e *Export) Revoke(pubKey string) {
|
||||||
|
e.RevokeAt(pubKey, time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
// RevokeAt enters a revocation by publickey and timestamp into this export
|
||||||
|
// If there is already a revocation for this public key that is newer, it is kept.
|
||||||
|
func (e *Export) RevokeAt(pubKey string, timestamp time.Time) {
|
||||||
|
if e.Revocations == nil {
|
||||||
|
e.Revocations = RevocationList{}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Revocations.Revoke(pubKey, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearRevocation removes any revocation for the public key
|
||||||
|
func (e *Export) ClearRevocation(pubKey string) {
|
||||||
|
e.Revocations.ClearRevocation(pubKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRevokedAt checks if the public key is in the revoked list with a timestamp later than
|
||||||
|
// the one passed in. Generally this method is called with time.Now() but other time's can
|
||||||
|
// be used for testing.
|
||||||
|
func (e *Export) IsRevokedAt(pubKey string, timestamp time.Time) bool {
|
||||||
|
return e.Revocations.IsRevoked(pubKey, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRevoked checks if the public key is in the revoked list with time.Now()
|
||||||
|
func (e *Export) IsRevoked(pubKey string) bool {
|
||||||
|
return e.Revocations.IsRevoked(pubKey, time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
// Exports is an array of exports
|
// Exports is an array of exports
|
||||||
type Exports []*Export
|
type Exports []*Export
|
||||||
|
|
||||||
|
|||||||
4
vendor/github.com/nats-io/jwt/genericlaims.go
generated
vendored
4
vendor/github.com/nats-io/jwt/genericlaims.go
generated
vendored
@@ -48,14 +48,14 @@ func (gc *GenericClaims) Claims() *ClaimsData {
|
|||||||
return &gc.ClaimsData
|
return &gc.ClaimsData
|
||||||
}
|
}
|
||||||
|
|
||||||
// Payload returns the custom part of the claiims data
|
// Payload returns the custom part of the claims data
|
||||||
func (gc *GenericClaims) Payload() interface{} {
|
func (gc *GenericClaims) Payload() interface{} {
|
||||||
return &gc.Data
|
return &gc.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode takes a generic claims and creates a JWT string
|
// Encode takes a generic claims and creates a JWT string
|
||||||
func (gc *GenericClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
func (gc *GenericClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
return gc.ClaimsData.encode(pair, gc)
|
return gc.ClaimsData.Encode(pair, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the generic part of the claims data
|
// Validate checks the generic part of the claims data
|
||||||
|
|||||||
6
vendor/github.com/nats-io/jwt/operator_claims.go
generated
vendored
6
vendor/github.com/nats-io/jwt/operator_claims.go
generated
vendored
@@ -73,6 +73,10 @@ func (o *Operator) validateAccountServerURL() error {
|
|||||||
|
|
||||||
// ValidateOperatorServiceURL returns an error if the URL is not a valid NATS or TLS url.
|
// ValidateOperatorServiceURL returns an error if the URL is not a valid NATS or TLS url.
|
||||||
func ValidateOperatorServiceURL(v string) error {
|
func ValidateOperatorServiceURL(v string) error {
|
||||||
|
// should be possible for the service url to not be expressed
|
||||||
|
if v == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
u, err := url.Parse(v)
|
u, err := url.Parse(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing operator service url %q: %v", v, err)
|
return fmt.Errorf("error parsing operator service url %q: %v", v, err)
|
||||||
@@ -152,7 +156,7 @@ func (oc *OperatorClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
oc.ClaimsData.Type = OperatorClaim
|
oc.ClaimsData.Type = OperatorClaim
|
||||||
return oc.ClaimsData.encode(pair, oc)
|
return oc.ClaimsData.Encode(pair, oc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeOperatorClaims tries to create an operator claims from a JWt string
|
// DecodeOperatorClaims tries to create an operator claims from a JWt string
|
||||||
|
|||||||
105
vendor/github.com/nats-io/jwt/revocation_claims.go
generated
vendored
105
vendor/github.com/nats-io/jwt/revocation_claims.go
generated
vendored
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018 The NATS Authors
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nats-io/nkeys"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Revocation defines the custom parts of a revocation JWt
|
|
||||||
type Revocation struct {
|
|
||||||
JWT string `json:"jwt,omitempty"`
|
|
||||||
Reason string `json:"reason,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks the JWT and reason for a revocation
|
|
||||||
func (u *Revocation) Validate(vr *ValidationResults) {
|
|
||||||
if u.JWT == "" {
|
|
||||||
vr.AddError("revocation token has no JWT to revoke")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := DecodeGeneric(u.JWT)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
vr.AddError("revocation token has an invalid JWT")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RevocationClaims defines a revocation tokens data
|
|
||||||
type RevocationClaims struct {
|
|
||||||
ClaimsData
|
|
||||||
Revocation `json:"nats,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRevocationClaims creates a new revocation JWT for the specified subject/public key
|
|
||||||
func NewRevocationClaims(subject string) *RevocationClaims {
|
|
||||||
if subject == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
c := &RevocationClaims{}
|
|
||||||
c.Subject = subject
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode translates the claims to a JWT string
|
|
||||||
func (rc *RevocationClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|
||||||
rc.ClaimsData.Type = RevocationClaim
|
|
||||||
return rc.ClaimsData.encode(pair, rc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeRevocationClaims tries to parse a JWT string as a RevocationClaims
|
|
||||||
func DecodeRevocationClaims(token string) (*RevocationClaims, error) {
|
|
||||||
v := RevocationClaims{}
|
|
||||||
if err := Decode(token, &v); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *RevocationClaims) String() string {
|
|
||||||
return rc.ClaimsData.String(rc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Payload returns the revocation specific part of the claims
|
|
||||||
func (rc *RevocationClaims) Payload() interface{} {
|
|
||||||
return &rc.Revocation
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks the generic and revocation parts of the claims
|
|
||||||
func (rc *RevocationClaims) Validate(vr *ValidationResults) {
|
|
||||||
rc.ClaimsData.Validate(vr)
|
|
||||||
rc.Revocation.Validate(vr)
|
|
||||||
|
|
||||||
theJWT, err := DecodeGeneric(rc.Revocation.JWT)
|
|
||||||
if err != nil {
|
|
||||||
vr.AddError("revocation contains an invalid JWT")
|
|
||||||
return // can't do the remaining checks
|
|
||||||
}
|
|
||||||
|
|
||||||
if theJWT.Issuer != rc.Issuer {
|
|
||||||
vr.AddError("Revocation issuer doesn't match JWT to revoke")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpectedPrefixes defines who can sign a revocation token, account or operator
|
|
||||||
func (rc *RevocationClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
|
||||||
return []nkeys.PrefixByte{nkeys.PrefixByteOperator, nkeys.PrefixByteAccount}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Claims returns the generic part of the claims
|
|
||||||
func (rc *RevocationClaims) Claims() *ClaimsData {
|
|
||||||
return &rc.ClaimsData
|
|
||||||
}
|
|
||||||
32
vendor/github.com/nats-io/jwt/revocation_list.go
generated
vendored
Normal file
32
vendor/github.com/nats-io/jwt/revocation_list.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package jwt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RevocationList is used to store a mapping of public keys to unix timestamps
|
||||||
|
type RevocationList map[string]int64
|
||||||
|
|
||||||
|
// Revoke enters a revocation by publickey and timestamp into this export
|
||||||
|
// If there is already a revocation for this public key that is newer, it is kept.
|
||||||
|
func (r RevocationList) Revoke(pubKey string, timestamp time.Time) {
|
||||||
|
newTS := timestamp.Unix()
|
||||||
|
if ts, ok := r[pubKey]; ok && ts > newTS {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r[pubKey] = newTS
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearRevocation removes any revocation for the public key
|
||||||
|
func (r RevocationList) ClearRevocation(pubKey string) {
|
||||||
|
delete(r, pubKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRevoked checks if the public key is in the revoked list with a timestamp later than
|
||||||
|
// the one passed in. Generally this method is called with time.Now() but other time's can
|
||||||
|
// be used for testing.
|
||||||
|
func (r RevocationList) IsRevoked(pubKey string, timestamp time.Time) bool {
|
||||||
|
ts, ok := r[pubKey]
|
||||||
|
return ok && ts > timestamp.Unix()
|
||||||
|
}
|
||||||
2
vendor/github.com/nats-io/jwt/server_claims.go
generated
vendored
2
vendor/github.com/nats-io/jwt/server_claims.go
generated
vendored
@@ -56,7 +56,7 @@ func (s *ServerClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
return "", errors.New("expected subject to be a server public key")
|
return "", errors.New("expected subject to be a server public key")
|
||||||
}
|
}
|
||||||
s.ClaimsData.Type = ServerClaim
|
s.ClaimsData.Type = ServerClaim
|
||||||
return s.ClaimsData.encode(pair, s)
|
return s.ClaimsData.Encode(pair, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeServerClaims tries to parse server claims from a JWT string
|
// DecodeServerClaims tries to parse server claims from a JWT string
|
||||||
|
|||||||
22
vendor/github.com/nats-io/jwt/types.go
generated
vendored
22
vendor/github.com/nats-io/jwt/types.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018 The NATS Authors
|
* Copyright 2018-2019 The NATS Authors
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@@ -220,16 +220,32 @@ func (p *Permission) Validate(vr *ValidationResults) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResponsePermission can be used to allow responses to any reply subject
|
||||||
|
// that is received on a valid subscription.
|
||||||
|
type ResponsePermission struct {
|
||||||
|
MaxMsgs int `json:"max"`
|
||||||
|
Expires time.Duration `json:"ttl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the response permission.
|
||||||
|
func (p *ResponsePermission) Validate(vr *ValidationResults) {
|
||||||
|
// Any values can be valid for now.
|
||||||
|
}
|
||||||
|
|
||||||
// Permissions are used to restrict subject access, either on a user or for everyone on a server by default
|
// Permissions are used to restrict subject access, either on a user or for everyone on a server by default
|
||||||
type Permissions struct {
|
type Permissions struct {
|
||||||
Pub Permission `json:"pub,omitempty"`
|
Pub Permission `json:"pub,omitempty"`
|
||||||
Sub Permission `json:"sub,omitempty"`
|
Sub Permission `json:"sub,omitempty"`
|
||||||
|
Resp *ResponsePermission `json:"resp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the pub and sub fields in the permissions list
|
// Validate the pub and sub fields in the permissions list
|
||||||
func (p *Permissions) Validate(vr *ValidationResults) {
|
func (p *Permissions) Validate(vr *ValidationResults) {
|
||||||
p.Pub.Validate(vr)
|
p.Pub.Validate(vr)
|
||||||
p.Sub.Validate(vr)
|
p.Sub.Validate(vr)
|
||||||
|
if p.Resp != nil {
|
||||||
|
p.Resp.Validate(vr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringList is a wrapper for an array of strings
|
// StringList is a wrapper for an array of strings
|
||||||
|
|||||||
4
vendor/github.com/nats-io/jwt/user_claims.go
generated
vendored
4
vendor/github.com/nats-io/jwt/user_claims.go
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018 The NATS Authors
|
* Copyright 2018-2019 The NATS Authors
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@@ -58,7 +58,7 @@ func (u *UserClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
|||||||
return "", errors.New("expected subject to be user public key")
|
return "", errors.New("expected subject to be user public key")
|
||||||
}
|
}
|
||||||
u.ClaimsData.Type = UserClaim
|
u.ClaimsData.Type = UserClaim
|
||||||
return u.ClaimsData.encode(pair, u)
|
return u.ClaimsData.Encode(pair, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeUserClaims tries to parse a user claims from a JWT string
|
// DecodeUserClaims tries to parse a user claims from a JWT string
|
||||||
|
|||||||
7
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
7
vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
@@ -197,8 +197,11 @@ const (
|
|||||||
FILE_MAP_READ = 0x04
|
FILE_MAP_READ = 0x04
|
||||||
FILE_MAP_EXECUTE = 0x20
|
FILE_MAP_EXECUTE = 0x20
|
||||||
|
|
||||||
CTRL_C_EVENT = 0
|
CTRL_C_EVENT = 0
|
||||||
CTRL_BREAK_EVENT = 1
|
CTRL_BREAK_EVENT = 1
|
||||||
|
CTRL_CLOSE_EVENT = 2
|
||||||
|
CTRL_LOGOFF_EVENT = 5
|
||||||
|
CTRL_SHUTDOWN_EVENT = 6
|
||||||
|
|
||||||
// Windows reserves errors >= 1<<29 for application use.
|
// Windows reserves errors >= 1<<29 for application use.
|
||||||
APPLICATION_ERROR = 1 << 29
|
APPLICATION_ERROR = 1 << 29
|
||||||
|
|||||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
# github.com/nats-io/jwt v0.2.8
|
# github.com/nats-io/jwt v0.2.13-0.20190726194050-829b612a49c3
|
||||||
github.com/nats-io/jwt
|
github.com/nats-io/jwt
|
||||||
# github.com/nats-io/nats.go v1.8.1
|
# github.com/nats-io/nats.go v1.8.1
|
||||||
github.com/nats-io/nats.go
|
github.com/nats-io/nats.go
|
||||||
@@ -13,7 +13,7 @@ golang.org/x/crypto/bcrypt
|
|||||||
golang.org/x/crypto/ed25519
|
golang.org/x/crypto/ed25519
|
||||||
golang.org/x/crypto/blowfish
|
golang.org/x/crypto/blowfish
|
||||||
golang.org/x/crypto/ed25519/internal/edwards25519
|
golang.org/x/crypto/ed25519/internal/edwards25519
|
||||||
# golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542
|
# golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e
|
||||||
golang.org/x/sys/windows/svc/eventlog
|
golang.org/x/sys/windows/svc/eventlog
|
||||||
golang.org/x/sys/windows/svc
|
golang.org/x/sys/windows/svc
|
||||||
golang.org/x/sys/windows/svc/debug
|
golang.org/x/sys/windows/svc/debug
|
||||||
|
|||||||
Reference in New Issue
Block a user