pubsub jetstream: add nkey based authentication (#1441)
* pubsub jetstream: add nkey based authentication Signed-off-by: Tim Burkert <burkert.tim@gmail.com> * fix godot: comment should end in a period Signed-off-by: Tim Burkert <burkert.tim@gmail.com> * go mod tidy Signed-off-by: Tim Burkert <burkert.tim@gmail.com> * fix: go mod tidy Signed-off-by: Tim Burkert <burkert.tim@gmail.com> * pubsub jetstream: add e2e test Signed-off-by: Tim Burkert <burkert.tim@gmail.com> * Cleanup not needed files and move jwt Signed-off-by: Tim Burkert <burkert.tim@gmail.com> Co-authored-by: Looong Dai <long.dai@intel.com>
This commit is contained in:
parent
2bf7f68e0c
commit
b835eb4e1e
3
go.mod
3
go.mod
|
@ -160,6 +160,8 @@ require (
|
|||
github.com/oracle/oci-go-sdk/v54 v54.0.0
|
||||
)
|
||||
|
||||
require github.com/nats-io/nkeys v0.3.0
|
||||
|
||||
require (
|
||||
github.com/99designs/keyring v1.1.5 // indirect
|
||||
github.com/AthenZ/athenz v1.10.15 // indirect
|
||||
|
@ -251,7 +253,6 @@ require (
|
|||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/nats-io/nkeys v0.3.0 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible // indirect
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nkeys"
|
||||
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
"github.com/dapr/kit/logger"
|
||||
|
@ -50,6 +51,15 @@ func (js *jetstreamPubSub) Init(metadata pubsub.Metadata) error {
|
|||
var opts []nats.Option
|
||||
opts = append(opts, nats.Name(js.meta.name))
|
||||
|
||||
// Set nats.UserJWT options when jwt and seed key is provided.
|
||||
if js.meta.jwt != "" && js.meta.seedKey != "" {
|
||||
opts = append(opts, nats.UserJWT(func() (string, error) {
|
||||
return js.meta.jwt, nil
|
||||
}, func(nonce []byte) ([]byte, error) {
|
||||
return sigHandler(js.meta.seedKey, nonce)
|
||||
}))
|
||||
}
|
||||
|
||||
js.nc, err = nats.Connect(js.meta.natsURL, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -166,3 +176,16 @@ func (js *jetstreamPubSub) Close() error {
|
|||
|
||||
return js.nc.Drain()
|
||||
}
|
||||
|
||||
// Handle nats signature request for challenge response authentication.
|
||||
func sigHandler(seedKey string, nonce []byte) ([]byte, error) {
|
||||
kp, err := nkeys.FromSeed([]byte(seedKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Wipe our key on exit.
|
||||
defer kp.Wipe()
|
||||
|
||||
sig, _ := kp.Sign(nonce)
|
||||
return sig, nil
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
|
||||
type metadata struct {
|
||||
natsURL string
|
||||
jwt string
|
||||
seedKey string
|
||||
|
||||
name string
|
||||
durableName string
|
||||
|
@ -42,6 +44,17 @@ func parseMetadata(psm pubsub.Metadata) (metadata, error) {
|
|||
return metadata{}, fmt.Errorf("missing nats URL")
|
||||
}
|
||||
|
||||
m.jwt = psm.Properties["jwt"]
|
||||
m.seedKey = psm.Properties["seedKey"]
|
||||
|
||||
if m.jwt != "" && m.seedKey == "" {
|
||||
return metadata{}, fmt.Errorf("missing seed key")
|
||||
}
|
||||
|
||||
if m.jwt == "" && m.seedKey != "" {
|
||||
return metadata{}, fmt.Errorf("missing jwt")
|
||||
}
|
||||
|
||||
if m.name = psm.Properties["name"]; m.name == "" {
|
||||
m.name = "dapr.io - pubsub.jetstream"
|
||||
}
|
||||
|
|
|
@ -22,37 +22,87 @@ import (
|
|||
)
|
||||
|
||||
func TestParseMetadata(t *testing.T) {
|
||||
psm := pubsub.Metadata{
|
||||
Properties: map[string]string{
|
||||
"natsURL": "nats://localhost:4222",
|
||||
"name": "myName",
|
||||
"durableName": "myDurable",
|
||||
"queueGroupName": "myQueue",
|
||||
"startSequence": "1",
|
||||
"startTime": "1629328511",
|
||||
"deliverAll": "true",
|
||||
"flowControl": "true",
|
||||
testCases := []struct {
|
||||
desc string
|
||||
input pubsub.Metadata
|
||||
want metadata
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
desc: "Valid Metadata",
|
||||
input: pubsub.Metadata{
|
||||
Properties: map[string]string{
|
||||
"natsURL": "nats://localhost:4222",
|
||||
"name": "myName",
|
||||
"durableName": "myDurable",
|
||||
"queueGroupName": "myQueue",
|
||||
"startSequence": "1",
|
||||
"startTime": "1629328511",
|
||||
"deliverAll": "true",
|
||||
"flowControl": "true",
|
||||
},
|
||||
},
|
||||
want: metadata{
|
||||
natsURL: "nats://localhost:4222",
|
||||
name: "myName",
|
||||
durableName: "myDurable",
|
||||
queueGroupName: "myQueue",
|
||||
startSequence: 1,
|
||||
startTime: time.Unix(1629328511, 0),
|
||||
deliverAll: true,
|
||||
flowControl: true,
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
desc: "Invalid metadata with missing seed key",
|
||||
input: pubsub.Metadata{
|
||||
Properties: map[string]string{
|
||||
"natsURL": "nats://localhost:4222",
|
||||
"name": "myName",
|
||||
"durableName": "myDurable",
|
||||
"queueGroupName": "myQueue",
|
||||
"startSequence": "1",
|
||||
"startTime": "1629328511",
|
||||
"deliverAll": "true",
|
||||
"flowControl": "true",
|
||||
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
|
||||
},
|
||||
},
|
||||
want: metadata{},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
desc: "Invalid metadata with missing jwt",
|
||||
input: pubsub.Metadata{
|
||||
Properties: map[string]string{
|
||||
"natsURL": "nats://localhost:4222",
|
||||
"name": "myName",
|
||||
"durableName": "myDurable",
|
||||
"queueGroupName": "myQueue",
|
||||
"startSequence": "1",
|
||||
"startTime": "1629328511",
|
||||
"deliverAll": "true",
|
||||
"flowControl": "true",
|
||||
"seedKey": "SUACS34K232OKPRDOMKC6QEWXWUDJTT6R6RZM2WPMURUS5Z3POU7BNIL4Y",
|
||||
},
|
||||
},
|
||||
want: metadata{},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
ts := time.Unix(1629328511, 0)
|
||||
|
||||
want := metadata{
|
||||
natsURL: "nats://localhost:4222",
|
||||
name: "myName",
|
||||
durableName: "myDurable",
|
||||
queueGroupName: "myQueue",
|
||||
startSequence: 1,
|
||||
startTime: ts,
|
||||
deliverAll: true,
|
||||
flowControl: true,
|
||||
}
|
||||
|
||||
got, err := parseMetadata(psm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("unexpected metadata: got=%v, want=%v", got, want)
|
||||
for _, tC := range testCases {
|
||||
t.Run(tC.desc, func(t *testing.T) {
|
||||
got, err := parseMetadata(tC.input)
|
||||
if !tC.expectErr && err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tC.expectErr && err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tC.want) {
|
||||
t.Fatalf("unexpected metadata: got=%v, want=%v", got, tC.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/docker-existing-docker-compose
|
||||
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
|
||||
{
|
||||
"name": "Existing Docker Compose (Extend)",
|
||||
|
||||
// Update the 'dockerComposeFile' list if you have more compose files or use different names.
|
||||
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
|
||||
"dockerComposeFile": [
|
||||
"../docker-compose.yaml",
|
||||
"docker-compose.yml"
|
||||
],
|
||||
|
||||
// The 'service' property is the name of the service for the container that VS Code should
|
||||
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
|
||||
"service": "dev",
|
||||
|
||||
// The optional 'workspaceFolder' property is the path VS Code should open by default when
|
||||
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
|
||||
"workspaceFolder": "/workspace",
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"golang.go"
|
||||
]
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Uncomment the next line if you want start specific services in your Docker Compose config.
|
||||
// "runServices": [],
|
||||
|
||||
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
|
||||
// "shutdownAction": "none",
|
||||
|
||||
// Uncomment the next line to run commands after the container is created - for example installing curl.
|
||||
// "postCreateCommand": "apt-get update && apt-get install -y curl",
|
||||
|
||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
// "remoteUser": "vscode"
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
version: '3.5'
|
||||
services:
|
||||
# Update this to the name of the service you want to work with in your docker-compose.yml file
|
||||
dev:
|
||||
# If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
|
||||
# property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
|
||||
# debugging) to execute as the user. Uncomment the next line if you want the entire
|
||||
# container to run as this user instead. Note that, on Linux, you may need to
|
||||
# ensure the UID and GID of the container user you create matches your local user.
|
||||
# See https://aka.ms/vscode-remote/containers/non-root for details.
|
||||
#
|
||||
# user: vscode
|
||||
|
||||
# Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
|
||||
# folder. Note that the path of the Dockerfile and context is relative to the *primary*
|
||||
# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
|
||||
# array). The sample below assumes your primary file is in the root of your project.
|
||||
#
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: .devcontainer/Dockerfile
|
||||
|
||||
volumes:
|
||||
# Update this to wherever you want VS Code to mount the folder of your project
|
||||
- .:/workspace:cached
|
||||
|
||||
# Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
|
||||
# - /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
|
||||
cap_add:
|
||||
- SYS_PTRACE
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
|
||||
# Overrides default command so things don't shut down after the process ends.
|
||||
command: /bin/sh -c "while sleep 1000; do :; done"
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package authentication_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/dapr/components-contrib/pubsub"
|
||||
"github.com/dapr/components-contrib/pubsub/jetstream"
|
||||
"github.com/dapr/kit/logger"
|
||||
)
|
||||
|
||||
func TestAuthentication(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
jwt string
|
||||
seedKey string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
desc: "Valid jwt and valid seed",
|
||||
jwt: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJWS1UySENWNUlBRzUzSkNQT0hRNllaTDJKSEZZVkJBVzJSQ1RMUUtBWTJLT0UySDZSSDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBRFU0UVVNV0RQMkJKVFBIWktFWkNLVkw3STNIQTRPR1dRUUNWMjJRVlBHSVNTV1Q0T1hRN0VOUyIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiVUFUSkNBWFRCNUoyRVVWNDJCU0UzMkRBSEpKS01WTkZNNlNIUkZXWDVUWkVMWDZEU1hURVlXVTUiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e30sInN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.7K5VA23V8bBipH4Vkzhg01_jaQVw6MWW9NgxUkiYBUaMLNHLZB4_DnuT2mBz9SrQwi8XohNoZeKI7WTTbQxxBg",
|
||||
seedKey: "SUAJF7ALJKFPLKTA23BOP6CILVPH3SV4V7EGM7VFZ3KCFWHKPPI7HCCZKI",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
desc: "Valid jwt and invalid seed",
|
||||
jwt: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJWS1UySENWNUlBRzUzSkNQT0hRNllaTDJKSEZZVkJBVzJSQ1RMUUtBWTJLT0UySDZSSDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBRFU0UVVNV0RQMkJKVFBIWktFWkNLVkw3STNIQTRPR1dRUUNWMjJRVlBHSVNTV1Q0T1hRN0VOUyIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiVUFUSkNBWFRCNUoyRVVWNDJCU0UzMkRBSEpKS01WTkZNNlNIUkZXWDVUWkVMWDZEU1hURVlXVTUiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e30sInN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.7K5VA23V8bBipH4Vkzhg01_jaQVw6MWW9NgxUkiYBUaMLNHLZB4_DnuT2mBz9SrQwi8XohNoZeKI7WTTbQxxBg",
|
||||
seedKey: "SUAIGUGTLK7FZMRVYLGCROG3TTCZK64D2MZOYFGKH7WJRADFYOMTL3QQZU",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
desc: "Invalid jwt and valid seed",
|
||||
jwt: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiI0SlJGU0RHTk9JM1BDUTIyTVhLMk1SNkhTSk1SREhZTlNDSlNaUDcyVzJUQ1g2Sk9SWDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBQzc0QllIS1VEUzVLUEg0TDRZVkNVRUNEVDJIUFQzRDVFU1pXUVNDTDNMVFhaRkhEVEg2T1ZSVyIsIm5hbWUiOiJzeXMiLCJzdWIiOiJVQk03WEpHRU5VUUtQQVY2RE9XUjJaWDdXM0ZQUEJVUE9DQlZRNzU2UFFaUUg2VlVGRjdORFNTNSIsIm5hdHMiOnsicHViIjp7fSwic3ViIjp7fSwic3VicyI6LTEsImRhdGEiOi0xLCJwYXlsb2FkIjotMSwiaXNzdWVyX2FjY291bnQiOiJBQ0dDV1ZZWjYySTZSWkRRNlVVU0FEM0lTTE1FMkNFUEdOWlczUVpCN09KUkE1VU5LMkRDT08zQSIsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.Cj_dQFE9c_BDZrHLzIJRtDI0ZrXB1u-eG_NJw54Dg3Df3QdJOrl-rU_M6f0D0rAGH1THQl0vD4lRkGp_SfzeAQ",
|
||||
seedKey: "SUAJF7ALJKFPLKTA23BOP6CILVPH3SV4V7EGM7VFZ3KCFWHKPPI7HCCZKI",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
for _, tC := range testCases {
|
||||
t.Run(tC.desc, func(t *testing.T) {
|
||||
log := logger.NewLogger("natsE2E")
|
||||
js := jetstream.NewJetStream(log)
|
||||
md := pubsub.Metadata{
|
||||
Properties: map[string]string{
|
||||
"natsURL": "nats://localhost",
|
||||
"jwt": tC.jwt,
|
||||
"seedKey": tC.seedKey,
|
||||
"durableName": "test",
|
||||
"queueGroupName": "test",
|
||||
"startSequence": "0",
|
||||
"startTime": "0",
|
||||
"deliverAll": "true",
|
||||
"flowControl": "false",
|
||||
},
|
||||
}
|
||||
err := js.Init(md)
|
||||
if err != nil && !tC.expectError {
|
||||
t.Fatal("Did not expect error during connect", err.Error())
|
||||
}
|
||||
if err == nil && tC.expectError {
|
||||
t.Fatal("Did expect error during connect")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
version: "3.5"
|
||||
services:
|
||||
nats:
|
||||
image: nats
|
||||
command: "--config /config/server.conf"
|
||||
volumes:
|
||||
- ./nsc:/nsc
|
||||
- ./:/config
|
||||
- ./jwt:/jwt
|
||||
|
||||
dev:
|
||||
image: golang:1.17.6
|
||||
network_mode:
|
||||
service:nats
|
||||
volumes:
|
||||
- ../../../../:/go/src/github.com/dapr/components-contrib:cached
|
||||
depends_on:
|
||||
- nats
|
|
@ -0,0 +1,26 @@
|
|||
module github.com/dapr/components-contrib/tests/e2e/pubsub/jetstream
|
||||
|
||||
go 1.17
|
||||
|
||||
require github.com/dapr/components-contrib v1.5.1
|
||||
|
||||
require (
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/dapr/kit v0.0.2-0.20210614175626-b9074b64d233 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.2.0 // indirect
|
||||
github.com/nats-io/nats.go v1.12.0 // indirect
|
||||
github.com/nats-io/nkeys v0.3.0 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
|
||||
)
|
||||
|
||||
replace github.com/dapr/components-contrib => /go/src/github.com/dapr/components-contrib
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJCTFEzMzZGR0ZONDdJR1JHUjY0WUROVU5OSFdHV0hMUTU1S1ZDRlpPR0NQNlFDWjdMT1VRIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJPRFJMUldYSEZITUtGU0FWRkZaUVQ1SUVQRFpNTkg1M0VKREZOSEhDMlM3RERSN0dKTk9HWVFVViIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiQURVNFFVTVdEUDJCSlRQSFpLRVpDS1ZMN0kzSEE0T0dXUVFDVjIyUVZQR0lTU1dUNE9YUTdFTlMiLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJpbXBvcnRzIjotMSwiZXhwb3J0cyI6LTEsIndpbGRjYXJkcyI6dHJ1ZSwiY29ubiI6LTEsImxlYWYiOi0xfSwiZGVmYXVsdF9wZXJtaXNzaW9ucyI6eyJwdWIiOnt9LCJzdWIiOnt9fSwidHlwZSI6ImFjY291bnQiLCJ2ZXJzaW9uIjoyfX0.tBnQVWRBHBnkxWg3B8PH3GKb5Rym2K3APP5PoMN8pSzt67Fztz__1nGTf0-S7ag2JEdtqydlfAUq4IkoAHqPCA
|
|
@ -0,0 +1 @@
|
|||
{"managed":false,"name":"loving_keller","kind":"operator","version":"1"}
|
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJITzNISUNWQkU2UlE1S1lLN1dKM0hEM0hHUlgzVVpTRllSWTVWNDJSUENYQzRGQ01UUE1BIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJPRFJMUldYSEZITUtGU0FWRkZaUVQ1SUVQRFpNTkg1M0VKREZOSEhDMlM3RERSN0dKTk9HWVFVViIsIm5hbWUiOiJTWVMiLCJzdWIiOiJBQ0dDV1ZZWjYySTZSWkRRNlVVU0FEM0lTTE1FMkNFUEdOWlczUVpCN09KUkE1VU5LMkRDT08zQSIsIm5hdHMiOnsibGltaXRzIjp7InN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwid2lsZGNhcmRzIjp0cnVlLCJjb25uIjotMSwibGVhZiI6LTF9LCJzaWduaW5nX2tleXMiOlsiQUM3NEJZSEtVRFM1S1BINEw0WVZDVUVDRFQySFBUM0Q1RVNaV1FTQ0wzTFRYWkZIRFRINk9WUlciXSwiZGVmYXVsdF9wZXJtaXNzaW9ucyI6eyJwdWIiOnt9LCJzdWIiOnt9fSwidHlwZSI6ImFjY291bnQiLCJ2ZXJzaW9uIjoyfX0._V43fywLpEabOiILR8xhx-GT5JjIXpSRVOjJO_j2WLNkbWrEz8wvZM_L02eLQsZCcaeZJMudVAUCK--nxmPCCw
|
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiI0SlJGU0RHTk9JM1BDUTIyTVhLMk1SNkhTSk1SREhZTlNDSlNaUDcyVzJUQ1g2Sk9SWDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBQzc0QllIS1VEUzVLUEg0TDRZVkNVRUNEVDJIUFQzRDVFU1pXUVNDTDNMVFhaRkhEVEg2T1ZSVyIsIm5hbWUiOiJzeXMiLCJzdWIiOiJVQk03WEpHRU5VUUtQQVY2RE9XUjJaWDdXM0ZQUEJVUE9DQlZRNzU2UFFaUUg2VlVGRjdORFNTNSIsIm5hdHMiOnsicHViIjp7fSwic3ViIjp7fSwic3VicyI6LTEsImRhdGEiOi0xLCJwYXlsb2FkIjotMSwiaXNzdWVyX2FjY291bnQiOiJBQ0dDV1ZZWjYySTZSWkRRNlVVU0FEM0lTTE1FMkNFUEdOWlczUVpCN09KUkE1VU5LMkRDT08zQSIsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.Cj_dQFE9c_BDZrHLzIJRtDI0ZrXB1u-eG_NJw54Dg3Df3QdJOrl-rU_M6f0D0rAGH1THQl0vD4lRkGp_SfzeAQ
|
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJCTFEzMzZGR0ZONDdJR1JHUjY0WUROVU5OSFdHV0hMUTU1S1ZDRlpPR0NQNlFDWjdMT1VRIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJPRFJMUldYSEZITUtGU0FWRkZaUVQ1SUVQRFpNTkg1M0VKREZOSEhDMlM3RERSN0dKTk9HWVFVViIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiQURVNFFVTVdEUDJCSlRQSFpLRVpDS1ZMN0kzSEE0T0dXUVFDVjIyUVZQR0lTU1dUNE9YUTdFTlMiLCJuYXRzIjp7ImxpbWl0cyI6eyJzdWJzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJpbXBvcnRzIjotMSwiZXhwb3J0cyI6LTEsIndpbGRjYXJkcyI6dHJ1ZSwiY29ubiI6LTEsImxlYWYiOi0xfSwiZGVmYXVsdF9wZXJtaXNzaW9ucyI6eyJwdWIiOnt9LCJzdWIiOnt9fSwidHlwZSI6ImFjY291bnQiLCJ2ZXJzaW9uIjoyfX0.tBnQVWRBHBnkxWg3B8PH3GKb5Rym2K3APP5PoMN8pSzt67Fztz__1nGTf0-S7ag2JEdtqydlfAUq4IkoAHqPCA
|
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJWS1UySENWNUlBRzUzSkNQT0hRNllaTDJKSEZZVkJBVzJSQ1RMUUtBWTJLT0UySDZSSDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBRFU0UVVNV0RQMkJKVFBIWktFWkNLVkw3STNIQTRPR1dRUUNWMjJRVlBHSVNTV1Q0T1hRN0VOUyIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiVUFUSkNBWFRCNUoyRVVWNDJCU0UzMkRBSEpKS01WTkZNNlNIUkZXWDVUWkVMWDZEU1hURVlXVTUiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e30sInN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.7K5VA23V8bBipH4Vkzhg01_jaQVw6MWW9NgxUkiYBUaMLNHLZB4_DnuT2mBz9SrQwi8XohNoZeKI7WTTbQxxBg
|
|
@ -0,0 +1 @@
|
|||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiIzVDdVS0JSUUhOT1VXUUtLSVNRRU9KRldYN01DTk1FR1hXNFJHTlhMR1pNN0M2UUJWUEtBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJPRFJMUldYSEZITUtGU0FWRkZaUVQ1SUVQRFpNTkg1M0VKREZOSEhDMlM3RERSN0dKTk9HWVFVViIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiT0RSTFJXWEhGSE1LRlNBVkZGWlFUNUlFUERaTU5INTNFSkRGTkhIQzJTN0REUjdHSk5PR1lRVVYiLCJuYXRzIjp7Im9wZXJhdG9yX3NlcnZpY2VfdXJscyI6WyJuYXRzOi8vbG9jYWxob3N0OjQyMjIiXSwic3lzdGVtX2FjY291bnQiOiJBQ0dDV1ZZWjYySTZSWkRRNlVVU0FEM0lTTE1FMkNFUEdOWlczUVpCN09KUkE1VU5LMkRDT08zQSIsInR5cGUiOiJvcGVyYXRvciIsInZlcnNpb24iOjJ9fQ.jtc9HQdUBVcEVyS1DaX84T4JXZ0w6cF0GQZMa0kWIIHu3O5h0clpxytH4LMwTIB_VsQlJR3asE6lT6baFsRCCA
|
|
@ -0,0 +1,13 @@
|
|||
-----BEGIN NATS USER JWT-----
|
||||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiI0SlJGU0RHTk9JM1BDUTIyTVhLMk1SNkhTSk1SREhZTlNDSlNaUDcyVzJUQ1g2Sk9SWDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBQzc0QllIS1VEUzVLUEg0TDRZVkNVRUNEVDJIUFQzRDVFU1pXUVNDTDNMVFhaRkhEVEg2T1ZSVyIsIm5hbWUiOiJzeXMiLCJzdWIiOiJVQk03WEpHRU5VUUtQQVY2RE9XUjJaWDdXM0ZQUEJVUE9DQlZRNzU2UFFaUUg2VlVGRjdORFNTNSIsIm5hdHMiOnsicHViIjp7fSwic3ViIjp7fSwic3VicyI6LTEsImRhdGEiOi0xLCJwYXlsb2FkIjotMSwiaXNzdWVyX2FjY291bnQiOiJBQ0dDV1ZZWjYySTZSWkRRNlVVU0FEM0lTTE1FMkNFUEdOWlczUVpCN09KUkE1VU5LMkRDT08zQSIsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.Cj_dQFE9c_BDZrHLzIJRtDI0ZrXB1u-eG_NJw54Dg3Df3QdJOrl-rU_M6f0D0rAGH1THQl0vD4lRkGp_SfzeAQ
|
||||
------END NATS USER JWT------
|
||||
|
||||
************************* IMPORTANT *************************
|
||||
NKEY Seed printed below can be used to sign and prove identity.
|
||||
NKEYs are sensitive and should be treated as secrets.
|
||||
|
||||
-----BEGIN USER NKEY SEED-----
|
||||
SUAIGUGTLK7FZMRVYLGCROG3TTCZK64D2MZOYFGKH7WJRADFYOMTL3QQZU
|
||||
------END USER NKEY SEED------
|
||||
|
||||
*************************************************************
|
|
@ -0,0 +1,13 @@
|
|||
-----BEGIN NATS USER JWT-----
|
||||
eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJWS1UySENWNUlBRzUzSkNQT0hRNllaTDJKSEZZVkJBVzJSQ1RMUUtBWTJLT0UySDZSSDdBIiwiaWF0IjoxNjQyNDkwNjU5LCJpc3MiOiJBRFU0UVVNV0RQMkJKVFBIWktFWkNLVkw3STNIQTRPR1dRUUNWMjJRVlBHSVNTV1Q0T1hRN0VOUyIsIm5hbWUiOiJsb3Zpbmdfa2VsbGVyIiwic3ViIjoiVUFUSkNBWFRCNUoyRVVWNDJCU0UzMkRBSEpKS01WTkZNNlNIUkZXWDVUWkVMWDZEU1hURVlXVTUiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e30sInN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsInR5cGUiOiJ1c2VyIiwidmVyc2lvbiI6Mn19.7K5VA23V8bBipH4Vkzhg01_jaQVw6MWW9NgxUkiYBUaMLNHLZB4_DnuT2mBz9SrQwi8XohNoZeKI7WTTbQxxBg
|
||||
------END NATS USER JWT------
|
||||
|
||||
************************* IMPORTANT *************************
|
||||
NKEY Seed printed below can be used to sign and prove identity.
|
||||
NKEYs are sensitive and should be treated as secrets.
|
||||
|
||||
-----BEGIN USER NKEY SEED-----
|
||||
SUAJF7ALJKFPLKTA23BOP6CILVPH3SV4V7EGM7VFZ3KCFWHKPPI7HCCZKI
|
||||
------END USER NKEY SEED------
|
||||
|
||||
*************************************************************
|
|
@ -0,0 +1 @@
|
|||
SAAJMIGVNJEMDXHEFG4ZEEOAPF7D6O6MNZPXEKNTHIE4LYACZPARQE72LA
|
|
@ -0,0 +1 @@
|
|||
SAAPB7HK6ZMZ7XGLS6OECY3ZB24B3VR2ZMKEF5SQNUUVQSNJXZ4V5CLHMU
|
|
@ -0,0 +1 @@
|
|||
SAADF5COLGE3HENQTI7RSXXDCQLTNL6GOYZYGFB5X56ILH4UNS7JTFWMDA
|
|
@ -0,0 +1 @@
|
|||
SOAI4FAEB4F23C43A3TO7T3JANMOU4N6KLJOLTESY2OEGQIUHHKT2Q63AY
|
|
@ -0,0 +1 @@
|
|||
SUAJF7ALJKFPLKTA23BOP6CILVPH3SV4V7EGM7VFZ3KCFWHKPPI7HCCZKI
|
|
@ -0,0 +1 @@
|
|||
SUAIGUGTLK7FZMRVYLGCROG3TTCZK64D2MZOYFGKH7WJRADFYOMTL3QQZU
|
|
@ -0,0 +1,19 @@
|
|||
operator: /nsc/loving_keller/loving_keller.jwt
|
||||
|
||||
resolver: {
|
||||
type: full
|
||||
# Directory in which account jwt will be stored
|
||||
dir: './jwt'
|
||||
# In order to support jwt deletion, set to true
|
||||
# If the resolver type is full delete will rename the jwt.
|
||||
# This is to allow manual restoration in case of inadvertent deletion.
|
||||
# To restore a jwt, remove the added suffix .delete and restart or send a reload signal.
|
||||
# To free up storage you must manually delete files with the suffix .delete.
|
||||
allow_delete: false
|
||||
# Interval at which a nats-server with a nats based account resolver will compare
|
||||
# it's state with one random nats based account resolver in the cluster and if needed,
|
||||
# exchange jwt and converge on the same set of jwt.
|
||||
interval: "2m"
|
||||
# limit on the number of jwt stored, will reject new jwt once limit is hit.
|
||||
limit: 1000
|
||||
}
|
Loading…
Reference in New Issue