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

scoped signing keys can't be used for KV/OBJ buckets. #5681

Closed
chezgi opened this issue Jul 21, 2024 · 21 comments · Fixed by nats-io/nsc#668
Closed

scoped signing keys can't be used for KV/OBJ buckets. #5681

chezgi opened this issue Jul 21, 2024 · 21 comments · Fixed by nats-io/nsc#668
Labels
defect Suspected defect such as a bug or regression

Comments

@chezgi
Copy link

chezgi commented Jul 21, 2024

Observed behavior

it seems that we can't use scoped signing keys for KV/OBJ buckets.
we have some inconsistencies in NATS design decisions.

  1. user tags is only applied to a whole section of topic, not to subsections.
    but in KV service APIs, bucket name is part of an topic section. like: $JS.API.STREAM.INFO.KV_bucket1
    therefore we cant set permissions based on bucket name.
    for example i cant restrict $JS.API.STREAM.INFO service to my bucket based on tags on scoped signing key.
    the tag robucket:bucket1 , doesn't match $JS.API.STREAM.INFO.KV_{{tag(robucket)}}

  2. user tags is lower case, but topics are case sensitive. and bucket names always prefixed by uppercase KV_
    for example robucket:KV_bucket1 will be converted to robucket:kv_bucket1 and cant be used for template in permissions
    therefore we cant use tags at all for restriction on buckets.

when nats topics are case sensitive, why tags are designed to be lower case?

Expected behavior

expected that i can use scoped signing keys to allow/deny some groups of users to read/write access on KV/OBJ buckets.
how we can improve scoped signing keys to be usable for KV/OBJ buckets?
it seams that:

  • tag parsing must be case sensitive
  • templates cab be applied to subsections, not whole sections

Server and client version

in latest nats-server

Host environment

No response

Steps to reproduce

No response

@chezgi chezgi added the defect Suspected defect such as a bug or regression label Jul 21, 2024
@chezgi
Copy link
Author

chezgi commented Sep 8, 2024

authorization in NATS is only good for basic operations like pub/sub and req/reply.
it is not suitable for Jetstream and its derivations like KV.
you can't apply simple restrictions
for sample: cant restrict user to only create ephemeral consumers with new API, because durable moved to body of request.

@chezgi
Copy link
Author

chezgi commented Sep 8, 2024

nobody wants to respond to this design problems?

@derekcollison
Copy link
Member

@chezgi We realize we want better abstractions for authZ, especially within the realm of JetStream. The server's primitives are low level and core based on subject permissions. I think that is correct. The question we are working on is not only what the higher level authZ abstractions may or may not look like, but where they are interpreted.

@chezgi
Copy link
Author

chezgi commented Sep 10, 2024

thanks @derekcollison,
Is there any ongoing thread discussing authZ or any plan for its design and implementation?
Some issues could be temporarily resolved with simple changes:

  • Make user tags case sensitive
  • Create an alias API for all $JS.API.STREAM.*.KV_* to $KV.$2.$1

NATS already has an authZ system that works on topics, but the API is expanding into headers and body. Checking headers and body could be expensive.
Here are a few potential solutions,

  1. Implement two-level checks: the first level matches user-provided topics, followed by checks on the header and body.
  2. Provide hardcoded permissions such as JetstreamPermissions, KvPermissions, ObjPermissions, NexPermissions in the user JWT.

The first solution offers a better design with minimal impact on the code

@chezgi
Copy link
Author

chezgi commented Sep 10, 2024

Can we add a namespace concept for Jetstream, or introduce a new separator within topics that could be used for wildcards and user tags?

  • Namespace example: $JS.API.NSTREAM.INFO.KV.bucketname
  • New separator: $JS.API.STREAM.INFO.KV:bucketname
    permission: $JS.API.STREAM.INFO.KV:{{tag(orgname)}}

@derekcollison
Copy link
Member

There are several things we are considering. But good to understand that the core server will always operate on subject based permissions. We can abstract ACLs that can be decomposed into core subject based permissions for sure.

We will also deliver a core callout option for any subject, similar to auth callout but for any subject, that would allow JS requests to be filtered through an external entity which can allow, modify or reject the request itself..

@chezgi
Copy link
Author

chezgi commented Sep 11, 2024

The authZ callout looks promising, but what about case-sensitive tags? Topics are case-sensitive, but tags aren't. Can this be fixed
Will the authZ callout be released in 2.11, or is it planned for any upcoming release in the near future?

@derekcollison
Copy link
Member

What do you mean by tags in this context?

@ripienaar
Copy link
Contributor

Users can have tags which a scoped signing key can expand with the tag() function, iirc these are always downcase. To me this seems like a good idea, it would be easy to make mistakes otherwise

@chezgi
Copy link
Author

chezgi commented Sep 12, 2024

As @ripienaar explained,
user tags is lower case, but topics are case sensitive. and bucket names always prefixed by uppercase KV_
for example robucket:KV_bucket1 will be converted to robucket:kv_bucket1 and cant be used for template in permissions.

  • defined tag in user jwt: robucket:KV_bucket1 <<--- uppercase
  • Scoped sigining key permission template: $JS.API.STREAM.INFO.{{tag(robucket)}}
  • Permission rule after expanding tag: $JS.API.STREAM.INFO.kv_bucket1 <<--- lowercase
  • API to be matched: $JS.API.STREAM.INFO.KV_bucket1

@derekcollison
Copy link
Member

Looping in @aricart here as well.

@aricart
Copy link
Member

aricart commented Sep 12, 2024

the tag restriction that it must be an entire token in the subject makes a workaround impossible - not sure how not to break anyone using this by changing it to case-sensitive - perhaps JWT could change to be case-insensitive but case preserving on the value portions of tags only. This would allow simple tags like hello still be forced to "hello", be lowercased, but tags like "n:HelloWorld" would lowercase the name of the tag n, but preserve the value portion to be whatever it is entered. @ripienaar @derekcollison what do you think?

@aricart
Copy link
Member

aricart commented Sep 12, 2024

I think I would change the API on jwt to have additional Add() and perhaps have --case-insensitive-tag option to trigger its use. I know this is arcane but this functionality even if used not very often, has been like this since the beginning of time.

@derekcollison
Copy link
Member

derekcollison commented Sep 12, 2024

Thanks @aricart, can you and @ripienaar come to a decision here.

Seems like case sensitive is important for this use case for sure since we depend on subjects here.

@aricart
Copy link
Member

aricart commented Sep 12, 2024

Working on the PRs...

@aricart
Copy link
Member

aricart commented Sep 18, 2024

@chezgi I have released nsc v2.9.0 which enables the use case. Let me know of any issues in the nsc repo

@aricart
Copy link
Member

aricart commented Oct 10, 2024

@chezgi I have retracted the --strict-tags feature on NSC, for now tags have to be downcased - this means that there's a new version of JWT and nsc - However until we can figure out a better strategy for case-preserving tags, I have opened a PR that will allow you to create templates where you can specify KV_{{tag(something)}} which are not bounded by a subject token - see #5981 - while this still has a restriction that the template must be lowercase for tags, at least that gives a workaround for the problem you are trying to address.

@chezgi
Copy link
Author

chezgi commented Oct 11, 2024

Thanks @aricart,
Is something like my.topic.for_{{name()}}_in_{{account-name()}}.* also works?

@aricart
Copy link
Member

aricart commented Oct 11, 2024

yes that will work. Realize that name/account-name are possibly really bad options if the account/user name has a space.

@aricart
Copy link
Member

aricart commented Oct 11, 2024

You can also do my.topic.for_{{tag(name)}} but the tag will be in lowercase

@chezgi
Copy link
Author

chezgi commented Oct 12, 2024

Thanks @aricart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defect Suspected defect such as a bug or regression
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants