mirror of
https://github.com/openfaas/faas.git
synced 2025-06-09 16:56:47 +00:00
Bump queue-worker and NATS
NATS moved its primary library to: github.com/nats-io/stan.go This commit synchronises the library in the gateway to match the queue worker. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
parent
542d7c0b83
commit
9bde25aedb
44
gateway/Gopkg.lock
generated
44
gateway/Gopkg.lock
generated
@ -54,27 +54,24 @@
|
|||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:2ca73053216eb11c8eea2855c8099ad82773638522f91cc0542ec9759163ff3c"
|
digest = "1:9b8ee267e79a1730cde2e326cc53035913fce52ceef48142c24f3a15e3c65cb3"
|
||||||
name = "github.com/nats-io/go-nats"
|
name = "github.com/nats-io/jwt"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "0c3fc7aed8bb2534e7bfdf0968a75890402d48cd"
|
||||||
|
version = "v0.3.2"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:2e964212558ab7559cec820aebdf9f04c369f27aafe8581932ae5f0b6826572b"
|
||||||
|
name = "github.com/nats-io/nats.go"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"encoders/builtin",
|
"encoders/builtin",
|
||||||
"util",
|
"util",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "70fe06cee50d4b6f98248d9675fb55f2a3aa7228"
|
revision = "4d5d5d17e7df8f8e3bf3c1426a5ed759012faab8"
|
||||||
version = "v1.7.2"
|
version = "v1.9.2"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:25a0458641a719a972fa7850c900aaae6b12e74efa6fe35c9bd7a772543bc635"
|
|
||||||
name = "github.com/nats-io/go-nats-streaming"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"pb",
|
|
||||||
]
|
|
||||||
pruneopts = "UT"
|
|
||||||
revision = "7cd94c239033c0405a43454be55a0810d3a3ca89"
|
|
||||||
version = "v0.4.4"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:237d85e4f5e91ac6cfc13bad508627570ff29efa28f523d41aac2d39ca15950f"
|
digest = "1:237d85e4f5e91ac6cfc13bad508627570ff29efa28f523d41aac2d39ca15950f"
|
||||||
@ -92,6 +89,17 @@
|
|||||||
revision = "4b96681fa6d28dd0ab5fe79bac63b3a493d9ee94"
|
revision = "4b96681fa6d28dd0ab5fe79bac63b3a493d9ee94"
|
||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:30147647e2ded41b85f4991e306053e478c009a817f4b53ce5e55ee7b5d2fbf6"
|
||||||
|
name = "github.com/nats-io/stan.go"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"pb",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "e2d4c025a5eea41d9566dc8e978c7ee697470b64"
|
||||||
|
version = "v0.6.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:340f4e2e095ead4e0a15b4646da3e4533f8b6520e3a382eaf586e8166f3bbcb5"
|
digest = "1:340f4e2e095ead4e0a15b4646da3e4533f8b6520e3a382eaf586e8166f3bbcb5"
|
||||||
name = "github.com/openfaas/faas"
|
name = "github.com/openfaas/faas"
|
||||||
@ -112,15 +120,15 @@
|
|||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:b7c06bdc590871ac5c88f8a85acc9f892c994d6327de311ec5871aaecb6f9489"
|
digest = "1:1cf86a1a93c110ebcf836468bd917e8c116d6d2fc7612829c15e946b02dbf864"
|
||||||
name = "github.com/openfaas/nats-queue-worker"
|
name = "github.com/openfaas/nats-queue-worker"
|
||||||
packages = [
|
packages = [
|
||||||
"handler",
|
"handler",
|
||||||
"nats",
|
"nats",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "dea1c90b8cc66dc73597b7531a4fd29a32b5f88c"
|
revision = "a1835cb71db56e6b814b91df027acf62425a76ad"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:eb04f69c8991e52eff33c428bd729e04208bf03235be88e4df0d88497c6861b9"
|
digest = "1:eb04f69c8991e52eff33c428bd729e04208bf03235be88e4df0d88497c6861b9"
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/openfaas/nats-queue-worker"
|
name = "github.com/openfaas/nats-queue-worker"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
|
2
gateway/vendor/github.com/gorilla/mux/go.mod
generated
vendored
2
gateway/vendor/github.com/gorilla/mux/go.mod
generated
vendored
@ -1,3 +1 @@
|
|||||||
module github.com/gorilla/mux
|
module github.com/gorilla/mux
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
21
gateway/vendor/github.com/nats-io/go-nats/.travis.yml
generated
vendored
21
gateway/vendor/github.com/nats-io/go-nats/.travis.yml
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
language: go
|
|
||||||
sudo: false
|
|
||||||
go:
|
|
||||||
- 1.11.x
|
|
||||||
- 1.10.x
|
|
||||||
go_import_path: github.com/nats-io/go-nats
|
|
||||||
install:
|
|
||||||
- go get -t ./...
|
|
||||||
- go get github.com/nats-io/gnatsd
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- go get github.com/wadey/gocovmerge
|
|
||||||
- go get -u honnef.co/go/tools/cmd/staticcheck
|
|
||||||
- go get -u github.com/client9/misspell/cmd/misspell
|
|
||||||
before_script:
|
|
||||||
- $(exit $(go fmt ./... | wc -l))
|
|
||||||
- go vet ./...
|
|
||||||
- misspell -error -locale US .
|
|
||||||
- staticcheck -ignore "$(cat staticcheck.ignore)" ./...
|
|
||||||
script:
|
|
||||||
- go test -i -race ./...
|
|
||||||
- if [[ "$TRAVIS_GO_VERSION" =~ 1.11 ]]; then ./scripts/cov.sh TRAVIS; else go test -race ./...; fi
|
|
4
gateway/vendor/github.com/nats-io/go-nats/staticcheck.ignore
generated
vendored
4
gateway/vendor/github.com/nats-io/go-nats/staticcheck.ignore
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
github.com/nats-io/go-nats/*_test.go:SA2002
|
|
||||||
github.com/nats-io/go-nats/*/*_test.go:SA2002
|
|
||||||
github.com/nats-io/go-nats/test/context_test.go:SA1012
|
|
||||||
github.com/nats-io/go-nats/nats.go:SA6000
|
|
16
gateway/vendor/github.com/nats-io/jwt/.gitignore
generated
vendored
Normal file
16
gateway/vendor/github.com/nats-io/jwt/.gitignore
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# IDE Files
|
||||||
|
.vscode
|
||||||
|
.idea/
|
@ -1,22 +1,22 @@
|
|||||||
language: go
|
language: go
|
||||||
sudo: false
|
sudo: false
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
- 1.13.x
|
||||||
- 1.12.x
|
- 1.12.x
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get -t ./...
|
- go get -t ./...
|
||||||
- go get github.com/nats-io/nats-streaming-server
|
|
||||||
- go get github.com/mattn/goveralls
|
- go get github.com/mattn/goveralls
|
||||||
- go get github.com/wadey/gocovmerge
|
- go get github.com/wadey/gocovmerge
|
||||||
- go get -u honnef.co/go/tools/cmd/staticcheck
|
- go get -u honnef.co/go/tools/cmd/staticcheck
|
||||||
- go get -u github.com/client9/misspell/cmd/misspell
|
- go get -u github.com/client9/misspell/cmd/misspell
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- $(exit $(go fmt ./... | wc -l))
|
- $(exit $(go fmt ./... | wc -l))
|
||||||
- go vet ./...
|
- go vet ./...
|
||||||
- misspell -error -locale US .
|
- misspell -error -locale US .
|
||||||
- staticcheck ./...
|
- staticcheck ./...
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go test -i -race ./...
|
|
||||||
- go test -v -race ./...
|
- go test -v -race ./...
|
||||||
after_success:
|
|
||||||
- if [[ "$TRAVIS_GO_VERSION" =~ 1.12 ]]; then ./scripts/cov.sh TRAVIS; fi
|
- if [[ "$TRAVIS_GO_VERSION" =~ 1.12 ]]; then ./scripts/cov.sh TRAVIS; fi
|
19
gateway/vendor/github.com/nats-io/jwt/Makefile
generated
vendored
Normal file
19
gateway/vendor/github.com/nats-io/jwt/Makefile
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.PHONY: test cover
|
||||||
|
|
||||||
|
build:
|
||||||
|
go build
|
||||||
|
|
||||||
|
test:
|
||||||
|
gofmt -s -w *.go
|
||||||
|
goimports -w *.go
|
||||||
|
go vet ./...
|
||||||
|
go test -v
|
||||||
|
go test -v --race
|
||||||
|
staticcheck ./...
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
gofmt -w -s *.go
|
||||||
|
|
||||||
|
cover:
|
||||||
|
go test -v -covermode=count -coverprofile=coverage.out
|
||||||
|
go tool cover -html=coverage.out
|
54
gateway/vendor/github.com/nats-io/jwt/README.md
generated
vendored
Normal file
54
gateway/vendor/github.com/nats-io/jwt/README.md
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# JWT
|
||||||
|
A [JWT](https://jwt.io/) implementation that uses [nkeys](https://github.com/nats-io/nkeys) to digitally sign JWT tokens.
|
||||||
|
Nkeys use [Ed25519](https://ed25519.cr.yp.to/) to provide authentication of JWT claims.
|
||||||
|
|
||||||
|
|
||||||
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
[](http://goreportcard.com/report/nats-io/jwt)
|
||||||
|
[](http://travis-ci.org/nats-io/jwt)
|
||||||
|
[](http://godoc.org/github.com/nats-io/jwt)
|
||||||
|
[](https://coveralls.io/github/nats-io/jwt?branch=master)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Need a private key to sign the claim, nkeys makes it easy to create
|
||||||
|
kp, err := nkeys.CreateAccount()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unable to create account key", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pk, err := kp.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error getting public key", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new claim
|
||||||
|
claims := NewAccountClaims(pk)
|
||||||
|
claims.Expires = time.Now().Add(time.Duration(time.Hour)).Unix()
|
||||||
|
|
||||||
|
|
||||||
|
// add details by modifying claims.Account
|
||||||
|
|
||||||
|
// serialize the claim to a JWT token
|
||||||
|
token, err := claims.Encode(kp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error encoding token", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// on the receiving side, decode the token
|
||||||
|
c, err := DecodeAccountClaims(token)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the token was decoded, it means that it
|
||||||
|
// validated and it wasn't tampered. the remaining and
|
||||||
|
// required test is to insure the issuer is trusted
|
||||||
|
pk, err := kp.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to read public key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Issuer != pk {
|
||||||
|
t.Fatalf("the public key is not trusted")
|
||||||
|
}
|
||||||
|
```
|
5
gateway/vendor/github.com/nats-io/jwt/ReleaseNotes.md
generated
vendored
Normal file
5
gateway/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.
|
222
gateway/vendor/github.com/nats-io/jwt/account_claims.go
generated
vendored
Normal file
222
gateway/vendor/github.com/nats-io/jwt/account_claims.go
generated
vendored
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"errors"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NoLimit is used to indicate a limit field is unlimited in value.
|
||||||
|
const NoLimit = -1
|
||||||
|
|
||||||
|
// OperatorLimits are used to limit access by an account
|
||||||
|
type OperatorLimits struct {
|
||||||
|
Subs int64 `json:"subs,omitempty"` // Max number of subscriptions
|
||||||
|
Conn int64 `json:"conn,omitempty"` // Max number of active connections
|
||||||
|
LeafNodeConn int64 `json:"leaf,omitempty"` // Max number of active leaf node connections
|
||||||
|
Imports int64 `json:"imports,omitempty"` // Max number of imports
|
||||||
|
Exports int64 `json:"exports,omitempty"` // Max number of exports
|
||||||
|
Data int64 `json:"data,omitempty"` // Max number of bytes
|
||||||
|
Payload int64 `json:"payload,omitempty"` // Max message payload
|
||||||
|
WildcardExports bool `json:"wildcards,omitempty"` // Are wildcards allowed in exports
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if all of the limits are 0/false.
|
||||||
|
func (o *OperatorLimits) IsEmpty() bool {
|
||||||
|
return *o == OperatorLimits{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUnlimited returns true if all limits are
|
||||||
|
func (o *OperatorLimits) IsUnlimited() bool {
|
||||||
|
return *o == OperatorLimits{NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, true}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks that the operator limits contain valid values
|
||||||
|
func (o *OperatorLimits) Validate(vr *ValidationResults) {
|
||||||
|
// negative values mean unlimited, so all numbers are valid
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if the account is valid, based on the wrapper
|
||||||
|
func (a *Account) Validate(acct *AccountClaims, vr *ValidationResults) {
|
||||||
|
a.Imports.Validate(acct.Subject, vr)
|
||||||
|
a.Exports.Validate(vr)
|
||||||
|
a.Limits.Validate(vr)
|
||||||
|
|
||||||
|
for _, i := range a.Identities {
|
||||||
|
i.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Limits.IsEmpty() && a.Limits.Imports >= 0 && int64(len(a.Imports)) > a.Limits.Imports {
|
||||||
|
vr.AddError("the account contains more imports than allowed by the operator")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Imports and Exports for limit violations.
|
||||||
|
if a.Limits.Imports != NoLimit {
|
||||||
|
if int64(len(a.Imports)) > a.Limits.Imports {
|
||||||
|
vr.AddError("the account contains more imports than allowed by the operator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if a.Limits.Exports != NoLimit {
|
||||||
|
if int64(len(a.Exports)) > a.Limits.Exports {
|
||||||
|
vr.AddError("the account contains more exports than allowed by the operator")
|
||||||
|
}
|
||||||
|
// Check for wildcard restrictions
|
||||||
|
if !a.Limits.WildcardExports {
|
||||||
|
for _, ex := range a.Exports {
|
||||||
|
if ex.Subject.HasWildCards() {
|
||||||
|
vr.AddError("the account contains wildcard exports that are not allowed by the operator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range a.SigningKeys {
|
||||||
|
if !nkeys.IsValidPublicAccountKey(k) {
|
||||||
|
vr.AddError("%s is not an account public key", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountClaims defines the body of an account JWT
|
||||||
|
type AccountClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Account `json:"nats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAccountClaims creates a new account JWT
|
||||||
|
func NewAccountClaims(subject string) *AccountClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := &AccountClaims{}
|
||||||
|
// Set to unlimited to start. We do it this way so we get compiler
|
||||||
|
// errors if we add to the OperatorLimits.
|
||||||
|
c.Limits = OperatorLimits{NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, NoLimit, true}
|
||||||
|
c.Subject = subject
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode converts account claims into a JWT string
|
||||||
|
func (a *AccountClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicAccountKey(a.Subject) {
|
||||||
|
return "", errors.New("expected subject to be account public key")
|
||||||
|
}
|
||||||
|
sort.Sort(a.Exports)
|
||||||
|
sort.Sort(a.Imports)
|
||||||
|
a.ClaimsData.Type = AccountClaim
|
||||||
|
return a.ClaimsData.Encode(pair, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeAccountClaims decodes account claims from a JWT string
|
||||||
|
func DecodeAccountClaims(token string) (*AccountClaims, error) {
|
||||||
|
v := AccountClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AccountClaims) String() string {
|
||||||
|
return a.ClaimsData.String(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload pulls the accounts specific payload out of the claims
|
||||||
|
func (a *AccountClaims) Payload() interface{} {
|
||||||
|
return &a.Account
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the accounts contents
|
||||||
|
func (a *AccountClaims) Validate(vr *ValidationResults) {
|
||||||
|
a.ClaimsData.Validate(vr)
|
||||||
|
a.Account.Validate(a, vr)
|
||||||
|
|
||||||
|
if nkeys.IsValidPublicAccountKey(a.ClaimsData.Issuer) {
|
||||||
|
if len(a.Identities) > 0 {
|
||||||
|
vr.AddWarning("self-signed account JWTs shouldn't contain identity proofs")
|
||||||
|
}
|
||||||
|
if !a.Limits.IsEmpty() {
|
||||||
|
vr.AddWarning("self-signed account JWTs shouldn't contain operator limits")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the types that can encode an account jwt, account and operator
|
||||||
|
func (a *AccountClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteAccount, nkeys.PrefixByteOperator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the accounts claims data
|
||||||
|
func (a *AccountClaims) Claims() *ClaimsData {
|
||||||
|
return &a.ClaimsData
|
||||||
|
}
|
||||||
|
|
||||||
|
// DidSign checks the claims against the account's public key and its signing keys
|
||||||
|
func (a *AccountClaims) DidSign(op Claims) bool {
|
||||||
|
if op != nil {
|
||||||
|
issuer := op.Claims().Issuer
|
||||||
|
if issuer == a.Subject {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return a.SigningKeys.Contains(issuer)
|
||||||
|
}
|
||||||
|
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())
|
||||||
|
}
|
166
gateway/vendor/github.com/nats-io/jwt/activation_claims.go
generated
vendored
Normal file
166
gateway/vendor/github.com/nats-io/jwt/activation_claims.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base32"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Activation defines the custom parts of an activation claim
|
||||||
|
type Activation struct {
|
||||||
|
ImportSubject Subject `json:"subject,omitempty"`
|
||||||
|
ImportType ExportType `json:"type,omitempty"`
|
||||||
|
Limits
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsService returns true if an Activation is for a service
|
||||||
|
func (a *Activation) IsService() bool {
|
||||||
|
return a.ImportType == Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStream returns true if an Activation is for a stream
|
||||||
|
func (a *Activation) IsStream() bool {
|
||||||
|
return a.ImportType == Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the exports and limits in an activation JWT
|
||||||
|
func (a *Activation) Validate(vr *ValidationResults) {
|
||||||
|
if !a.IsService() && !a.IsStream() {
|
||||||
|
vr.AddError("invalid export type: %q", a.ImportType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.IsService() {
|
||||||
|
if a.ImportSubject.HasWildCards() {
|
||||||
|
vr.AddError("services cannot have wildcard subject: %q", a.ImportSubject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.ImportSubject.Validate(vr)
|
||||||
|
a.Limits.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActivationClaims holds the data specific to an activation JWT
|
||||||
|
type ActivationClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Activation `json:"nats,omitempty"`
|
||||||
|
// IssuerAccount stores the public key for the account the issuer represents.
|
||||||
|
// When set, the claim was issued by a signing key.
|
||||||
|
IssuerAccount string `json:"issuer_account,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewActivationClaims creates a new activation claim with the provided sub
|
||||||
|
func NewActivationClaims(subject string) *ActivationClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ac := &ActivationClaims{}
|
||||||
|
ac.Subject = subject
|
||||||
|
return ac
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode turns an activation claim into a JWT strimg
|
||||||
|
func (a *ActivationClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicAccountKey(a.ClaimsData.Subject) {
|
||||||
|
return "", errors.New("expected subject to be an account")
|
||||||
|
}
|
||||||
|
a.ClaimsData.Type = ActivationClaim
|
||||||
|
return a.ClaimsData.Encode(pair, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeActivationClaims tries to create an activation claim from a JWT string
|
||||||
|
func DecodeActivationClaims(token string) (*ActivationClaims, error) {
|
||||||
|
v := ActivationClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the activation specific part of the JWT
|
||||||
|
func (a *ActivationClaims) Payload() interface{} {
|
||||||
|
return a.Activation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the claims
|
||||||
|
func (a *ActivationClaims) Validate(vr *ValidationResults) {
|
||||||
|
a.ClaimsData.Validate(vr)
|
||||||
|
a.Activation.Validate(vr)
|
||||||
|
if a.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(a.IssuerAccount) {
|
||||||
|
vr.AddError("account_id is not an account public key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the types that can sign an activation jwt, account and oeprator
|
||||||
|
func (a *ActivationClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteAccount, nkeys.PrefixByteOperator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the generic part of the JWT
|
||||||
|
func (a *ActivationClaims) Claims() *ClaimsData {
|
||||||
|
return &a.ClaimsData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ActivationClaims) String() string {
|
||||||
|
return a.ClaimsData.String(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashID returns a hash of the claims that can be used to identify it.
|
||||||
|
// The hash is calculated by creating a string with
|
||||||
|
// issuerPubKey.subjectPubKey.<subject> and constructing the sha-256 hash and base32 encoding that.
|
||||||
|
// <subject> is the exported subject, minus any wildcards, so foo.* becomes foo.
|
||||||
|
// the one special case is that if the export start with "*" or is ">" the <subject> "_"
|
||||||
|
func (a *ActivationClaims) HashID() (string, error) {
|
||||||
|
|
||||||
|
if a.Issuer == "" || a.Subject == "" || a.ImportSubject == "" {
|
||||||
|
return "", fmt.Errorf("not enough data in the activaion claims to create a hash")
|
||||||
|
}
|
||||||
|
|
||||||
|
subject := cleanSubject(string(a.ImportSubject))
|
||||||
|
base := fmt.Sprintf("%s.%s.%s", a.Issuer, a.Subject, subject)
|
||||||
|
h := sha256.New()
|
||||||
|
h.Write([]byte(base))
|
||||||
|
sha := h.Sum(nil)
|
||||||
|
hash := base32.StdEncoding.EncodeToString(sha)
|
||||||
|
|
||||||
|
return hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanSubject(subject string) string {
|
||||||
|
split := strings.Split(subject, ".")
|
||||||
|
cleaned := ""
|
||||||
|
|
||||||
|
for i, tok := range split {
|
||||||
|
if tok == "*" || tok == ">" {
|
||||||
|
if i == 0 {
|
||||||
|
cleaned = "_"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
cleaned = strings.Join(split[:i], ".")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cleaned == "" {
|
||||||
|
cleaned = subject
|
||||||
|
}
|
||||||
|
return cleaned
|
||||||
|
}
|
302
gateway/vendor/github.com/nats-io/jwt/claims.go
generated
vendored
Normal file
302
gateway/vendor/github.com/nats-io/jwt/claims.go
generated
vendored
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding/base32"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClaimType is used to indicate the type of JWT being stored in a Claim
|
||||||
|
type ClaimType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AccountClaim is the type of an Account JWT
|
||||||
|
AccountClaim = "account"
|
||||||
|
//ActivationClaim is the type of an activation JWT
|
||||||
|
ActivationClaim = "activation"
|
||||||
|
//UserClaim is the type of an user JWT
|
||||||
|
UserClaim = "user"
|
||||||
|
//ServerClaim is the type of an server JWT
|
||||||
|
ServerClaim = "server"
|
||||||
|
//ClusterClaim is the type of an cluster JWT
|
||||||
|
ClusterClaim = "cluster"
|
||||||
|
//OperatorClaim is the type of an operator JWT
|
||||||
|
OperatorClaim = "operator"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Claims is a JWT claims
|
||||||
|
type Claims interface {
|
||||||
|
Claims() *ClaimsData
|
||||||
|
Encode(kp nkeys.KeyPair) (string, error)
|
||||||
|
ExpectedPrefixes() []nkeys.PrefixByte
|
||||||
|
Payload() interface{}
|
||||||
|
String() string
|
||||||
|
Validate(vr *ValidationResults)
|
||||||
|
Verify(payload string, sig []byte) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClaimsData is the base struct for all claims
|
||||||
|
type ClaimsData struct {
|
||||||
|
Audience string `json:"aud,omitempty"`
|
||||||
|
Expires int64 `json:"exp,omitempty"`
|
||||||
|
ID string `json:"jti,omitempty"`
|
||||||
|
IssuedAt int64 `json:"iat,omitempty"`
|
||||||
|
Issuer string `json:"iss,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
NotBefore int64 `json:"nbf,omitempty"`
|
||||||
|
Subject string `json:"sub,omitempty"`
|
||||||
|
Tags TagList `json:"tags,omitempty"`
|
||||||
|
Type ClaimType `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefix holds the prefix byte for an NKey
|
||||||
|
type Prefix struct {
|
||||||
|
nkeys.PrefixByte
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeToString(d []byte) string {
|
||||||
|
return base64.RawURLEncoding.EncodeToString(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeString(s string) ([]byte, error) {
|
||||||
|
return base64.RawURLEncoding.DecodeString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serialize(v interface{}) (string, error) {
|
||||||
|
j, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return encodeToString(j), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClaimsData) doEncode(header *Header, kp nkeys.KeyPair, claim Claims) (string, error) {
|
||||||
|
if header == nil {
|
||||||
|
return "", errors.New("header is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if kp == nil {
|
||||||
|
return "", errors.New("keypair is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Subject == "" {
|
||||||
|
return "", errors.New("subject is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := serialize(header)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
issuerBytes, err := kp.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixes := claim.ExpectedPrefixes()
|
||||||
|
if prefixes != nil {
|
||||||
|
ok := false
|
||||||
|
for _, p := range prefixes {
|
||||||
|
switch p {
|
||||||
|
case nkeys.PrefixByteAccount:
|
||||||
|
if nkeys.IsValidPublicAccountKey(issuerBytes) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteOperator:
|
||||||
|
if nkeys.IsValidPublicOperatorKey(issuerBytes) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteServer:
|
||||||
|
if nkeys.IsValidPublicServerKey(issuerBytes) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteCluster:
|
||||||
|
if nkeys.IsValidPublicClusterKey(issuerBytes) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteUser:
|
||||||
|
if nkeys.IsValidPublicUserKey(issuerBytes) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("unable to validate expected prefixes - %v", prefixes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Issuer = string(issuerBytes)
|
||||||
|
c.IssuedAt = time.Now().UTC().Unix()
|
||||||
|
|
||||||
|
c.ID, err = c.hash()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := serialize(claim)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := kp.Sign([]byte(payload))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
eSig := encodeToString(sig)
|
||||||
|
return fmt.Sprintf("%s.%s.%s", h, payload, eSig), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClaimsData) hash() (string, error) {
|
||||||
|
j, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
h := sha512.New512_256()
|
||||||
|
h.Write(j)
|
||||||
|
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
|
||||||
|
// provided nkey's private key
|
||||||
|
func (c *ClaimsData) Encode(kp nkeys.KeyPair, payload Claims) (string, error) {
|
||||||
|
return c.doEncode(&Header{TokenTypeJwt, AlgorithmNkey}, kp, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a JSON representation of the claim
|
||||||
|
func (c *ClaimsData) String(claim interface{}) string {
|
||||||
|
j, err := json.MarshalIndent(claim, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseClaims(s string, target Claims) error {
|
||||||
|
h, err := decodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return json.Unmarshal(h, &target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify verifies that the encoded payload was signed by the
|
||||||
|
// provided public key. Verify is called automatically with
|
||||||
|
// the claims portion of the token and the public key in the claim.
|
||||||
|
// Client code need to insure that the public key in the
|
||||||
|
// claim is trusted.
|
||||||
|
func (c *ClaimsData) Verify(payload string, sig []byte) bool {
|
||||||
|
// decode the public key
|
||||||
|
kp, err := nkeys.FromPublicKey(c.Issuer)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err := kp.Verify([]byte(payload), sig); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks a claim to make sure it is valid. Validity checks
|
||||||
|
// include expiration and not before constraints.
|
||||||
|
func (c *ClaimsData) Validate(vr *ValidationResults) {
|
||||||
|
now := time.Now().UTC().Unix()
|
||||||
|
if c.Expires > 0 && now > c.Expires {
|
||||||
|
vr.AddTimeCheck("claim is expired")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.NotBefore > 0 && c.NotBefore > now {
|
||||||
|
vr.AddTimeCheck("claim is not yet valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSelfSigned returns true if the claims issuer is the subject
|
||||||
|
func (c *ClaimsData) IsSelfSigned() bool {
|
||||||
|
return c.Issuer == c.Subject
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode takes a JWT string decodes it and validates it
|
||||||
|
// and return the embedded Claims. If the token header
|
||||||
|
// doesn't match the expected algorithm, or the claim is
|
||||||
|
// not valid or verification fails an error is returned.
|
||||||
|
func Decode(token string, target Claims) error {
|
||||||
|
// must have 3 chunks
|
||||||
|
chunks := strings.Split(token, ".")
|
||||||
|
if len(chunks) != 3 {
|
||||||
|
return errors.New("expected 3 chunks")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := parseHeaders(chunks[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := parseClaims(chunks[1], target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := decodeString(chunks[2])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.Verify(chunks[1], sig) {
|
||||||
|
return errors.New("claim failed signature verification")
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixes := target.ExpectedPrefixes()
|
||||||
|
if prefixes != nil {
|
||||||
|
ok := false
|
||||||
|
issuer := target.Claims().Issuer
|
||||||
|
for _, p := range prefixes {
|
||||||
|
switch p {
|
||||||
|
case nkeys.PrefixByteAccount:
|
||||||
|
if nkeys.IsValidPublicAccountKey(issuer) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteOperator:
|
||||||
|
if nkeys.IsValidPublicOperatorKey(issuer) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteServer:
|
||||||
|
if nkeys.IsValidPublicServerKey(issuer) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteCluster:
|
||||||
|
if nkeys.IsValidPublicClusterKey(issuer) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
case nkeys.PrefixByteUser:
|
||||||
|
if nkeys.IsValidPublicUserKey(issuer) {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unable to validate expected prefixes - %v", prefixes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
94
gateway/vendor/github.com/nats-io/jwt/cluster_claims.go
generated
vendored
Normal file
94
gateway/vendor/github.com/nats-io/jwt/cluster_claims.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cluster stores the cluster specific elements of a cluster JWT
|
||||||
|
type Cluster struct {
|
||||||
|
Trust []string `json:"identity,omitempty"`
|
||||||
|
Accounts []string `json:"accts,omitempty"`
|
||||||
|
AccountURL string `json:"accturl,omitempty"`
|
||||||
|
OperatorURL string `json:"opurl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the cluster and permissions for a cluster JWT
|
||||||
|
func (c *Cluster) Validate(vr *ValidationResults) {
|
||||||
|
// fixme validate cluster data
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClusterClaims defines the data in a cluster JWT
|
||||||
|
type ClusterClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Cluster `json:"nats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClusterClaims creates a new cluster JWT with the specified subject/public key
|
||||||
|
func NewClusterClaims(subject string) *ClusterClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := &ClusterClaims{}
|
||||||
|
c.Subject = subject
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode tries to turn the cluster claims into a JWT string
|
||||||
|
func (c *ClusterClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicClusterKey(c.Subject) {
|
||||||
|
return "", errors.New("expected subject to be a cluster public key")
|
||||||
|
}
|
||||||
|
c.ClaimsData.Type = ClusterClaim
|
||||||
|
return c.ClaimsData.Encode(pair, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeClusterClaims tries to parse cluster claims from a JWT string
|
||||||
|
func DecodeClusterClaims(token string) (*ClusterClaims, error) {
|
||||||
|
v := ClusterClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterClaims) String() string {
|
||||||
|
return c.ClaimsData.String(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the cluster specific data
|
||||||
|
func (c *ClusterClaims) Payload() interface{} {
|
||||||
|
return &c.Cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the generic and cluster data in the cluster claims
|
||||||
|
func (c *ClusterClaims) Validate(vr *ValidationResults) {
|
||||||
|
c.ClaimsData.Validate(vr)
|
||||||
|
c.Cluster.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the types that can encode a cluster JWT, operator or cluster
|
||||||
|
func (c *ClusterClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteOperator, nkeys.PrefixByteCluster}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the generic data
|
||||||
|
func (c *ClusterClaims) Claims() *ClaimsData {
|
||||||
|
return &c.ClaimsData
|
||||||
|
}
|
203
gateway/vendor/github.com/nats-io/jwt/creds_utils.go
generated
vendored
Normal file
203
gateway/vendor/github.com/nats-io/jwt/creds_utils.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecorateSeed takes a seed and returns a string that wraps
|
||||||
|
// the seed in the form:
|
||||||
|
// ************************* 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------
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDecoratedJWT takes a creds file and returns the JWT portion.
|
||||||
|
func ParseDecoratedJWT(contents []byte) (string, error) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDecoratedNKey takes a creds file, finds the NKey portion and creates a
|
||||||
|
// key pair from it.
|
||||||
|
func ParseDecoratedNKey(contents []byte) (nkeys.KeyPair, error) {
|
||||||
|
var seed []byte
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDecoratedUserNKey takes a creds file, finds the NKey portion and creates a
|
||||||
|
// key pair from it. Similar to ParseDecoratedNKey but fails for non-user keys.
|
||||||
|
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
|
||||||
|
}
|
236
gateway/vendor/github.com/nats-io/jwt/exports.go
generated
vendored
Normal file
236
gateway/vendor/github.com/nats-io/jwt/exports.go
generated
vendored
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResponseType is used to store an export response type
|
||||||
|
type ResponseType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ResponseTypeSingleton is used for a service that sends a single response only
|
||||||
|
ResponseTypeSingleton = "Singleton"
|
||||||
|
|
||||||
|
// ResponseTypeStream is used for a service that will send multiple responses
|
||||||
|
ResponseTypeStream = "Stream"
|
||||||
|
|
||||||
|
// ResponseTypeChunked is used for a service that sends a single response in chunks (so not quite a stream)
|
||||||
|
ResponseTypeChunked = "Chunked"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServiceLatency is used when observing and exported service for
|
||||||
|
// latency measurements.
|
||||||
|
// Sampling 1-100, represents sampling rate, defaults to 100.
|
||||||
|
// Results is the subject where the latency metrics are published.
|
||||||
|
// A metric will be defined by the nats-server's ServiceLatency. Time durations
|
||||||
|
// are in nanoseconds.
|
||||||
|
// see https://github.com/nats-io/nats-server/blob/master/server/accounts.go#L524
|
||||||
|
// e.g.
|
||||||
|
// {
|
||||||
|
// "app": "dlc22",
|
||||||
|
// "start": "2019-09-16T21:46:23.636869585-07:00",
|
||||||
|
// "svc": 219732,
|
||||||
|
// "nats": {
|
||||||
|
// "req": 320415,
|
||||||
|
// "resp": 228268,
|
||||||
|
// "sys": 0
|
||||||
|
// },
|
||||||
|
// "total": 768415
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
type ServiceLatency struct {
|
||||||
|
Sampling int `json:"sampling,omitempty"`
|
||||||
|
Results Subject `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *ServiceLatency) Validate(vr *ValidationResults) {
|
||||||
|
if sl.Sampling < 1 || sl.Sampling > 100 {
|
||||||
|
vr.AddError("sampling percentage needs to be between 1-100")
|
||||||
|
}
|
||||||
|
sl.Results.Validate(vr)
|
||||||
|
if sl.Results.HasWildCards() {
|
||||||
|
vr.AddError("results subject can not contain wildcards")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsService returns true if an export is for a service
|
||||||
|
func (e *Export) IsService() bool {
|
||||||
|
return e.Type == Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStream returns true if an export is for a stream
|
||||||
|
func (e *Export) IsStream() bool {
|
||||||
|
return e.Type == Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSingleResponse returns true if an export has a single response
|
||||||
|
// or no resopnse type is set, also checks that the type is service
|
||||||
|
func (e *Export) IsSingleResponse() bool {
|
||||||
|
return e.Type == Service && (e.ResponseType == ResponseTypeSingleton || e.ResponseType == "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsChunkedResponse returns true if an export has a chunked response
|
||||||
|
func (e *Export) IsChunkedResponse() bool {
|
||||||
|
return e.Type == Service && e.ResponseType == ResponseTypeChunked
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStreamResponse returns true if an export has a chunked response
|
||||||
|
func (e *Export) IsStreamResponse() bool {
|
||||||
|
return e.Type == Service && e.ResponseType == ResponseTypeStream
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate appends validation issues to the passed in results list
|
||||||
|
func (e *Export) Validate(vr *ValidationResults) {
|
||||||
|
if !e.IsService() && !e.IsStream() {
|
||||||
|
vr.AddError("invalid export type: %q", e.Type)
|
||||||
|
}
|
||||||
|
if e.IsService() && !e.IsSingleResponse() && !e.IsChunkedResponse() && !e.IsStreamResponse() {
|
||||||
|
vr.AddError("invalid response type for service: %q", e.ResponseType)
|
||||||
|
}
|
||||||
|
if e.IsStream() && e.ResponseType != "" {
|
||||||
|
vr.AddError("invalid response type for stream: %q", e.ResponseType)
|
||||||
|
}
|
||||||
|
if e.Latency != nil {
|
||||||
|
if !e.IsService() {
|
||||||
|
vr.AddError("latency tracking only permitted for services")
|
||||||
|
}
|
||||||
|
e.Latency.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 a slice of exports
|
||||||
|
type Exports []*Export
|
||||||
|
|
||||||
|
// Add appends exports to the list
|
||||||
|
func (e *Exports) Add(i ...*Export) {
|
||||||
|
*e = append(*e, i...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isContainedIn(kind ExportType, subjects []Subject, vr *ValidationResults) {
|
||||||
|
m := make(map[string]string)
|
||||||
|
for i, ns := range subjects {
|
||||||
|
for j, s := range subjects {
|
||||||
|
if i == j {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ns.IsContainedIn(s) {
|
||||||
|
str := string(s)
|
||||||
|
_, ok := m[str]
|
||||||
|
if !ok {
|
||||||
|
m[str] = string(ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) != 0 {
|
||||||
|
for k, v := range m {
|
||||||
|
var vi ValidationIssue
|
||||||
|
vi.Blocking = true
|
||||||
|
vi.Description = fmt.Sprintf("%s export subject %q already exports %q", kind, k, v)
|
||||||
|
vr.Add(&vi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate calls validate on all of the exports
|
||||||
|
func (e *Exports) Validate(vr *ValidationResults) error {
|
||||||
|
var serviceSubjects []Subject
|
||||||
|
var streamSubjects []Subject
|
||||||
|
|
||||||
|
for _, v := range *e {
|
||||||
|
if v.IsService() {
|
||||||
|
serviceSubjects = append(serviceSubjects, v.Subject)
|
||||||
|
} else {
|
||||||
|
streamSubjects = append(streamSubjects, v.Subject)
|
||||||
|
}
|
||||||
|
v.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
isContainedIn(Service, serviceSubjects, vr)
|
||||||
|
isContainedIn(Stream, streamSubjects, vr)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasExportContainingSubject checks if the export list has an export with the provided subject
|
||||||
|
func (e *Exports) HasExportContainingSubject(subject Subject) bool {
|
||||||
|
for _, s := range *e {
|
||||||
|
if subject.IsContainedIn(s.Subject) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Exports) Len() int {
|
||||||
|
return len(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Exports) Swap(i, j int) {
|
||||||
|
e[i], e[j] = e[j], e[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Exports) Less(i, j int) bool {
|
||||||
|
return e[i].Subject < e[j].Subject
|
||||||
|
}
|
73
gateway/vendor/github.com/nats-io/jwt/genericlaims.go
generated
vendored
Normal file
73
gateway/vendor/github.com/nats-io/jwt/genericlaims.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
// GenericClaims can be used to read a JWT as a map for any non-generic fields
|
||||||
|
type GenericClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Data map[string]interface{} `json:"nats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGenericClaims creates a map-based Claims
|
||||||
|
func NewGenericClaims(subject string) *GenericClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := GenericClaims{}
|
||||||
|
c.Subject = subject
|
||||||
|
c.Data = make(map[string]interface{})
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeGeneric takes a JWT string and decodes it into a ClaimsData and map
|
||||||
|
func DecodeGeneric(token string) (*GenericClaims, error) {
|
||||||
|
v := GenericClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the standard part of the generic claim
|
||||||
|
func (gc *GenericClaims) Claims() *ClaimsData {
|
||||||
|
return &gc.ClaimsData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the custom part of the claims data
|
||||||
|
func (gc *GenericClaims) Payload() interface{} {
|
||||||
|
return &gc.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode takes a generic claims and creates a JWT string
|
||||||
|
func (gc *GenericClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
return gc.ClaimsData.Encode(pair, gc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the generic part of the claims data
|
||||||
|
func (gc *GenericClaims) Validate(vr *ValidationResults) {
|
||||||
|
gc.ClaimsData.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *GenericClaims) String() string {
|
||||||
|
return gc.ClaimsData.String(gc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes returns the types allowed to encode a generic JWT, which is nil for all
|
||||||
|
func (gc *GenericClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return nil
|
||||||
|
}
|
3
gateway/vendor/github.com/nats-io/jwt/go.mod
generated
vendored
Normal file
3
gateway/vendor/github.com/nats-io/jwt/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/nats-io/jwt
|
||||||
|
|
||||||
|
require github.com/nats-io/nkeys v0.1.3
|
9
gateway/vendor/github.com/nats-io/jwt/go.sum
generated
vendored
Normal file
9
gateway/vendor/github.com/nats-io/jwt/go.sum
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
github.com/nats-io/nkeys v0.1.3 h1:6JrEfig+HzTH85yxzhSVbjHRJv9cn0p6n3IngIcM5/k=
|
||||||
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
|
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/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=
|
71
gateway/vendor/github.com/nats-io/jwt/header.go
generated
vendored
Normal file
71
gateway/vendor/github.com/nats-io/jwt/header.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Version is semantic version.
|
||||||
|
Version = "0.3.2"
|
||||||
|
|
||||||
|
// TokenTypeJwt is the JWT token type supported JWT tokens
|
||||||
|
// encoded and decoded by this library
|
||||||
|
TokenTypeJwt = "jwt"
|
||||||
|
|
||||||
|
// AlgorithmNkey is the algorithm supported by JWT tokens
|
||||||
|
// encoded and decoded by this library
|
||||||
|
AlgorithmNkey = "ed25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Header is a JWT Jose Header
|
||||||
|
type Header struct {
|
||||||
|
Type string `json:"typ"`
|
||||||
|
Algorithm string `json:"alg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a header JWT token
|
||||||
|
func parseHeaders(s string) (*Header, error) {
|
||||||
|
h, err := decodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
header := Header{}
|
||||||
|
if err := json.Unmarshal(h, &header); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := header.Valid(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &header, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid validates the Header. It returns nil if the Header is
|
||||||
|
// a JWT header, and the algorithm used is the NKEY algorithm.
|
||||||
|
func (h *Header) Valid() error {
|
||||||
|
if TokenTypeJwt != strings.ToLower(h.Type) {
|
||||||
|
return fmt.Errorf("not supported type %q", h.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if AlgorithmNkey != strings.ToLower(h.Algorithm) {
|
||||||
|
return fmt.Errorf("unexpected %q algorithm", h.Algorithm)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
151
gateway/vendor/github.com/nats-io/jwt/imports.go
generated
vendored
Normal file
151
gateway/vendor/github.com/nats-io/jwt/imports.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Import describes a mapping from another account into this one
|
||||||
|
type Import struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
// Subject field in an import is always from the perspective of the
|
||||||
|
// initial publisher - in the case of a stream it is the account owning
|
||||||
|
// the stream (the exporter), and in the case of a service it is the
|
||||||
|
// account making the request (the importer).
|
||||||
|
Subject Subject `json:"subject,omitempty"`
|
||||||
|
Account string `json:"account,omitempty"`
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
// To field in an import is always from the perspective of the subscriber
|
||||||
|
// in the case of a stream it is the client of the stream (the importer),
|
||||||
|
// from the perspective of a service, it is the subscription waiting for
|
||||||
|
// requests (the exporter). If the field is empty, it will default to the
|
||||||
|
// value in the Subject field.
|
||||||
|
To Subject `json:"to,omitempty"`
|
||||||
|
Type ExportType `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsService returns true if the import is of type service
|
||||||
|
func (i *Import) IsService() bool {
|
||||||
|
return i.Type == Service
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStream returns true if the import is of type stream
|
||||||
|
func (i *Import) IsStream() bool {
|
||||||
|
return i.Type == Stream
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks if an import is valid for the wrapping account
|
||||||
|
func (i *Import) Validate(actPubKey string, vr *ValidationResults) {
|
||||||
|
if !i.IsService() && !i.IsStream() {
|
||||||
|
vr.AddError("invalid import type: %q", i.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.Account == "" {
|
||||||
|
vr.AddWarning("account to import from is not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
i.Subject.Validate(vr)
|
||||||
|
|
||||||
|
if i.IsService() && i.Subject.HasWildCards() {
|
||||||
|
vr.AddError("services cannot have wildcard subject: %q", i.Subject)
|
||||||
|
}
|
||||||
|
if i.IsStream() && i.To.HasWildCards() {
|
||||||
|
vr.AddError("streams cannot have wildcard to subject: %q", i.Subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
var act *ActivationClaims
|
||||||
|
|
||||||
|
if i.Token != "" {
|
||||||
|
// Check to see if its an embedded JWT or a URL.
|
||||||
|
if url, err := url.Parse(i.Token); err == nil && url.Scheme != "" {
|
||||||
|
c := &http.Client{Timeout: 5 * time.Second}
|
||||||
|
resp, err := c.Get(url.String())
|
||||||
|
if err != nil {
|
||||||
|
vr.AddWarning("import %s contains an unreachable token URL %q", i.Subject, i.Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
vr.AddWarning("import %s contains an unreadable token URL %q", i.Subject, i.Token)
|
||||||
|
} else {
|
||||||
|
act, err = DecodeActivationClaims(string(body))
|
||||||
|
if err != nil {
|
||||||
|
vr.AddWarning("import %s contains a url %q with an invalid activation token", i.Subject, i.Token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
act, err = DecodeActivationClaims(i.Token)
|
||||||
|
if err != nil {
|
||||||
|
vr.AddWarning("import %q contains an invalid activation token", i.Subject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if act != nil {
|
||||||
|
if act.Issuer != i.Account {
|
||||||
|
vr.AddWarning("activation token doesn't match account for import %q", i.Subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
if act.ClaimsData.Subject != actPubKey {
|
||||||
|
vr.AddWarning("activation token doesn't match account it is being included in, %q", i.Subject)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vr.AddWarning("no activation provided for import %s", i.Subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports is a list of import structs
|
||||||
|
type Imports []*Import
|
||||||
|
|
||||||
|
// Validate checks if an import is valid for the wrapping account
|
||||||
|
func (i *Imports) Validate(acctPubKey string, vr *ValidationResults) {
|
||||||
|
toSet := make(map[Subject]bool, len(*i))
|
||||||
|
for _, v := range *i {
|
||||||
|
if v.Type == Service {
|
||||||
|
if _, ok := toSet[v.To]; ok {
|
||||||
|
vr.AddError("Duplicate To subjects for %q", v.To)
|
||||||
|
}
|
||||||
|
toSet[v.To] = true
|
||||||
|
}
|
||||||
|
v.Validate(acctPubKey, vr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add is a simple way to add imports
|
||||||
|
func (i *Imports) Add(a ...*Import) {
|
||||||
|
*i = append(*i, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Imports) Len() int {
|
||||||
|
return len(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Imports) Swap(j, k int) {
|
||||||
|
i[j], i[k] = i[k], i[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Imports) Less(j, k int) bool {
|
||||||
|
return i[j].Subject < i[k].Subject
|
||||||
|
}
|
204
gateway/vendor/github.com/nats-io/jwt/operator_claims.go
generated
vendored
Normal file
204
gateway/vendor/github.com/nats-io/jwt/operator_claims.go
generated
vendored
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operator specific claims
|
||||||
|
type Operator struct {
|
||||||
|
// Slice of real identies (like websites) that can be used to identify the operator.
|
||||||
|
Identities []Identity `json:"identity,omitempty"`
|
||||||
|
// Slice of other operator NKeys that can be used to sign on behalf of the main
|
||||||
|
// operator identity.
|
||||||
|
SigningKeys StringList `json:"signing_keys,omitempty"`
|
||||||
|
// AccountServerURL is a partial URL like "https://host.domain.org:<port>/jwt/v1"
|
||||||
|
// tools will use the prefix and build queries by appending /accounts/<account_id>
|
||||||
|
// or /operator to the path provided. Note this assumes that the account server
|
||||||
|
// can handle requests in a nats-account-server compatible way. See
|
||||||
|
// https://github.com/nats-io/nats-account-server.
|
||||||
|
AccountServerURL string `json:"account_server_url,omitempty"`
|
||||||
|
// A list of NATS urls (tls://host:port) where tools can connect to the server
|
||||||
|
// using proper credentials.
|
||||||
|
OperatorServiceURLs StringList `json:"operator_service_urls,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the validity of the operators contents
|
||||||
|
func (o *Operator) Validate(vr *ValidationResults) {
|
||||||
|
if err := o.validateAccountServerURL(); err != nil {
|
||||||
|
vr.AddError(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range o.validateOperatorServiceURLs() {
|
||||||
|
if v != nil {
|
||||||
|
vr.AddError(v.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range o.Identities {
|
||||||
|
i.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range o.SigningKeys {
|
||||||
|
if !nkeys.IsValidPublicOperatorKey(k) {
|
||||||
|
vr.AddError("%s is not an operator public key", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operator) validateAccountServerURL() error {
|
||||||
|
if o.AccountServerURL != "" {
|
||||||
|
// We don't care what kind of URL it is so long as it parses
|
||||||
|
// and has a protocol. The account server may impose additional
|
||||||
|
// constraints on the type of URLs that it is able to notify to
|
||||||
|
u, err := url.Parse(o.AccountServerURL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing account server url: %v", err)
|
||||||
|
}
|
||||||
|
if u.Scheme == "" {
|
||||||
|
return fmt.Errorf("account server url %q requires a protocol", o.AccountServerURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateOperatorServiceURL returns an error if the URL is not a valid NATS or TLS url.
|
||||||
|
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)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing operator service url %q: %v", v, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.User != nil {
|
||||||
|
return fmt.Errorf("operator service url %q - credentials are not supported", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Path != "" {
|
||||||
|
return fmt.Errorf("operator service url %q - paths are not supported", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
lcs := strings.ToLower(u.Scheme)
|
||||||
|
switch lcs {
|
||||||
|
case "nats":
|
||||||
|
return nil
|
||||||
|
case "tls":
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("operator service url %q - protocol not supported (only 'nats' or 'tls' only)", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Operator) validateOperatorServiceURLs() []error {
|
||||||
|
var errors []error
|
||||||
|
for _, v := range o.OperatorServiceURLs {
|
||||||
|
if v != "" {
|
||||||
|
if err := ValidateOperatorServiceURL(v); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorClaims define the data for an operator JWT
|
||||||
|
type OperatorClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Operator `json:"nats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOperatorClaims creates a new operator claim with the specified subject, which should be an operator public key
|
||||||
|
func NewOperatorClaims(subject string) *OperatorClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := &OperatorClaims{}
|
||||||
|
c.Subject = subject
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// DidSign checks the claims against the operator's public key and its signing keys
|
||||||
|
func (oc *OperatorClaims) DidSign(op Claims) bool {
|
||||||
|
if op == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
issuer := op.Claims().Issuer
|
||||||
|
if issuer == oc.Subject {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return oc.SigningKeys.Contains(issuer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: AddSigningKey, use claim.SigningKeys.Add()
|
||||||
|
func (oc *OperatorClaims) AddSigningKey(pk string) {
|
||||||
|
oc.SigningKeys.Add(pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the claims into a JWT string
|
||||||
|
func (oc *OperatorClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicOperatorKey(oc.Subject) {
|
||||||
|
return "", errors.New("expected subject to be an operator public key")
|
||||||
|
}
|
||||||
|
err := oc.validateAccountServerURL()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
oc.ClaimsData.Type = OperatorClaim
|
||||||
|
return oc.ClaimsData.Encode(pair, oc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeOperatorClaims tries to create an operator claims from a JWt string
|
||||||
|
func DecodeOperatorClaims(token string) (*OperatorClaims, error) {
|
||||||
|
v := OperatorClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (oc *OperatorClaims) String() string {
|
||||||
|
return oc.ClaimsData.String(oc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the operator specific data for an operator JWT
|
||||||
|
func (oc *OperatorClaims) Payload() interface{} {
|
||||||
|
return &oc.Operator
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the contents of the claims
|
||||||
|
func (oc *OperatorClaims) Validate(vr *ValidationResults) {
|
||||||
|
oc.ClaimsData.Validate(vr)
|
||||||
|
oc.Operator.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the nkey types that can sign operator claims, operator
|
||||||
|
func (oc *OperatorClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteOperator}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the generic claims data
|
||||||
|
func (oc *OperatorClaims) Claims() *ClaimsData {
|
||||||
|
return &oc.ClaimsData
|
||||||
|
}
|
32
gateway/vendor/github.com/nats-io/jwt/revocation_list.go
generated
vendored
Normal file
32
gateway/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()
|
||||||
|
}
|
94
gateway/vendor/github.com/nats-io/jwt/server_claims.go
generated
vendored
Normal file
94
gateway/vendor/github.com/nats-io/jwt/server_claims.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server defines the custom part of a server jwt
|
||||||
|
type Server struct {
|
||||||
|
Permissions
|
||||||
|
Cluster string `json:"cluster,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the cluster and permissions for a server JWT
|
||||||
|
func (s *Server) Validate(vr *ValidationResults) {
|
||||||
|
if s.Cluster == "" {
|
||||||
|
vr.AddError("servers can't contain an empty cluster")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServerClaims defines the data in a server JWT
|
||||||
|
type ServerClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
Server `json:"nats,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServerClaims creates a new server JWT with the specified subject/public key
|
||||||
|
func NewServerClaims(subject string) *ServerClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := &ServerClaims{}
|
||||||
|
c.Subject = subject
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode tries to turn the server claims into a JWT string
|
||||||
|
func (s *ServerClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicServerKey(s.Subject) {
|
||||||
|
return "", errors.New("expected subject to be a server public key")
|
||||||
|
}
|
||||||
|
s.ClaimsData.Type = ServerClaim
|
||||||
|
return s.ClaimsData.Encode(pair, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeServerClaims tries to parse server claims from a JWT string
|
||||||
|
func DecodeServerClaims(token string) (*ServerClaims, error) {
|
||||||
|
v := ServerClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerClaims) String() string {
|
||||||
|
return s.ClaimsData.String(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the server specific data
|
||||||
|
func (s *ServerClaims) Payload() interface{} {
|
||||||
|
return &s.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the generic and server data in the server claims
|
||||||
|
func (s *ServerClaims) Validate(vr *ValidationResults) {
|
||||||
|
s.ClaimsData.Validate(vr)
|
||||||
|
s.Server.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the types that can encode a server JWT, operator or cluster
|
||||||
|
func (s *ServerClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteOperator, nkeys.PrefixByteCluster}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the generic data
|
||||||
|
func (s *ServerClaims) Claims() *ClaimsData {
|
||||||
|
return &s.ClaimsData
|
||||||
|
}
|
334
gateway/vendor/github.com/nats-io/jwt/types.go
generated
vendored
Normal file
334
gateway/vendor/github.com/nats-io/jwt/types.go
generated
vendored
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExportType defines the type of import/export.
|
||||||
|
type ExportType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Unknown is used if we don't know the type
|
||||||
|
Unknown ExportType = iota
|
||||||
|
// Stream defines the type field value for a stream "stream"
|
||||||
|
Stream
|
||||||
|
// Service defines the type field value for a service "service"
|
||||||
|
Service
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t ExportType) String() string {
|
||||||
|
switch t {
|
||||||
|
case Stream:
|
||||||
|
return "stream"
|
||||||
|
case Service:
|
||||||
|
return "service"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals the enum as a quoted json string
|
||||||
|
func (t *ExportType) MarshalJSON() ([]byte, error) {
|
||||||
|
switch *t {
|
||||||
|
case Stream:
|
||||||
|
return []byte("\"stream\""), nil
|
||||||
|
case Service:
|
||||||
|
return []byte("\"service\""), nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unknown export type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmashals a quoted json string to the enum value
|
||||||
|
func (t *ExportType) UnmarshalJSON(b []byte) error {
|
||||||
|
var j string
|
||||||
|
err := json.Unmarshal(b, &j)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch j {
|
||||||
|
case "stream":
|
||||||
|
*t = Stream
|
||||||
|
return nil
|
||||||
|
case "service":
|
||||||
|
*t = Service
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unknown export type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subject is a string that represents a NATS subject
|
||||||
|
type Subject string
|
||||||
|
|
||||||
|
// Validate checks that a subject string is valid, ie not empty and without spaces
|
||||||
|
func (s Subject) Validate(vr *ValidationResults) {
|
||||||
|
v := string(s)
|
||||||
|
if v == "" {
|
||||||
|
vr.AddError("subject cannot be empty")
|
||||||
|
}
|
||||||
|
if strings.Contains(v, " ") {
|
||||||
|
vr.AddError("subject %q cannot have spaces", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasWildCards is used to check if a subject contains a > or *
|
||||||
|
func (s Subject) HasWildCards() bool {
|
||||||
|
v := string(s)
|
||||||
|
return strings.HasSuffix(v, ".>") ||
|
||||||
|
strings.Contains(v, ".*.") ||
|
||||||
|
strings.HasSuffix(v, ".*") ||
|
||||||
|
strings.HasPrefix(v, "*.") ||
|
||||||
|
v == "*" ||
|
||||||
|
v == ">"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsContainedIn does a simple test to see if the subject is contained in another subject
|
||||||
|
func (s Subject) IsContainedIn(other Subject) bool {
|
||||||
|
otherArray := strings.Split(string(other), ".")
|
||||||
|
myArray := strings.Split(string(s), ".")
|
||||||
|
|
||||||
|
if len(myArray) > len(otherArray) && otherArray[len(otherArray)-1] != ">" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(myArray) < len(otherArray) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for ind, tok := range otherArray {
|
||||||
|
myTok := myArray[ind]
|
||||||
|
|
||||||
|
if ind == len(otherArray)-1 && tok == ">" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if tok != myTok && tok != "*" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamedSubject is the combination of a subject and a name for it
|
||||||
|
type NamedSubject struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Subject Subject `json:"subject,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the subject
|
||||||
|
func (ns *NamedSubject) Validate(vr *ValidationResults) {
|
||||||
|
ns.Subject.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeRange is used to represent a start and end time
|
||||||
|
type TimeRange struct {
|
||||||
|
Start string `json:"start,omitempty"`
|
||||||
|
End string `json:"end,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the values in a time range struct
|
||||||
|
func (tr *TimeRange) Validate(vr *ValidationResults) {
|
||||||
|
format := "15:04:05"
|
||||||
|
|
||||||
|
if tr.Start == "" {
|
||||||
|
vr.AddError("time ranges start must contain a start")
|
||||||
|
} else {
|
||||||
|
_, err := time.Parse(format, tr.Start)
|
||||||
|
if err != nil {
|
||||||
|
vr.AddError("start in time range is invalid %q", tr.Start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tr.End == "" {
|
||||||
|
vr.AddError("time ranges end must contain an end")
|
||||||
|
} else {
|
||||||
|
_, err := time.Parse(format, tr.End)
|
||||||
|
if err != nil {
|
||||||
|
vr.AddError("end in time range is invalid %q", tr.End)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limits are used to control acccess for users and importing accounts
|
||||||
|
// Src is a comma separated list of CIDR specifications
|
||||||
|
type Limits struct {
|
||||||
|
Max int64 `json:"max,omitempty"`
|
||||||
|
Payload int64 `json:"payload,omitempty"`
|
||||||
|
Src string `json:"src,omitempty"`
|
||||||
|
Times []TimeRange `json:"times,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the values in a limit struct
|
||||||
|
func (l *Limits) Validate(vr *ValidationResults) {
|
||||||
|
if l.Max < 0 {
|
||||||
|
vr.AddError("limits cannot contain a negative maximum, %d", l.Max)
|
||||||
|
}
|
||||||
|
if l.Payload < 0 {
|
||||||
|
vr.AddError("limits cannot contain a negative payload, %d", l.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.Src != "" {
|
||||||
|
elements := strings.Split(l.Src, ",")
|
||||||
|
|
||||||
|
for _, cidr := range elements {
|
||||||
|
cidr = strings.TrimSpace(cidr)
|
||||||
|
_, ipNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil || ipNet == nil {
|
||||||
|
vr.AddError("invalid cidr %q in user src limits", cidr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.Times != nil && len(l.Times) > 0 {
|
||||||
|
for _, t := range l.Times {
|
||||||
|
t.Validate(vr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permission defines allow/deny subjects
|
||||||
|
type Permission struct {
|
||||||
|
Allow StringList `json:"allow,omitempty"`
|
||||||
|
Deny StringList `json:"deny,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the allow, deny elements of a permission
|
||||||
|
func (p *Permission) Validate(vr *ValidationResults) {
|
||||||
|
for _, subj := range p.Allow {
|
||||||
|
Subject(subj).Validate(vr)
|
||||||
|
}
|
||||||
|
for _, subj := range p.Deny {
|
||||||
|
Subject(subj).Validate(vr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
type Permissions struct {
|
||||||
|
Pub Permission `json:"pub,omitempty"`
|
||||||
|
Sub Permission `json:"sub,omitempty"`
|
||||||
|
Resp *ResponsePermission `json:"resp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the pub and sub fields in the permissions list
|
||||||
|
func (p *Permissions) Validate(vr *ValidationResults) {
|
||||||
|
p.Pub.Validate(vr)
|
||||||
|
p.Sub.Validate(vr)
|
||||||
|
if p.Resp != nil {
|
||||||
|
p.Resp.Validate(vr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringList is a wrapper for an array of strings
|
||||||
|
type StringList []string
|
||||||
|
|
||||||
|
// Contains returns true if the list contains the string
|
||||||
|
func (u *StringList) Contains(p string) bool {
|
||||||
|
for _, t := range *u {
|
||||||
|
if t == p {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends 1 or more strings to a list
|
||||||
|
func (u *StringList) Add(p ...string) {
|
||||||
|
for _, v := range p {
|
||||||
|
if !u.Contains(v) && v != "" {
|
||||||
|
*u = append(*u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes 1 or more strings from a list
|
||||||
|
func (u *StringList) Remove(p ...string) {
|
||||||
|
for _, v := range p {
|
||||||
|
for i, t := range *u {
|
||||||
|
if t == v {
|
||||||
|
a := *u
|
||||||
|
*u = append(a[:i], a[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagList is a unique array of lower case strings
|
||||||
|
// All tag list methods lower case the strings in the arguments
|
||||||
|
type TagList []string
|
||||||
|
|
||||||
|
// Contains returns true if the list contains the tags
|
||||||
|
func (u *TagList) Contains(p string) bool {
|
||||||
|
p = strings.ToLower(p)
|
||||||
|
for _, t := range *u {
|
||||||
|
if t == p {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add appends 1 or more tags to a list
|
||||||
|
func (u *TagList) Add(p ...string) {
|
||||||
|
for _, v := range p {
|
||||||
|
v = strings.ToLower(v)
|
||||||
|
if !u.Contains(v) && v != "" {
|
||||||
|
*u = append(*u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes 1 or more tags from a list
|
||||||
|
func (u *TagList) Remove(p ...string) {
|
||||||
|
for _, v := range p {
|
||||||
|
v = strings.ToLower(v)
|
||||||
|
for i, t := range *u {
|
||||||
|
if t == v {
|
||||||
|
a := *u
|
||||||
|
*u = append(a[:i], a[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity is used to associate an account or operator with a real entity
|
||||||
|
type Identity struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Proof string `json:"proof,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the values in an Identity
|
||||||
|
func (u *Identity) Validate(vr *ValidationResults) {
|
||||||
|
//Fixme identity validation
|
||||||
|
}
|
99
gateway/vendor/github.com/nats-io/jwt/user_claims.go
generated
vendored
Normal file
99
gateway/vendor/github.com/nats-io/jwt/user_claims.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2019 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 (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User defines the user specific data in a user JWT
|
||||||
|
type User struct {
|
||||||
|
Permissions
|
||||||
|
Limits
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the permissions and limits in a User jwt
|
||||||
|
func (u *User) Validate(vr *ValidationResults) {
|
||||||
|
u.Permissions.Validate(vr)
|
||||||
|
u.Limits.Validate(vr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserClaims defines a user JWT
|
||||||
|
type UserClaims struct {
|
||||||
|
ClaimsData
|
||||||
|
User `json:"nats,omitempty"`
|
||||||
|
// IssuerAccount stores the public key for the account the issuer represents.
|
||||||
|
// When set, the claim was issued by a signing key.
|
||||||
|
IssuerAccount string `json:"issuer_account,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUserClaims creates a user JWT with the specific subject/public key
|
||||||
|
func NewUserClaims(subject string) *UserClaims {
|
||||||
|
if subject == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
c := &UserClaims{}
|
||||||
|
c.Subject = subject
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode tries to turn the user claims into a JWT string
|
||||||
|
func (u *UserClaims) Encode(pair nkeys.KeyPair) (string, error) {
|
||||||
|
if !nkeys.IsValidPublicUserKey(u.Subject) {
|
||||||
|
return "", errors.New("expected subject to be user public key")
|
||||||
|
}
|
||||||
|
u.ClaimsData.Type = UserClaim
|
||||||
|
return u.ClaimsData.Encode(pair, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeUserClaims tries to parse a user claims from a JWT string
|
||||||
|
func DecodeUserClaims(token string) (*UserClaims, error) {
|
||||||
|
v := UserClaims{}
|
||||||
|
if err := Decode(token, &v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the generic and specific parts of the user jwt
|
||||||
|
func (u *UserClaims) Validate(vr *ValidationResults) {
|
||||||
|
u.ClaimsData.Validate(vr)
|
||||||
|
u.User.Validate(vr)
|
||||||
|
if u.IssuerAccount != "" && !nkeys.IsValidPublicAccountKey(u.IssuerAccount) {
|
||||||
|
vr.AddError("account_id is not an account public key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpectedPrefixes defines the types that can encode a user JWT, account
|
||||||
|
func (u *UserClaims) ExpectedPrefixes() []nkeys.PrefixByte {
|
||||||
|
return []nkeys.PrefixByte{nkeys.PrefixByteAccount}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claims returns the generic data from a user jwt
|
||||||
|
func (u *UserClaims) Claims() *ClaimsData {
|
||||||
|
return &u.ClaimsData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Payload returns the user specific data from a user JWT
|
||||||
|
func (u *UserClaims) Payload() interface{} {
|
||||||
|
return &u.User
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserClaims) String() string {
|
||||||
|
return u.ClaimsData.String(u)
|
||||||
|
}
|
107
gateway/vendor/github.com/nats-io/jwt/validation.go
generated
vendored
Normal file
107
gateway/vendor/github.com/nats-io/jwt/validation.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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 (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidationIssue represents an issue during JWT validation, it may or may not be a blocking error
|
||||||
|
type ValidationIssue struct {
|
||||||
|
Description string
|
||||||
|
Blocking bool
|
||||||
|
TimeCheck bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ve *ValidationIssue) Error() string {
|
||||||
|
return ve.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidationResults is a list of ValidationIssue pointers
|
||||||
|
type ValidationResults struct {
|
||||||
|
Issues []*ValidationIssue
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateValidationResults creates an empty list of validation issues
|
||||||
|
func CreateValidationResults() *ValidationResults {
|
||||||
|
issues := []*ValidationIssue{}
|
||||||
|
return &ValidationResults{
|
||||||
|
Issues: issues,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add appends an issue to the list
|
||||||
|
func (v *ValidationResults) Add(vi *ValidationIssue) {
|
||||||
|
v.Issues = append(v.Issues, vi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddError creates a new validation error and adds it to the list
|
||||||
|
func (v *ValidationResults) AddError(format string, args ...interface{}) {
|
||||||
|
v.Add(&ValidationIssue{
|
||||||
|
Description: fmt.Sprintf(format, args...),
|
||||||
|
Blocking: true,
|
||||||
|
TimeCheck: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTimeCheck creates a new validation issue related to a time check and adds it to the list
|
||||||
|
func (v *ValidationResults) AddTimeCheck(format string, args ...interface{}) {
|
||||||
|
v.Add(&ValidationIssue{
|
||||||
|
Description: fmt.Sprintf(format, args...),
|
||||||
|
Blocking: false,
|
||||||
|
TimeCheck: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddWarning creates a new validation warning and adds it to the list
|
||||||
|
func (v *ValidationResults) AddWarning(format string, args ...interface{}) {
|
||||||
|
v.Add(&ValidationIssue{
|
||||||
|
Description: fmt.Sprintf(format, args...),
|
||||||
|
Blocking: false,
|
||||||
|
TimeCheck: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsBlocking returns true if the list contains a blocking error
|
||||||
|
func (v *ValidationResults) IsBlocking(includeTimeChecks bool) bool {
|
||||||
|
for _, i := range v.Issues {
|
||||||
|
if i.Blocking {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if includeTimeChecks && i.TimeCheck {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if the list is empty
|
||||||
|
func (v *ValidationResults) IsEmpty() bool {
|
||||||
|
return len(v.Issues) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errors returns only blocking issues as errors
|
||||||
|
func (v *ValidationResults) Errors() []error {
|
||||||
|
var errs []error
|
||||||
|
for _, v := range v.Issues {
|
||||||
|
if v.Blocking {
|
||||||
|
errs = append(errs, errors.New(v.Description))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errs
|
||||||
|
}
|
@ -37,3 +37,6 @@ _testmain.go
|
|||||||
.settings/
|
.settings/
|
||||||
|
|
||||||
# bin
|
# bin
|
||||||
|
|
||||||
|
# Goland
|
||||||
|
.idea
|
24
gateway/vendor/github.com/nats-io/nats.go/.travis.yml
generated
vendored
Normal file
24
gateway/vendor/github.com/nats-io/nats.go/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
go:
|
||||||
|
- 1.13.x
|
||||||
|
- 1.12.x
|
||||||
|
env:
|
||||||
|
- GO111MODULE=off
|
||||||
|
go_import_path: github.com/nats-io/nats.go
|
||||||
|
install:
|
||||||
|
- go get -t ./...
|
||||||
|
- go get github.com/nats-io/nats-server
|
||||||
|
- go get github.com/mattn/goveralls
|
||||||
|
- go get github.com/wadey/gocovmerge
|
||||||
|
- go get -u honnef.co/go/tools/cmd/staticcheck
|
||||||
|
- go get -u github.com/client9/misspell/cmd/misspell
|
||||||
|
before_script:
|
||||||
|
- $(exit $(go fmt ./... | wc -l))
|
||||||
|
- go vet ./...
|
||||||
|
- find . -type f -name "*.go" | xargs misspell -error -locale US
|
||||||
|
- staticcheck ./...
|
||||||
|
script:
|
||||||
|
- go test -i -race ./...
|
||||||
|
- go test -v -run=TestNoRace -p=1 ./...
|
||||||
|
- if [[ "$TRAVIS_GO_VERSION" =~ 1.13 ]]; then ./scripts/cov.sh TRAVIS; else go test -race -v -p=1 ./... --failfast; fi
|
3
gateway/vendor/github.com/nats-io/nats.go/CODE-OF-CONDUCT.md
generated
vendored
Normal file
3
gateway/vendor/github.com/nats-io/nats.go/CODE-OF-CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
## Community Code of Conduct
|
||||||
|
|
||||||
|
NATS follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
201
gateway/vendor/github.com/nats-io/nats.go/LICENSE
generated
vendored
Normal file
201
gateway/vendor/github.com/nats-io/nats.go/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
@ -3,22 +3,36 @@ A [Go](http://golang.org) client for the [NATS messaging system](https://nats.io
|
|||||||
|
|
||||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fgo-nats?ref=badge_shield)
|
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fnats-io%2Fgo-nats?ref=badge_shield)
|
||||||
[](https://goreportcard.com/report/github.com/nats-io/go-nats) [](http://travis-ci.org/nats-io/go-nats) [](http://godoc.org/github.com/nats-io/go-nats) [](https://coveralls.io/r/nats-io/go-nats?branch=master)
|
[](https://goreportcard.com/report/github.com/nats-io/nats.go) [](http://travis-ci.org/nats-io/nats.go) [](http://godoc.org/github.com/nats-io/nats.go) [](https://coveralls.io/r/nats-io/nats.go?branch=master)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Go client
|
# Go client
|
||||||
go get github.com/nats-io/go-nats
|
go get github.com/nats-io/nats.go/
|
||||||
|
|
||||||
# Server
|
# Server
|
||||||
go get github.com/nats-io/gnatsd
|
go get github.com/nats-io/nats-server
|
||||||
|
```
|
||||||
|
|
||||||
|
When using or transitioning to Go modules support:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Go client latest or explicit version
|
||||||
|
go get github.com/nats-io/nats.go/@latest
|
||||||
|
go get github.com/nats-io/nats.go/@v1.9.2
|
||||||
|
|
||||||
|
# For latest NATS Server, add /v2 at the end
|
||||||
|
go get github.com/nats-io/nats-server/v2
|
||||||
|
|
||||||
|
# NATS Server v1 is installed otherwise
|
||||||
|
# go get github.com/nats-io/nats-server
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import nats "github.com/nats-io/go-nats"
|
import nats "github.com/nats-io/nats.go"
|
||||||
|
|
||||||
// Connect to a server
|
// Connect to a server
|
||||||
nc, _ := nats.Connect(nats.DefaultURL)
|
nc, _ := nats.Connect(nats.DefaultURL)
|
||||||
@ -31,6 +45,11 @@ nc.Subscribe("foo", func(m *nats.Msg) {
|
|||||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Responding to a request message
|
||||||
|
nc.Subscribe("request", func(m *nats.Msg) {
|
||||||
|
m.Respond([]byte("answer is 42"))
|
||||||
|
})
|
||||||
|
|
||||||
// Simple Sync Subscriber
|
// Simple Sync Subscriber
|
||||||
sub, err := nc.SubscribeSync("foo")
|
sub, err := nc.SubscribeSync("foo")
|
||||||
m, err := sub.NextMsg(timeout)
|
m, err := sub.NextMsg(timeout)
|
||||||
@ -50,7 +69,7 @@ sub.Drain()
|
|||||||
msg, err := nc.Request("help", []byte("help me"), 10*time.Millisecond)
|
msg, err := nc.Request("help", []byte("help me"), 10*time.Millisecond)
|
||||||
|
|
||||||
// Replies
|
// Replies
|
||||||
nc.Subscribe("help", func(m *Msg) {
|
nc.Subscribe("help", func(m *nats.Msg) {
|
||||||
nc.Publish(m.Reply, []byte("I can help!"))
|
nc.Publish(m.Reply, []byte("I can help!"))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -97,12 +116,12 @@ c.Publish("hello", me)
|
|||||||
|
|
||||||
// Unsubscribe
|
// Unsubscribe
|
||||||
sub, err := c.Subscribe("foo", nil)
|
sub, err := c.Subscribe("foo", nil)
|
||||||
...
|
// ...
|
||||||
sub.Unsubscribe()
|
sub.Unsubscribe()
|
||||||
|
|
||||||
// Requests
|
// Requests
|
||||||
var response string
|
var response string
|
||||||
err := c.Request("help", "help me", &response, 10*time.Millisecond)
|
err = c.Request("help", "help me", &response, 10*time.Millisecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Request failed: %v\n", err)
|
fmt.Printf("Request failed: %v\n", err)
|
||||||
}
|
}
|
||||||
@ -122,21 +141,21 @@ This requires server with version >= 2.0.0
|
|||||||
NATS servers have a new security and authentication mechanism to authenticate with user credentials and Nkeys.
|
NATS servers have a new security and authentication mechanism to authenticate with user credentials and Nkeys.
|
||||||
The simplest form is to use the helper method UserCredentials(credsFilepath).
|
The simplest form is to use the helper method UserCredentials(credsFilepath).
|
||||||
```go
|
```go
|
||||||
nc, err := nats.Connect(url, UserCredentials("user.creds"))
|
nc, err := nats.Connect(url, nats.UserCredentials("user.creds"))
|
||||||
```
|
```
|
||||||
|
|
||||||
The helper methos creates two callback handlers to present the user JWT and sign the nonce challenge from the server.
|
The helper methods creates two callback handlers to present the user JWT and sign the nonce challenge from the server.
|
||||||
The core client library never has direct access to your private key and simply performs the callback for signing the server challenge.
|
The core client library never has direct access to your private key and simply performs the callback for signing the server challenge.
|
||||||
The helper will load and wipe and erase memory it uses for each connect or reconnect.
|
The helper will load and wipe and erase memory it uses for each connect or reconnect.
|
||||||
|
|
||||||
The helper also can take two entries, one for the JWT and one for the NKey seed file.
|
The helper also can take two entries, one for the JWT and one for the NKey seed file.
|
||||||
```go
|
```go
|
||||||
nc, err := nats.Connect(url, UserCredentials("user.jwt", "user.nk"))
|
nc, err := nats.Connect(url, nats.UserCredentials("user.jwt", "user.nk"))
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also set the callback handlers directly and manage challenge signing directly.
|
You can also set the callback handlers directly and manage challenge signing directly.
|
||||||
```go
|
```go
|
||||||
nc, err := nats.Connect(url, UserJWT(jwtCB, sigCB))
|
nc, err := nats.Connect(url, nats.UserJWT(jwtCB, sigCB))
|
||||||
```
|
```
|
||||||
|
|
||||||
Bare Nkeys are also supported. The nkey seed should be in a read only file, e.g. seed.txt
|
Bare Nkeys are also supported. The nkey seed should be in a read only file, e.g. seed.txt
|
||||||
@ -155,7 +174,7 @@ opt, err := nats.NkeyOptionFromSeed("seed.txt")
|
|||||||
nc, err := nats.Connect(serverUrl, opt)
|
nc, err := nats.Connect(serverUrl, opt)
|
||||||
|
|
||||||
// Direct
|
// Direct
|
||||||
nc, err := nats.Connect(serverUrl, Nkey(pubNkey, sigCB))
|
nc, err := nats.Connect(serverUrl, nats.Nkey(pubNkey, sigCB))
|
||||||
```
|
```
|
||||||
|
|
||||||
## TLS
|
## TLS
|
||||||
@ -311,8 +330,8 @@ nc, err = nats.Connect(servers, nats.DontRandomize())
|
|||||||
|
|
||||||
// Setup callbacks to be notified on disconnects, reconnects and connection closed.
|
// Setup callbacks to be notified on disconnects, reconnects and connection closed.
|
||||||
nc, err = nats.Connect(servers,
|
nc, err = nats.Connect(servers,
|
||||||
nats.DisconnectHandler(func(nc *nats.Conn) {
|
nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
|
||||||
fmt.Printf("Got disconnected!\n")
|
fmt.Printf("Got disconnected! Reason: %q\n", err)
|
||||||
}),
|
}),
|
||||||
nats.ReconnectHandler(func(nc *nats.Conn) {
|
nats.ReconnectHandler(func(nc *nats.Conn) {
|
||||||
fmt.Printf("Got reconnected to %v!\n", nc.ConnectedUrl())
|
fmt.Printf("Got reconnected to %v!\n", nc.ConnectedUrl())
|
||||||
@ -339,9 +358,9 @@ nc, err = nats.Connect("nats://localhost:4222",
|
|||||||
nats.Token("S3cretT0ken"))
|
nats.Token("S3cretT0ken"))
|
||||||
|
|
||||||
// Note that if credentials are specified in the initial URLs, they take
|
// Note that if credentials are specified in the initial URLs, they take
|
||||||
// precedence on the credentials specfied through the options.
|
// precedence on the credentials specified through the options.
|
||||||
// For instance, in the connect call below, the client library will use
|
// For instance, in the connect call below, the client library will use
|
||||||
// the user "my" and password "pwd" to connect to locahost:4222, however,
|
// the user "my" and password "pwd" to connect to localhost:4222, however,
|
||||||
// it will use username "foo" and password "bar" when (re)connecting to
|
// it will use username "foo" and password "bar" when (re)connecting to
|
||||||
// a different server URL that it got as part of the auto-discovery.
|
// a different server URL that it got as part of the auto-discovery.
|
||||||
nc, err = nats.Connect("nats://my:pwd@localhost:4222", nats.UserInfo("foo", "bar"))
|
nc, err = nats.Connect("nats://my:pwd@localhost:4222", nats.UserInfo("foo", "bar"))
|
@ -43,29 +43,7 @@ func (nc *Conn) RequestWithContext(ctx context.Context, subj string, data []byte
|
|||||||
return nc.oldRequestWithContext(ctx, subj, data)
|
return nc.oldRequestWithContext(ctx, subj, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do setup for the new style.
|
mch, token, err := nc.createNewRequestAndSend(subj, data)
|
||||||
if nc.respMap == nil {
|
|
||||||
nc.initNewResp()
|
|
||||||
}
|
|
||||||
// Create literal Inbox and map to a chan msg.
|
|
||||||
mch := make(chan *Msg, RequestChanLen)
|
|
||||||
respInbox := nc.newRespInbox()
|
|
||||||
token := respToken(respInbox)
|
|
||||||
nc.respMap[token] = mch
|
|
||||||
createSub := nc.respMux == nil
|
|
||||||
ginbox := nc.respSub
|
|
||||||
nc.mu.Unlock()
|
|
||||||
|
|
||||||
if createSub {
|
|
||||||
// Make sure scoped subscription is setup only once.
|
|
||||||
var err error
|
|
||||||
nc.respSetup.Do(func() { err = nc.createRespMux(ginbox) })
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := nc.PublishRequest(subj, respInbox, data)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -93,7 +71,7 @@ func (nc *Conn) oldRequestWithContext(ctx context.Context, subj string, data []b
|
|||||||
inbox := NewInbox()
|
inbox := NewInbox()
|
||||||
ch := make(chan *Msg, RequestChanLen)
|
ch := make(chan *Msg, RequestChanLen)
|
||||||
|
|
||||||
s, err := nc.subscribe(inbox, _EMPTY_, nil, ch)
|
s, err := nc.subscribe(inbox, _EMPTY_, nil, ch, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -140,7 +118,7 @@ func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) {
|
|||||||
select {
|
select {
|
||||||
case msg, ok = <-mch:
|
case msg, ok = <-mch:
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrConnectionClosed
|
return nil, s.getNextMsgErr()
|
||||||
}
|
}
|
||||||
if err := s.processNextMsgDelivered(msg); err != nil {
|
if err := s.processNextMsgDelivered(msg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -153,7 +131,7 @@ func (s *Subscription) NextMsgWithContext(ctx context.Context) (*Msg, error) {
|
|||||||
select {
|
select {
|
||||||
case msg, ok = <-mch:
|
case msg, ok = <-mch:
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrConnectionClosed
|
return nil, s.getNextMsgErr()
|
||||||
}
|
}
|
||||||
if err := s.processNextMsgDelivered(msg); err != nil {
|
if err := s.processNextMsgDelivered(msg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2012-2018 The NATS Authors
|
// Copyright 2012-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
|
||||||
@ -21,7 +21,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
// Default Encoders
|
// Default Encoders
|
||||||
"github.com/nats-io/go-nats/encoders/builtin"
|
"github.com/nats-io/nats.go/encoders/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encoder interface is for all register encoders
|
// Encoder interface is for all register encoders
|
||||||
@ -33,7 +33,7 @@ type Encoder interface {
|
|||||||
var encMap map[string]Encoder
|
var encMap map[string]Encoder
|
||||||
var encLock sync.Mutex
|
var encLock sync.Mutex
|
||||||
|
|
||||||
// Indexe names into the Registered Encoders.
|
// Indexed names into the Registered Encoders.
|
||||||
const (
|
const (
|
||||||
JSON_ENCODER = "json"
|
JSON_ENCODER = "json"
|
||||||
GOB_ENCODER = "gob"
|
GOB_ENCODER = "gob"
|
||||||
@ -234,7 +234,7 @@ func (c *EncodedConn) subscribe(subject, queue string, cb Handler) (*Subscriptio
|
|||||||
cbValue.Call(oV)
|
cbValue.Call(oV)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Conn.subscribe(subject, queue, natsCB, nil)
|
return c.Conn.subscribe(subject, queue, natsCB, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushTimeout allows a Flush operation to have an associated timeout.
|
// FlushTimeout allows a Flush operation to have an associated timeout.
|
7
gateway/vendor/github.com/nats-io/nats.go/go.mod
generated
vendored
Normal file
7
gateway/vendor/github.com/nats-io/nats.go/go.mod
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module github.com/nats-io/nats.go
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/nats-io/jwt v0.3.2
|
||||||
|
github.com/nats-io/nkeys v0.1.4
|
||||||
|
github.com/nats-io/nuid v1.0.1
|
||||||
|
)
|
15
gateway/vendor/github.com/nats-io/nats.go/go.sum
generated
vendored
Normal file
15
gateway/vendor/github.com/nats-io/nats.go/go.sum
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
|
||||||
|
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||||
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
|
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/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
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/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
File diff suppressed because it is too large
Load Diff
@ -107,5 +107,5 @@ func (c *EncodedConn) bindRecvChan(subject, queue string, channel interface{}) (
|
|||||||
chVal.Send(oPtr)
|
chVal.Send(oPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Conn.subscribe(subject, queue, cb, nil)
|
return c.Conn.subscribe(subject, queue, cb, nil, false)
|
||||||
}
|
}
|
@ -26,3 +26,4 @@ _testmain.go
|
|||||||
# Eclipse stuff
|
# Eclipse stuff
|
||||||
.project
|
.project
|
||||||
.settings/
|
.settings/
|
||||||
|
.idea
|
23
gateway/vendor/github.com/nats-io/stan.go/.travis.yml
generated
vendored
Normal file
23
gateway/vendor/github.com/nats-io/stan.go/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
language: go
|
||||||
|
sudo: false
|
||||||
|
go:
|
||||||
|
- 1.12.x
|
||||||
|
- 1.13.x
|
||||||
|
env:
|
||||||
|
- GO111MODULE=off
|
||||||
|
go_import_path: github.com/nats-io/stan.go
|
||||||
|
install:
|
||||||
|
- go get -t -v ./...
|
||||||
|
- go get github.com/nats-io/nats-streaming-server
|
||||||
|
- go get -u honnef.co/go/tools/cmd/staticcheck
|
||||||
|
- go get -u github.com/client9/misspell/cmd/misspell
|
||||||
|
before_script:
|
||||||
|
- $(exit $(go fmt ./... | wc -l))
|
||||||
|
- go vet ./...
|
||||||
|
- find . -type f -name "*.go" | grep -v "/pb/" | xargs misspell -error -locale US
|
||||||
|
- staticcheck ./...
|
||||||
|
script:
|
||||||
|
- go test -i -v ./...
|
||||||
|
- go test -v -race ./...
|
||||||
|
after_success:
|
||||||
|
- if [[ "$TRAVIS_GO_VERSION" =~ 1.13 ]]; then ./scripts/cov.sh TRAVIS; fi
|
@ -3,9 +3,9 @@
|
|||||||
NATS Streaming is an extremely performant, lightweight reliable streaming platform powered by [NATS](https://nats.io).
|
NATS Streaming is an extremely performant, lightweight reliable streaming platform powered by [NATS](https://nats.io).
|
||||||
|
|
||||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
[](http://travis-ci.org/nats-io/go-nats-streaming)
|
[](http://travis-ci.org/nats-io/stan.go)
|
||||||
[](https://coveralls.io/r/nats-io/go-nats-streaming?branch=master)
|
[](https://coveralls.io/r/nats-io/stan.go?branch=master)
|
||||||
[](http://godoc.org/github.com/nats-io/go-nats-streaming)
|
[](http://godoc.org/github.com/nats-io/stan.go)
|
||||||
|
|
||||||
NATS Streaming provides the following high-level feature set:
|
NATS Streaming provides the following high-level feature set:
|
||||||
- Log based persistence
|
- Log based persistence
|
||||||
@ -16,19 +16,27 @@ NATS Streaming provides the following high-level feature set:
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Please raise questions/issues via the [Issue Tracker](https://github.com/nats-io/go-nats-streaming/issues).
|
- Please raise questions/issues via the [Issue Tracker](https://github.com/nats-io/stan.go/issues).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Go client
|
# Go client
|
||||||
go get github.com/nats-io/go-nats-streaming
|
go get github.com/nats-io/stan.go/
|
||||||
|
```
|
||||||
|
|
||||||
|
When using or transitioning to Go modules support:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Go client latest or explicit version
|
||||||
|
go get github.com/nats-io/stan.go/@latest
|
||||||
|
go get github.com/nats-io/stan.go/@v0.6.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import stan "github.com/nats-io/go-nats-streaming"
|
import stan "github.com/nats-io/stan.go"
|
||||||
|
|
||||||
sc, _ := stan.Connect(clusterID, clientID)
|
sc, _ := stan.Connect(clusterID, clientID)
|
||||||
|
|
7
gateway/vendor/github.com/nats-io/stan.go/go.mod
generated
vendored
Normal file
7
gateway/vendor/github.com/nats-io/stan.go/go.mod
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module github.com/nats-io/stan.go
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gogo/protobuf v1.2.1
|
||||||
|
github.com/nats-io/nats.go v1.9.1
|
||||||
|
github.com/nats-io/nuid v1.0.1
|
||||||
|
)
|
20
gateway/vendor/github.com/nats-io/stan.go/go.sum
generated
vendored
Normal file
20
gateway/vendor/github.com/nats-io/stan.go/go.sum
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/nats-io/jwt v0.3.0 h1:xdnzwFETV++jNc4W1mw//qFyJGb2ABOombmZJQS4+Qo=
|
||||||
|
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||||
|
github.com/nats-io/nats.go v1.9.1 h1:ik3HbLhZ0YABLto7iX80pZLPw/6dx3T+++MZJwLnMrQ=
|
||||||
|
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||||
|
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/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||||
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
|
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/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=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
@ -109,6 +109,7 @@ type MsgProto struct {
|
|||||||
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
|
||||||
Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
Timestamp int64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||||
Redelivered bool `protobuf:"varint,6,opt,name=redelivered,proto3" json:"redelivered,omitempty"`
|
Redelivered bool `protobuf:"varint,6,opt,name=redelivered,proto3" json:"redelivered,omitempty"`
|
||||||
|
RedeliveryCount uint32 `protobuf:"varint,7,opt,name=redeliveryCount,proto3" json:"redeliveryCount,omitempty"`
|
||||||
CRC32 uint32 `protobuf:"varint,10,opt,name=CRC32,proto3" json:"CRC32,omitempty"`
|
CRC32 uint32 `protobuf:"varint,10,opt,name=CRC32,proto3" json:"CRC32,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,6 +406,11 @@ func (m *MsgProto) MarshalTo(dAtA []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
if m.RedeliveryCount != 0 {
|
||||||
|
dAtA[i] = 0x38
|
||||||
|
i++
|
||||||
|
i = encodeVarintProtocol(dAtA, i, uint64(m.RedeliveryCount))
|
||||||
|
}
|
||||||
if m.CRC32 != 0 {
|
if m.CRC32 != 0 {
|
||||||
dAtA[i] = 0x50
|
dAtA[i] = 0x50
|
||||||
i++
|
i++
|
||||||
@ -898,6 +904,9 @@ func (m *MsgProto) Size() (n int) {
|
|||||||
if m.Redelivered {
|
if m.Redelivered {
|
||||||
n += 2
|
n += 2
|
||||||
}
|
}
|
||||||
|
if m.RedeliveryCount != 0 {
|
||||||
|
n += 1 + sovProtocol(uint64(m.RedeliveryCount))
|
||||||
|
}
|
||||||
if m.CRC32 != 0 {
|
if m.CRC32 != 0 {
|
||||||
n += 1 + sovProtocol(uint64(m.CRC32))
|
n += 1 + sovProtocol(uint64(m.CRC32))
|
||||||
}
|
}
|
||||||
@ -1664,6 +1673,25 @@ func (m *MsgProto) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Redelivered = bool(v != 0)
|
m.Redelivered = bool(v != 0)
|
||||||
|
case 7:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field RedeliveryCount", wireType)
|
||||||
|
}
|
||||||
|
m.RedeliveryCount = 0
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowProtocol
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
m.RedeliveryCount |= (uint32(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
case 10:
|
case 10:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field CRC32", wireType)
|
return fmt.Errorf("proto: wrong wireType = %d for field CRC32", wireType)
|
||||||
@ -3327,57 +3355,58 @@ var (
|
|||||||
func init() { proto.RegisterFile("protocol.proto", fileDescriptorProtocol) }
|
func init() { proto.RegisterFile("protocol.proto", fileDescriptorProtocol) }
|
||||||
|
|
||||||
var fileDescriptorProtocol = []byte{
|
var fileDescriptorProtocol = []byte{
|
||||||
// 823 bytes of a gzipped FileDescriptorProto
|
// 840 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc1, 0x8e, 0xe3, 0x44,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xd1, 0x6e, 0xe3, 0x44,
|
||||||
0x10, 0x1d, 0xc7, 0x76, 0x26, 0x53, 0x93, 0x84, 0x6c, 0x13, 0xad, 0xac, 0x08, 0x45, 0x23, 0x6b,
|
0x14, 0x86, 0x3b, 0x89, 0x9d, 0xa6, 0xa7, 0x49, 0x36, 0x3b, 0x54, 0x2b, 0xab, 0x42, 0x51, 0x65,
|
||||||
0x41, 0xab, 0x91, 0xc8, 0x4a, 0x59, 0x01, 0x07, 0x4e, 0x90, 0xd1, 0x42, 0x04, 0xb3, 0x1b, 0x39,
|
0x2d, 0xa8, 0xaa, 0x44, 0x57, 0xea, 0x0a, 0xb8, 0xe0, 0x0a, 0x52, 0x2d, 0x44, 0xd0, 0xdd, 0xc8,
|
||||||
0x20, 0xae, 0xb4, 0x9d, 0x5e, 0xa7, 0x19, 0xa7, 0xed, 0x75, 0xb7, 0x87, 0xcc, 0x11, 0xbe, 0x80,
|
0x05, 0x71, 0xcb, 0xd8, 0x99, 0x75, 0x87, 0x3a, 0x33, 0x5e, 0xcf, 0xb8, 0xb4, 0x97, 0xf0, 0x04,
|
||||||
0x0f, 0xe1, 0x23, 0x38, 0xee, 0x81, 0x03, 0x9f, 0x00, 0xc3, 0x8d, 0xaf, 0x40, 0x5d, 0x76, 0x9c,
|
0x3c, 0x08, 0x0f, 0xb2, 0x17, 0x5c, 0xf0, 0x08, 0x50, 0xee, 0x78, 0x0a, 0x34, 0xc7, 0x8e, 0x33,
|
||||||
0x76, 0x86, 0x1d, 0x90, 0xb8, 0xf5, 0x7b, 0xa9, 0x6e, 0xd7, 0x7b, 0xaf, 0x2a, 0xd0, 0xcf, 0xf2,
|
0x4e, 0x69, 0x41, 0xe2, 0xce, 0xff, 0x97, 0xe3, 0xc9, 0x9c, 0xff, 0x3f, 0xc7, 0x30, 0xca, 0x0b,
|
||||||
0x54, 0xa5, 0x51, 0x9a, 0x4c, 0xf0, 0x40, 0x5a, 0x59, 0x38, 0x7a, 0x3f, 0xe6, 0x6a, 0x5d, 0x84,
|
0x65, 0x54, 0xa2, 0xb2, 0x63, 0x7c, 0xa0, 0x9d, 0x3c, 0xde, 0xff, 0x20, 0x15, 0xe6, 0xa2, 0x8c,
|
||||||
0x93, 0x28, 0xdd, 0x3c, 0x89, 0xd3, 0x38, 0x7d, 0x82, 0x3f, 0x85, 0xc5, 0x4b, 0x44, 0x08, 0xf0,
|
0x8f, 0x13, 0xb5, 0x7c, 0x96, 0xaa, 0x54, 0x3d, 0xc3, 0x9f, 0xe2, 0xf2, 0x35, 0x2a, 0x14, 0xf8,
|
||||||
0x54, 0x5e, 0xf1, 0x7f, 0xb6, 0xa0, 0xbd, 0x28, 0xc2, 0x4b, 0x19, 0x93, 0x11, 0x74, 0xa2, 0x84,
|
0x54, 0xbd, 0x12, 0xfe, 0x42, 0xa0, 0x37, 0x2f, 0xe3, 0x33, 0x9d, 0xd2, 0x7d, 0xe8, 0x27, 0x99,
|
||||||
0x33, 0xa1, 0xe6, 0x17, 0x9e, 0x75, 0x66, 0x3d, 0x3e, 0x09, 0x6a, 0x4c, 0x08, 0x38, 0x71, 0xc1,
|
0xe0, 0xd2, 0xcc, 0x4e, 0x03, 0x72, 0x40, 0x0e, 0x77, 0xa2, 0x46, 0x53, 0x0a, 0x5e, 0x5a, 0x8a,
|
||||||
0x57, 0x5e, 0x0b, 0x79, 0x3c, 0x13, 0x0f, 0x8e, 0x65, 0x11, 0x7e, 0xc7, 0x22, 0xe5, 0xd9, 0x48,
|
0x45, 0xd0, 0x41, 0x8e, 0xcf, 0x34, 0x80, 0x6d, 0x5d, 0xc6, 0xdf, 0xf3, 0xc4, 0x04, 0x5d, 0xc4,
|
||||||
0xef, 0x20, 0x19, 0x82, 0x9b, 0xb3, 0x2c, 0xb9, 0xf1, 0x1c, 0xe4, 0x4b, 0xa0, 0xdf, 0x58, 0x51,
|
0x2b, 0x49, 0xf7, 0xc0, 0x2f, 0x78, 0x9e, 0xdd, 0x04, 0x1e, 0xf2, 0x4a, 0xd8, 0x33, 0x16, 0xcc,
|
||||||
0x45, 0x3d, 0xf7, 0xcc, 0x7a, 0xdc, 0x0d, 0xf0, 0x4c, 0x1e, 0x42, 0x3b, 0x4a, 0x85, 0x98, 0x5f,
|
0xb0, 0xc0, 0x3f, 0x20, 0x87, 0x83, 0x08, 0x9f, 0xe9, 0x13, 0xe8, 0x25, 0x4a, 0xca, 0xd9, 0x69,
|
||||||
0x78, 0x6d, 0x64, 0x2b, 0xa4, 0x79, 0xb9, 0xa6, 0xd3, 0x0f, 0x3e, 0xf4, 0xa0, 0xe4, 0x4b, 0xe4,
|
0xd0, 0x43, 0x5a, 0x2b, 0xcb, 0xf5, 0x05, 0x3b, 0xf9, 0xf0, 0xa3, 0x00, 0x2a, 0x5e, 0xa9, 0xf0,
|
||||||
0x4f, 0xb1, 0xdb, 0x4f, 0xa2, 0xab, 0xba, 0x23, 0xcb, 0xe8, 0x68, 0x08, 0x2e, 0xcb, 0xf3, 0x34,
|
0x04, 0x6f, 0xfb, 0x69, 0x72, 0xd9, 0xdc, 0x88, 0x38, 0x37, 0xda, 0x03, 0x9f, 0x17, 0x85, 0x2a,
|
||||||
0xaf, 0xda, 0x2c, 0x81, 0xff, 0x8b, 0x05, 0x9d, 0x4b, 0x19, 0x2f, 0xd0, 0xa2, 0x11, 0x74, 0x24,
|
0xea, 0x6b, 0x56, 0x22, 0xfc, 0x8b, 0x40, 0xff, 0x4c, 0xa7, 0x73, 0xb4, 0x68, 0x1f, 0xfa, 0x9a,
|
||||||
0x7b, 0x55, 0x30, 0x11, 0x31, 0xbc, 0xea, 0x04, 0x35, 0x36, 0x05, 0xb5, 0xde, 0x20, 0xc8, 0xfe,
|
0xbf, 0x29, 0xb9, 0x4c, 0x38, 0xbe, 0xea, 0x45, 0x8d, 0x76, 0x1b, 0xea, 0xdc, 0xd3, 0x50, 0xf7,
|
||||||
0x27, 0x41, 0x8e, 0x21, 0xe8, 0x1d, 0x38, 0x51, 0x7c, 0xc3, 0xa4, 0xa2, 0x9b, 0x0c, 0x95, 0xda,
|
0x9f, 0x1a, 0xf2, 0x9c, 0x86, 0xde, 0x85, 0x1d, 0x23, 0x96, 0x5c, 0x1b, 0xb6, 0xcc, 0xb1, 0xd3,
|
||||||
0xc1, 0x9e, 0x20, 0x67, 0x70, 0x9a, 0xb3, 0x15, 0x4b, 0xf8, 0x35, 0xcb, 0xd9, 0x0a, 0x35, 0x77,
|
0x6e, 0xb4, 0x06, 0xf4, 0x00, 0x76, 0x0b, 0xbe, 0xe0, 0x99, 0xb8, 0xe2, 0x05, 0x5f, 0x60, 0xcf,
|
||||||
0x02, 0x93, 0xd2, 0x5f, 0x9a, 0x05, 0xb3, 0xa7, 0x53, 0xd4, 0xdd, 0x0b, 0x4a, 0xe0, 0x7f, 0x0c,
|
0xfd, 0xc8, 0x45, 0xf4, 0x10, 0x1e, 0x35, 0xf2, 0x66, 0xaa, 0x4a, 0x69, 0x82, 0xed, 0x03, 0x72,
|
||||||
0xb6, 0xd6, 0x6c, 0x34, 0x68, 0x35, 0x1b, 0x34, 0x65, 0xb5, 0x9a, 0xb2, 0xfc, 0x5f, 0x2d, 0xe8,
|
0x38, 0x8c, 0x36, 0xb1, 0xbd, 0xd3, 0x34, 0x9a, 0x3e, 0x3f, 0x41, 0x87, 0x86, 0x51, 0x25, 0xc2,
|
||||||
0xcf, 0x52, 0x21, 0x58, 0xa4, 0x02, 0xcd, 0x49, 0x75, 0x6f, 0xd4, 0xef, 0x41, 0x7f, 0xcd, 0x68,
|
0x4f, 0xa0, 0x6b, 0xdd, 0x71, 0x5a, 0x21, 0xed, 0x56, 0x5c, 0x03, 0x3a, 0x6d, 0x03, 0xc2, 0x5f,
|
||||||
0xae, 0x42, 0x46, 0xd5, 0x5c, 0x84, 0xe9, 0xb6, 0x32, 0xe3, 0x80, 0xd5, 0x6f, 0xec, 0xc6, 0x0f,
|
0x09, 0x8c, 0xa6, 0x4a, 0x4a, 0x9e, 0x98, 0xc8, 0x32, 0x6d, 0x1e, 0x1c, 0x8a, 0xf7, 0x61, 0x74,
|
||||||
0x6d, 0x71, 0x83, 0x1a, 0x1b, 0xb1, 0x3a, 0x8d, 0x58, 0x7d, 0xe8, 0x66, 0x5c, 0xc4, 0x73, 0xa1,
|
0xc1, 0x59, 0x61, 0x62, 0xce, 0xcc, 0x4c, 0xc6, 0xea, 0xba, 0xb6, 0x6d, 0x83, 0xda, 0x33, 0x56,
|
||||||
0x58, 0x7e, 0x4d, 0x13, 0x34, 0xc8, 0x0d, 0x1a, 0x1c, 0x19, 0x03, 0x68, 0x7c, 0x49, 0xb7, 0x2f,
|
0x83, 0x8a, 0x06, 0xfa, 0x51, 0xa3, 0x9d, 0x01, 0xf0, 0x5a, 0x03, 0x10, 0xc2, 0x20, 0x17, 0x32,
|
||||||
0x0a, 0x85, 0x16, 0xb9, 0x81, 0xc1, 0xf8, 0x3f, 0xd8, 0xf0, 0x56, 0x2d, 0x47, 0x66, 0xa9, 0x90,
|
0x9d, 0x49, 0xc3, 0x8b, 0x2b, 0x96, 0xa1, 0x95, 0x7e, 0xd4, 0x62, 0x74, 0x02, 0x60, 0xf5, 0x19,
|
||||||
0x4c, 0xbb, 0x9e, 0x15, 0xe1, 0x22, 0x67, 0x2f, 0xf9, 0xb6, 0x12, 0xb4, 0x27, 0xb4, 0xeb, 0xb2,
|
0xbb, 0x7e, 0x55, 0x1a, 0x34, 0xd3, 0x8f, 0x1c, 0x12, 0xfe, 0xd8, 0x85, 0x47, 0x4d, 0x3b, 0x3a,
|
||||||
0x08, 0x2b, 0xed, 0xb2, 0x92, 0x63, 0x52, 0xe4, 0x11, 0xf4, 0x0a, 0x61, 0xd6, 0x94, 0x39, 0x37,
|
0x57, 0x52, 0x73, 0x9b, 0x4f, 0x5e, 0xc6, 0xf3, 0x82, 0xbf, 0x16, 0xd7, 0x75, 0x43, 0x6b, 0x60,
|
||||||
0x49, 0x5d, 0x15, 0x25, 0xa9, 0x64, 0x75, 0x55, 0x39, 0xde, 0x4d, 0x72, 0x3f, 0x84, 0xae, 0x31,
|
0xf3, 0xd1, 0x65, 0x5c, 0xf7, 0xae, 0xeb, 0x76, 0x5c, 0x44, 0x9f, 0xc2, 0xb0, 0x94, 0x6e, 0x4d,
|
||||||
0x84, 0xe4, 0x1c, 0x06, 0xb2, 0x08, 0x67, 0x8d, 0xeb, 0x6d, 0x2c, 0xb8, 0xc3, 0xef, 0x5c, 0xaa,
|
0x35, 0x11, 0x6d, 0x68, 0xab, 0x92, 0x4c, 0x69, 0xde, 0x54, 0x55, 0x8b, 0xd0, 0x86, 0xeb, 0x71,
|
||||||
0xeb, 0x8e, 0xb1, 0xae, 0xc1, 0xdd, 0x71, 0xb2, 0xf3, 0xaf, 0x4e, 0x9e, 0x1c, 0x3a, 0xd9, 0x48,
|
0xf5, 0x9d, 0x71, 0xa5, 0x47, 0x30, 0xd6, 0x65, 0x3c, 0x6d, 0xbd, 0xde, 0xc3, 0x82, 0x3b, 0x7c,
|
||||||
0x10, 0x0e, 0x12, 0x2c, 0x1d, 0x4d, 0x78, 0xf4, 0x05, 0xbb, 0xf1, 0x56, 0xb5, 0xa3, 0x25, 0xe1,
|
0xe5, 0x52, 0x53, 0xb7, 0x8d, 0x75, 0x2d, 0x76, 0xc7, 0xc9, 0xfe, 0xbf, 0x3a, 0xb9, 0xb3, 0xe9,
|
||||||
0x8f, 0xc1, 0x59, 0x70, 0x11, 0x1b, 0x39, 0x5b, 0x66, 0xce, 0xfe, 0x23, 0xe8, 0x2e, 0xb0, 0xdb,
|
0x64, 0x2b, 0x41, 0xd8, 0x48, 0xb0, 0x72, 0x34, 0x13, 0xc9, 0x97, 0xfc, 0x26, 0x58, 0x34, 0x8e,
|
||||||
0x2a, 0x9f, 0xda, 0x13, 0xcb, 0x5c, 0xcc, 0xbf, 0x5a, 0xf0, 0xf6, 0xb2, 0x08, 0x65, 0x94, 0xf3,
|
0x56, 0x20, 0x9c, 0x80, 0x37, 0x17, 0x32, 0x75, 0x72, 0x26, 0x6e, 0xce, 0xe1, 0x53, 0x18, 0xcc,
|
||||||
0x4c, 0xf1, 0x54, 0xfc, 0x97, 0xe9, 0x7c, 0xf3, 0x8e, 0x3e, 0x84, 0xf6, 0xab, 0xcf, 0xf2, 0xb4,
|
0xf1, 0xb6, 0x75, 0x3e, 0x8d, 0x27, 0xa4, 0xb5, 0xc2, 0x1d, 0x78, 0xe7, 0xbc, 0x8c, 0x75, 0x52,
|
||||||
0xc8, 0xaa, 0xf0, 0x2a, 0xa4, 0xbf, 0xcd, 0x71, 0x8c, 0xab, 0x3f, 0x23, 0x04, 0x7a, 0x26, 0x36,
|
0x88, 0xdc, 0x08, 0x25, 0xff, 0xcb, 0x74, 0xde, 0xbf, 0xcd, 0x4f, 0xa0, 0xf7, 0xe6, 0xf3, 0x42,
|
||||||
0x74, 0x3b, 0x17, 0xcf, 0x12, 0x1e, 0xaf, 0x55, 0x35, 0x88, 0x26, 0xa5, 0xd3, 0xa6, 0xd1, 0xd5,
|
0x95, 0x79, 0x1d, 0x5e, 0xad, 0xec, 0x7f, 0x0b, 0x1c, 0xe3, 0xfa, 0xb3, 0x85, 0xc2, 0xce, 0xc4,
|
||||||
0x37, 0x94, 0xab, 0xb9, 0x58, 0xb2, 0x48, 0x56, 0xa3, 0xd8, 0x24, 0xf5, 0x3b, 0xab, 0x22, 0xa7,
|
0x92, 0x5d, 0xcf, 0xe4, 0x8b, 0x4c, 0xa4, 0x17, 0xa6, 0x1e, 0x44, 0x17, 0xd9, 0xb4, 0x59, 0x72,
|
||||||
0x61, 0xc2, 0x9e, 0xd3, 0x0d, 0xab, 0xa2, 0x32, 0x29, 0xf2, 0x11, 0xf4, 0xa4, 0xa2, 0xb9, 0x5a,
|
0xf9, 0x2d, 0x13, 0x66, 0x26, 0xcf, 0x79, 0xa2, 0xeb, 0x51, 0x6c, 0x43, 0x7b, 0xce, 0xa2, 0x2c,
|
||||||
0xa4, 0x92, 0x6b, 0x95, 0x68, 0x75, 0x7f, 0xfa, 0x60, 0x92, 0x85, 0x93, 0xa5, 0xf9, 0x43, 0xd0,
|
0x58, 0x9c, 0xf1, 0x97, 0x6c, 0xc9, 0xeb, 0xa8, 0x5c, 0x44, 0x3f, 0x86, 0xa1, 0x36, 0xac, 0x30,
|
||||||
0xac, 0xd3, 0x0d, 0x20, 0xb1, 0xdc, 0x2d, 0xf6, 0x29, 0x2e, 0x76, 0x93, 0xd4, 0xeb, 0x8a, 0xc4,
|
0x73, 0xa5, 0x85, 0xed, 0x12, 0xad, 0x1e, 0x9d, 0x3c, 0x3e, 0xce, 0xe3, 0xe3, 0x73, 0xf7, 0x87,
|
||||||
0x57, 0x7c, 0xc3, 0x2e, 0x58, 0xa2, 0xa8, 0xd7, 0xc5, 0x7f, 0x9d, 0x03, 0xd6, 0xff, 0x1c, 0x86,
|
0xa8, 0x5d, 0x67, 0x2f, 0x80, 0xe0, 0x7c, 0xb5, 0xd8, 0xbb, 0xb8, 0xd8, 0x6d, 0x68, 0xd7, 0x15,
|
||||||
0x4d, 0xaf, 0xab, 0x68, 0x46, 0xd0, 0xa1, 0xd1, 0x95, 0xb9, 0xe8, 0x35, 0xde, 0xc7, 0x66, 0x9b,
|
0xc1, 0xd7, 0x62, 0xc9, 0x4f, 0x79, 0x66, 0x58, 0x30, 0xc0, 0xef, 0xd3, 0x06, 0x0d, 0xbf, 0x80,
|
||||||
0xb1, 0xfd, 0x68, 0x01, 0xf9, 0x5a, 0x2f, 0x86, 0x7e, 0x2c, 0x64, 0xff, 0x2f, 0xb5, 0x3a, 0x1d,
|
0xbd, 0xb6, 0xd7, 0x75, 0x34, 0xfb, 0xd0, 0x67, 0xc9, 0xa5, 0xbb, 0xe8, 0x8d, 0x5e, 0xc7, 0xd6,
|
||||||
0xfb, 0x20, 0x1d, 0xd3, 0x55, 0xe7, 0x8e, 0xab, 0xfe, 0x39, 0x74, 0xcd, 0xa5, 0xb9, 0xef, 0xeb,
|
0x75, 0x63, 0xfb, 0x89, 0x00, 0xfd, 0xc6, 0x2e, 0x86, 0x3d, 0x2c, 0xe6, 0xff, 0x2f, 0xb5, 0x26,
|
||||||
0xfe, 0xbb, 0xd0, 0xab, 0x6a, 0xef, 0x1b, 0xc7, 0xf3, 0x6f, 0xa1, 0xd7, 0xc8, 0x83, 0x9c, 0xc2,
|
0x9d, 0xee, 0x46, 0x3a, 0xae, 0xab, 0xde, 0x1d, 0x57, 0xc3, 0x23, 0x18, 0xb8, 0x4b, 0xf3, 0xd0,
|
||||||
0xf1, 0x73, 0xf6, 0xfd, 0x0b, 0x91, 0xdc, 0x0c, 0x8e, 0xc8, 0x00, 0xba, 0x5f, 0x52, 0xa9, 0x02,
|
0xbf, 0x87, 0xef, 0xc1, 0xb0, 0xae, 0x7d, 0x68, 0x1c, 0x8f, 0xbe, 0x83, 0x61, 0x2b, 0x0f, 0xba,
|
||||||
0x16, 0x31, 0x7e, 0xcd, 0x56, 0x03, 0x8b, 0x10, 0xe8, 0xd7, 0xf6, 0xe2, 0xc5, 0x41, 0x8b, 0x3c,
|
0x0b, 0xdb, 0x2f, 0xf9, 0x0f, 0xaf, 0x64, 0x76, 0x33, 0xde, 0xa2, 0x63, 0x18, 0x7c, 0xc5, 0xb4,
|
||||||
0x80, 0xde, 0x2e, 0x99, 0x92, 0xb2, 0xc9, 0x09, 0xb8, 0xcf, 0x78, 0x2e, 0xd5, 0xc0, 0xf9, 0x74,
|
0x89, 0x78, 0xc2, 0xc5, 0x15, 0x5f, 0x8c, 0x09, 0xa5, 0x30, 0x6a, 0xec, 0xc5, 0x17, 0xc7, 0x1d,
|
||||||
0xf8, 0xfa, 0x8f, 0xf1, 0xd1, 0xeb, 0xdb, 0xb1, 0xf5, 0xdb, 0xed, 0xd8, 0xfa, 0xfd, 0x76, 0x6c,
|
0xfa, 0x18, 0x86, 0xab, 0x64, 0x2a, 0xd4, 0xa5, 0x3b, 0xe0, 0xbf, 0x10, 0x85, 0x36, 0x63, 0xef,
|
||||||
0xfd, 0xf4, 0xe7, 0xf8, 0x28, 0x6c, 0xe3, 0xd2, 0x3d, 0xfd, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x66,
|
0xb3, 0xbd, 0xb7, 0x7f, 0x4c, 0xb6, 0xde, 0xde, 0x4e, 0xc8, 0x6f, 0xb7, 0x13, 0xf2, 0xfb, 0xed,
|
||||||
0xcd, 0xb9, 0x27, 0xce, 0x07, 0x00, 0x00,
|
0x84, 0xfc, 0xfc, 0xe7, 0x64, 0x2b, 0xee, 0xe1, 0xd2, 0x3d, 0xff, 0x3b, 0x00, 0x00, 0xff, 0xff,
|
||||||
|
0x89, 0xd0, 0xaf, 0x8e, 0xf8, 0x07, 0x00, 0x00,
|
||||||
}
|
}
|
@ -51,6 +51,7 @@ message MsgProto {
|
|||||||
bytes data = 4; // payload
|
bytes data = 4; // payload
|
||||||
int64 timestamp = 5; // received timestamp
|
int64 timestamp = 5; // received timestamp
|
||||||
bool redelivered = 6; // Flag specifying if the message is being redelivered
|
bool redelivered = 6; // Flag specifying if the message is being redelivered
|
||||||
|
uint32 redeliveryCount = 7; // Number of times the message has been redelivered (count currently not persisted)
|
||||||
|
|
||||||
uint32 CRC32 = 10; // optional IEEE CRC32
|
uint32 CRC32 = 10; // optional IEEE CRC32
|
||||||
}
|
}
|
@ -20,17 +20,17 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nats-io/go-nats"
|
"github.com/nats-io/nats.go"
|
||||||
"github.com/nats-io/go-nats-streaming/pb"
|
|
||||||
"github.com/nats-io/nuid"
|
"github.com/nats-io/nuid"
|
||||||
|
"github.com/nats-io/stan.go/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version is the NATS Streaming Go Client version
|
// Version is the NATS Streaming Go Client version
|
||||||
const Version = "0.4.4"
|
const Version = "0.6.0"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// DefaultNatsURL is the default URL the client connects to
|
// DefaultNatsURL is the default URL the client connects to
|
||||||
DefaultNatsURL = "nats://localhost:4222"
|
DefaultNatsURL = "nats://127.0.0.1:4222"
|
||||||
// DefaultConnectWait is the default timeout used for the connect operation
|
// DefaultConnectWait is the default timeout used for the connect operation
|
||||||
DefaultConnectWait = 2 * time.Second
|
DefaultConnectWait = 2 * time.Second
|
||||||
// DefaultDiscoverPrefix is the prefix subject used to connect to the NATS Streaming server
|
// DefaultDiscoverPrefix is the prefix subject used to connect to the NATS Streaming server
|
||||||
@ -48,6 +48,7 @@ const (
|
|||||||
|
|
||||||
// Conn represents a connection to the NATS Streaming subsystem. It can Publish and
|
// Conn represents a connection to the NATS Streaming subsystem. It can Publish and
|
||||||
// Subscribe to messages within the NATS Streaming cluster.
|
// Subscribe to messages within the NATS Streaming cluster.
|
||||||
|
// The connection is safe to use in multiple Go routines concurrently.
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
// Publish will publish to the cluster and wait for an ACK.
|
// Publish will publish to the cluster and wait for an ACK.
|
||||||
Publish(subject string, data []byte) error
|
Publish(subject string, data []byte) error
|
||||||
@ -99,7 +100,7 @@ const (
|
|||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
var (
|
var (
|
||||||
ErrConnectReqTimeout = errors.New("stan: connect request timeout")
|
ErrConnectReqTimeout = errors.New("stan: connect request timeout (possibly wrong cluster ID?)")
|
||||||
ErrCloseReqTimeout = errors.New("stan: close request timeout")
|
ErrCloseReqTimeout = errors.New("stan: close request timeout")
|
||||||
ErrSubReqTimeout = errors.New("stan: subscribe request timeout")
|
ErrSubReqTimeout = errors.New("stan: subscribe request timeout")
|
||||||
ErrUnsubReqTimeout = errors.New("stan: unsubscribe request timeout")
|
ErrUnsubReqTimeout = errors.New("stan: unsubscribe request timeout")
|
||||||
@ -156,9 +157,12 @@ type Options struct {
|
|||||||
// calls block.
|
// calls block.
|
||||||
MaxPubAcksInflight int
|
MaxPubAcksInflight int
|
||||||
|
|
||||||
|
// DEPRECATED: Please use PingInterval instead
|
||||||
|
PingIterval int
|
||||||
|
|
||||||
// PingInterval is the interval at which client sends PINGs to the server
|
// PingInterval is the interval at which client sends PINGs to the server
|
||||||
// to detect the loss of a connection.
|
// to detect the loss of a connection.
|
||||||
PingIterval int
|
PingInterval int
|
||||||
|
|
||||||
// PingMaxOut specifies the maximum number of PINGs without a corresponding
|
// PingMaxOut specifies the maximum number of PINGs without a corresponding
|
||||||
// PONG before declaring the connection permanently lost.
|
// PONG before declaring the connection permanently lost.
|
||||||
@ -169,16 +173,24 @@ type Options struct {
|
|||||||
ConnectionLostCB ConnectionLostHandler
|
ConnectionLostCB ConnectionLostHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultOptions are the NATS Streaming client's default options
|
// GetDefaultOptions returns default configuration options for the client.
|
||||||
var DefaultOptions = Options{
|
func GetDefaultOptions() Options {
|
||||||
|
return Options{
|
||||||
NatsURL: DefaultNatsURL,
|
NatsURL: DefaultNatsURL,
|
||||||
ConnectTimeout: DefaultConnectWait,
|
ConnectTimeout: DefaultConnectWait,
|
||||||
AckTimeout: DefaultAckWait,
|
AckTimeout: DefaultAckWait,
|
||||||
DiscoverPrefix: DefaultDiscoverPrefix,
|
DiscoverPrefix: DefaultDiscoverPrefix,
|
||||||
MaxPubAcksInflight: DefaultMaxPubAcksInflight,
|
MaxPubAcksInflight: DefaultMaxPubAcksInflight,
|
||||||
PingIterval: DefaultPingInterval,
|
PingInterval: DefaultPingInterval,
|
||||||
PingMaxOut: DefaultPingMaxOut,
|
PingMaxOut: DefaultPingMaxOut,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: Use GetDefaultOptions() instead.
|
||||||
|
// DefaultOptions is not safe for use by multiple clients.
|
||||||
|
// For details see https://github.com/nats-io/nats.go/issues/308.
|
||||||
|
// DefaultOptions are the NATS Streaming client's default options
|
||||||
|
var DefaultOptions = GetDefaultOptions()
|
||||||
|
|
||||||
// Option is a function on the options for a connection.
|
// Option is a function on the options for a connection.
|
||||||
type Option func(*Options) error
|
type Option func(*Options) error
|
||||||
@ -242,11 +254,11 @@ func Pings(interval, maxOut int) Option {
|
|||||||
// by the library as milliseconds. If this test boolean is set,
|
// by the library as milliseconds. If this test boolean is set,
|
||||||
// do not check values.
|
// do not check values.
|
||||||
if !testAllowMillisecInPings {
|
if !testAllowMillisecInPings {
|
||||||
if interval < 1 || maxOut <= 2 {
|
if interval < 1 || maxOut < 2 {
|
||||||
return fmt.Errorf("invalid ping values: interval=%v (min>0) maxOut=%v (min=2)", interval, maxOut)
|
return fmt.Errorf("invalid ping values: interval=%v (min>0) maxOut=%v (min=2)", interval, maxOut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.PingIterval = interval
|
o.PingInterval = interval
|
||||||
o.PingMaxOut = maxOut
|
o.PingMaxOut = maxOut
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -279,21 +291,27 @@ type conn struct {
|
|||||||
subMap map[string]*subscription
|
subMap map[string]*subscription
|
||||||
pubAckMap map[string]*ack
|
pubAckMap map[string]*ack
|
||||||
pubAckChan chan (struct{})
|
pubAckChan chan (struct{})
|
||||||
|
pubAckCloseChan chan (struct{})
|
||||||
opts Options
|
opts Options
|
||||||
nc *nats.Conn
|
nc *nats.Conn
|
||||||
ncOwned bool // NATS Streaming created the connection, so needs to close it.
|
ncOwned bool // NATS Streaming created the connection, so needs to close it.
|
||||||
pubNUID *nuid.NUID // NUID generator for published messages.
|
pubNUID *nuid.NUID // NUID generator for published messages.
|
||||||
connLostCB ConnectionLostHandler
|
connLostCB ConnectionLostHandler
|
||||||
|
closed bool
|
||||||
|
ping pingInfo
|
||||||
|
}
|
||||||
|
|
||||||
pingMu sync.Mutex
|
// Holds all field related to the client-to-server pings
|
||||||
pingSub *nats.Subscription
|
type pingInfo struct {
|
||||||
pingTimer *time.Timer
|
mu sync.Mutex
|
||||||
pingBytes []byte
|
sub *nats.Subscription
|
||||||
pingRequests string
|
timer *time.Timer
|
||||||
pingInbox string
|
proto []byte
|
||||||
pingInterval time.Duration
|
requests string
|
||||||
pingMaxOut int
|
inbox string
|
||||||
pingOut int
|
interval time.Duration
|
||||||
|
maxOut int
|
||||||
|
out int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closure for ack contexts.
|
// Closure for ack contexts.
|
||||||
@ -307,7 +325,15 @@ type ack struct {
|
|||||||
// Note that clientID can contain only alphanumeric and `-` or `_` characters.
|
// Note that clientID can contain only alphanumeric and `-` or `_` characters.
|
||||||
func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
||||||
// Process Options
|
// Process Options
|
||||||
c := conn{clientID: clientID, opts: DefaultOptions, connID: []byte(nuid.Next()), pubNUID: nuid.New()}
|
c := conn{
|
||||||
|
clientID: clientID,
|
||||||
|
opts: DefaultOptions,
|
||||||
|
connID: []byte(nuid.Next()),
|
||||||
|
pubNUID: nuid.New(),
|
||||||
|
pubAckMap: make(map[string]*ack),
|
||||||
|
pubAckCloseChan: make(chan struct{}),
|
||||||
|
subMap: make(map[string]*subscription),
|
||||||
|
}
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
if err := opt(&c.opts); err != nil {
|
if err := opt(&c.opts); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -347,7 +373,8 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
|||||||
// Prepare a subscription on ping responses, even if we are not
|
// Prepare a subscription on ping responses, even if we are not
|
||||||
// going to need it, so that if that fails, it fails before initiating
|
// going to need it, so that if that fails, it fails before initiating
|
||||||
// a connection.
|
// a connection.
|
||||||
if c.pingSub, err = c.nc.Subscribe(nats.NewInbox(), c.processPingResponse); err != nil {
|
p := &c.ping
|
||||||
|
if p.sub, err = c.nc.Subscribe(nats.NewInbox(), c.processPingResponse); err != nil {
|
||||||
c.failConnect(err)
|
c.failConnect(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -359,7 +386,7 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
|||||||
HeartbeatInbox: hbInbox,
|
HeartbeatInbox: hbInbox,
|
||||||
ConnID: c.connID,
|
ConnID: c.connID,
|
||||||
Protocol: protocolOne,
|
Protocol: protocolOne,
|
||||||
PingInterval: int32(c.opts.PingIterval),
|
PingInterval: int32(c.opts.PingInterval),
|
||||||
PingMaxOut: int32(c.opts.PingMaxOut),
|
PingMaxOut: int32(c.opts.PingMaxOut),
|
||||||
}
|
}
|
||||||
b, _ := req.Marshal()
|
b, _ := req.Marshal()
|
||||||
@ -399,11 +426,7 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
|||||||
c.Close()
|
c.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.ackSubscription.SetPendingLimits(1024*1024, 32*1024*1024)
|
c.ackSubscription.SetPendingLimits(-1, -1)
|
||||||
c.pubAckMap = make(map[string]*ack)
|
|
||||||
|
|
||||||
// Create Subscription map
|
|
||||||
c.subMap = make(map[string]*subscription)
|
|
||||||
|
|
||||||
c.pubAckChan = make(chan struct{}, c.opts.MaxPubAcksInflight)
|
c.pubAckChan = make(chan struct{}, c.opts.MaxPubAcksInflight)
|
||||||
|
|
||||||
@ -423,28 +446,28 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
|||||||
unsubPingSub = false
|
unsubPingSub = false
|
||||||
|
|
||||||
// These will be immutable.
|
// These will be immutable.
|
||||||
c.pingRequests = cr.PingRequests
|
p.requests = cr.PingRequests
|
||||||
c.pingInbox = c.pingSub.Subject
|
p.inbox = p.sub.Subject
|
||||||
// In test, it is possible that we get a negative value
|
// In test, it is possible that we get a negative value
|
||||||
// to represent milliseconds.
|
// to represent milliseconds.
|
||||||
if testAllowMillisecInPings && cr.PingInterval < 0 {
|
if testAllowMillisecInPings && cr.PingInterval < 0 {
|
||||||
c.pingInterval = time.Duration(cr.PingInterval*-1) * time.Millisecond
|
p.interval = time.Duration(cr.PingInterval*-1) * time.Millisecond
|
||||||
} else {
|
} else {
|
||||||
// PingInterval is otherwise assumed to be in seconds.
|
// PingInterval is otherwise assumed to be in seconds.
|
||||||
c.pingInterval = time.Duration(cr.PingInterval) * time.Second
|
p.interval = time.Duration(cr.PingInterval) * time.Second
|
||||||
}
|
}
|
||||||
c.pingMaxOut = int(cr.PingMaxOut)
|
p.maxOut = int(cr.PingMaxOut)
|
||||||
c.pingBytes, _ = (&pb.Ping{ConnID: c.connID}).Marshal()
|
p.proto, _ = (&pb.Ping{ConnID: c.connID}).Marshal()
|
||||||
// Set the timer now that we are set. Use lock to create
|
// Set the timer now that we are set. Use lock to create
|
||||||
// synchronization point.
|
// synchronization point.
|
||||||
c.pingMu.Lock()
|
p.mu.Lock()
|
||||||
c.pingTimer = time.AfterFunc(c.pingInterval, c.pingServer)
|
p.timer = time.AfterFunc(p.interval, c.pingServer)
|
||||||
c.pingMu.Unlock()
|
p.mu.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if unsubPingSub {
|
if unsubPingSub {
|
||||||
c.pingSub.Unsubscribe()
|
p.sub.Unsubscribe()
|
||||||
c.pingSub = nil
|
p.sub = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &c, nil
|
return &c, nil
|
||||||
@ -466,24 +489,24 @@ func (sc *conn) failConnect(err error) {
|
|||||||
// If the total number is > than the PingMaxOut option, then the connection
|
// If the total number is > than the PingMaxOut option, then the connection
|
||||||
// is closed, and connection error callback invoked if one was specified.
|
// is closed, and connection error callback invoked if one was specified.
|
||||||
func (sc *conn) pingServer() {
|
func (sc *conn) pingServer() {
|
||||||
sc.pingMu.Lock()
|
p := &sc.ping
|
||||||
|
p.mu.Lock()
|
||||||
// In case the timer fired while we were stopping it.
|
// In case the timer fired while we were stopping it.
|
||||||
if sc.pingTimer == nil {
|
if p.timer == nil {
|
||||||
sc.pingMu.Unlock()
|
p.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sc.pingOut++
|
p.out++
|
||||||
if sc.pingOut > sc.pingMaxOut {
|
if p.out > p.maxOut {
|
||||||
sc.pingMu.Unlock()
|
p.mu.Unlock()
|
||||||
sc.closeDueToPing(ErrMaxPings)
|
sc.closeDueToPing(ErrMaxPings)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sc.pingTimer.Reset(sc.pingInterval)
|
p.timer.Reset(p.interval)
|
||||||
nc := sc.nc
|
p.mu.Unlock()
|
||||||
sc.pingMu.Unlock()
|
// Send the PING now. If the NATS connection is reported closed, we are done.
|
||||||
// Send the PING now. If the NATS connection is reported closed,
|
// sc.nc is immutable and never nil, even if connection is closed.
|
||||||
// we are done.
|
if err := sc.nc.PublishRequest(p.requests, p.inbox, p.proto); err == nats.ErrConnectionClosed {
|
||||||
if err := nc.PublishRequest(sc.pingRequests, sc.pingInbox, sc.pingBytes); err == nats.ErrConnectionClosed {
|
|
||||||
sc.closeDueToPing(err)
|
sc.closeDueToPing(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,16 +532,17 @@ func (sc *conn) processPingResponse(m *nats.Msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do not attempt to decrement, simply reset to 0.
|
// Do not attempt to decrement, simply reset to 0.
|
||||||
sc.pingMu.Lock()
|
p := &sc.ping
|
||||||
sc.pingOut = 0
|
p.mu.Lock()
|
||||||
sc.pingMu.Unlock()
|
p.out = 0
|
||||||
|
p.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closes a connection and invoke the connection error callback if one
|
// Closes a connection and invoke the connection error callback if one
|
||||||
// was registered when the connection was created.
|
// was registered when the connection was created.
|
||||||
func (sc *conn) closeDueToPing(err error) {
|
func (sc *conn) closeDueToPing(err error) {
|
||||||
sc.Lock()
|
sc.Lock()
|
||||||
if sc.nc == nil {
|
if sc.closed {
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -529,10 +553,8 @@ func (sc *conn) closeDueToPing(err error) {
|
|||||||
if sc.ncOwned && !sc.nc.IsClosed() {
|
if sc.ncOwned && !sc.nc.IsClosed() {
|
||||||
sc.nc.Close()
|
sc.nc.Close()
|
||||||
}
|
}
|
||||||
// Mark this streaming connection as closed. Do this under pingMu lock.
|
// Mark this streaming connection as closed.
|
||||||
sc.pingMu.Lock()
|
sc.closed = true
|
||||||
sc.nc = nil
|
|
||||||
sc.pingMu.Unlock()
|
|
||||||
// Capture callback (even though this is immutable).
|
// Capture callback (even though this is immutable).
|
||||||
cb := sc.connLostCB
|
cb := sc.connLostCB
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
@ -545,12 +567,13 @@ func (sc *conn) closeDueToPing(err error) {
|
|||||||
// Do some cleanup when connection is lost or closed.
|
// Do some cleanup when connection is lost or closed.
|
||||||
// Connection lock is held on entry, and sc.nc is guaranteed not to be nil.
|
// Connection lock is held on entry, and sc.nc is guaranteed not to be nil.
|
||||||
func (sc *conn) cleanupOnClose(err error) {
|
func (sc *conn) cleanupOnClose(err error) {
|
||||||
sc.pingMu.Lock()
|
p := &sc.ping
|
||||||
if sc.pingTimer != nil {
|
p.mu.Lock()
|
||||||
sc.pingTimer.Stop()
|
if p.timer != nil {
|
||||||
sc.pingTimer = nil
|
p.timer.Stop()
|
||||||
|
p.timer = nil
|
||||||
}
|
}
|
||||||
sc.pingMu.Unlock()
|
p.mu.Unlock()
|
||||||
|
|
||||||
// Unsubscribe only if the NATS connection is not already closed
|
// Unsubscribe only if the NATS connection is not already closed
|
||||||
// and we don't own it (otherwise connection is going to be closed
|
// and we don't own it (otherwise connection is going to be closed
|
||||||
@ -559,8 +582,8 @@ func (sc *conn) cleanupOnClose(err error) {
|
|||||||
if sc.hbSubscription != nil {
|
if sc.hbSubscription != nil {
|
||||||
sc.hbSubscription.Unsubscribe()
|
sc.hbSubscription.Unsubscribe()
|
||||||
}
|
}
|
||||||
if sc.pingSub != nil {
|
if p.sub != nil {
|
||||||
sc.pingSub.Unsubscribe()
|
p.sub.Unsubscribe()
|
||||||
}
|
}
|
||||||
if sc.ackSubscription != nil {
|
if sc.ackSubscription != nil {
|
||||||
sc.ackSubscription.Unsubscribe()
|
sc.ackSubscription.Unsubscribe()
|
||||||
@ -568,20 +591,34 @@ func (sc *conn) cleanupOnClose(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fail all pending pubs
|
// Fail all pending pubs
|
||||||
|
if len(sc.pubAckMap) > 0 {
|
||||||
|
// Collect only the ones that have a timer that can be stopped.
|
||||||
|
// All others will be handled either in publishAsync() or their
|
||||||
|
// timer has already fired.
|
||||||
|
acks := map[string]*ack{}
|
||||||
for guid, pubAck := range sc.pubAckMap {
|
for guid, pubAck := range sc.pubAckMap {
|
||||||
if pubAck.t != nil {
|
if pubAck.t != nil && pubAck.t.Stop() {
|
||||||
pubAck.t.Stop()
|
|
||||||
}
|
|
||||||
if pubAck.ah != nil {
|
|
||||||
pubAck.ah(guid, err)
|
|
||||||
} else if pubAck.ch != nil {
|
|
||||||
pubAck.ch <- err
|
|
||||||
}
|
|
||||||
delete(sc.pubAckMap, guid)
|
delete(sc.pubAckMap, guid)
|
||||||
if len(sc.pubAckChan) > 0 {
|
acks[guid] = pubAck
|
||||||
<-sc.pubAckChan
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If we collected any, start a go routine that will do the job.
|
||||||
|
// We can't do it in place in case user's ackHandler uses the connection.
|
||||||
|
if len(acks) > 0 {
|
||||||
|
go func() {
|
||||||
|
for guid, a := range acks {
|
||||||
|
if a.ah != nil {
|
||||||
|
a.ah(guid, ErrConnectionClosed)
|
||||||
|
} else if a.ch != nil {
|
||||||
|
a.ch <- ErrConnectionClosed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Prevent publish calls that have passed the connection close check but
|
||||||
|
// not yet send to pubAckChan to be possibly blocked.
|
||||||
|
close(sc.pubAckCloseChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close a connection to the stan system.
|
// Close a connection to the stan system.
|
||||||
@ -589,30 +626,24 @@ func (sc *conn) Close() error {
|
|||||||
sc.Lock()
|
sc.Lock()
|
||||||
defer sc.Unlock()
|
defer sc.Unlock()
|
||||||
|
|
||||||
if sc.nc == nil {
|
if sc.closed {
|
||||||
// We are already closed.
|
// We are already closed.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// Signals we are closed.
|
||||||
|
sc.closed = true
|
||||||
|
|
||||||
// Capture for NATS calls below.
|
// Capture for NATS calls below.
|
||||||
nc := sc.nc
|
|
||||||
if sc.ncOwned {
|
if sc.ncOwned {
|
||||||
defer nc.Close()
|
defer sc.nc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now close ourselves.
|
// Now close ourselves.
|
||||||
sc.cleanupOnClose(ErrConnectionClosed)
|
sc.cleanupOnClose(ErrConnectionClosed)
|
||||||
|
|
||||||
// Signals we are closed.
|
|
||||||
// Do this also under pingMu lock so that we don't need
|
|
||||||
// to grab sc's lock in pingServer.
|
|
||||||
sc.pingMu.Lock()
|
|
||||||
sc.nc = nil
|
|
||||||
sc.pingMu.Unlock()
|
|
||||||
|
|
||||||
req := &pb.CloseRequest{ClientID: sc.clientID}
|
req := &pb.CloseRequest{ClientID: sc.clientID}
|
||||||
b, _ := req.Marshal()
|
b, _ := req.Marshal()
|
||||||
reply, err := nc.Request(sc.closeRequests, b, sc.opts.ConnectTimeout)
|
reply, err := sc.nc.Request(sc.closeRequests, b, sc.opts.ConnectTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == nats.ErrTimeout {
|
if err == nats.ErrTimeout {
|
||||||
return ErrCloseReqTimeout
|
return ErrCloseReqTimeout
|
||||||
@ -636,6 +667,9 @@ func (sc *conn) Close() error {
|
|||||||
func (sc *conn) NatsConn() *nats.Conn {
|
func (sc *conn) NatsConn() *nats.Conn {
|
||||||
sc.RLock()
|
sc.RLock()
|
||||||
nc := sc.nc
|
nc := sc.nc
|
||||||
|
if sc.closed {
|
||||||
|
nc = nil
|
||||||
|
}
|
||||||
sc.RUnlock()
|
sc.RUnlock()
|
||||||
return nc
|
return nc
|
||||||
}
|
}
|
||||||
@ -643,12 +677,8 @@ func (sc *conn) NatsConn() *nats.Conn {
|
|||||||
// Process a heartbeat from the NATS Streaming cluster
|
// Process a heartbeat from the NATS Streaming cluster
|
||||||
func (sc *conn) processHeartBeat(m *nats.Msg) {
|
func (sc *conn) processHeartBeat(m *nats.Msg) {
|
||||||
// No payload assumed, just reply.
|
// No payload assumed, just reply.
|
||||||
sc.RLock()
|
// sc.nc is immutable and never nil, even if connection is closed.
|
||||||
nc := sc.nc
|
sc.nc.Publish(m.Reply, nil)
|
||||||
sc.RUnlock()
|
|
||||||
if nc != nil {
|
|
||||||
nc.Publish(m.Reply, nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process an ack from the NATS Streaming cluster
|
// Process an ack from the NATS Streaming cluster
|
||||||
@ -698,7 +728,7 @@ func (sc *conn) PublishAsync(subject string, data []byte, ah AckHandler) (string
|
|||||||
func (sc *conn) publishAsync(subject string, data []byte, ah AckHandler, ch chan error) (string, error) {
|
func (sc *conn) publishAsync(subject string, data []byte, ah AckHandler, ch chan error) (string, error) {
|
||||||
a := &ack{ah: ah, ch: ch}
|
a := &ack{ah: ah, ch: ch}
|
||||||
sc.Lock()
|
sc.Lock()
|
||||||
if sc.nc == nil {
|
if sc.closed {
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
return "", ErrConnectionClosed
|
return "", ErrConnectionClosed
|
||||||
}
|
}
|
||||||
@ -717,18 +747,28 @@ func (sc *conn) publishAsync(subject string, data []byte, ah AckHandler, ch chan
|
|||||||
// snapshot
|
// snapshot
|
||||||
ackSubject := sc.ackSubject
|
ackSubject := sc.ackSubject
|
||||||
ackTimeout := sc.opts.AckTimeout
|
ackTimeout := sc.opts.AckTimeout
|
||||||
pac := sc.pubAckChan
|
|
||||||
nc := sc.nc
|
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
|
|
||||||
// Use the buffered channel to control the number of outstanding acks.
|
// Use the buffered channel to control the number of outstanding acks.
|
||||||
pac <- struct{}{}
|
select {
|
||||||
|
case sc.pubAckChan <- struct{}{}:
|
||||||
|
default:
|
||||||
|
// It seems faster to first try to send to pubAckChan and only if
|
||||||
|
// it fails to retry with the check on pubAckCloseChan than having
|
||||||
|
// simply only the select with the 2 cases.
|
||||||
|
select {
|
||||||
|
case sc.pubAckChan <- struct{}{}:
|
||||||
|
case <-sc.pubAckCloseChan:
|
||||||
|
return "", ErrConnectionClosed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := nc.PublishRequest(subj, ackSubject, b)
|
// sc.nc is immutable and never nil once connection is created.
|
||||||
|
err := sc.nc.PublishRequest(subj, ackSubject, b)
|
||||||
|
|
||||||
// Setup the timer for expiration.
|
// Setup the timer for expiration.
|
||||||
sc.Lock()
|
sc.Lock()
|
||||||
if err != nil || sc.nc == nil {
|
if err != nil || sc.closed {
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
// If we got and error on publish or the connection has been closed,
|
// If we got and error on publish or the connection has been closed,
|
||||||
// we need to return an error only if:
|
// we need to return an error only if:
|
||||||
@ -797,8 +837,7 @@ func (sc *conn) processMsg(raw *nats.Msg) {
|
|||||||
var sub *subscription
|
var sub *subscription
|
||||||
// Lookup the subscription
|
// Lookup the subscription
|
||||||
sc.RLock()
|
sc.RLock()
|
||||||
nc := sc.nc
|
isClosed := sc.closed
|
||||||
isClosed := nc == nil
|
|
||||||
if !isClosed {
|
if !isClosed {
|
||||||
sub = sc.subMap[raw.Subject]
|
sub = sc.subMap[raw.Subject]
|
||||||
}
|
}
|
||||||
@ -825,10 +864,11 @@ func (sc *conn) processMsg(raw *nats.Msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process auto-ack
|
// Process auto-ack
|
||||||
if !isManualAck && nc != nil {
|
if !isManualAck {
|
||||||
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
||||||
b, _ := ack.Marshal()
|
b, _ := ack.Marshal()
|
||||||
// FIXME(dlc) - Async error handler? Retry?
|
// FIXME(dlc) - Async error handler? Retry?
|
||||||
nc.Publish(ackSubject, b)
|
// sc.nc is immutable and never nil once connection is created.
|
||||||
|
sc.nc.Publish(ackSubject, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package stan is a Go client for the NATS Streaming messaging system (https://nats.io).
|
|
||||||
package stan
|
package stan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -19,8 +18,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nats-io/go-nats"
|
"github.com/nats-io/nats.go"
|
||||||
"github.com/nats-io/go-nats-streaming/pb"
|
"github.com/nats-io/stan.go/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -40,6 +39,7 @@ type Msg struct {
|
|||||||
|
|
||||||
// Subscription represents a subscription within the NATS Streaming cluster. Subscriptions
|
// Subscription represents a subscription within the NATS Streaming cluster. Subscriptions
|
||||||
// will be rate matched and follow at-least once delivery semantics.
|
// will be rate matched and follow at-least once delivery semantics.
|
||||||
|
// The subscription is safe to use in multiple Go routines concurrently.
|
||||||
type Subscription interface {
|
type Subscription interface {
|
||||||
// Unsubscribe removes interest in the subscription.
|
// Unsubscribe removes interest in the subscription.
|
||||||
// For durables, it means that the durable interest is also removed from
|
// For durables, it means that the durable interest is also removed from
|
||||||
@ -56,7 +56,7 @@ type Subscription interface {
|
|||||||
// These functions have been added for expert-users that need to get details
|
// These functions have been added for expert-users that need to get details
|
||||||
// about the low level NATS Subscription used internally to receive messages
|
// about the low level NATS Subscription used internally to receive messages
|
||||||
// for this streaming subscription. They are documented in the Go client
|
// for this streaming subscription. They are documented in the Go client
|
||||||
// library: https://godoc.org/github.com/nats-io/go-nats#Subscription.ClearMaxPending
|
// library: https://godoc.org/github.com/nats-io/nats.go#Subscription.ClearMaxPending
|
||||||
|
|
||||||
// ClearMaxPending resets the maximums seen so far.
|
// ClearMaxPending resets the maximums seen so far.
|
||||||
ClearMaxPending() error
|
ClearMaxPending() error
|
||||||
@ -238,25 +238,27 @@ func (sc *conn) subscribe(subject, qgroup string, cb MsgHandler, options ...Subs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc.Lock()
|
sc.Lock()
|
||||||
if sc.nc == nil {
|
if sc.closed {
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
return nil, ErrConnectionClosed
|
return nil, ErrConnectionClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register subscription.
|
// Register subscription.
|
||||||
sc.subMap[sub.inbox] = sub
|
sc.subMap[sub.inbox] = sub
|
||||||
nc := sc.nc
|
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
|
|
||||||
// Hold lock throughout.
|
// Hold lock throughout.
|
||||||
sub.Lock()
|
sub.Lock()
|
||||||
defer sub.Unlock()
|
defer sub.Unlock()
|
||||||
|
|
||||||
|
// sc.nc is immutable and never nil once connection is created.
|
||||||
|
|
||||||
// Listen for actual messages.
|
// Listen for actual messages.
|
||||||
nsub, err := nc.Subscribe(sub.inbox, sc.processMsg)
|
nsub, err := sc.nc.Subscribe(sub.inbox, sc.processMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
nsub.SetPendingLimits(-1, -1)
|
||||||
sub.inboxSub = nsub
|
sub.inboxSub = nsub
|
||||||
|
|
||||||
// Create a subscription request
|
// Create a subscription request
|
||||||
@ -281,7 +283,7 @@ func (sc *conn) subscribe(subject, qgroup string, cb MsgHandler, options ...Subs
|
|||||||
}
|
}
|
||||||
|
|
||||||
b, _ := sr.Marshal()
|
b, _ := sr.Marshal()
|
||||||
reply, err := nc.Request(sc.subRequests, b, sc.opts.ConnectTimeout)
|
reply, err := sc.nc.Request(sc.subRequests, b, sc.opts.ConnectTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sub.inboxSub.Unsubscribe()
|
sub.inboxSub.Unsubscribe()
|
||||||
if err == nats.ErrTimeout {
|
if err == nats.ErrTimeout {
|
||||||
@ -407,7 +409,7 @@ func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
|
|||||||
sub.Unlock()
|
sub.Unlock()
|
||||||
|
|
||||||
sc.Lock()
|
sc.Lock()
|
||||||
if sc.nc == nil {
|
if sc.closed {
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
return ErrConnectionClosed
|
return ErrConnectionClosed
|
||||||
}
|
}
|
||||||
@ -421,19 +423,17 @@ func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
|
|||||||
return ErrNoServerSupport
|
return ErrNoServerSupport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot connection to avoid data race, since the connection may be
|
|
||||||
// closing while we try to send the request
|
|
||||||
nc := sc.nc
|
|
||||||
sc.Unlock()
|
sc.Unlock()
|
||||||
|
|
||||||
|
// sc.nc is immutable and never nil once connection is created.
|
||||||
|
|
||||||
usr := &pb.UnsubscribeRequest{
|
usr := &pb.UnsubscribeRequest{
|
||||||
ClientID: sc.clientID,
|
ClientID: sc.clientID,
|
||||||
Subject: sub.subject,
|
Subject: sub.subject,
|
||||||
Inbox: sub.ackInbox,
|
Inbox: sub.ackInbox,
|
||||||
}
|
}
|
||||||
b, _ := usr.Marshal()
|
b, _ := usr.Marshal()
|
||||||
reply, err := nc.Request(reqSubject, b, sc.opts.ConnectTimeout)
|
reply, err := sc.nc.Request(reqSubject, b, sc.opts.ConnectTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == nats.ErrTimeout {
|
if err == nats.ErrTimeout {
|
||||||
if doClose {
|
if doClose {
|
||||||
@ -485,16 +485,15 @@ func (msg *Msg) Ack() error {
|
|||||||
if sc == nil {
|
if sc == nil {
|
||||||
return ErrBadSubscription
|
return ErrBadSubscription
|
||||||
}
|
}
|
||||||
// Get nc from the connection (needs locking to avoid race)
|
|
||||||
sc.RLock()
|
// sc.nc is immutable and never nil once connection is created.
|
||||||
nc := sc.nc
|
|
||||||
sc.RUnlock()
|
|
||||||
if nc == nil {
|
|
||||||
return ErrBadConnection
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ack here.
|
// Ack here.
|
||||||
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
||||||
b, _ := ack.Marshal()
|
b, _ := ack.Marshal()
|
||||||
return nc.Publish(ackSubject, b)
|
err := sc.nc.Publish(ackSubject, b)
|
||||||
|
if err == nats.ErrConnectionClosed {
|
||||||
|
return ErrBadConnection
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
2
gateway/vendor/github.com/openfaas/nats-queue-worker/handler/nats_queue.go
generated
vendored
2
gateway/vendor/github.com/openfaas/nats-queue-worker/handler/nats_queue.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
stan "github.com/nats-io/go-nats-streaming"
|
stan "github.com/nats-io/stan.go"
|
||||||
"github.com/openfaas/faas/gateway/queue"
|
"github.com/openfaas/faas/gateway/queue"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user