-
Notifications
You must be signed in to change notification settings - Fork 12
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
Add design proposal and implementation for ZedTokens table #257
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
70f6e1c
Add design proposal and implementation for ZedTokens table
jnschaeffer 4df0e78
Run "go mod tidy"
jnschaeffer bbf69c5
Remove the ZedToken cache from the query engine
jnschaeffer 4f90f4d
Simplify relationship updates, commit ZedTokens out of band
jnschaeffer f26dac9
Prevent reading of expired ZedTokens
jnschaeffer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Consistency with ZedTokens | ||
|
||
## Overview | ||
|
||
In SpiceDB, resources are arranged in a graph where different services may be contributing to that graph. For example, permissions-api itself manages roles and role bindings, while tenant-api manages tenants. Resources are updated over NATS request/reply. | ||
|
||
SpiceDB breaks updates down into quantized revisions of configurable duration, meaning ACL updates within a given revision window are not visible by default until the next revision begins. Using ZedTokens, however, clients can request data at least as fresh as a given exact point in time. This allows for clients to control the consistency they need for a given SpiceDB request on a per-request basis. | ||
|
||
In general, services expect that immediately after updating relationships in permissions-api, they can make authorization decisions based on data at least as fresh as when they made those updates. | ||
|
||
## Goals | ||
|
||
This proposal is meant to achieve the following goals: | ||
|
||
* Permissions checks made on a resource after it is updated must use data at least as fresh as the last update to that resource | ||
|
||
## Non-goals | ||
|
||
This proposal is not meant to achieve the following goals: | ||
|
||
* Updates to the graph are globally and immediately propagated | ||
|
||
## Proposed solution | ||
|
||
To mitigate this issue, permissions-api can be updated to use a table in CRDB to populate ZedTokens for recently updated resources. By doing this, permissions-api becomes responsible for determining the freshness of lookups. On permissions checks for a given resource, the following consistency strategy is used: | ||
|
||
* If a ZedToken exists for that resource, use `at_least_as_fresh` with the given ZedToken | ||
* If no ZedToken exists, use `minimize_latency` | ||
|
||
The advantage of this approach is that it keeps management of consistency within permissions-api, meaning future changes do not (necessarily) require updates to other services, nor does it change current API semantics. Additionally, it does not introduce new dependencies to permissions-api, instead leveraging CRDB's availability and fault tolerance guarantees. | ||
|
||
## Constraints and limitations | ||
|
||
As designed, this only provides immediately visible updates for a given resource; other indirectly affected resources are not updated (but could be in the future). Additionally, given CRDB leaseholder behavior, multi-region deployments may see longer durations when performing permissions checks if the ZedToken table is not a global table. | ||
|
||
## Alternatives considered | ||
|
||
### Stream ZedToken updates using the SpiceDB Watch API | ||
|
||
We could minimize lookup time for ZedTokens by using the SpiceDB Watch API and streaming updates to all permissions-api replicas. However, this means updates will not be immediately visible for a given resource globally. While tokens could be stored in clients (i.e., using the IAM runtime), this merely pushes the complexity of managing ZedTokens to downstream services. | ||
|
||
### Store ZedTokens using NATS KV | ||
|
||
ZedTokens could be stored using KV in NATS as a coordination mechanism between servers globally. NATS clusters are in general meant to have very low latency between servers, where a single cluster coordinates a given stream (and thus a given KV bucket). This means that for immediate updates to resources using KV, all permissions-api replicas either need to read from a single NATS cluster (introducing latency as a function of distance from the cluster) or use a large cluster that spans many regions. The latter approach is [explicitly discouraged][nats-discussion] by NATS maintainers. | ||
|
||
[nats-discussion]: https://github.com/nats-io/nats-server/discussions/5317#discussioncomment-9138192 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still trying to understand this full stack, so excuse my ignorance. It seems like another alternative is no ZedTokens at all. Reading this post seems to indicate that this won't happen in CRDB. Also it seems even less likely because of our prefixing.
Am I missing something in my reading of that post and our usage of SpiceDB?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So that blog post is primarily about controlling write ordering in CRDB, not ACL updates. There are a few strategies we can adopt if the current default of using a single key for ordering transactions becomes a problem, but we haven't run into scaling issues there.
Where things get more interesting is around ZedTokens. The use of ZedTokens isn't really specific to CRDB, but rather inherent to how Zanzibar and SpiceDB operate. SpiceDB revisions (known as snapshots in the Zanzibar paper) are generally some number of seconds long and reads happen within a given revision. All datastores, including CRDB, use revisions for reading data.
ZedTokens allow for the client to request data newer than whatever a given SpiceDB replica might have available in its cache or whatever the current revision it's using is. In a CRDB deployment environment that uses follower reads, this would mean requesting data that might be newer than what the nearest replica has, thus incurring a one-time round trip to the leaseholder coordinating work. Following this, the data are cached in memory in SpiceDB for the remainder of the revision duration. Other storage engines don't have the same horizontal/multi-region scaling capability that CRDB offers.
Not using ZedTokens would require either waiting for a new revision to elapse before ACL updates are visible or leveraging full consistency in permissions checks, which means we get none of the caching benefits SpiceDB provides.