Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NATS authorization when using NATS Streaming #1122

Closed
SkinnySackboy opened this issue Nov 9, 2020 · 7 comments
Closed

NATS authorization when using NATS Streaming #1122

SkinnySackboy opened this issue Nov 9, 2020 · 7 comments

Comments

@SkinnySackboy
Copy link

SkinnySackboy commented Nov 9, 2020

Hi,

We are currently using NATS Streaming (very happy with it) and would like to start enabling authorization. I'm aware this is not currently supported and should be eventually with JetStream, although in the meantime I have the following question:

When running a NATS Streaming service, is it at least possible to enable authorization for the embedded NATS hosted within the process?

I have successfully used the following configuration when using standard NATS:

authorization {
  default_permissions = {
    publish = "SANDBOX.*"
    subscribe = ["PUBLIC.>", "_INBOX.>"]
  }
  ADMIN = {
    publish = ">"
    subscribe = ">"
  }
  REQUESTOR = {
    publish = ["req.a", "req.b"]
    subscribe = "_INBOX.>"
  }
  RESPONDER = {
    subscribe = ["req.a", "req.b"]
    publish = "_INBOX.>"
  }
  users = [
    {user: admin,   password: abc, permissions: $ADMIN}
    {user: client,  password: abc, permissions: $REQUESTOR}
    {user: service,  password: abc, permissions: $RESPONDER}
    {user: other, password: abc}
  ]
}

However when I try to supply either a single config file to NATS streaming or indeed seperately (via -c and -sc) I see the following error:

STREAM: Failed to start: nats: Authorization Violation

Thanks in advance.

@kozlovic
Copy link
Member

kozlovic commented Nov 9, 2020

You are defining a list of users that are allowed to connect to the NATS Server. The NATS Streaming "server" does connect to the NATS Server (even if embedded), so you need to provide a user/pass that is on that list. You can do so from command line parameters (see https://docs.nats.io/nats-streaming-server/configuring/tls#authenticating-users), or since v0.19.0, you can add it in the streaming{} block. See username/password here.

That being said, seeing requestor/responder in the above configuration worries me since NATS Streaming is not at all suited for request/reply. You will notice that there is no streaming "Request()" API in the client libraries.

Moreover, it is currently not possible to prevent streaming applications to subscribe to a given channel. This is because there is not actual subscription by the streaming server on a given channel/subject, and subscription requests are sent to a generic _STAN.sub.<cluster name | some nuid, depending the mode server is running on>, so even publish permissions cannot be used to effectively limit what an user could subscribe to (by preventing to send the subscribe request).

@SkinnySackboy
Copy link
Author

Many thanks @kozlovic for the incredibly detailed reply.

The example I provided above was a copy/paste from the NATS documentation, rather than something real, but reading your explanation it is now totally clear why it was failing. What we're after is only a way to stop certain NATS-only publishers from publishing on any subject by default. Following your suggestion I'm able to create some basic users which do not by default have the ability to publish anywhere, which is precisely what I was after.

I guess my next questions are:

  1. Does this seem like a sensible use of authorization, i.e. limiting the ability to publish on embedded NATS?
  2. You mentioned we need to pass credentials when starting up the NATS Streaming server - is there anything in particular that this user must be configured to be able to do? For example, would the following suffice?
    ADMIN = { publish = ">" }

@kozlovic
Copy link
Member

@SkinnySackboy As soon as you configure an authorization{} block with users (and possibly permissions), you make the NATS Server run in authentication mode where clients need to authenticate. Since NATS Streaming is a "client" with respect to NATS Server, it also needs to authenticate (it creates client NATS connections). Since v0.19.0 (the latest release), you can provide the username/password to use for the streaming server in the config file:

streaming {
   username: admin
   password: abc
   ...
}

or provide them from the command line.

The user that will be used by the NATS Streaming server needs to be able to publish and subscribe on various subjects, so unless you want to be really accurate in what you want to allow/deny, I would recommend that you have this user able to publish and subscribe on ">".

For limiting your Streaming clients, you can use permissions to publish on the channels, as you said, but also at a higher level even limit which ones can connect (to NATS) in the first place. If your streaming clients do not provide a user/pass that is in the list of the authorization{} block, then won't even be able to create the NATS Streaming connection.

@SkinnySackboy
Copy link
Author

Excellent thanks @kozlovic we'll try that!

@SkinnySackboy
Copy link
Author

@kozlovic am I right in thinking that once we decide to use authorization, it is no longer possible to subscribe/publish without passing credentials, even if default_permissions is set?

@kozlovic
Copy link
Member

@SkinnySackboy Correct. You permissions have a meaning only for users, even default_permissions are applied to existing users. And if you define a username or users, clients are forced to authenticate with a user from the list in order to connect.

@SkinnySackboy
Copy link
Author

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants