From 0f8d6c61b9a7849d54d26fadaf91aadfd2d48d23 Mon Sep 17 00:00:00 2001 From: ainsley Date: Fri, 20 Dec 2019 16:28:34 -0600 Subject: [PATCH 1/2] adding gists --- .../securing_nats/auth_intro/nkey_auth.md | 202 ++++++++++++++++++ nats-server/installation.md | 102 +++++++++ nats-streaming-concepts/monitoring/README.md | 32 +++ 3 files changed, 336 insertions(+) diff --git a/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md b/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md index 2b2ba0c..ec95736 100644 --- a/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md +++ b/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md @@ -59,3 +59,205 @@ const nc = NATS.connect({ The client provides a function that it uses to parse the seed \(the private key\) and sign the connection challenge. +## Mixing NKEYS and Trusted Operator setup in NATS v2 + +Mixing both nkeys static config and trusted operator setup (decentralized auth model) is possible +but needs some preparation in order to be able to do it. + +The way this can be done is by **first** preparing a basic trusted operator setup +that could be used in the future, and then base from that configuration to create the +NKEYS static config using the same shared public nkeys for the accounts and then use +clustering routes to bridge the two different auth setups during the transition. + +For example, creating the following initial setup using [NSC](/nsc/readme.md): + +```sh + nsc add account --name SYS + nsc add user --name sys + nsc add account --name A + nsc add user -a A --name test + nsc add account --name B + nsc add user -a B --name test +``` + +This will then generate something like the following: + +```sh + nsc list accounts +╭─────────────────────────────────────────────────────────────────╮ +│ Accounts │ +├──────┬──────────────────────────────────────────────────────────┤ +│ Name │ Public Key │ +├──────┼──────────────────────────────────────────────────────────┤ +│ A │ ADFB2JXYTXOJEL6LNAXDREUGRX35BOLZI3B4PFFAC7IRPR3OA4QNKBN2 │ +│ B │ ACWOMQA7PZTKJSBTR7BF6TBK3D776734PWHWDKO7HFMQOM5BIOYPSYZZ │ +│ SYS │ ABKOWIYVTHNEK5HELPWLAT2CF2CUPELIK4SZH2VCJHLFU22B5U2IIZUO │ +╰──────┴──────────────────────────────────────────────────────────╯ + + nsc list users -a A +╭─────────────────────────────────────────────────────────────────╮ +│ Users │ +├──────┬──────────────────────────────────────────────────────────┤ +│ Name │ Public Key │ +├──────┼──────────────────────────────────────────────────────────┤ +│ test │ UAPOK2P7EN3UFBL7SBJPQK3M3JMLALYRYKX5XWSVMVYK63ZMBHTOHVJR │ +╰──────┴──────────────────────────────────────────────────────────╯ +``` + +We could use this configuration as the initial starting configuration for an nkeys config now, +where all the NKEYS users public nkeys are explicitly listed (centralized auth model). + +```hcl +port = 4222 + +cluster { + port = 6222 + + # We will bridge two different servers with different auth models via routes + # routes [ nats://127.0.0.1:6223 ] +} + +system_account = ABKOWIYVTHNEK5HELPWLAT2CF2CUPELIK4SZH2VCJHLFU22B5U2IIZUO + +accounts { + # Account A + ADFB2JXYTXOJEL6LNAXDREUGRX35BOLZI3B4PFFAC7IRPR3OA4QNKBN2 { + nkey: ADFB2JXYTXOJEL6LNAXDREUGRX35BOLZI3B4PFFAC7IRPR3OA4QNKBN2 + users = [ + {nkey: "UAPOK2P7EN3UFBL7SBJPQK3M3JMLALYRYKX5XWSVMVYK63ZMBHTOHVJR" } + ] + } + + # Account B + ACWOMQA7PZTKJSBTR7BF6TBK3D776734PWHWDKO7HFMQOM5BIOYPSYZZ { + } + + # Account SYS + ABKOWIYVTHNEK5HELPWLAT2CF2CUPELIK4SZH2VCJHLFU22B5U2IIZUO { + } +} +``` + + +By using `nsc` it is possible to create a mem based resolver for the trusted operator setup: + +``` +nsc generate config --mem-resolver --sys-account SYS +``` + +An example configuration from the second node with the trusted operator setup could then be: + +```hcl +port = 4223 + +cluster { + port = 6223 + routes [ nats://127.0.0.1:6222 ] +} + +# debug = true +# trace = true + +# Operator +operator = eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJQNDJBSkFTVVA0TUdGRU1EQzVCRVVGUkM1MlQ1M05OTzRIWkhRNEdETVk0S0RZTFVRV0JBIiwiaWF0IjoxNTc0Mzc1OTE2LCJpc3MiOiJPQ09KSk5aSUNINkNHUU5LM1NRMzVXTFpXWkpDUkRBTFJIWjZPVzQ0RFpZVVdNVVYzV1BSSEZSRCIsIm5hbWUiOiJLTyIsInN1YiI6Ik9DT0pKTlpJQ0g2Q0dRTkszU1EzNVdMWldaSkNSREFMUkhaNk9XNDREWllVV01VVjNXUFJIRlJEIiwidHlwZSI6Im9wZXJhdG9yIiwibmF0cyI6e319.pppa9-xhWXJLSCCtqj_dqlvXKR7WlVCh0cqoZ6lr8zg3WlWM8U0bNf6FHw_67-wRS7jj0n4PuA0P0MAJdE3pDA + +system_account = ABKOWIYVTHNEK5HELPWLAT2CF2CUPELIK4SZH2VCJHLFU22B5U2IIZUO + +resolver = MEMORY + +resolver_preload = { + # Account "A" + ADFB2JXYTXOJEL6LNAXDREUGRX35BOLZI3B4PFFAC7IRPR3OA4QNKBN2: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiIyQjNYNUJPQzQ3M05TU0hFWUVHTzJYRUhaTVNGRVBORFFBREJXWkJLRVdQVlg2TUlZU1JRIiwiaWF0IjoxNTc0Mzc1OTE2LCJpc3MiOiJPQ09KSk5aSUNINkNHUU5LM1NRMzVXTFpXWkpDUkRBTFJIWjZPVzQ0RFpZVVdNVVYzV1BSSEZSRCIsIm5hbWUiOiJBIiwic3ViIjoiQURGQjJKWFlUWE9KRUw2TE5BWERSRVVHUlgzNUJPTFpJM0I0UEZGQUM3SVJQUjNPQTRRTktCTjIiLCJ0eXBlIjoiYWNjb3VudCIsIm5hdHMiOnsiZXhwb3J0cyI6W3sibmFtZSI6InRlc3QiLCJzdWJqZWN0IjoidGVzdCIsInR5cGUiOiJzZXJ2aWNlIiwic2VydmljZV9sYXRlbmN5Ijp7InNhbXBsaW5nIjoxMDAsInJlc3VsdHMiOiJsYXRlbmN5Lm9uLnRlc3QifX1dLCJsaW1pdHMiOnsic3VicyI6LTEsImNvbm4iOi0xLCJsZWFmIjotMSwiaW1wb3J0cyI6LTEsImV4cG9ydHMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsIndpbGRjYXJkcyI6dHJ1ZX19fQ.zZBetgDN6nCFDVpwzF_124BPkc8amGPDnrOmiKUa12xski5zskUI0Y0OeIa1vTo0bkHIKTgM2QDYpmXUQOHnAQ + + # Account "B" + ACWOMQA7PZTKJSBTR7BF6TBK3D776734PWHWDKO7HFMQOM5BIOYPSYZZ: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJBTFNFQkZGWDZMR0pQTlVMU1NXTDNTRTNISkk2WUZSWlVKSDNLV0E1VE41WUtWRE5MVTJRIiwiaWF0IjoxNTc0Mzc1OTE2LCJpc3MiOiJPQ09KSk5aSUNINkNHUU5LM1NRMzVXTFpXWkpDUkRBTFJIWjZPVzQ0RFpZVVdNVVYzV1BSSEZSRCIsIm5hbWUiOiJCIiwic3ViIjoiQUNXT01RQTdQWlRLSlNCVFI3QkY2VEJLM0Q3NzY3MzRQV0hXREtPN0hGTVFPTTVCSU9ZUFNZWloiLCJ0eXBlIjoiYWNjb3VudCIsIm5hdHMiOnsiaW1wb3J0cyI6W3sibmFtZSI6InRlc3QiLCJzdWJqZWN0IjoidGVzdCIsImFjY291bnQiOiJBREZCMkpYWVRYT0pFTDZMTkFYRFJFVUdSWDM1Qk9MWkkzQjRQRkZBQzdJUlBSM09BNFFOS0JOMiIsInRvIjoidGVzdCIsInR5cGUiOiJzZXJ2aWNlIn1dLCJsaW1pdHMiOnsic3VicyI6LTEsImNvbm4iOi0xLCJsZWFmIjotMSwiaW1wb3J0cyI6LTEsImV4cG9ydHMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsIndpbGRjYXJkcyI6dHJ1ZX19fQ.AnzziBwt5Tnphc2prONUUOpMpkkAlJHvCPaag0GUtTYPCHKDphcJrwtAHi4v5NOI6npjoes0F0MlrfnHqidDAg + + # Account "SYS" + ABKOWIYVTHNEK5HELPWLAT2CF2CUPELIK4SZH2VCJHLFU22B5U2IIZUO: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiI1WVUyWkc1UkRTSU1TN1pGVE1MU0NZQUtLVkVFWUpPUlc0TDJPTlY3N1g1TlJZWkFGSkRRIiwiaWF0IjoxNTc0Mzc1OTE2LCJpc3MiOiJPQ09KSk5aSUNINkNHUU5LM1NRMzVXTFpXWkpDUkRBTFJIWjZPVzQ0RFpZVVdNVVYzV1BSSEZSRCIsIm5hbWUiOiJTWVMiLCJzdWIiOiJBQktPV0lZVlRITkVLNUhFTFBXTEFUMkNGMkNVUEVMSUs0U1pIMlZDSkhMRlUyMkI1VTJJSVpVTyIsInR5cGUiOiJhY2NvdW50IiwibmF0cyI6eyJsaW1pdHMiOnsic3VicyI6LTEsImNvbm4iOi0xLCJsZWFmIjotMSwiaW1wb3J0cyI6LTEsImV4cG9ydHMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsIndpbGRjYXJkcyI6dHJ1ZX19fQ.5FrO4sZbWuFgRLuy7c1eQLUq_BQ4PNhIAN5A-sRLkYWmvlc4c_Y4VfTbgl5zhNzCxfvj9SxT7ySgphup2BiRAA +} +``` + +**These two servers even though they have different auth mechanisms are able to route the accounts because the account public nkeys are the same.** + +We have created at least one user, in this case with creds: + +```conf +-----BEGIN NATS USER JWT----- +eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJNRkM3V1E1N0hKUE9aWUVOTEhVRTZTWFVQTDVKTURWSkxIQzJRTkpYNUVJS0RGR1U1REhRIiwiaWF0IjoxNTc0Mzc1OTE2LCJpc3MiOiJBREZCMkpYWVRYT0pFTDZMTkFYRFJFVUdSWDM1Qk9MWkkzQjRQRkZBQzdJUlBSM09BNFFOS0JOMiIsIm5hbWUiOiJ0ZXN0Iiwic3ViIjoiVUFQT0syUDdFTjNVRkJMN1NCSlBRSzNNM0pNTEFMWVJZS1g1WFdTVk1WWUs2M1pNQkhUT0hWSlIiLCJ0eXBlIjoidXNlciIsIm5hdHMiOnsicHViIjp7ImFsbG93IjpbIl9JTkJPWC5cdTAwM2UiLCJfUl8iLCJfUl8uXHUwMDNlIiwidGVzdCIsInRlc3QuXHUwMDNlIl19LCJzdWIiOnsiYWxsb3ciOlsiX0lOQk9YLlx1MDAzZSIsIl9SXyIsIl9SXy5cdTAwM2UiLCJsYXRlbmN5Lm9uLnRlc3QiLCJ0ZXN0IiwidGVzdC5cdTAwM2UiXX19fQ.MSU2aUIBK1iUsg7h52lLrfEfTwVMF_wB3HDq75ECskxSyyDDMtk9_3957UtQF-3yoGCIhKOkWjzX8C-WXnLADw +------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----- +SUANVBWRHHFMGHNIT6UJHPN2TGVBVIILE7VPVNEQ7DGCJ26ZD2V3KAHT4M +------END USER NKEY SEED------ +************************************************************* +``` + +And this same user is able to connect to either one of the servers (bound to 4222 and 4223 respectively): + +Subscriber Service: + +```go +package main + +import ( + "log" + + "github.com/nats-io/nats.go" +) + +func main() { + opts := make([]nats.Option, 0) + + // Extract public nkey from seed + // + // Public: UAPOK2P7EN3UFBL7SBJPQK3M3JMLALYRYKX5XWSVMVYK63ZMBHTOHVJR + // Private: SUANVBWRHHFMGHNIT6UJHPN2TGVBVIILE7VPVNEQ7DGCJ26ZD2V3KAHT4M + // + nkey, err := nats.NkeyOptionFromSeed("path/to/seed.nkey") + if err != nil { + log.Fatal(err) + } + opts = append(opts, nkey) + nc, err := nats.Connect("127.0.0.1:4222", opts...) + if err != nil { + log.Fatal(err) + } + nc.Subscribe("test", func(m *nats.Msg){ + log.Printf("[Received] %q, replying... \n", string(m.Data)) + m.Respond([]byte("pong from nkeys based server")) + }) + + select {} +} +``` + +Requestor: + +```go +package main + +import ( + "log" + "time" + + "github.com/nats-io/nats.go" +) + +func main() { + nc, err := nats.Connect("127.0.0.1:4223", nats.UserCredentials("path/to/user.creds")) + if err != nil { + log.Fatal(err) + } + + for range time.NewTicker(1 * time.Second).C { + resp, err := nc.Request("test", []byte("test"), 1*time.Second) + if err != nil { + log.Println("[Error]", err) + continue + } + log.Println("[Received]", string(resp.Data)) + } +} +``` \ No newline at end of file diff --git a/nats-server/installation.md b/nats-server/installation.md index 848906f..0e4f41f 100644 --- a/nats-server/installation.md +++ b/nats-server/installation.md @@ -103,3 +103,105 @@ To test your installation \(provided the $GOPATH/bin is set\): [41634] 2019/05/13 09:42:11.746252 [INF] Server is ready ``` +## NATS v2 and Go Modules + +If you are having issues when using the recent versions of NATS and Go modules such as: + +``` +go: github.com/nats-io/go-nats@v1.8.1: parsing go.mod: unexpected module path "github.com/nats-io/nats.go" +go: github.com/nats-io/go-nats-streaming@v0.5.0: parsing go.mod: unexpected module path "github.com/nats-io/stan.go" +``` + +To fix it: + +1) Update your `go.mod` using the latest tags, for example for both NATS and NATS Streaming clients: + +```ruby +module github.com/wallyqs/hello-nats-go-mod + +go 1.12 + +require ( + github.com/nats-io/nats.go v1.8.1 + github.com/nats-io/stan.go v0.5.0 +) +``` + +Or if you want to import the NATS Server v2 to embed it, notice the `/v2` after the nats-server module name. If that is not present, then go modules will not fetch it and would accidentally end up with 1.4.1 version of the server. + +```ruby +require ( + github.com/nats-io/nats-server/v2 v2.0.0 + github.com/nats-io/nats.go v1.8.1 +) +``` + +If embedding both NATS Streaming and NATS Servers: + +```ruby +require ( + github.com/nats-io/nats-server/v2 v2.0.0 // indirect + github.com/nats-io/nats-streaming-server v0.15.1 +) +``` + +2) Next, update the imports within the repo: + +```sh +find ./ -type f -name "*.go" -exec sed -i -e 's/github.com\/nats-io\/go-nats-streaming/github.com\/nats-io\/stan.go/g' {} \; + +find ./ -type f -name "*.go" -exec sed -i -e 's/github.com\/nats-io\/go-nats/github.com\/nats-io\/nats.go/g' {} \; + +find ./ -type f -name "*.go" -exec sed -i -e 's/github.com\/nats-io\/gnatsd/github.com\/nats-io\/nats-server\/v2/g' {} \; + +find ./ -type f -name "*.go" -exec sed -i -e 's/github.com\/nats-io\/nats-server/github.com\/nats-io\/nats-server\/v2/g' {} \; +``` + +3) (Recommended) Run Go fmt as the rename will affect the proper ordering of the imports + +### Gotchas when using `go get` + +If using `go get` for the client, then have to be careful with adding an extra slash at the end of the repo for example: + +``` +GO111MODULE=on go get github.com/nats-io/nats.go/@latest +GO111MODULE=on go get github.com/nats-io/nats.go/@v1.8.1 +``` + +If trying to fetch the latest version of the server with `go get`, then have to add `v2` at the end: + +``` +GO111MODULE=on go get github.com/nats-io/nats-server/v2@latest +``` + +Otherwise, `go get` will fetch the `v1.4.1` version of the server, which is also named (`gnatsd`), the previous name for nats-server. + +``` +GO111MODULE=on go get github.com/nats-io/nats-server@latest +go: finding github.com/nats-io/gnatsd/server latest +go: finding golang.org/x/crypto/bcrypt latest +go: finding golang.org/x/crypto latest +``` + +In order to use an older tag, you will also have to use the previous name (gnatsd) otherwise it would results in `go mod` parsing errors. + +``` +# OK +GO111MODULE=on go get github.com/nats-io/go-nats/@v1.7.2 + +# Not OK +GO111MODULE=on go get github.com/nats-io/nats.go/@v1.7.2 +go: finding github.com/nats-io/nats.go v1.7.2 +go: downloading github.com/nats-io/nats.go v1.7.2 +go: extracting github.com/nats-io/nats.go v1.7.2 +go: finding github.com/nats-io/go-nats/encoders/builtin latest +go: finding github.com/nats-io/go-nats/util latest +go: finding github.com/nats-io/go-nats/encoders latest +go: finding github.com/nats-io/go-nats v1.8.1 +go: downloading github.com/nats-io/go-nats v1.8.1 +go: extracting github.com/nats-io/go-nats v1.8.1 +go: github.com/nats-io/go-nats@v1.8.1: parsing go.mod: unexpected module path "github.com/nats-io/nats.go" +go: error loading module requirements +``` + +For more information you can review the original issue in [GitHub](https://github.com/nats-io/nats.go/issues/478). \ No newline at end of file diff --git a/nats-streaming-concepts/monitoring/README.md b/nats-streaming-concepts/monitoring/README.md index 4584b7d..01643e7 100644 --- a/nats-streaming-concepts/monitoring/README.md +++ b/nats-streaming-concepts/monitoring/README.md @@ -65,3 +65,35 @@ curl 127.0.0.1:8222/streaming/channelsz } ``` +## Monitoring a NATS Streaming channel with Grafana and Prometheus + +Here you can find a few examples of monitoring NATS Streaming channels: + +### Pending Messages from Channel Foo + +``` +sum(nss_chan_subs_pending_count{channel="foo"}) by (client_id) +``` + +Pending + +### Messages Per Sec Delivered on Channel Foo + +In this case, `3` is the size of the quorum of NATS Streaming Server nodes. In case of a single instance backed by a relational database we would set it to `1`: + +``` +sum(rate(nss_chan_msgs_total{channel="foo"}[5m])) by (channel) / 3 +``` + +msgs-per-sec + +### Msgs/Sec vs Pending on Channel + +Example of combining the rate of messages with the pending count to detect whether processing is getting behind: + +``` +sum(rate(nss_chan_msgs_total{channel="foo"}[5m])) by (channel) / 3 +sum(nss_chan_subs_pending_count{channel="foo"}) by (channel) / 3 +``` + +combination \ No newline at end of file From d0963d55dba35e6fadbcf718e27ff601a403ade9 Mon Sep 17 00:00:00 2001 From: ainsley Date: Mon, 30 Dec 2019 09:31:50 -0600 Subject: [PATCH 2/2] updating based on Colin's comments --- nats-server/configuration/securing_nats/auth_intro/nkey_auth.md | 2 +- nats-streaming-concepts/monitoring/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md b/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md index ec95736..4eaea92 100644 --- a/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md +++ b/nats-server/configuration/securing_nats/auth_intro/nkey_auth.md @@ -177,7 +177,7 @@ resolver_preload = { } ``` -**These two servers even though they have different auth mechanisms are able to route the accounts because the account public nkeys are the same.** +Even though they have different authorization mechanisms, these two servers are able to route account messages because they share the same NKEY. We have created at least one user, in this case with creds: diff --git a/nats-streaming-concepts/monitoring/README.md b/nats-streaming-concepts/monitoring/README.md index 01643e7..dedc2bf 100644 --- a/nats-streaming-concepts/monitoring/README.md +++ b/nats-streaming-concepts/monitoring/README.md @@ -67,7 +67,7 @@ curl 127.0.0.1:8222/streaming/channelsz ## Monitoring a NATS Streaming channel with Grafana and Prometheus -Here you can find a few examples of monitoring NATS Streaming channels: +Here you'll find examples demonstrating how to use Prometheus query expressions to monitor NATS streaming channels. ### Pending Messages from Channel Foo