diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-24 17:58:01 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-24 17:58:01 -0600 |
| commit | 72296119fc9755774719f8f625ad03e0e0ec457a (patch) | |
| tree | ed236ddee12a20fb55b7cfecf13f62d3a000dcb5 /vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go | |
| parent | a920a8cfe415858bb2777371a77018599ffed23f (diff) | |
| parent | eaa1bd3b8e12934aed06413d75e7482ac58d805a (diff) | |
Merge branch 'the-spice-must-flow' into 'main'
Add SpiceDB Authorization
See merge request gitlab-org/software-supply-chain-security/authorization/sparkled!19
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go')
| -rw-r--r-- | vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go b/vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go new file mode 100644 index 0000000..3885036 --- /dev/null +++ b/vendor/github.com/authzed/spicedb/pkg/middleware/nodeid/nodeid.go @@ -0,0 +1,102 @@ +package nodeid + +import ( + "context" + "fmt" + "os" + + "github.com/cespare/xxhash/v2" + middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2" + "github.com/rs/zerolog/log" + "google.golang.org/grpc" +) + +const spiceDBPrefix = "spicedb:" + +type ctxKeyType struct{} + +var nodeIDKey ctxKeyType = struct{}{} + +type nodeIDHandle struct { + nodeID string +} + +var defaultNodeID string + +func init() { + hostname, err := os.Hostname() + if err != nil { + log.Warn().Err(err).Msg("failed to get hostname, using an empty node ID") + return + } + + // Hash the hostname to get the final default node ID. + hasher := xxhash.New() + if _, err := hasher.WriteString(hostname); err != nil { + log.Warn().Err(err).Msg("failed to hash hostname, using an empty node ID") + return + } + + defaultNodeID = spiceDBPrefix + fmt.Sprintf("%x", hasher.Sum(nil)) +} + +// ContextWithHandle adds a placeholder to a context that will later be +// filled by the Node ID. +func ContextWithHandle(ctx context.Context) context.Context { + return context.WithValue(ctx, nodeIDKey, &nodeIDHandle{}) +} + +// FromContext reads the node's ID out of a context.Context. +func FromContext(ctx context.Context) (string, error) { + if c := ctx.Value(nodeIDKey); c != nil { + handle := c.(*nodeIDHandle) + if handle.nodeID != "" { + return handle.nodeID, nil + } + } + + if err := setInContext(ctx, defaultNodeID); err != nil { + return "", err + } + + return defaultNodeID, nil +} + +// setInContext adds a node ID to the given context +func setInContext(ctx context.Context, nodeID string) error { + handle := ctx.Value(nodeIDKey) + if handle == nil { + return nil + } + handle.(*nodeIDHandle).nodeID = nodeID + return nil +} + +// UnaryServerInterceptor returns a new unary server interceptor that adds the +// node ID to the context. If empty, spicedb:$hostname is used. +func UnaryServerInterceptor(nodeID string) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + newCtx := ContextWithHandle(ctx) + if nodeID != "" { + if err := setInContext(newCtx, nodeID); err != nil { + return nil, err + } + } + return handler(newCtx, req) + } +} + +// StreamServerInterceptor returns a new stream server interceptor that adds the +// node ID to the context. If empty, spicedb:$hostname is used. +func StreamServerInterceptor(nodeID string) grpc.StreamServerInterceptor { + return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + wrapped := middleware.WrapServerStream(stream) + wrapped.WrappedContext = ContextWithHandle(wrapped.WrappedContext) + if nodeID != "" { + if err := setInContext(wrapped.WrappedContext, nodeID); err != nil { + return err + } + } + return handler(srv, wrapped) + } +} |
