Files
grafana/pkg/setting/settings_zanzana.go
Alexander Zobnin 0b9046be15 Zanzana: Add more openfga settings for fine tuning (#115928)
* Zanzana: Add more openfga settings for fine tuning

* neat

* refactor
2026-01-07 13:07:13 +01:00

300 lines
16 KiB
Go

package setting
import (
"slices"
"time"
)
type ZanzanaMode string
const (
ZanzanaModeClient ZanzanaMode = "client"
ZanzanaModeEmbedded ZanzanaMode = "embedded"
)
type ZanzanaClientSettings struct {
// Mode can either be embedded or client.
Mode ZanzanaMode
// Addr is the address of the Zanzana server.
// Only used when mode is set to client.
Addr string
// Certificate used to authenticate the Server
// Only used when mode is set to client
ServerCertFile string
// Token used to perform the exchange request.
// Only used when mode is set to client.
Token string
// URL called to perform exchange request.
// Only used when mode is set to client.
TokenExchangeURL string
// Namespace to use for the token.
TokenNamespace string
}
type ZanzanaServerSettings struct {
// OpenFGA http server address which allows to connect with fga cli.
// Can only be used in dev mode.
OpenFGAHttpAddr string
// Cache settings
CacheSettings OpenFgaCacheSettings
// OpenFGA server settings
OpenFgaServerSettings OpenFgaServerSettings
// Max number of results returned by ListObjects() query. Default is 1000.
ListObjectsMaxResults uint32
// Deadline for the ListObjects() query. Default is 3 seconds.
ListObjectsDeadline time.Duration
// Use streamed version of list objects.
// Returns full list of objects, but takes more time.
UseStreamedListObjects bool
// URL for fetching signing keys.
SigningKeysURL string
// Allow insecure connections to the server for development purposes.
AllowInsecure bool
}
type OpenFgaServerSettings struct {
// ListObjects settings
// Max number of concurrent datastore reads for ListObjects queries
MaxConcurrentReadsForListObjects uint32
// Enable dispatch throttling for ListObjects queries
ListObjectsDispatchThrottlingEnabled bool
// Frequency for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingFrequency time.Duration
// Threshold for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingThreshold uint32
// Max threshold for dispatch throttling in ListObjects queries
ListObjectsDispatchThrottlingMaxThreshold uint32
// Database throttle threshold for ListObjects queries
ListObjectsDatabaseThrottleThreshold int
// Database throttle duration for ListObjects queries
ListObjectsDatabaseThrottleDuration time.Duration
// ListUsers settings
// Deadline for ListUsers queries
ListUsersDeadline time.Duration
// Max number of results returned by ListUsers queries
ListUsersMaxResults uint32
// Max number of concurrent datastore reads for ListUsers queries
MaxConcurrentReadsForListUsers uint32
// Enable dispatch throttling for ListUsers queries
ListUsersDispatchThrottlingEnabled bool
// Frequency for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingFrequency time.Duration
// Threshold for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingThreshold uint32
// Max threshold for dispatch throttling in ListUsers queries
ListUsersDispatchThrottlingMaxThreshold uint32
// Database throttle threshold for ListUsers queries
ListUsersDatabaseThrottleThreshold int
// Database throttle duration for ListUsers queries
ListUsersDatabaseThrottleDuration time.Duration
// Check settings
// Max number of concurrent datastore reads for Check queries
MaxConcurrentReadsForCheck uint32
// Database throttle threshold for Check queries
CheckDatabaseThrottleThreshold int
// Database throttle duration for Check queries
CheckDatabaseThrottleDuration time.Duration
// Batch check settings
// Max number of concurrent checks per batch check request
MaxConcurrentChecksPerBatchCheck uint32
// Max number of checks per batch check request
MaxChecksPerBatchCheck uint32
// Resolve node settings
// Max number of nodes that can be resolved in a single query
ResolveNodeLimit uint32
// Max breadth of nodes that can be resolved in a single query
ResolveNodeBreadthLimit uint32
// Dispatch throttling settings for Check resolver
// Enable dispatch throttling for Check resolver
DispatchThrottlingCheckResolverEnabled bool
// Frequency for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverFrequency time.Duration
// Threshold for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverThreshold uint32
// Max threshold for dispatch throttling in Check resolver
DispatchThrottlingCheckResolverMaxThreshold uint32
// Shadow check/query settings
// Timeout for shadow check resolver
ShadowCheckResolverTimeout time.Duration
// Timeout for shadow ListObjects query
ShadowListObjectsQueryTimeout time.Duration
// Max delta items for shadow ListObjects query
ShadowListObjectsQueryMaxDeltaItems int
// Request settings
// Global request timeout
RequestTimeout time.Duration
// Max size in bytes for authorization model
MaxAuthorizationModelSizeInBytes int
// Size of the authorization model cache
AuthorizationModelCacheSize int
// Offset for changelog horizon
ChangelogHorizonOffset int
}
// Parameters to configure OpenFGA cache.
type OpenFgaCacheSettings struct {
// Number of items that will be kept in the in-memory cache used to resolve Check queries.
// If CheckQueryCacheEnabled or CheckIteratorCacheEnabled, this is the size limit of the cache
CheckCacheLimit uint32
// When enabled, cache controller will verify whether check subproblem cache and check
// iterator cache needs to be invalidated when there is a check or list objects API request.
// The invalidation determination is based on whether there are recent write or deletes for
// the store. This feature allows a larger check-query-cache-ttl and check-iterator-cache-ttl
// at the expense of additional datastore queries for recent writes and deletes.
CacheControllerEnabled bool
// Specifies how frequently the cache controller checks for Writes occurring. While the
// cache controller result is cached, the server will not read the datastore to check
// whether subproblem cache and iterator cache needs to be invalidated.
CacheControllerTTL time.Duration
// Enables in-memory caching of Check subproblems. For example, if you have a relation
// `define viewer: owner or editor`, and the query is `Check(user:anne, viewer, doc:1)`,
// we'll evaluate the `owner` relation and the `editor` relation and cache both results:
// `(user:anne, viewer, doc:1) -> allowed=true` and `(user:anne, owner, doc:1) -> allowed=true`.
CheckQueryCacheEnabled bool
// Time that items will be kept in the cache of Check subproblems
CheckQueryCacheTTL time.Duration
// Enables in-memory caching of database iterators. Each iterator is the result of a database
// query, for example, usersets related to a specific object, or objects related to a specific
// user, up to a certain number of tuples per iterator
CheckIteratorCacheEnabled bool
// Number of tuples that will be stored for each database iterator
CheckIteratorCacheMaxResults uint32
// Time that items will be kept in the cache of database iterators
CheckIteratorCacheTTL time.Duration
// Enables in-memory caching of database iterators for ListObjects. Each iterator is the result
// of a database query, for example, usersets related to a specific object, or objects related
// to a specific user, up to a certain number of tuples per iterator
ListObjectsIteratorCacheEnabled bool
// Number of tuples that will be stored for each ListObjects database iterator
ListObjectsIteratorCacheMaxResults uint32
// Time that items will be kept in the cache of ListObjects database iterators
ListObjectsIteratorCacheTTL time.Duration
// Enables sharing of datastore iterators with different consumers. Each iterator is the result
// of a database query, for example usersets related to a specific object, or objects related
// to a specific user, up to a certain number of tuples per iterator
SharedIteratorEnabled bool
// Limit of the number of iterators that can be shared when shared iterator is enabled
SharedIteratorLimit uint32
// Time that shared iterators will be kept in the cache
SharedIteratorTTL time.Duration
}
func (cfg *Cfg) readZanzanaSettings() {
zc := ZanzanaClientSettings{}
clientSec := cfg.SectionWithEnvOverrides("zanzana.client")
zc.Mode = ZanzanaMode(clientSec.Key("mode").MustString("embedded"))
validModes := []ZanzanaMode{ZanzanaModeEmbedded, ZanzanaModeClient}
if !slices.Contains(validModes, zc.Mode) {
cfg.Logger.Warn("Invalid zanzana mode", "expected", validModes, "got", zc.Mode)
zc.Mode = "embedded"
}
zc.Addr = clientSec.Key("address").MustString("")
zc.ServerCertFile = clientSec.Key("tls_cert").MustString("")
grpcClientAuthSection := cfg.SectionWithEnvOverrides("grpc_client_authentication")
zc.Token = grpcClientAuthSection.Key("token").MustString("")
zc.TokenExchangeURL = grpcClientAuthSection.Key("token_exchange_url").MustString("")
zc.TokenNamespace = grpcClientAuthSection.Key("token_namespace").MustString("stacks-" + cfg.StackID)
// TODO: remove old settings when migrated
token := clientSec.Key("token").MustString("")
tokenExchangeURL := clientSec.Key("token_exchange_url").MustString("")
if token != "" {
zc.Token = token
}
if tokenExchangeURL != "" {
zc.TokenExchangeURL = tokenExchangeURL
}
cfg.ZanzanaClient = zc
zs := ZanzanaServerSettings{}
serverSec := cfg.SectionWithEnvOverrides("zanzana.server")
zs.OpenFGAHttpAddr = serverSec.Key("http_addr").MustString("127.0.0.1:8080")
zs.ListObjectsDeadline = serverSec.Key("list_objects_deadline").MustDuration(3 * time.Second)
zs.ListObjectsMaxResults = uint32(serverSec.Key("list_objects_max_results").MustUint(1000))
zs.UseStreamedListObjects = serverSec.Key("use_streamed_list_objects").MustBool(false)
zs.SigningKeysURL = serverSec.Key("signing_keys_url").MustString("")
zs.AllowInsecure = serverSec.Key("allow_insecure").MustBool(false)
// Cache settings
zs.CacheSettings.CheckCacheLimit = uint32(serverSec.Key("check_cache_limit").MustUint(10000))
zs.CacheSettings.CacheControllerEnabled = serverSec.Key("cache_controller_enabled").MustBool(false)
zs.CacheSettings.CacheControllerTTL = serverSec.Key("cache_controller_ttl").MustDuration(10 * time.Second)
zs.CacheSettings.CheckQueryCacheEnabled = serverSec.Key("check_query_cache_enabled").MustBool(true)
zs.CacheSettings.CheckQueryCacheTTL = serverSec.Key("check_query_cache_ttl").MustDuration(10 * time.Second)
zs.CacheSettings.CheckIteratorCacheEnabled = serverSec.Key("check_iterator_cache_enabled").MustBool(false)
zs.CacheSettings.CheckIteratorCacheMaxResults = uint32(serverSec.Key("check_iterator_cache_max_results").MustUint(1000))
zs.CacheSettings.CheckIteratorCacheTTL = serverSec.Key("check_iterator_cache_ttl").MustDuration(10 * time.Second)
zs.CacheSettings.ListObjectsIteratorCacheEnabled = serverSec.Key("list_objects_iterator_cache_enabled").MustBool(false)
zs.CacheSettings.ListObjectsIteratorCacheMaxResults = uint32(serverSec.Key("list_objects_iterator_cache_max_results").MustUint(1000))
zs.CacheSettings.ListObjectsIteratorCacheTTL = serverSec.Key("list_objects_iterator_cache_ttl").MustDuration(10 * time.Second)
zs.CacheSettings.SharedIteratorEnabled = serverSec.Key("shared_iterator_enabled").MustBool(false)
zs.CacheSettings.SharedIteratorLimit = uint32(serverSec.Key("shared_iterator_limit").MustUint(1000))
zs.CacheSettings.SharedIteratorTTL = serverSec.Key("shared_iterator_ttl").MustDuration(10 * time.Second)
openfgaSec := cfg.SectionWithEnvOverrides("openfga")
// ListObjects settings
zs.OpenFgaServerSettings.MaxConcurrentReadsForListObjects = uint32(openfgaSec.Key("max_concurrent_reads_for_list_objects").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingEnabled = openfgaSec.Key("list_objects_dispatch_throttling_enabled").MustBool(false)
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingFrequency = openfgaSec.Key("list_objects_dispatch_throttling_frequency").MustDuration(0)
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingThreshold = uint32(openfgaSec.Key("list_objects_dispatch_throttling_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDispatchThrottlingMaxThreshold = uint32(openfgaSec.Key("list_objects_dispatch_throttling_max_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListObjectsDatabaseThrottleThreshold = openfgaSec.Key("list_objects_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.ListObjectsDatabaseThrottleDuration = openfgaSec.Key("list_objects_database_throttle_duration").MustDuration(0)
// ListUsers settings
zs.OpenFgaServerSettings.ListUsersDeadline = openfgaSec.Key("list_users_deadline").MustDuration(0)
zs.OpenFgaServerSettings.ListUsersMaxResults = uint32(openfgaSec.Key("list_users_max_results").MustUint(0))
zs.OpenFgaServerSettings.MaxConcurrentReadsForListUsers = uint32(openfgaSec.Key("max_concurrent_reads_for_list_users").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingEnabled = openfgaSec.Key("list_users_dispatch_throttling_enabled").MustBool(false)
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingFrequency = openfgaSec.Key("list_users_dispatch_throttling_frequency").MustDuration(0)
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingThreshold = uint32(openfgaSec.Key("list_users_dispatch_throttling_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDispatchThrottlingMaxThreshold = uint32(openfgaSec.Key("list_users_dispatch_throttling_max_threshold").MustUint(0))
zs.OpenFgaServerSettings.ListUsersDatabaseThrottleThreshold = openfgaSec.Key("list_users_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.ListUsersDatabaseThrottleDuration = openfgaSec.Key("list_users_database_throttle_duration").MustDuration(0)
// Check settings
zs.OpenFgaServerSettings.MaxConcurrentReadsForCheck = uint32(openfgaSec.Key("max_concurrent_reads_for_check").MustUint(0))
zs.OpenFgaServerSettings.CheckDatabaseThrottleThreshold = openfgaSec.Key("check_database_throttle_threshold").MustInt(0)
zs.OpenFgaServerSettings.CheckDatabaseThrottleDuration = openfgaSec.Key("check_database_throttle_duration").MustDuration(0)
// Batch check settings
zs.OpenFgaServerSettings.MaxConcurrentChecksPerBatchCheck = uint32(openfgaSec.Key("max_concurrent_checks_per_batch_check").MustUint(0))
zs.OpenFgaServerSettings.MaxChecksPerBatchCheck = uint32(openfgaSec.Key("max_checks_per_batch_check").MustUint(0))
// Resolve node settings
zs.OpenFgaServerSettings.ResolveNodeLimit = uint32(openfgaSec.Key("resolve_node_limit").MustUint(0))
zs.OpenFgaServerSettings.ResolveNodeBreadthLimit = uint32(openfgaSec.Key("resolve_node_breadth_limit").MustUint(0))
// Dispatch throttling settings for Check resolver
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverEnabled = openfgaSec.Key("dispatch_throttling_check_resolver_enabled").MustBool(false)
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverFrequency = openfgaSec.Key("dispatch_throttling_check_resolver_frequency").MustDuration(0)
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverThreshold = uint32(openfgaSec.Key("dispatch_throttling_check_resolver_threshold").MustUint(0))
zs.OpenFgaServerSettings.DispatchThrottlingCheckResolverMaxThreshold = uint32(openfgaSec.Key("dispatch_throttling_check_resolver_max_threshold").MustUint(0))
// Shadow check/query settings
zs.OpenFgaServerSettings.ShadowCheckResolverTimeout = openfgaSec.Key("shadow_check_resolver_timeout").MustDuration(0)
zs.OpenFgaServerSettings.ShadowListObjectsQueryTimeout = openfgaSec.Key("shadow_list_objects_query_timeout").MustDuration(0)
zs.OpenFgaServerSettings.ShadowListObjectsQueryMaxDeltaItems = openfgaSec.Key("shadow_list_objects_query_max_delta_items").MustInt(0)
zs.OpenFgaServerSettings.RequestTimeout = openfgaSec.Key("request_timeout").MustDuration(0)
zs.OpenFgaServerSettings.MaxAuthorizationModelSizeInBytes = openfgaSec.Key("max_authorization_model_size_in_bytes").MustInt(0)
zs.OpenFgaServerSettings.AuthorizationModelCacheSize = openfgaSec.Key("authorization_model_cache_size").MustInt(0)
zs.OpenFgaServerSettings.ChangelogHorizonOffset = openfgaSec.Key("changelog_horizon_offset").MustInt(0)
cfg.ZanzanaServer = zs
}