nats-server icon indicating copy to clipboard operation
nats-server copied to clipboard

Deny wildcard subscriptions but allow literals

Open jcidoni-ocp opened this issue 3 years ago • 15 comments

Feature Request

There should be a feature to deny wildcard subscriptions, but allow literal-variable subscriptions. This would be huge in preventing wiretap situations.

For example, I should be able to subscribe to: "client.69f3-432f-s234", but not to "client.*", without having to of had entered "69f3-432f-s234" already in the NATS configuration file for specifically "client.69f3-432f-s234".

Use Case:

This is useful for those of us who incorporate application-level GUIDs into topic names and do not want others to be able to easily listen to all communications to all GUIDs.

Proposed Change:

A change in the configuration file to allow for the denial of wildcard subscriptions, but acceptance of wildcard subscriptions that are entered literally.

Who Benefits From The Change(s)?

Everyone who wants to prevent wiretapping.

Alternative Approaches

I've seen other mention the JWT approach, but that is a lot more complicated and cumbersome to implement. A simple option to exclude wildcard subscriptions while allowing literal variable subscriptions

jcidoni-ocp avatar Nov 02 '21 18:11 jcidoni-ocp

Allow by default is open, but deny can limit scope. So would not deny <client.*> work in your case for sub perms?

derekcollison avatar Nov 02 '21 18:11 derekcollison

This is what happens with a simple deny of <client.*>, even if you specify <client.asd>, you are still disallowed from subscribing. And the key part is, the "asd" in <client.asd> is unknown, considering it is a dynamically generated GUID only good for the life of the client session.

joshc@DESKTOP-T5GGTU1:/mnt/c/Users/ec$ nats sub "client.*"
14:16:11 Subscribing on client.*
14:16:11 Unexpected NATS error: nats: Permissions Violation for Subscription to "client.*"
nats: error: nats: Permissions Violation for Subscription to "client.*", try --help
joshc@DESKTOP-T5GGTU1:/mnt/c/Users/ec$ nats sub "client.asd"
14:16:14 Subscribing on client.asd
14:16:14 Unexpected NATS error: nats: Permissions Violation for Subscription to "client.asd"
nats: error: nats: Permissions Violation for Subscription to "client.asd", try --help

This is with the following permissions:

authorization: {
    users = [
        {
            user: test
            password: test
            permissions: {
                publish: {
                    deny: ">"
                },
                subscribe: {
                  deny: "client.*"
                }
            }
        }
    ]
}

jcidoni-ocp avatar Nov 02 '21 18:11 jcidoni-ocp

Ah you are correct.. We will consider, thanks.

derekcollison avatar Nov 02 '21 20:11 derekcollison

+1

I remember there is similar discussion on slack but so long ago that it gone. also https://github.com/nats-io/nats-server/issues/664 is similar in nature I guess, though this one raised before the deny feature

nuharaf avatar Nov 03 '21 02:11 nuharaf

We ran into this recently. We have tens of thousands of clients, and would like them to be able to subscribe to their specific client ID clients.<id>, but would like to disallow the snooping of clients.* by any specific client.

themartorana avatar Sep 05 '23 13:09 themartorana

+1

We are evaluating replacing mosquitto with nats and have quickly run into this issue. In mosquitto, we have read ACLs set up using client/%c/#, allowing clients by default to sub to their specific topic(s) but not others. Would be nice to enable this type of feature in nats.

kumpfdp avatar Oct 09 '23 21:10 kumpfdp

You can do what you need today. I think this is specifically asking about disallowing wildcard subscriptions. For what you are trying to do @kumpfdp its not needed AFAIK.

derekcollison avatar Oct 09 '23 22:10 derekcollison

Interesting @derekcollison, I may have misunderstood. I was thinking this is about avoiding wiretapping, or as i understand it, restricting clients from reading from other clients' topics but still allowing them access to their own.

If I currently have an ACL set up as read client/%c/# in mosquitto, this allows clients to read from their specific client id topics under client/. %c is a special character that allows this to work. Is there something similar in nats that I've overlooked?

kumpfdp avatar Oct 10 '23 19:10 kumpfdp

In NATS you would need to be more explicit, but can achieve the same thing. Say you want all communications for a client to have a prefix of CLIENT.<ID>, where ID uniquely identifies the client.

It would follow that you could place allow perms for both pub and sub to CLIENT.<ID>.>.

You would use the inbox prefix to make sure request / response followed same rules.

Lastly you could use account scoped subject mappings to make this a bit more transparent to the end applications if desired.

derekcollison avatar Oct 11 '23 02:10 derekcollison

Is <ID> dynamic meaning it applies to any client’s id? Or do you have to know the client id before configuring the authorization within nats? If it’s the latter, that’s a deal breaker for our use case.

kumpfdp avatar Oct 11 '23 03:10 kumpfdp

Yes you would need to know. NATS is not a single server system, you can arrange NATS servers into any topology you want. Meaning that the permissions would be beyond a single server.

Most of our users/customers who care deeply about this have an external identity of some sort, whether it be a client certificate or the credentials themselves used to connect to a NATS system, which also gives you a unique identity within our system.

derekcollison avatar Oct 11 '23 03:10 derekcollison

Yes, we care very much about the identity of the connections, as well. However, these identities aren’t known upfront in my scenario. This is where having the system be capable of dynamically injecting a client id into an authorization subject definition would be beneficial.

Example would be client.%cid.> where %cid is replaced with the connected client’s id by the system automatically for the connecting client. This would allow for a single authorization definition that could apply without having to know the exact client id of the connecting client.

Appreciate the continued discussion @derekcollison.

kumpfdp avatar Oct 11 '23 03:10 kumpfdp

How do you trust the connection? The CID in NATS world is an ephemeral identity that is scoped to the server. It's not used for AuthN nor AuthZ, in a NATS system.

Most folks use either NATS JWTs or client certificates. These for the AuthN and bind to the connection. For the NATS JWT, it has all the information included for AuthZ.

derekcollison avatar Oct 11 '23 04:10 derekcollison

We do enforce trust of our connections and it is handled externally from our broker. This external component assigns the client id which is unique, per client connection. What I'm looking to replicate from mosquitto into nats is the pattern ACLs (https://mosquitto.org/man/mosquitto-conf-5.html). Specifically, %c and %u topic patterns.

kumpfdp avatar Oct 11 '23 16:10 kumpfdp

I think your use case maybe could be implemented using the new Auth callout feature. That unique ID that is assigned by another system could be simply part of what the client application passes as an authentication token, which is then passed to your implementation of the authentication callout service that can generate the JWT on the fly allowing the subscription to "foo.<id>" but disallowing subscriptions to "foo.>".

jnmoyne avatar Feb 19 '24 02:02 jnmoyne