mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
FIX #12 - updated nsc output to match current tooling.
This commit is contained in:
parent
84839acba3
commit
12539d5997
@ -3,12 +3,13 @@
|
||||
NATS account configurations are built using the `nsc` tool. The NSC tool allows you to:
|
||||
|
||||
- Create and edit Operators, Accounts, Users
|
||||
- Manage subscribe and publish permissions for Users
|
||||
- Add and delete Exports and Imports
|
||||
- Generate Activation tokens
|
||||
- Manage publish and subscribe permissions for Users
|
||||
- Define Service and Stream exports from an account
|
||||
- Reference Service and Streams from another account
|
||||
- Generate Activation tokens that grants access to a private service or stream
|
||||
- Generate User credential files
|
||||
- Describe Operators, Accounts, Users, and Activations
|
||||
- Push account JWTs to a server or pull account JWTs from a server
|
||||
- Push and pull account JWTs to an account JWTs server
|
||||
|
||||
## Installation
|
||||
|
||||
@ -40,4 +41,4 @@ It can be found within the tool itself:
|
||||
> nsc help
|
||||
```
|
||||
|
||||
Or an online version [here](https://nats-io.github.io/nsc).
|
||||
Or an online version [here](https://nats-io.github.io/nsc).
|
@ -1,188 +1,306 @@
|
||||
# NSC
|
||||
|
||||
NATS uses JWTs to armor the various identity and authorization artifacts. These JWTs are created with the `nsc` tool. NSC simplifies the tasks of creating and managing identities and other JWT artifacts.
|
||||
NSC allows you to manage identities. Identities take the form of _nkeys_. Nkeys are a public-key signature system based on Ed25519 for the NATS ecosystem.
|
||||
|
||||
The nkey identities are associated with NATS configuration in the form of a Jason Web Token (JWT). These JWT are digitally signed by the private key of an issuer forming a chain of trust. The `nsc` tool creates and manages these identities and allows you to deploy them to a JWT account server, which in turn makes the configurations available to nats-servers.
|
||||
|
||||
There’s a logical hierarchy to the entities:
|
||||
|
||||
- `Operators` are responsible for running nats-servers, and signing account JWTs that set the limits on what an account can do, such as the number of connections, data limits, etc.
|
||||
- `Operators` are responsible for running nats-servers, and issue account JWTs. Operators set the limits on what an account can do, such as the number of connections, data limits, etc.
|
||||
|
||||
- `Accounts` are responsible for issuing user JWTs, and for declaring what subjects can be exported to other accounts, and what subjects they import from other accounts and what the local subjects for those imports are.
|
||||
- `Accounts` are responsible for issuing user JWTs. An account defines streams and services that can be exported to other accounts. Likewise, they import streams and services from other accounts.
|
||||
|
||||
- `Users` are issued by an account, and encode limits regarding usage and authorization over the subject space.
|
||||
- `Users` are issued by an account, and encode limits regarding usage and authorization over the account's subject space.
|
||||
|
||||
NSC allows you to create, edit, delete these entities, and will be central to all account based configuration.
|
||||
NSC allows you to create, edit, delete these entities, and will be central to all account-based configuration.
|
||||
|
||||
In this guide, you’ll run end-to-end on some of the configuration scenarios:
|
||||
|
||||
- generate JWTs
|
||||
- make JWTs accessible to a nats-server
|
||||
- configure a nats-server to use JWTs
|
||||
- Generate NKey identities and their associated JWTs
|
||||
- Make JWTs accessible to a nats-server
|
||||
- Configure a nats-server to use JWTs
|
||||
|
||||
Let’s run through the process of creating some identities and JWTs and work through the process.
|
||||
|
||||
## The NSC Environment
|
||||
## Creating an Operator, Account and User
|
||||
|
||||
By default JWTs are written to ~/.nsc and secrets to ~/.nkeys. nsc also tracks a value called the "stores directory". This directory contains the operators you are currently working with. By default the stores directory is ~/.nsc/nats but you can switch it to another folder if you want to separate JWTs for use in a revision control system, or co-locate them with a project, etc..
|
||||
Let’s create an operator called `O`:
|
||||
|
||||
To see the current NSC environment use the command `nsc env`:
|
||||
|
||||
```text
|
||||
> nsc env
|
||||
╭──────────────────────────────────────────╮
|
||||
│ NSC Environment │
|
||||
├──────────────────┬─────┬─────────────────┤
|
||||
│ Setting │ Set │ Effective Value │
|
||||
├──────────────────┼─────┼─────────────────┤
|
||||
│ $NKEYS_PATH │ No │ ~/.nkeys │
|
||||
│ $NSC_HOME │ No │ ~/.nsc │
|
||||
│ Config │ │ ~/.nsc/nsc.json │
|
||||
├──────────────────┼─────┼─────────────────┤
|
||||
│ Stores Dir │ │ ~/.nsc/nats │
|
||||
│ Default Operator │ │ │
|
||||
│ Default Account │ │ │
|
||||
│ Default Cluster │ │ │
|
||||
╰──────────────────┴─────┴─────────────────╯
|
||||
```bash
|
||||
> nsc add operator O
|
||||
[ OK ] generated and stored operator key "OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG"
|
||||
[ OK ] added operator "O"
|
||||
```
|
||||
|
||||
As you can see there is a setting for the nkeys folder and the nsc home. By default you’ll see that generated secrets are stored in `~/.nkeys`, and configurations in `~/.nsc/nats`. All operations are assumed to be in a context of the current operator and current account. When working with multiple operators and accounts you may need to set the current one. You can easily do so by issuing the `nsc env` and provide flags to set the current operator or account. See `nsc env —help` for more details.
|
||||
With the above incantation, the tool generated an NKEY for the operator, stored the private key safely in it's keystore.
|
||||
|
||||
You can easily change the home and keys locations by setting `NSC_HOME` and `NKEYS_PATH` respectively in your environment to your desired locations. The environment itself is stored in the `NSC_HOME`. Operator folders are in the stores directory which can be inside `NSC_HOME` or external to it.
|
||||
Lets add a service URL to the operator. Service URLs specify where the nats-server is listening. Tooling such as `nsc` can make use of that configuration:
|
||||
|
||||
> The $NKEYS_PATH stores secrets. Since nkeys relies on cryptographic signatures to prove identity, anyone with access to your private keys will be able to assume your identity. With that said, treat them as secrets and guard them carefully.
|
||||
|
||||
## Creating an Operator
|
||||
|
||||
Let’s create an operator called `Test`:
|
||||
|
||||
```text
|
||||
> nsc add operator -n Test
|
||||
Generated operator key - private key stored “~/.nkeys/Test/Test.nk”
|
||||
Success! - added operator "Test"
|
||||
```bash
|
||||
> nsc edit operator --service-url nats://localhost:4222
|
||||
[ OK ] added service url "nats://localhost:4222"
|
||||
[ OK ] edited operator "O"
|
||||
```
|
||||
|
||||
With the above incantation, the tool generated an NKEY for the operator, stored the private key safely in `~/.nkeys/Test/Test.nk`. The file contains a single line, with the seed value for the NKEY.
|
||||
|
||||
> You can tell the key is a seed if it starts with the letter `S`. The type of the key is the second letter - an `O`, `A` or `U` for _Operator_, _Account_ or _User_. If the key does not start with an `S` you have instead a public key.
|
||||
Creating an account is just as easy:
|
||||
|
||||
The tool also created a JWT with all default settings for the operator test, and stored it in `~/.nsc/nats/Test/Test.jwt`. The `~/.nsc/nats/Test` directory will also contain a directory where accounts related to this operator will live.
|
||||
```bash
|
||||
> nsc add account A
|
||||
[ OK ] generated and stored account key "ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE"
|
||||
[ OK ] added account "A"
|
||||
```
|
||||
|
||||
You can view the JWT by entering the command:
|
||||
As expected, the tool generated an NKEY representing the account, and stored the private key safely in the keystore.
|
||||
|
||||
```text
|
||||
Finally, let's create a user:
|
||||
|
||||
```bash
|
||||
> nsc add user U
|
||||
[ OK ] generated and stored user key "UDBD5FNQPSLIO6CDMIS5D4EBNFKYWVDNULQTFTUZJXWFNYLGFF52VZN7"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O/A/U.creds"
|
||||
[ OK ] added user "U" to account "A"
|
||||
```
|
||||
|
||||
As expected, the tool generated an NKEY representing the user, and stored the private key safely in the keystore. In addition, the tool generated a _credentials_ file. A credentials file contains the JWT for the user and the private key for the user. Credential files are used by nats-clients to identify themselves to the system. The client will extract and present the JWT to the nats-server and use the private key to verify its identity.
|
||||
|
||||
|
||||
### NSC Assets
|
||||
|
||||
NSC manages three different directories:
|
||||
|
||||
- The nsc home directory which stores nsc related data. By default nsc home lives in `~/.nsc` and can be changed via the `$NSC_HOME` environment variable.
|
||||
- An _nkeys_ directory, which stores all the private keys. This directory by default lives in `~/.nkeys` and can be changed via the `$NKEYS_PATH` environment variable. The contents of the nkeys directory should be treated as secrets.
|
||||
- A _stores_ directory, which contains JWTs representing the various entities. This directory lives in `$NSC_HOME/nats`, and can be changed using the command `nsc env -s <dir>`. The stores directory can stored under revision control. The JWTs themselves do not contain any secrets.
|
||||
|
||||
#### The NSC Stores Directory
|
||||
|
||||
The stores directory contains a number of directories. Each named by an operator in question, which in turn contains all accounts and users:
|
||||
|
||||
```bash
|
||||
tree ~/.nsc/nats
|
||||
/Users/aricart/.nsc/nats
|
||||
└── O
|
||||
├── O.jwt
|
||||
└── accounts
|
||||
└── A
|
||||
├── A.jwt
|
||||
└── users
|
||||
└── U.jwt
|
||||
```
|
||||
|
||||
These JWTs are the same artifacts that nats-servers will use to validate if an account is valid and its limits as well as the JWTs that are presented by clients when they connect to the nats-server.
|
||||
|
||||
#### The NKEYS Directory
|
||||
|
||||
The nkeys directory contains all the private keys and credential files. As mentioned before, care must be taken to keep these files secure.
|
||||
|
||||
The structure keys directory is machine friendly. All keys are sharded by their kind `O` for operators, `A` for accounts, `U` for users. These prefixes are also part of the public key. The second and third letters in the public key are used to create directories where other like-named keys are stored.
|
||||
|
||||
```
|
||||
tree ~/.nkeys
|
||||
/Users/aricart/.nkeys
|
||||
├── creds
|
||||
│ └── O
|
||||
│ └── A
|
||||
│ └── U.creds
|
||||
└── keys
|
||||
├── A
|
||||
│ └── DE
|
||||
│ └── ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE.nk
|
||||
├── O
|
||||
│ └── AF
|
||||
│ └── OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG.nk
|
||||
└── U
|
||||
└── DB
|
||||
└── UDBD5FNQPSLIO6CDMIS5D4EBNFKYWVDNULQTFTUZJXWFNYLGFF52VZN7.nk
|
||||
```
|
||||
|
||||
The `nk` files themselves are named after the complete public key, and store a single string - the private key in question:
|
||||
```bash
|
||||
cat ~/.nkeys/keys/U/DB/UDBD5FNQPSLIO6CDMIS5D4EBNFKYWVDNULQTFTUZJXWFNYLGFF52VZN7.nk
|
||||
SUAG35IAY2EF5DOZRV6MUSOFDGJ6O2BQCZHSRPLIK6J3GVCX366BFAYSNA
|
||||
```
|
||||
|
||||
The private keys are encoded into a string, and always begin with an `S` for _seed_. The second letter starts with the type of key in question. `O` for operators, `A` for accounts, `U` for users.
|
||||
|
||||
In addition to containing keys, the nkeys directory contains a `creds` directory. This directory is organized in a way friendly to humans. It stores user credential files or `creds` files for short. A credentials file contains a copy of the user JWT and the private key for the user. These files are used by nats-clients to connect to a nats-server:
|
||||
|
||||
|
||||
```bash
|
||||
> cat ~/.nkeys/creds/O/A/U.creds
|
||||
-----BEGIN NATS USER JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJTVERPU0NJSzNNUFRQNkxXSjdMMjVNRFRRNEFPU0cyU1lZRFpSQ01GQjZFUzIyQ1FGTk9BIiwiaWF0IjoxNTc1NDY5Mzg4LCJpc3MiOiJBREVUUFQzNldCSUJVS00zSUJDVk00QTVZVVNEWEZFSlBXNE02R0dWQllDQlc3UlJORlRWNU5HRSIsIm5hbWUiOiJVIiwic3ViIjoiVURCRDVGTlFQU0xJTzZDRE1JUzVENEVCTkZLWVdWRE5VTFFURlRVWkpYV0ZOWUxHRkY1MlZaTjciLCJ0eXBlIjoidXNlciIsIm5hdHMiOnsicHViIjp7fSwic3ViIjp7fX19.xRzBaOwJZ7RJNVSpputYvG2U6a0QTfh-Srs47Z9dIfVk3JHVg-znPPWxJ5BAYvkW8Fa1R1S7O5WR_ZnIob9aDw
|
||||
------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-----
|
||||
SUAG35IAY2EF5DOZRV6MUSOFDGJ6O2BQCZHSRPLIK6J3GVCX366BFAYSNA
|
||||
------END USER NKEY SEED------
|
||||
|
||||
*************************************************************
|
||||
```
|
||||
|
||||
### Listing Keys
|
||||
|
||||
You can list the current entities you are working with by doing:
|
||||
|
||||
```bash
|
||||
nsc list keys
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Keys │
|
||||
├────────┬──────────────────────────────────────────────────────────┬─────────────┬────────┤
|
||||
│ Entity │ Key │ Signing Key │ Stored │
|
||||
├────────┼──────────────────────────────────────────────────────────┼─────────────┼────────┤
|
||||
│ O │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │ │ * │
|
||||
│ A │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │ │ * │
|
||||
│ U │ UDBD5FNQPSLIO6CDMIS5D4EBNFKYWVDNULQTFTUZJXWFNYLGFF52VZN7 │ │ * │
|
||||
╰────────┴──────────────────────────────────────────────────────────┴─────────────┴────────╯
|
||||
```
|
||||
|
||||
The different entity names are listed along with their public key, and weather the key is stored. Stored keys are those that are found in the nkeys directory.
|
||||
|
||||
In some cases you may want to view the private keys:
|
||||
|
||||
|
||||
```
|
||||
> nsc list keys --show-seeds
|
||||
╭───────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Seeds Keys │
|
||||
├────────┬────────────────────────────────────────────────────────────┬─────────────┤
|
||||
│ Entity │ Private Key │ Signing Key │
|
||||
├────────┼────────────────────────────────────────────────────────────┼─────────────┤
|
||||
│ O │ SOAFQM2X42LW26R6WRSC45AUVUEUQTITYUF7UBGG6MMAB4X54AS6YBBY7Q │ │
|
||||
│ A │ SAAJBXIGQL5IKNVTZMFZSNRSSAQGHQJWVOXIIPCXWTXCRWIQIXCI67MBYE │ │
|
||||
│ U │ SUAG35IAY2EF5DOZRV6MUSOFDGJ6O2BQCZHSRPLIK6J3GVCX366BFAYSNA │ │
|
||||
╰────────┴────────────────────────────────────────────────────────────┴─────────────╯
|
||||
[ ! ] seed is not stored
|
||||
[ERR] error reading seed
|
||||
```
|
||||
|
||||
If you don't have the seed (perhaps you don't control the operator), nsc will decorate the row with a `!`.
|
||||
If you have more than one account, you can show them all by specifying the `--all` flag.
|
||||
|
||||
## The Operator JWT
|
||||
|
||||
You can view a human readable version of the JWT by using `nsc`:
|
||||
|
||||
```bash
|
||||
> nsc describe operator
|
||||
╭───────────────────────────────────────╮
|
||||
│ Operator Details │
|
||||
├─────────────┬─────────────────────────┤
|
||||
│ Name │ Test │
|
||||
│ Operator ID │ OCEWHXFL3I5I │
|
||||
│ Issuer ID │ OCEWHXFL3I5I │
|
||||
│ Issued │ 2019-06-11 16:25:37 UTC │
|
||||
│ Expires │ │
|
||||
╰─────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Operator Details │
|
||||
├───────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ O │
|
||||
│ Operator ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 14:12:52 UTC │
|
||||
│ Expires │ │
|
||||
│ Operator Service URLs │ nats://localhost:4222 │
|
||||
╰───────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Note that the Operator ID is truncated to simplify the output, to get the full ID, do:
|
||||
|
||||
```text
|
||||
> nsc describe operator -W
|
||||
╭────────────────────────────────────────────────────────────────────────╮
|
||||
│ Operator Details │
|
||||
├─────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ Test │
|
||||
│ Operator ID │ OCEWHXFL3I5IWPFK2674IUQTFHRZXHI52S2DKQIQJXRXC6P6GWSINZ3H │
|
||||
│ Issuer ID │ OCEWHXFL3I5IWPFK2674IUQTFHRZXHI52S2DKQIQJXRXC6P6GWSINZ3H │
|
||||
│ Issued │ 2019-06-11 16:25:37 UTC │
|
||||
│ Expires │ │
|
||||
╰─────────────┴──────────────────────────────────────────────────────────╯
|
||||
Since the operator JWT is just a JWT you can use other tools, such as jwt.io to decode a JWT an inspect it's contents. All jwts have a header, payload, and signature:
|
||||
```json
|
||||
{
|
||||
"typ": "jwt",
|
||||
"alg": "ed25519"
|
||||
}
|
||||
{
|
||||
"jti": "ZP2X3T2R57SLXD2U5J3OLLYIVW2LFBMTXRPMMGISQ5OF7LANUQPQ",
|
||||
"iat": 1575468772,
|
||||
"iss": "OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG",
|
||||
"name": "O",
|
||||
"sub": "OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG",
|
||||
"type": "operator",
|
||||
"nats": {
|
||||
"operator_service_urls": [
|
||||
"nats://localhost:4222"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The operator JWT contains two important URLs. The `account-jwt-server-url` is used by `nsc` when you want to push JWTs to an account server. The `service-url`s are used by `nsc` when you run the tool commands, like `nsc tool pub`.
|
||||
For NATS JWTs all well use the `algorithm` ed25519 for signature.
|
||||
The payload will list different things, on our basically empty operator we only standard JWT `claim` fields:
|
||||
|
||||
With an operator, we are ready to create our first account.
|
||||
`jti` - a jwt id
|
||||
`iat` - the timestamp when the JWT was issued in UNIX time
|
||||
`iss` - the issuer of the JWT, in this case the operator's public key
|
||||
`sub` - the subject or identity represented by the JWT, in this case the same operator
|
||||
`type` - since this is an operator JWT, `operator` is the type
|
||||
|
||||
## Creating an Account
|
||||
NATS specific is the `nats` object, which is where we add NATS specific JWT configuration to the JWT claim.
|
||||
|
||||
Let’s create an account called `TestAccount`:
|
||||
Because the issuer and subject are one and the same, this JWT is self-signed.
|
||||
|
||||
```
|
||||
> nsc add account -n TestAccount
|
||||
Generated account key - private key stored “~/.nkeys/Test/accounts/TestAccount/TestAccount.nk"
|
||||
Success! - added account "TestAccount"
|
||||
### The Account JWT
|
||||
|
||||
Again we can inspect the account:
|
||||
|
||||
```bash
|
||||
> nsc describe account
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 14:21:05 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
As we did with the operator, we can describe the account:
|
||||
### The User JWT
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭─────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬─────────────────────────┤
|
||||
│ Name │ TestAccount │
|
||||
│ Account ID │ ADM7UGD4FV52 │
|
||||
│ Issuer ID │ OCEWHXFL3I5I │
|
||||
│ Issued │ 2019-06-11 16:25:57 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴─────────────────────────╯
|
||||
```
|
||||
Finally the user JWT:
|
||||
|
||||
Again, specifying the `-W` flag will print the complete account ID (the public key identifying the account).
|
||||
|
||||
Note that the issuer for the account is the ID for the operator (the public key identifying the operator).
|
||||
|
||||
Now we are ready to add a user.
|
||||
|
||||
## Creating a User
|
||||
|
||||
Let’s add a user named ‘TestUser’:
|
||||
|
||||
```text
|
||||
> nsc add user -n TestUser
|
||||
Generated user key - private key stored "~/.nkeys/Test/accounts/TestAccount/users/TestUser.nk"
|
||||
Generated user creds file "~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds"
|
||||
Success! - added user "TestUser" to "TestAccount"
|
||||
```
|
||||
|
||||
Note that when we added the user, we got a message telling us about a `.creds` file being created. The `.creds` file contains the JWT describing the user, and the private (seed) key for the user. This file is formatted in a special way for use by nats client libraries. Client libraries can extract the JWT and seed key, and connect to a server expecting JWT authentication, provide the JWT and use the private key to sign the nonce to verify its identity.
|
||||
|
||||
And let’s describe it:
|
||||
|
||||
```text
|
||||
```bash
|
||||
> nsc describe user
|
||||
╭───────────────────────────────────────────╮
|
||||
│ User │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Name │ TestUser │
|
||||
│ User ID │ UBV36EUP2B3Q │
|
||||
│ Issuer ID │ ADM7UGD4FV52 │
|
||||
│ Issued │ 2019-06-11 16:26:22 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
╭─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ User │
|
||||
├──────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ U │
|
||||
│ User ID │ UDBD5FNQPSLIO6CDMIS5D4EBNFKYWVDNULQTFTUZJXWFNYLGFF52VZN7 │
|
||||
│ Issuer ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issued │ 2019-12-04 14:23:08 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Response Permissions │ Not Set │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰──────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Let’s put all of this together, and create a simple server configuration that accepts sessions from TestUser.
|
||||
The user id is the public key for the user, the issuer is the account. This user can publish and subscribe to anything, as no limits are set.
|
||||
|
||||
When a user connects to a nats-server, it presents it's user JWT and signs an nonce using its private key. The server verifies the user is who they say they are by validating that the nonce was signed using the private key associated with the public key representing the identify of the user. Next, the server fetches the issuer account and validates that the account was issued by a trusted operator completing the chain of trust verification.
|
||||
|
||||
|
||||
Let’s put all of this together, and create a simple server configuration that accepts sessions from `U`.
|
||||
|
||||
## Account Server Configuration
|
||||
|
||||
To configure a server to use accounts you need an _account resolver_. An account resolver exposes a URL where a nats-server can query for JWTs belonging to an account.
|
||||
To configure a server to use accounts, you need an _account resolver_. An account resolver exposes a URL where a nats-server can query for JWTs belonging to an account.
|
||||
|
||||
A simple built-in resolver is the `MEMORY` resolver which simply statically maps account public keys to an account JWT in the server’s configuration file. It is somewhat easier to configure because it doesn’t require another moving part, but fails to provide the needed experience of setting up an account server. Let’s setup an _Account Server_.
|
||||
A simple built-in resolver is the `MEMORY` resolver, which statically maps account public keys to an account JWT in the server’s configuration file. It is somewhat easier to configure because it doesn’t require another moving part, but fails to provide the needed experience of setting up an account server. Let’s set up an _Account Server_.
|
||||
|
||||
Installing the Account Server
|
||||
|
||||
@ -193,12 +311,12 @@ Installing the Account Server
|
||||
The account server has options to enable you to use an nsc directory directly. Let’s start one:
|
||||
|
||||
```text
|
||||
> nats-account-server -nsc ~/.nsc/nats/Test
|
||||
> nats-account-server -nsc ~/.nsc/nats/O
|
||||
```
|
||||
|
||||
Above we pointed the account server to our nsc data directory (more specifically to the `Test` operator that we created earlier). By default, the server listens on the localhost at port 9090.
|
||||
Above, we pointed the account server to our nsc data directory (more specifically to the `O` operator that we created earlier). By default, the server listens on the localhost at port 9090.
|
||||
|
||||
You can also run the account server with a data directory that is not your nsc folder. In this mode you can upload account JWTs to the server. See the help for `nsc push` for more information about how to push JWTs to the account server.
|
||||
You can also run the account server with a data directory that is not your nsc folder. In this mode, you can upload account JWTs to the server. See the help for `nsc push` for more information about how to push JWTs to the account server.
|
||||
|
||||
We are now ready to configure the nats-server.
|
||||
|
||||
@ -213,11 +331,11 @@ If you don’t have a nats-server installed, let’s do that now:
|
||||
Let’s create a configuration that references our operator JWT and the nats-account-server as a resolver:
|
||||
|
||||
```yaml
|
||||
operator: /Users/synadia/.nsc/nats/Test/Test.jwt
|
||||
operator: $HOME/.nsc/nats/O/O.jwt
|
||||
resolver: URL(http://localhost:9090/jwt/v1/accounts/)
|
||||
```
|
||||
|
||||
At minimum the server requires the `operator` JWT, which we have pointed at directly, and a resolver. The resolver has two types `MEM` and `URL`. We are interested in the `URL` since we want the nats-server to talk to the account server. Note we put the URL of the server with the path `/jwt/v1/accounts`. Currently this is where the account server expects requests for account information.
|
||||
At minimum, the server requires the `operator` JWT, which we have pointed at directly, and a resolver. The resolver has two options `MEM` and `URL`. We are interested in the `URL` since we want the nats-server to talk to the account server. Note we put the URL of the server with the path `/jwt/v1/accounts`. Currently, this is where the account server expects requests for account information.
|
||||
|
||||
## Client Testing
|
||||
|
||||
@ -232,14 +350,14 @@ Let’s install some tooling:
|
||||
Create a subscriber:
|
||||
|
||||
```text
|
||||
nats-sub -creds ~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds ">"
|
||||
nats-sub -creds ~/.nkeys/creds/O/A/U.creds ">"
|
||||
Listening on [>]
|
||||
```
|
||||
|
||||
Publish a message:
|
||||
|
||||
```text
|
||||
nats-pub -creds ~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds hello NATS
|
||||
nats-pub -creds ~/.nkeys/creds/O/A/U.creds hello NATS
|
||||
Published [hello] : 'NATS'
|
||||
```
|
||||
|
||||
@ -249,68 +367,116 @@ Subscriber shows:
|
||||
[#1] Received on [hello]: ’NATS’
|
||||
```
|
||||
|
||||
|
||||
### NSC Embeds NATS tooling
|
||||
|
||||
To make it easier to work, you can use the nats clients built right into NSC. These tools know how to find the credential files in the keyring.
|
||||
For convenience, the tools are aliased to `sub`, `pub`, `req`, `reply`:
|
||||
|
||||
```bash
|
||||
nsc sub --user U ">"
|
||||
...
|
||||
|
||||
nsc pub --user U hello NATS
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
See `nsc tool -h` for more detailed information.
|
||||
|
||||
|
||||
## User Authorization
|
||||
|
||||
User authorization, as expected, also works with JWT authentication. With `nsc` you can specify authorization for specific subjects to which the user can or cannot publish or subscribe. By default a user doesn't have any limits on the subjects that it can publish or subscribe to. Any message stream or message published in the account is subscribable by the user. The user can also publish to any subject or imported service. Note that authorization, if configured, must be specified on a per user basis.
|
||||
|
||||
When specifying limits it is important to remember that clients by default use generated "inboxes" to allow publish requests. When specifying subscribe and publish permissions, you need to enable clients to subscribe and publish to `_INBOX.>`. You can further restrict it, but you'll be responsible for segmenting the subject space so as to not break request/reply communications between clients.
|
||||
|
||||
Let's say you have a service that your account clients can make requests to under `req.a`. To enable the service to receive and respond to requests it requires permissions to subscribe to `req.a` and publish permissions under `_INBOX.>`:
|
||||
Let's say you have a service that your account clients can make requests to under `q`. To enable the service to receive and respond to requests it requires permissions to subscribe to `q` and publish permissions under `_INBOX.>`:
|
||||
|
||||
```text
|
||||
> nsc add user --name TestService --allow-pub "_INBOX.>" --allow-sub "req.a"
|
||||
Generated user key - private key stored "~/.nkeys/Test/accounts/TestAccount/users/TestService.nk"
|
||||
Generated user creds file "~/.nkeys/Test/accounts/TestAccount/users/TestService.creds"
|
||||
Success! - added user "TestService" to "TestAccount"
|
||||
```bash
|
||||
> nsc add user s --allow-pub "_INBOX.>" --allow-sub q
|
||||
[ OK ] generated and stored user key "UDJETJR7SVL7JSSO6G6XXKFKDETYSDCMLNKIH2U2ABS2M4F3OBMUFM4A"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O/A/s.creds"
|
||||
[ OK ] added user "s" to account "A"
|
||||
|
||||
> nsc describe user --name TestService
|
||||
╭───────────────────────────────────────────╮
|
||||
│ User │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Name │ TestService │
|
||||
│ User ID │ UCAYGJXTF5WO │
|
||||
│ Issuer ID │ ADM7UGD4FV52 │
|
||||
│ Issued │ 2019-06-11 16:41:03 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Pub Allow │ _INBOX.> │
|
||||
│ Sub Allow │ req.a │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
> nsc describe user s
|
||||
╭─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ User │
|
||||
├──────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ s │
|
||||
│ User ID │ UDJETJR7SVL7JSSO6G6XXKFKDETYSDCMLNKIH2U2ABS2M4F3OBMUFM4A │
|
||||
│ Issuer ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issued │ 2019-12-04 15:41:45 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Pub Allow │ _INBOX.> │
|
||||
│ Sub Allow │ q │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Response Permissions │ Not Set │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰──────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
As you can see this client is not limited to publishing responses to `_INBOX.>` addresses, and to subscribing to the service's request subject.
|
||||
|
||||
Similarly, we can limit a client:
|
||||
|
||||
```text
|
||||
> nsc add user --name TestClient --allow-pub "req.a" --allow-sub "_INBOX.>"
|
||||
Generated user key - private key stored "~/.nkeys/Test/accounts/TestAccount/users/TestClient.nk"
|
||||
Generated user creds file "~/.nkeys/Test/accounts/TestAccount/users/TestClient.creds"
|
||||
Success! - added user "TestClient" to "TestAccount"
|
||||
```bash
|
||||
> nsc add user c --allow-pub q --allow-sub "_INBOX.>"
|
||||
[ OK ] generated and stored user key "UDOJHZKLOQJHDVBCPTR3AATK76HZMCIFBSEJKRSSB2ANO6F3PGNAYYOH"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O/A/c.creds"
|
||||
[ OK ] added user "c" to account "A"
|
||||
|
||||
> nsc describe user --name TestClient
|
||||
╭───────────────────────────────────────────╮
|
||||
│ User │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Name │ TestClient │
|
||||
│ User ID │ UDJ3LCVNTYXL │
|
||||
│ Issuer ID │ ADM7UGD4FV52 │
|
||||
│ Issued │ 2019-06-11 16:43:46 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Pub Allow │ req.a │
|
||||
│ Sub Allow │ _INBOX.> │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
> nsc describe user c
|
||||
╭─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ User │
|
||||
├──────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ c │
|
||||
│ User ID │ UDOJHZKLOQJHDVBCPTR3AATK76HZMCIFBSEJKRSSB2ANO6F3PGNAYYOH │
|
||||
│ Issuer ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issued │ 2019-12-04 15:44:17 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Pub Allow │ q │
|
||||
│ Sub Allow │ _INBOX.> │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Response Permissions │ Not Set │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰──────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
The client has the opposite permissions of the service. It can publish on the request subject `req.a`, and receive replies on an inbox.
|
||||
The client has the opposite permissions of the service. It can publish on the request subject `q`, and receive replies on an inbox.
|
||||
|
||||
|
||||
## The NSC Environment
|
||||
|
||||
As your projects become more involved, you may work with one or more accounts. Nsc tracks your current operator and account. If you are not in a directory containing an operator, account or user, it will use the last operator/account context.
|
||||
|
||||
To view your current environment:
|
||||
|
||||
```bash
|
||||
> nsc env
|
||||
╭──────────────────────────────────────────╮
|
||||
│ NSC Environment │
|
||||
├──────────────────┬─────┬─────────────────┤
|
||||
│ Setting │ Set │ Effective Value │
|
||||
├──────────────────┼─────┼─────────────────┤
|
||||
│ $NKEYS_PATH │ No │ ~/.nkeys │
|
||||
│ $NSC_HOME │ No │ ~/.nsc │
|
||||
│ Config │ │ ~/.nsc/nsc.json │
|
||||
├──────────────────┼─────┼─────────────────┤
|
||||
│ Stores Dir │ │ ~/.nsc/nats │
|
||||
│ Default Operator │ │ O │
|
||||
│ Default Account │ │ A │
|
||||
╰──────────────────┴─────┴─────────────────╯
|
||||
```
|
||||
|
||||
If you have multiple accounts, you can `nsc env --account <account name>` to set the account as the current default. If you have defined `NKEYS_PATH` or `NSC_HOME` in the environment, you'll also see their current effective values. Finally, if you want to set the stores directory to anything else other than the default, you can do `nsc env --store <dir containing an operator>`. If you have multiple accounts, you can try having multiple terminals, each in a directory for a different account.
|
||||
|
@ -6,42 +6,43 @@ To share services that other accounts can reach via request reply, you have to _
|
||||
|
||||
To add a service to your account:
|
||||
|
||||
```text
|
||||
> nsc add export --name "srv" --subject "help" --service
|
||||
Success! - added public service export "srv"
|
||||
```bash
|
||||
> nsc add export --name help --subject help --service
|
||||
[ OK ] added public service export "help"
|
||||
```
|
||||
|
||||
To review the service export:
|
||||
|
||||
```text
|
||||
```bash
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ TestAccount │
|
||||
│ Account ID │ AC7PO3MREV26 │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-29 14:20:13 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 18:20:42 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭───────────────────────────────────╮
|
||||
│ Exports │
|
||||
├──────┬─────────┬─────────┬────────┤
|
||||
│ Name │ Type │ Subject │ Public │
|
||||
├──────┼─────────┼─────────┼────────┤
|
||||
│ help │ Service │ help │ Yes │
|
||||
╰──────┴─────────┴─────────┴────────╯
|
||||
╭────────────────────────────────────────────────────────────╮
|
||||
│ Exports │
|
||||
├──────┬─────────┬─────────┬────────┬─────────────┬──────────┤
|
||||
│ Name │ Type │ Subject │ Public │ Revocations │ Tracking │
|
||||
├──────┼─────────┼─────────┼────────┼─────────────┼──────────┤
|
||||
│ help │ Service │ help │ Yes │ 0 │ - │
|
||||
╰──────┴─────────┴─────────┴────────┴─────────────┴──────────╯
|
||||
```
|
||||
|
||||
## Importing a Service
|
||||
@ -55,61 +56,81 @@ Importing a service enables you to send requests to the remote _Account_. To imp
|
||||
|
||||
To learn how to inspect a JWT from an account server, [check this article](../nas/inspecting_jwts.md).
|
||||
|
||||
First lets create a second account to import the service into:
|
||||
|
||||
```text
|
||||
> nsc add import --src-account AC7PO3MREV26U3LFZFP5BN3HAI32X3PKLBRVMPAETLEHWPQEUG7EJY4H --remote-subject help --service
|
||||
Success! - added service import "help"
|
||||
```bash
|
||||
> nsc add account B
|
||||
[ OK ] generated and stored account key "AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
[ OK ] added account "B"
|
||||
|
||||
|
||||
> nsc add import --src-account ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE --remote-subject help --service
|
||||
[ OK ] added service import "help"
|
||||
```
|
||||
|
||||
Verifying our work:
|
||||
|
||||
```text
|
||||
```bash
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ AccountB │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-29 14:37:49 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ B │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 20:12:42 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭─────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├─────────┬─────────┬─────────┬─────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local │ Expires │ From Account │ Public │
|
||||
├─────────┼─────────┼─────────┼─────────┼─────────┼──────────────┼────────┤
|
||||
│ help │ Service │ help │ help │ │ AC7PO3MREV26 │ Yes │
|
||||
╰─────────┴─────────┴─────────┴─────────┴─────────┴──────────────┴────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├──────┬─────────┬────────┬──────────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local/Prefix │ Expires │ From Account │ Public │
|
||||
├──────┼─────────┼────────┼──────────────┼─────────┼──────────────┼────────┤
|
||||
│ help │ Service │ help │ help │ │ A │ Yes │
|
||||
╰──────┴─────────┴────────┴──────────────┴─────────┴──────────────┴────────╯
|
||||
```
|
||||
|
||||
Let's also add user to make requests from the service:
|
||||
|
||||
```bash
|
||||
> nsc add user b
|
||||
[ OK ] generated and stored user key "UDKNTNEL5YD66U2FZZ2B3WX2PLJFKEFHAPJ3NWJBFF44PT76Y2RAVFVE"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O/B/b.creds"
|
||||
[ OK ] added user "b" to account "B"
|
||||
```
|
||||
|
||||
|
||||
### Testing the Service
|
||||
|
||||
To test the service, we can install the `nats-req` and `nats-rply` tools:
|
||||
|
||||
Set up a process to handle the request:
|
||||
Set up a process to handle the request. This process will run from account 'A' using user 'U':
|
||||
```text
|
||||
> go get github.com/nats-io/nats.go/examples/nats-rply
|
||||
|
||||
> nats-rply -creds ~/.nkeys/Test/accounts/AccountB/users/userb.creds "help" "I will help"
|
||||
> nats-rply -creds ~/.nkeys/creds/O/A/U.creds help "I will help"
|
||||
Listening on [help]
|
||||
|
||||
# Remember you can also do:
|
||||
nsc reply --account A --user U help "I will help"
|
||||
```
|
||||
|
||||
Send the request:
|
||||
```text
|
||||
> go get github.com/nats-io/nats.go/examples/nats-req
|
||||
> nats-req -creds ~/.nkeys/Test/accounts/AccountB/users/userb.creds help me
|
||||
> nats-req -creds ~/.nkeys/creds/O/B/b.creds help me
|
||||
Published [help] : 'me'
|
||||
```
|
||||
|
||||
@ -123,84 +144,101 @@ And the response is received by the requestor:
|
||||
Received [_INBOX.v6KAX0v1bu87k49hbg3dgn.StIGJF0D] : 'I will help'
|
||||
```
|
||||
|
||||
## Securing Services
|
||||
Or more simply:
|
||||
|
||||
If you want to create a service that is only accessible to accounts you designate you can create a _private_ service. The export will be visible in your account, but subscribing accounts will require an authorization token that must be created by you and generated specifically for the requesting account.
|
||||
```bash
|
||||
> nsc reply --account A --user U help "I will help"
|
||||
listening on [help]
|
||||
...
|
||||
|
||||
Let’s create an account and user for our stream client:
|
||||
```text
|
||||
> nsc add account --name AccountB
|
||||
Generated account key - private key stored “~/.nkeys/Test/accounts/AccountB/AccountB"
|
||||
Success! - added account "AccountB"
|
||||
|
||||
> nsc add user --name userb
|
||||
Generated user key - private key stored "~/.nkeys/Test/accounts/AccountB/users/userb”
|
||||
Generated user creds file "~/.nkeys/Test/accounts/AccountB/users/userb.creds"
|
||||
Success! - added user “userb” to “AccountB”
|
||||
> nsc req --account B --user b help me
|
||||
published request: [help] : 'me'
|
||||
received reply: [_INBOX.GCJltVq1wRSb5FoJrJ6SE9.w8utbBXR] : 'I will help'
|
||||
```
|
||||
|
||||
The authorization token is simply a JWT signed by your account where you authorize the client account to import your service.
|
||||
## Securing Services
|
||||
|
||||
If you want to create a service that is only accessible to accounts you designate you can create a _private_ service. The export will be visible in your account, but subscribing accounts will require an authorization token that must be created by you and generated specifically for the requesting account. The authorization token is simply a JWT signed by your account where you authorize the client account to import your service.
|
||||
|
||||
### Creating a Private Service Export
|
||||
|
||||
```text
|
||||
> nsc add export --name phelp --subject "help.>" --private --service
|
||||
Success! - added private service export "phelp"
|
||||
> nsc add export --subject "private.help.*" --private --service --account A
|
||||
[ OK ] added private service export "private.help.*"
|
||||
```
|
||||
|
||||
As before, we declared an export, but this time we added the `--private` flag. The other thing to note is that the subject for the request has a wildcard. This enables the account to map specific subjects to specifically authorized accounts.
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ TestAccount │
|
||||
│ Account ID │ AC7PO3MREV26 │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-29 14:59:42 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
> nsc describe account A
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 20:19:19 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭─────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Exports │
|
||||
├────────────────┬─────────┬────────────────┬────────┬─────────────┬──────────┤
|
||||
│ Name │ Type │ Subject │ Public │ Revocations │ Tracking │
|
||||
├────────────────┼─────────┼────────────────┼────────┼─────────────┼──────────┤
|
||||
│ help │ Service │ help │ Yes │ 0 │ - │
|
||||
│ private.help.* │ Service │ private.help.* │ No │ 0 │ - │
|
||||
╰────────────────┴─────────┴────────────────┴────────┴─────────────┴──────────╯
|
||||
|
||||
╭────────────────────────────────────╮
|
||||
│ Exports │
|
||||
├───────┬─────────┬─────────┬────────┤
|
||||
│ Name │ Type │ Subject │ Public │
|
||||
├───────┼─────────┼─────────┼────────┤
|
||||
│ phelp │ Service │ help.> │ No │
|
||||
╰───────┴─────────┴─────────┴────────╯
|
||||
```
|
||||
|
||||
### Generating an Activation Token
|
||||
|
||||
For the foreign account to _import_ a private service and be able to send requests, you have to generate an activation token. The activation token in addition to granting permission to the account allows you to subset the service’s subject:
|
||||
|
||||
To generate a token, you’ll need to know the public key of the account importing the service.
|
||||
To generate a token, you’ll need to know the public key of the account importing the service. We can easily find the public key for account B by doing:
|
||||
|
||||
```text
|
||||
> nsc generate activation -o /tmp/activation.jwt --target-account AAL5Q2B3SMSO5AS3APJFUNAIKUCEQJPAQ76XEBTVOCQCXXGKP3YMGGN4 --subject "help.AAL5Q2B3SM" --service
|
||||
generated "phelp" activation for account "AAL5Q2B3SMSO5AS3APJFUNAIKUCEQJPAQ76XEBTVOCQCXXGKP3YMGGN4".
|
||||
JTI is "IY4ZUWLNLOTO5N5UDLOFEBCOMHB6MKQMK4ZELA2BSPKMXSEARXOA"
|
||||
```bash
|
||||
> nsc list keys --account B
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Keys │
|
||||
├────────┬──────────────────────────────────────────────────────────┬─────────────┬────────┤
|
||||
│ Entity │ Key │ Signing Key │ Stored │
|
||||
├────────┼──────────────────────────────────────────────────────────┼─────────────┼────────┤
|
||||
│ O │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │ │ * │
|
||||
│ B │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │ │ * │
|
||||
│ b │ UDKNTNEL5YD66U2FZZ2B3WX2PLJFKEFHAPJ3NWJBFF44PT76Y2RAVFVE │ │ * │
|
||||
╰────────┴──────────────────────────────────────────────────────────┴─────────────┴────────╯
|
||||
```
|
||||
|
||||
In the above invocation, we generated an activation redirecting the output to `/tmp/activation.jwt`. The activation only allows the client account to perform requests on `help.AAL5Q2B3SM`.
|
||||
|
||||
```text
|
||||
> nsc generate activation --account A --target-account AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H --subject private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H -o /tmp/activation.jwt
|
||||
[ OK ] generated "private.help.*" activation for account "AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
[ OK ] wrote account description to "/tmp/activation.jwt"
|
||||
```
|
||||
|
||||
The command took the account that has the export ('A'), the public key of account B, the subject where requests from account B will be handled, and an output file where the token can be stored.
|
||||
The subject for the export allows the service to handle all requests coming on private.help.*, but account B can only request from a specific subject.
|
||||
|
||||
|
||||
For completeness, the contents of the JWT file looks like this:
|
||||
|
||||
```text
|
||||
```bash
|
||||
> cat /tmp/activation.jwt
|
||||
-----BEGIN NATS ACTIVATION JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJJWTRaVVdMTkxPVE81TjVVRExPRkVCQ09NSEI2TUtRTUs0WkVMQTJCU1BLTVhTRUFSWE9BIiwiaWF0IjoxNTU2NTUwMDczLCJpc3MiOiJBQzdQTzNNUkVWMjZVM0xGWkZQNUJOM0hBSTMyWDNQS0xCUlZNUEFFVExFSFdQUUVVRzdFSlk0SCIsIm5hbWUiOiJoZWxwLkFBTDVRMkIzU00iLCJzdWIiOiJBQUw1UTJCM1NNU081QVMzQVBKRlVOQUlLVUNFUUpQQVE3NlhFQlRWT0NRQ1hYR0tQM1lNR0dONCIsInR5cGUiOiJhY3RpdmF0aW9uIiwibmF0cyI6eyJzdWJqZWN0IjoiaGVscC5BQUw1UTJCM1NNIiwidHlwZSI6InNlcnZpY2UifX0.VFYHPA0e67RFR-XFy7Q7pS90hzZvP5k3OsldjaDrIXP4UdpuQeUhv9qK9EMK40pcgH6NzJ7gmaZLU6RpAcbXAg
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJUS01LNEFHT1pOVERDTERGUk9QTllNM0hHUVRDTEJTUktNQUxXWTVSUUhFVEVNNE1VTDdBIiwiaWF0IjoxNTc1NDkxNjEwLCJpc3MiOiJBREVUUFQzNldCSUJVS00zSUJDVk00QTVZVVNEWEZFSlBXNE02R0dWQllDQlc3UlJORlRWNU5HRSIsIm5hbWUiOiJwcml2YXRlLmhlbHAuQUFNNDZFM1lGNVdPWlNFNVdOWVdITjNZWUlTVlpPU0k2WEhURjJRNjRFQ1BYU0ZRWlJPSk1QMkgiLCJzdWIiOiJBQU00NkUzWUY1V09aU0U1V05ZV0hOM1lZSVNWWk9TSTZYSFRGMlE2NEVDUFhTRlFaUk9KTVAySCIsInR5cGUiOiJhY3RpdmF0aW9uIiwibmF0cyI6eyJzdWJqZWN0IjoicHJpdmF0ZS5oZWxwLkFBTTQ2RTNZRjVXT1pTRTVXTllXSE4zWVlJU1ZaT1NJNlhIVEYyUTY0RUNQWFNGUVpST0pNUDJIIiwidHlwZSI6InNlcnZpY2UifX0.4tFx_1UzPUwbV8wFNIJsQYu91K9hZaGRLE10nOphfHGetvMPv1384KC-1AiNdhApObSDFosdDcpjryD0QxaDCQ
|
||||
------END NATS ACTIVATION JWT------
|
||||
```
|
||||
|
||||
@ -208,85 +246,83 @@ When decoded it looks like this:
|
||||
|
||||
```text
|
||||
> nsc describe jwt -f /tmp/activation.jwt
|
||||
╭───────────────────────────────────────────╮
|
||||
│ Activation │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Import Type │ Service │
|
||||
│ Import Subject │ help.AAL5Q2B3SM │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ AC7PO3MREV26 │
|
||||
│ Issued │ 2019-04-29 15:01:13 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Activation │
|
||||
├─────────────────┬───────────────────────────────────────────────────────────────────────┤
|
||||
│ Name │ private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issued │ 2019-12-04 20:33:30 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼───────────────────────────────────────────────────────────────────────┤
|
||||
│ Hash ID │ DD6BZKI2LTQKAJYD5GTSI4OFUG72KD2BF74NFVLUNO47PR4OX64Q==== │
|
||||
├─────────────────┼───────────────────────────────────────────────────────────────────────┤
|
||||
│ Import Type │ Service │
|
||||
│ Import Subject │ private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
├─────────────────┼───────────────────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴───────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
The token can be shared directly with the client account.
|
||||
|
||||
> If you manage many tokens for many accounts, you may want to host activation tokens on a web server and share the URL with the account. The benefit to the hosted approach is that any updates to the token would be available to the importing account whenever their account is updated, provided the URL you host them in is stable.
|
||||
> If you manage many tokens for many accounts, you may want to host activation tokens on a web server and share the URL with the account. The benefit to the hosted approach is that any updates to the token would be available to the importing account whenever their account is updated, provided the URL you host them in is stable. When using a JWT account server, the tokens can be stored right on the server and shared by an URL that is printed when the token is generated.
|
||||
|
||||
## Importing a Private Service
|
||||
|
||||
As with streams, importing a private service is more natural than a public one because the activation token stores all the necessary details. Again, the token can be an actual file path or a remote URL.
|
||||
Importing a private service is more natural than a public one because the activation token stores all the necessary details. Again, the token can be an actual file path or a remote URL.
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ AccountB │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-29 15:26:39 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
> nsc add import --account B -u /tmp/activation.jwt --local-subject private.help --name private.help
|
||||
[ OK ] added service import "private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
|
||||
╭─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├─────────┬─────────┬─────────────────┬─────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local │ Expires │ From Account │ Public │
|
||||
├─────────┼─────────┼─────────────────┼─────────┼─────────┼──────────────┼────────┤
|
||||
│ help │ Service │ help.AAL5Q2B3SM │ help │ │ AC7PO3MREV26 │ No │
|
||||
╰─────────┴─────────┴─────────────────┴─────────┴─────────┴──────────────┴────────╯
|
||||
> nsc describe account B
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ B │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-04 20:38:06 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├──────────────┬─────────┬───────────────────────────────────────────────────────────────────────┬──────────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local/Prefix │ Expires │ From Account │ Public │
|
||||
├──────────────┼─────────┼───────────────────────────────────────────────────────────────────────┼──────────────┼─────────┼──────────────┼────────┤
|
||||
│ help │ Service │ help │ help │ │ A │ Yes │
|
||||
│ private.help │ Service │ private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │ private.help │ │ A │ No │
|
||||
╰──────────────┴─────────┴───────────────────────────────────────────────────────────────────────┴──────────────┴─────────┴──────────────┴────────╯
|
||||
```
|
||||
|
||||
When importing a service, you can specify the local subject you want to use to make requests. The local subject in this case is `private.help`. However when the request is forwarded by NATS, the request is sent on the remote subject.
|
||||
|
||||
### Testing the Private Service
|
||||
|
||||
Start the replier:
|
||||
Testing a private service is no different than a public one:
|
||||
|
||||
```text
|
||||
> nats-rply -creds ~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds "help.>" "I will help"
|
||||
Listening on [help.>]
|
||||
```
|
||||
|
||||
|
||||
Send a request:
|
||||
```text
|
||||
> nats-req -creds ~/.nkeys/Test/accounts/AccountB/users/userb.creds help me
|
||||
Published [help] : 'me'
|
||||
```
|
||||
|
||||
The service receives the message:
|
||||
```text
|
||||
[#1] Received on [help.AAL5Q2B3SM]: 'me'
|
||||
```
|
||||
|
||||
The requester receives its response:
|
||||
```text
|
||||
Received [_INBOX.N3IiqWbiAQfPoINCBpBrUM.ZjBNtkB3] : 'I will help'
|
||||
```bash
|
||||
> nsc reply --account A --user U "private.help.*" "help is here"
|
||||
listening on [private.help.*]
|
||||
[#1] received on [private.help.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H]: 'help_me'
|
||||
|
||||
> nsc req --account B --user b private.help help_me
|
||||
published request: [private.help] : 'help_me'
|
||||
received reply: [_INBOX.3MhS0iCHfqO8wUl1x59bHB.jpE2jvEj] : 'help is here'
|
||||
```
|
||||
|
@ -25,20 +25,19 @@ All signing key operations revolve around the global `nsc` flag `-K` or `--priva
|
||||
|
||||
Creating the operator:
|
||||
|
||||
```text
|
||||
> nsc add operator -n O2
|
||||
Generated operator key - private key stored "/Users/synadia/.nkeys/O2/O2.nk"
|
||||
Success! - added operator "O2"
|
||||
|
||||
```bash
|
||||
> nsc add operator O2
|
||||
[ OK ] generated and stored operator key "OABX3STBZZRBHMWMIMVHNQVNUG2O3D54BMZXX5LMBYKSAPDSHIWPMMFY"
|
||||
[ OK ] added operator "O2"
|
||||
```
|
||||
|
||||
To add a signing key we have to first generate one with `nk`. `NSC` doesn’t at this time offer a way to generate keys that are not associated with an entity. This means that you will have to generate and store the secrets yourself:
|
||||
To add a signing key we have to first generate one with `nsc`:
|
||||
|
||||
```text
|
||||
# generate an operator keypair:
|
||||
> nk -gen operator -pubout
|
||||
SOAIHSQSAM3ZJI5W6U5M4INH7FUCQQ5ETJ5RMPVJZCJLTDREY6ZNEE6LZQ
|
||||
ODMYCI5TSZY6MFLOBBQ2RNRBRAXRKJKAC5UACRC6H6CJXCLR2STTGAAQ
|
||||
```bash
|
||||
> nsc generate nkey --operator --store
|
||||
SOAEW6Z4HCCGSLZJYZQMGFQY2SY6ZKOPIAKUQ5VZY6CW23WWYRNHTQWVOA
|
||||
OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5
|
||||
operator key stored ~/.nkeys/keys/O/AZ/OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5.nk
|
||||
```
|
||||
|
||||
> On a production environment private keys should be saved to a file and always referenced from the secured file.
|
||||
@ -46,105 +45,107 @@ ODMYCI5TSZY6MFLOBBQ2RNRBRAXRKJKAC5UACRC6H6CJXCLR2STTGAAQ
|
||||
Now we are going to edit the operator by adding a signing key with the `--sk` flag providing the generated operator public key (the one starting with `O`):
|
||||
|
||||
```text
|
||||
> nsc edit operator --sk ODMYCI5TSZY6MFLOBBQ2RNRBRAXRKJKAC5UACRC6H6CJXCLR2STTGAAQ
|
||||
Success! - edited operator
|
||||
-----BEGIN NATS OPERATOR JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJPMk5BMkNaQ1ZINkQyTEVCQkNDVUFHTEZaWFJPTTdKTEs1Q1ZXRDZMVlpPVU9TUExDS0dBIiwiaWF0IjoxNTU2NTczNTYzLCJpc3MiOiJPQks3M09MUU9KV05ZVE4yTzQ2SVpRTjRXTVNDN0hWVk5BM1k2VFdQV0tDRlhJV1MzWExTQVVJUyIsIm5hbWUiOiJPMiIsInN1YiI6Ik9CSzczT0xRT0pXTllUTjJPNDZJWlFONFdNU0M3SFZWTkEzWTZUV1BXS0NGWElXUzNYTFNBVUlTIiwidHlwZSI6Im9wZXJhdG9yIiwibmF0cyI6eyJzaWduaW5nX2tleXMiOlsiT0RNWUNJNVRTWlk2TUZMT0JCUTJSTlJCUkFYUktKS0FDNVVBQ1JDNkg2Q0pYQ0xSMlNUVEdBQVEiXX19.-VNSZhmOa3TrGglTZ3pGU3BPScb0uj5rdvTHzzOyZ18_WlCBfo6H8S01S3D2qf9J36lKhPplMtupheYqEo04Aw
|
||||
------END NATS OPERATOR JWT------
|
||||
> nsc edit operator --sk OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5
|
||||
[ OK ] added signing key "OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5"
|
||||
[ OK ] edited operator "O2"
|
||||
```
|
||||
|
||||
Check our handy work:
|
||||
|
||||
```text
|
||||
> nsc describe operator
|
||||
╭────────────────────────────────────────╮
|
||||
│ Operator Details │
|
||||
├──────────────┬─────────────────────────┤
|
||||
│ Name │ O2 │
|
||||
│ Operator ID │ OBK73OLQOJWN │
|
||||
│ Issuer ID │ OBK73OLQOJWN │
|
||||
│ Issued │ 2019-04-29 21:32:43 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────┼─────────────────────────┤
|
||||
│ Signing Keys │ ODMYCI5TSZY6 │
|
||||
╰──────────────┴─────────────────────────╯
|
||||
╭─────────────────────────────────────────────────────────────────────────╮
|
||||
│ Operator Details │
|
||||
├──────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ O2 │
|
||||
│ Operator ID │ OABX3STBZZRBHMWMIMVHNQVNUG2O3D54BMZXX5LMBYKSAPDSHIWPMMFY │
|
||||
│ Issuer ID │ OABX3STBZZRBHMWMIMVHNQVNUG2O3D54BMZXX5LMBYKSAPDSHIWPMMFY │
|
||||
│ Issued │ 2019-12-05 14:36:16 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Signing Keys │ OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5 │
|
||||
╰──────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
Now let’s create an account called `A` and sign it the generated operator private signing key. To sign it with the key specify the `-K` flag and the private key or a path to the private key:
|
||||
|
||||
```text
|
||||
> nsc add account --name A -K SOAIHSQSAM3ZJI5W6U5M4INH7FUCQQ5ETJ5RMPVJZCJLTDREY6ZNEE6LZQ
|
||||
Generated account key - private key stored "/Users/synadia/.nkeys/O2/accounts/A/A.nk"
|
||||
Success! - added account "A"
|
||||
> nsc add account A -K ~/.nkeys/keys/O/AZ/OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5.nk
|
||||
[ OK ] generated and stored account key "ACDXQQ6KD5MVSFMK7GNF5ARK3OJC6PEICWCH5PQ7HO27VKGCXQHFE33B"
|
||||
[ OK ] added account "A"
|
||||
```
|
||||
|
||||
Let’s generate an account signing key, again we use `nk`:
|
||||
|
||||
```text
|
||||
> nk -gen account -pubout
|
||||
SAAK3EL5BW4ZOR7JVTXZ4TJ6RQBSOIXK27AFPPSYVP4KDHJKSRQFVRAHIA
|
||||
ABHYL27UAHHQXA5HLH2YWHFQBIP4YMPC7RNZ4PSFRAMJHSSZUUIXF2RV
|
||||
> nsc generate nkey --account --store
|
||||
SAAA4BVFTJMBOW3GAYB3STG3VWFSR4TP4QJKG2OCECGA26SKONPFGC4HHE
|
||||
ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7
|
||||
account key stored ~/.nkeys/keys/A/DU/ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7.nk
|
||||
```
|
||||
|
||||
Let’s add the signing key to the account, and remember to sign the account with the operator signing key:
|
||||
|
||||
```text
|
||||
> nsc edit account --sk ABHYL27UAHHQXA5HLH2YWHFQBIP4YMPC7RNZ4PSFRAMJHSSZUUIXF2RV -K SOAIHSQSAM3ZJI5W6U5M4INH7FUCQQ5ETJ5RMPVJZCJLTDREY6ZNEE6LZQ
|
||||
Success! - edited account "A"
|
||||
> nsc edit account --sk ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7 -K ~/.nkeys/keys/O/AZ/OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5.nk
|
||||
[ OK ] added signing key "ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7"
|
||||
[ OK ] edited account "A"
|
||||
|
||||
|
||||
> nsc describe account
|
||||
╭─────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬─────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ AD7HDY5AS3LT │
|
||||
│ Issuer ID │ ODMYCI5TSZY6 │
|
||||
│ Issued │ 2019-04-30 22:33:13 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼─────────────────────────┤
|
||||
│ Signing Keys │ ABHYL27UAHHQ │
|
||||
├───────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ACDXQQ6KD5MVSFMK7GNF5ARK3OJC6PEICWCH5PQ7HO27VKGCXQHFE33B │
|
||||
│ Issuer ID │ OAZBRNE7DQGDYT5CSAGWDMI5ENGKOEJ57BXVU6WUTHFEAO3CU5GLQYF5 │
|
||||
│ Issued │ 2019-12-05 14:48:22 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Signing Keys │ ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7 │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
We can see that the signing key `ABHYL27UAHHQ` was added to the account. Also the issuer is the operator signing key (specified by the `-K`).
|
||||
We can see that the signing key `ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7` was added to the account. Also the issuer is the operator signing key (specified by the `-K`).
|
||||
|
||||
Now let’s create a user and signing it with account signing key starting with `ABHYL27UAHHQ`.
|
||||
|
||||
```text
|
||||
> nsc add user --name U -K SAAK3EL5BW4ZOR7JVTXZ4TJ6RQBSOIXK27AFPPSYVP4KDHJKSRQFVRAHIA
|
||||
Generated user key - private key stored "/Users/synadia/.nkeys/O2/accounts/A/users/U.nk"
|
||||
Generated user creds file "/Users/synadia/.nkeys/O2/accounts/A/users/U.creds"
|
||||
Success! - added user "U" to "A"
|
||||
> nsc add user U -K ~/.nkeys/keys/A/DU/ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7.nk
|
||||
[ OK ] generated and stored user key "UD47TOTKVDY4IQRGI6D7XMLZPHZVNV5FCD4CNQICLV3FXLQBY72A4UXL"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O2/A/U.creds"
|
||||
[ OK ] added user "U" to account "A"
|
||||
|
||||
> nsc describe user
|
||||
╭───────────────────────────────────────────╮
|
||||
│ User │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Name │ U │
|
||||
│ User ID │ UDYKZHLXFH56 │
|
||||
│ Issuer ID │ ABHYL27UAHHQ │
|
||||
│ Issuer Account │ AD7HDY5AS3LT │
|
||||
│ Issued │ 2019-04-30 22:43:46 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
╭─────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ User │
|
||||
├──────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ U │
|
||||
│ User ID │ UD47TOTKVDY4IQRGI6D7XMLZPHZVNV5FCD4CNQICLV3FXLQBY72A4UXL │
|
||||
│ Issuer ID │ ADUQTJD4TF4O6LTTHCKDKSHKGBN2NECCHHMWFREPKNO6MPA7ZETFEEF7 │
|
||||
│ Issuer Account │ ACDXQQ6KD5MVSFMK7GNF5ARK3OJC6PEICWCH5PQ7HO27VKGCXQHFE33B │
|
||||
│ Issued │ 2019-12-05 14:50:07 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Response Permissions │ Not Set │
|
||||
├──────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰──────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
As expected, the issuer is now the signing key we generated earlier. To map the user to the actual account, an `Issuer Account` field was added to the JWT that identifies the public key of account _A_.
|
||||
|
@ -6,44 +6,45 @@ To share messages you publish with other accounts, you have to _Export_ a _Strea
|
||||
|
||||
To add a stream to your account:
|
||||
|
||||
```text
|
||||
> nsc add export --name "abc" --subject "a.b.c.>"
|
||||
Success! - added public stream export "abc"
|
||||
```bash
|
||||
> nsc add export --name abc --subject "a.b.c.>"
|
||||
[ OK ] added public stream export "abc"
|
||||
```
|
||||
|
||||
> Note that we have exported stream with a subject that contains a wildcard. Any subject that matches the pattern will be exported.
|
||||
|
||||
To check that the export is how you intended:
|
||||
To review the stream export:
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ TestAccount │
|
||||
│ Account ID │ AC7PO3MREV26 │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-29 14:20:13 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-05 13:35:42 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭───────────────────────────────────╮
|
||||
│ Exports │
|
||||
├──────┬─────────┬─────────┬────────┤
|
||||
│ Name │ Type │ Subject │ Public │
|
||||
├──────┼─────────┼─────────┼────────┤
|
||||
│ abc │ Stream │ a.b.c.> │ Yes │
|
||||
╰──────┴─────────┴─────────┴────────╯
|
||||
╭───────────────────────────────────────────────────────────╮
|
||||
│ Exports │
|
||||
├──────┬────────┬─────────┬────────┬─────────────┬──────────┤
|
||||
│ Name │ Type │ Subject │ Public │ Revocations │ Tracking │
|
||||
├──────┼────────┼─────────┼────────┼─────────────┼──────────┤
|
||||
│ abc │ Stream │ a.b.c.> │ Yes │ 0 │ N/A │
|
||||
╰──────┴────────┴─────────┴────────┴─────────────┴──────────╯
|
||||
```
|
||||
|
||||
Messages this account publishes on `a.b.c.>` will be forwarded to all accounts that import this stream.
|
||||
@ -61,44 +62,71 @@ To learn how to inspect a JWT from an account server, [check this article](../na
|
||||
|
||||
With the required information, we can add an import to the public stream.
|
||||
|
||||
```text
|
||||
> nsc add import --src-account AC7PO3MREV26U3LFZFP5BN3HAI32X3PKLBRVMPAETLEHWPQEUG7EJY4H --remote-subject "a.b.c.>" --local-subject "abc.>"
|
||||
Success! - added stream import "a.b.c.>"
|
||||
```bash
|
||||
> nsc add account B
|
||||
[ OK ] generated and stored account key "AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
[ OK ] added account "B"
|
||||
|
||||
|
||||
> nsc add import --src-account ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE --remote-subject "a.b.c.>"
|
||||
[ OK ] added stream import "a.b.c.>"
|
||||
```
|
||||
|
||||
> Note we did fancy things here: The remote stream publishes messages as `a.b.c.>`, but we changed the prefix to be something else in the importing account’s subject space. We changed it to `abc.>`. Subscribers in our account can listen to `abc.>` to get the messages. The message will be delivered as `abc.a.b.c.>`.
|
||||
> Notice that messages published by the remote account will be received on the same subject as the are originally published. Sometimes you would like to prefix messages received from a stream. To add a prefix specify `--local-subject`. Subscribers in our account can listen to `abc.>`. For example if `--local-subject abc`, The message will be received as `abc.a.b.c.>`.
|
||||
|
||||
And verifying it:
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ AccountB │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-25 21:33:58 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ B │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-05 13:39:55 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├───────┬────────┬─────────┬───────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local │ Expires │ From Account │ Public │
|
||||
├───────┼────────┼─────────┼───────┼─────────┼──────────────┼────────┤
|
||||
│ abc.> │ Stream │ a.b.c.> │ abc.> │ │ AC7PO3MREV26 │ Yes │
|
||||
╰───────┴────────┴─────────┴───────┴─────────┴──────────────┴────────╯
|
||||
╭─────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├─────────┬────────┬─────────┬──────────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local/Prefix │ Expires │ From Account │ Public │
|
||||
├─────────┼────────┼─────────┼──────────────┼─────────┼──────────────┼────────┤
|
||||
│ a.b.c.> │ Stream │ a.b.c.> │ │ │ A │ Yes │
|
||||
╰─────────┴────────┴─────────┴──────────────┴─────────┴──────────────┴────────╯
|
||||
```
|
||||
|
||||
Let's also add user to make requests from the service:
|
||||
|
||||
```bash
|
||||
> nsc add user b
|
||||
[ OK ] generated and stored user key "UDKNTNEL5YD66U2FZZ2B3WX2PLJFKEFHAPJ3NWJBFF44PT76Y2RAVFVE"
|
||||
[ OK ] generated user creds file "~/.nkeys/creds/O/B/b.creds"
|
||||
[ OK ] added user "b" to account "B"
|
||||
```
|
||||
|
||||
### Testing the Stream
|
||||
|
||||
```bash
|
||||
> nsc sub --account B --user b "a.b.c.>"
|
||||
Listening on [a.b.c.>]
|
||||
...
|
||||
> nsc pub --account A --user U a.b.c.hello world
|
||||
Published [a.b.c.hello] : "world"
|
||||
...
|
||||
[#1] received on [a.b.c.hello]: 'world'
|
||||
```
|
||||
|
||||
## Securing Streams
|
||||
@ -110,41 +138,43 @@ The authorization token is simply a JWT signed by your account where you authori
|
||||
### Creating a Private Stream Export
|
||||
|
||||
```text
|
||||
> nsc add export --name pabc --subject "a.b.c.>" --private
|
||||
Success! - added private stream export "pabc"
|
||||
> nsc add export --subject "private.abc.*" --private --account A
|
||||
[ OK ] added private stream export "private.abc.*"
|
||||
```
|
||||
|
||||
Like before we defined an export, but this time we added the `--private` flag.
|
||||
Like before we defined an export, but this time we added the `--private` flag. The other thing to note is that the subject for the request has a wildcard. This enables the account to map specific subjects to specifically authorized accounts.
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ TestAccount │
|
||||
│ Account ID │ AC7PO3MREV26 │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-25 21:51:02 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
> nsc describe account A
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ A │
|
||||
│ Account ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-05 14:24:02 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Imports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭──────────────────────────────────╮
|
||||
│ Exports │
|
||||
├──────┬────────┬─────────┬────────┤
|
||||
│ Name │ Type │ Subject │ Public │
|
||||
├──────┼────────┼─────────┼────────┤
|
||||
│ pabc │ Stream │ a.b.c.> │ No │
|
||||
╰──────┴────────┴─────────┴────────╯
|
||||
╭──────────────────────────────────────────────────────────────────────────╮
|
||||
│ Exports │
|
||||
├───────────────┬────────┬───────────────┬────────┬─────────────┬──────────┤
|
||||
│ Name │ Type │ Subject │ Public │ Revocations │ Tracking │
|
||||
├───────────────┼────────┼───────────────┼────────┼─────────────┼──────────┤
|
||||
│ abc │ Stream │ a.b.c.> │ Yes │ 0 │ N/A │
|
||||
│ private.abc.* │ Stream │ private.abc.* │ No │ 0 │ N/A │
|
||||
╰───────────────┴────────┴───────────────┴────────┴─────────────┴──────────╯
|
||||
```
|
||||
|
||||
|
||||
@ -152,34 +182,35 @@ Like before we defined an export, but this time we added the `--private` flag.
|
||||
|
||||
For a foreign account to _import_ a private stream, you have to generate an activation token. The activation token in addition to granting permissions to the account, it also allows you to subset the exported stream’s subject.
|
||||
|
||||
Let’s create an account and user for our stream client:
|
||||
```text
|
||||
> nsc add account --name AccountB
|
||||
Generated account key - private key stored “~/.nkeys/Test/accounts/AccountB/AccountB"
|
||||
Success! - added account "AccountB"
|
||||
To generate a token, you’ll need to know the public key of the account importing the service. We can easily find the public key for account B by doing:
|
||||
|
||||
> nsc add user --name userb
|
||||
Generated user key - private key stored "~/.nkeys/Test/accounts/AccountB/users/userb”
|
||||
Generated user creds file "~/.nkeys/Test/accounts/ACcountB/users/userb.creds"
|
||||
Success! - added user “userb” to “AccountB”
|
||||
```bash
|
||||
> nsc list keys --account B
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Keys │
|
||||
├────────┬──────────────────────────────────────────────────────────┬─────────────┬────────┤
|
||||
│ Entity │ Key │ Signing Key │ Stored │
|
||||
├────────┼──────────────────────────────────────────────────────────┼─────────────┼────────┤
|
||||
│ O │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │ │ * │
|
||||
│ B │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │ │ * │
|
||||
│ b │ UDKNTNEL5YD66U2FZZ2B3WX2PLJFKEFHAPJ3NWJBFF44PT76Y2RAVFVE │ │ * │
|
||||
╰────────┴──────────────────────────────────────────────────────────┴─────────────┴────────╯
|
||||
```
|
||||
|
||||
To generate a token, you’ll need to know the public key of the account importing the stream.
|
||||
|
||||
```text
|
||||
> nsc generate activation -o /tmp/activation.jwt --target-account AAL5Q2B3SMSO5AS3APJFUNAIKUCEQJPAQ76XEBTVOCQCXXGKP3YMGGN4 —subject a.b.c.d
|
||||
generated "pabc" activation for account "AAL5Q2B3SMSO5AS3APJFUNAIKUCEQJPAQ76XEBTVOCQCXXGKP3YMGGN4".
|
||||
JTI is "VNT3Y32I5FNTEHIVL6PINEJNNZ6Z2BGGEJ2QWNA3TPQ4A4KBRGHQ"
|
||||
```bash
|
||||
> nsc generate activation --account A --target-account AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H --subject private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H -o /tmp/activation.jwt
|
||||
[ OK ] generated "private.abc.*" activation for account "AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
[ OK ] wrote account description to "/tmp/activation.jwt"
|
||||
```
|
||||
|
||||
In the above invocation, we generated an activation redirecting the output to `/tmp/activation.jwt`. The exporting account exported `a.b.c.>`, but on the activation token will only grant permission to `a.b.c.d` to the target account.
|
||||
The command took the account that has the export ('A'), the public key of account B, the subject where the stream will publish to account B.
|
||||
|
||||
For completeness, the contents of the JWT file look like this:
|
||||
|
||||
```text
|
||||
> cat /tmp/activation.jwt
|
||||
-----BEGIN NATS ACTIVATION JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJWTlQzWTMySTVGTlRFSElWTDZQSU5FSk5OWjZaMkJHR0VKMlFXTkEzVFBRNEE0S0JSR0hRIiwiaWF0IjoxNTU2MjI5NDk0LCJpc3MiOiJBQzdQTzNNUkVWMjZVM0xGWkZQNUJOM0hBSTMyWDNQS0xCUlZNUEFFVExFSFdQUUVVRzdFSlk0SCIsIm5hbWUiOiJhLmIuYy5kIiwic3ViIjoiQUFMNVEyQjNTTVNPNUFTM0FQSkZVTkFJS1VDRVFKUEFRNzZYRUJUVk9DUUNYWEdLUDNZTUdHTjQiLCJ0eXBlIjoiYWN0aXZhdGlvbiIsIm5hdHMiOnsic3ViamVjdCI6ImEuYi5jLmQiLCJ0eXBlIjoic3RyZWFtIn19.eA0W-mcxFXyIpEk0MUgaLjj7t5jxEHTar7MNY5IYcJ7NHlDoHU5IFog2LlFW_hpTCFA4qa989vqECsiTuBuCAA
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJIS1FPQU9aQkVKS1JYNFJRUVhXS0xYSVBVTlNOSkRRTkxXUFBTSTQ3NkhCVVNYT0paVFFRIiwiaWF0IjoxNTc1NTU1OTczLCJpc3MiOiJBREVUUFQzNldCSUJVS00zSUJDVk00QTVZVVNEWEZFSlBXNE02R0dWQllDQlc3UlJORlRWNU5HRSIsIm5hbWUiOiJwcml2YXRlLmFiYy5BQU00NkUzWUY1V09aU0U1V05ZV0hOM1lZSVNWWk9TSTZYSFRGMlE2NEVDUFhTRlFaUk9KTVAySCIsInN1YiI6IkFBTTQ2RTNZRjVXT1pTRTVXTllXSE4zWVlJU1ZaT1NJNlhIVEYyUTY0RUNQWFNGUVpST0pNUDJIIiwidHlwZSI6ImFjdGl2YXRpb24iLCJuYXRzIjp7InN1YmplY3QiOiJwcml2YXRlLmFiYy5BQU00NkUzWUY1V09aU0U1V05ZV0hOM1lZSVNWWk9TSTZYSFRGMlE2NEVDUFhTRlFaUk9KTVAySCIsInR5cGUiOiJzdHJlYW0ifX0.yD2HWhRQYUFy5aQ7zNV0YjXzLIMoTKnnsBB_NsZNXP-Qr5fz7nowyz9IhoP7UszkN58m__ovjIaDKI9ml0l9DA
|
||||
------END NATS ACTIVATION JWT------
|
||||
```
|
||||
|
||||
@ -187,21 +218,25 @@ When decoded it looks like this:
|
||||
|
||||
```text
|
||||
> nsc describe jwt -f /tmp/activation.jwt
|
||||
╭───────────────────────────────────────────╮
|
||||
│ Activation │
|
||||
├─────────────────┬─────────────────────────┤
|
||||
│ Import Type │ Stream │
|
||||
│ Import Subject │ a.b.c.d │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ AC7PO3MREV26 │
|
||||
│ Issued │ 2019-04-25 21:58:14 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼─────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴─────────────────────────╯
|
||||
╭────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Activation │
|
||||
├─────────────────┬──────────────────────────────────────────────────────────────────────┤
|
||||
│ Name │ private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ ADETPT36WBIBUKM3IBCVM4A5YUSDXFEJPW4M6GGVBYCBW7RRNFTV5NGE │
|
||||
│ Issued │ 2019-12-05 14:26:13 UTC │
|
||||
│ Expires │ │
|
||||
├─────────────────┼──────────────────────────────────────────────────────────────────────┤
|
||||
│ Hash ID │ GWIS5YCSET4EXEOBXVMQKXAR4CLY4IIXFV4MEMRUXPSQ7L4YTZ4Q==== │
|
||||
├─────────────────┼──────────────────────────────────────────────────────────────────────┤
|
||||
│ Import Type │ Stream │
|
||||
│ Import Subject │ private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
├─────────────────┼──────────────────────────────────────────────────────────────────────┤
|
||||
│ Max Messages │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Network Src │ Any │
|
||||
│ Time │ Any │
|
||||
╰─────────────────┴──────────────────────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
The token can be shared directly with the client account.
|
||||
@ -213,82 +248,54 @@ The token can be shared directly with the client account.
|
||||
Importing a private stream is more natural than a public one as the activation token given to you already has all the necessary details. Note that the token can be an actual file path or a remote URL.
|
||||
|
||||
```text
|
||||
> nsc add import --token /tmp/activation.jwt
|
||||
Success! - added stream import "a.b.c.d"
|
||||
> nsc add import --account B --token /tmp/activation.jwt
|
||||
[ OK ] added stream import "private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H"
|
||||
```
|
||||
|
||||
```text
|
||||
> nsc describe account
|
||||
nsc describe account
|
||||
╭────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├──────────────────────────┬─────────────────────────┤
|
||||
│ Name │ AccountB │
|
||||
│ Account ID │ AAL5Q2B3SMSO │
|
||||
│ Issuer ID │ OAYI3YUZSWDN │
|
||||
│ Issued │ 2019-04-25 22:04:29 UTC │
|
||||
│ Expires │ │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├──────────────────────────┼─────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰──────────────────────────┴─────────────────────────╯
|
||||
> nsc describe account B
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Account Details │
|
||||
├───────────────────────────┬──────────────────────────────────────────────────────────┤
|
||||
│ Name │ B │
|
||||
│ Account ID │ AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │
|
||||
│ Issuer ID │ OAFEEYZSYYVI4FXLRXJTMM32PQEI3RGOWZJT7Y3YFM4HB7ACPE4RTJPG │
|
||||
│ Issued │ 2019-12-05 14:29:16 UTC │
|
||||
│ Expires │ │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Max Connections │ Unlimited │
|
||||
│ Max Leaf Node Connections │ Unlimited │
|
||||
│ Max Data │ Unlimited │
|
||||
│ Max Exports │ Unlimited │
|
||||
│ Max Imports │ Unlimited │
|
||||
│ Max Msg Payload │ Unlimited │
|
||||
│ Max Subscriptions │ Unlimited │
|
||||
│ Exports Allows Wildcards │ True │
|
||||
├───────────────────────────┼──────────────────────────────────────────────────────────┤
|
||||
│ Exports │ None │
|
||||
╰───────────────────────────┴──────────────────────────────────────────────────────────╯
|
||||
|
||||
╭────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├─────────┬────────┬─────────┬─────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local │ Expires │ From Account │ Public │
|
||||
├─────────┼────────┼─────────┼─────────┼─────────┼──────────────┼────────┤
|
||||
│ a.b.c.d │ Stream │ a.b.c.d │ a.b.c.d │ │ AC7PO3MREV26 │ No │
|
||||
╰─────────┴────────┴─────────┴─────────┴─────────┴──────────────┴────────╯
|
||||
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Imports │
|
||||
├──────────────────────────────────────────────────────────────────────┬────────┬──────────────────────────────────────────────────────────────────────┬──────────────┬─────────┬──────────────┬────────┤
|
||||
│ Name │ Type │ Remote │ Local/Prefix │ Expires │ From Account │ Public │
|
||||
├──────────────────────────────────────────────────────────────────────┼────────┼──────────────────────────────────────────────────────────────────────┼──────────────┼─────────┼──────────────┼────────┤
|
||||
│ a.b.c.> │ Stream │ a.b.c.> │ │ │ A │ Yes │
|
||||
│ private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │ Stream │ private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H │ │ │ A │ No │
|
||||
╰──────────────────────────────────────────────────────────────────────┴────────┴──────────────────────────────────────────────────────────────────────┴──────────────┴─────────┴──────────────┴────────╯
|
||||
```
|
||||
|
||||
### Testing the Private Stream
|
||||
|
||||
Start the `nats-account-server`:
|
||||
```text
|
||||
> nats-account-server -nsc ~/.nsc/nats/Test
|
||||
Testing a private stream is no different than a public one:
|
||||
|
||||
```bash
|
||||
> nsc sub --account B --user b private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H
|
||||
Listening on [private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H]
|
||||
...
|
||||
> nsc pub --account A --user U private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H hello
|
||||
Published [private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H] : "hello"
|
||||
...
|
||||
[#1] received on [private.abc.AAM46E3YF5WOZSE5WNYWHN3YYISVZOSI6XHTF2Q64ECPXSFQZROJMP2H]: 'hello'
|
||||
```
|
||||
|
||||
Create a config for the nats server `server.conf`:
|
||||
```text
|
||||
operator: /Users/synadia/.nsc/nats/Test/Test.jwt
|
||||
resolver: URL(http://localhost:9090/jwt/v1/accounts/)
|
||||
```
|
||||
|
||||
Start the `nats-server`:
|
||||
```text
|
||||
> nats-server -c server.conf
|
||||
```
|
||||
|
||||
Start the subscriber for the client account:
|
||||
```text
|
||||
> nats-sub -creds ~/.nkeys/Test/accounts/AccountB/users/userb.creds ">"
|
||||
Listening on [>]
|
||||
```
|
||||
|
||||
Publish messages to the stream:
|
||||
|
||||
```text
|
||||
# Client won’t get this one since it only has permission
|
||||
# for messages ‘a.b.c.d’
|
||||
> nats-pub -creds ~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds a.b.c.a "hello"
|
||||
Published [a.b.c.a] : 'hello'
|
||||
|
||||
> nats-pub -creds ~/.nkeys/Test/accounts/TestAccount/users/TestUser.creds a.b.c.d "hello"
|
||||
Published [a.b.c.d] : 'hello'
|
||||
```
|
||||
|
||||
The subscriber as expected prints a message on the stream that it was allowed to receive:
|
||||
|
||||
```text
|
||||
[#1] Received on [a.b.c.d.a.b.c.d]: 'hello'
|
||||
```
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user