nats-server
nats-server copied to clipboard
Subscribe user permission not enforced for consumer
I wanted to document a behavior that was brought up on this Slack thread and I tried to articulate here. I don't want to claim this is a bug, but more of an FYI for discussion..
Here are the steps to demonstrate the behavior.
server.conf
jetstream: {}
accounts {
account: {
jetstream: true
users: [
{
user: manager,
password: manager,
},
{
user: sue,
password: sue,
permissions: {
allow_responses: true,
subscribe: [
"users.sue",
"_INBOX.>",
],
publish: [
"users.sue",
"$JS.API.CONSUMER.INFO.*.*",
"$JS.API.CONSUMER.MSG.NEXT.*.*",
]
}
}
]
}
sys: {
users: [{user: sys, password: sys}]
}
}
system_account: sys
- Run the server
nats-server -c server.conf
- Add a stream using the manager
nats --user manager --password manager stream add users --subjects="users.*"
(accept all other default settings) - Add a consumer using the manager
nats --user manager --password manager consumer add users users --pull --deliver=all
(accept all other defaults) - Publish some messages (for different users):
nats --user manager --password manager req users.sue ''
nats --user manager --password manager req users.joe ''
nats --user manager --password manager req users.pam ''
nats --user manager --password manager req users.sue ''
- Fetch messages using
sue
usernats --user sue --password sue consumer next --count 4 users users
- Note that the
users.joe
andusers.pam
messages were included
As currently implemented, it works as designed, however I think it was surprising to see that the subscribe permission on users.sue
was defined, but other subjects are leaking through since subscribing to a stream is different from core NATS.
I think the knowledge gap is that when permissions are defined, the user is thinking at the application level (which is true for core NATS), but with JetStream and intermediate APIs, the symmetry is no longer there.
I have been thinking of JetStream (from a client prospective at least) as a "permanent" copy of a subject, given the great deal of work the clients go through to hide the $JS.>
APIs. From that perspective, this seems like a bug and security leak.
I suppose as designed, creating a consumer must be considered a privileged operation in which authorization can be bypassed. Maybe at least some documentation to this effect could be in order?