diff options
| author | mo khan <mo@mokhan.ca> | 2025-05-20 14:28:06 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-05-23 14:49:19 -0600 |
| commit | 4beee46dc6c7642316e118a4d3aa51e4b407256e (patch) | |
| tree | 039bdf57b99061844aeb0fe55ad0bc1c864166af /vendor/github.com/bufbuild/protocompile/walk | |
| parent | 0ba49bfbde242920d8675a193d7af89420456fc0 (diff) | |
feat: add external authorization service (authzd) with JWT authentication
- Add new authzd gRPC service implementing Envoy's external authorization API
- Integrate JWT authentication filter in Envoy configuration with claim extraction
- Update middleware to support both cookie-based and header-based user authentication
- Add comprehensive test coverage for authorization service and server
- Configure proper service orchestration with authzd, sparkled, and Envoy
- Update build system and Docker configuration for multi-service deployment
- Add grpcurl tool for gRPC service debugging and testing
This enables fine-grained authorization control through Envoy's ext_authz filter
while maintaining backward compatibility with existing cookie-based authentication.
Diffstat (limited to 'vendor/github.com/bufbuild/protocompile/walk')
| -rw-r--r-- | vendor/github.com/bufbuild/protocompile/walk/walk.go | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/vendor/github.com/bufbuild/protocompile/walk/walk.go b/vendor/github.com/bufbuild/protocompile/walk/walk.go new file mode 100644 index 0000000..244fa72 --- /dev/null +++ b/vendor/github.com/bufbuild/protocompile/walk/walk.go @@ -0,0 +1,446 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package walk provides helper functions for traversing all elements in a +// protobuf file descriptor. There are versions both for traversing "rich" +// descriptors (protoreflect.Descriptor) and for traversing the underlying +// "raw" descriptor protos. +// +// # Enter And Exit +// +// This package includes variants of the functions that accept two callback +// functions. These variants have names ending with "EnterAndExit". One function +// is called as each element is visited ("enter") and the other is called after +// the element and all of its descendants have been visited ("exit"). This +// can be useful when you need to track state that is scoped to the visitation +// of a single element. +// +// # Source Path +// +// When traversing raw descriptor protos, this package include variants whose +// callback accepts a protoreflect.SourcePath. These variants have names that +// include "WithPath". This path can be used to locate corresponding data in the +// file's source code info (if present). +package walk + +import ( + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" + + "github.com/bufbuild/protocompile/internal" +) + +// Descriptors walks all descriptors in the given file using a depth-first +// traversal, calling the given function for each descriptor in the hierarchy. +// The walk ends when traversal is complete or when the function returns an +// error. If the function returns an error, that is returned as the result of the +// walk operation. +// +// Descriptors are visited using a pre-order traversal, where the function is +// called for a descriptor before it is called for any of its descendants. +func Descriptors(file protoreflect.FileDescriptor, fn func(protoreflect.Descriptor) error) error { + return DescriptorsEnterAndExit(file, fn, nil) +} + +// DescriptorsEnterAndExit walks all descriptors in the given file using a +// depth-first traversal, calling the given functions on entry and on exit +// for each descriptor in the hierarchy. The walk ends when traversal is +// complete or when a function returns an error. If a function returns an error, +// that is returned as the result of the walk operation. +// +// The enter function is called using a pre-order traversal, where the function +// is called for a descriptor before it is called for any of its descendants. +// The exit function is called using a post-order traversal, where the function +// is called for a descriptor only after it is called for any descendants. +func DescriptorsEnterAndExit(file protoreflect.FileDescriptor, enter, exit func(protoreflect.Descriptor) error) error { + if err := walkContainer(file, enter, exit); err != nil { + return err + } + services := file.Services() + for i, length := 0, services.Len(); i < length; i++ { + svc := services.Get(i) + if err := enter(svc); err != nil { + return err + } + methods := svc.Methods() + for i, length := 0, methods.Len(); i < length; i++ { + mtd := methods.Get(i) + if err := enter(mtd); err != nil { + return err + } + if exit != nil { + if err := exit(mtd); err != nil { + return err + } + } + } + if exit != nil { + if err := exit(svc); err != nil { + return err + } + } + } + return nil +} + +type container interface { + Messages() protoreflect.MessageDescriptors + Enums() protoreflect.EnumDescriptors + Extensions() protoreflect.ExtensionDescriptors +} + +func walkContainer(container container, enter, exit func(protoreflect.Descriptor) error) error { + messages := container.Messages() + for i, length := 0, messages.Len(); i < length; i++ { + msg := messages.Get(i) + if err := messageDescriptor(msg, enter, exit); err != nil { + return err + } + } + enums := container.Enums() + for i, length := 0, enums.Len(); i < length; i++ { + en := enums.Get(i) + if err := enumDescriptor(en, enter, exit); err != nil { + return err + } + } + exts := container.Extensions() + for i, length := 0, exts.Len(); i < length; i++ { + ext := exts.Get(i) + if err := enter(ext); err != nil { + return err + } + if exit != nil { + if err := exit(ext); err != nil { + return err + } + } + } + return nil +} + +func messageDescriptor(msg protoreflect.MessageDescriptor, enter, exit func(protoreflect.Descriptor) error) error { + if err := enter(msg); err != nil { + return err + } + fields := msg.Fields() + for i, length := 0, fields.Len(); i < length; i++ { + fld := fields.Get(i) + if err := enter(fld); err != nil { + return err + } + if exit != nil { + if err := exit(fld); err != nil { + return err + } + } + } + oneofs := msg.Oneofs() + for i, length := 0, oneofs.Len(); i < length; i++ { + oo := oneofs.Get(i) + if err := enter(oo); err != nil { + return err + } + if exit != nil { + if err := exit(oo); err != nil { + return err + } + } + } + if err := walkContainer(msg, enter, exit); err != nil { + return err + } + if exit != nil { + if err := exit(msg); err != nil { + return err + } + } + return nil +} + +func enumDescriptor(en protoreflect.EnumDescriptor, enter, exit func(protoreflect.Descriptor) error) error { + if err := enter(en); err != nil { + return err + } + vals := en.Values() + for i, length := 0, vals.Len(); i < length; i++ { + enVal := vals.Get(i) + if err := enter(enVal); err != nil { + return err + } + if exit != nil { + if err := exit(enVal); err != nil { + return err + } + } + } + if exit != nil { + if err := exit(en); err != nil { + return err + } + } + return nil +} + +// DescriptorProtosWithPath walks all descriptor protos in the given file using +// a depth-first traversal. This is the same as DescriptorProtos except that the +// callback function, fn, receives a protoreflect.SourcePath, that indicates the +// path for the element in the file's source code info. +func DescriptorProtosWithPath(file *descriptorpb.FileDescriptorProto, fn func(protoreflect.FullName, protoreflect.SourcePath, proto.Message) error) error { + return DescriptorProtosWithPathEnterAndExit(file, fn, nil) +} + +// DescriptorProtosWithPathEnterAndExit walks all descriptor protos in the given +// file using a depth-first traversal. This is the same as +// DescriptorProtosEnterAndExit except that the callback function, fn, receives +// a protoreflect.SourcePath, that indicates the path for the element in the +// file's source code info. +func DescriptorProtosWithPathEnterAndExit(file *descriptorpb.FileDescriptorProto, enter, exit func(protoreflect.FullName, protoreflect.SourcePath, proto.Message) error) error { + w := &protoWalker{usePath: true, enter: enter, exit: exit} + return w.walkDescriptorProtos(file) +} + +// DescriptorProtos walks all descriptor protos in the given file using a +// depth-first traversal, calling the given function for each descriptor proto +// in the hierarchy. The walk ends when traversal is complete or when the +// function returns an error. If the function returns an error, that is +// returned as the result of the walk operation. +// +// Descriptor protos are visited using a pre-order traversal, where the function +// is called for a descriptor before it is called for any of its descendants. +func DescriptorProtos(file *descriptorpb.FileDescriptorProto, fn func(protoreflect.FullName, proto.Message) error) error { + return DescriptorProtosEnterAndExit(file, fn, nil) +} + +// DescriptorProtosEnterAndExit walks all descriptor protos in the given file +// using a depth-first traversal, calling the given functions on entry and on +// exit for each descriptor in the hierarchy. The walk ends when traversal is +// complete or when a function returns an error. If a function returns an error, +// that is returned as the result of the walk operation. +// +// The enter function is called using a pre-order traversal, where the function +// is called for a descriptor proto before it is called for any of its +// descendants. The exit function is called using a post-order traversal, where +// the function is called for a descriptor proto only after it is called for any +// descendants. +func DescriptorProtosEnterAndExit(file *descriptorpb.FileDescriptorProto, enter, exit func(protoreflect.FullName, proto.Message) error) error { + enterWithPath := func(n protoreflect.FullName, _ protoreflect.SourcePath, m proto.Message) error { + return enter(n, m) + } + var exitWithPath func(protoreflect.FullName, protoreflect.SourcePath, proto.Message) error + if exit != nil { + exitWithPath = func(n protoreflect.FullName, _ protoreflect.SourcePath, m proto.Message) error { + return exit(n, m) + } + } + w := &protoWalker{ + enter: enterWithPath, + exit: exitWithPath, + } + return w.walkDescriptorProtos(file) +} + +type protoWalker struct { + usePath bool + enter, exit func(protoreflect.FullName, protoreflect.SourcePath, proto.Message) error +} + +func (w *protoWalker) walkDescriptorProtos(file *descriptorpb.FileDescriptorProto) error { + prefix := file.GetPackage() + if prefix != "" { + prefix += "." + } + var path protoreflect.SourcePath + for i, msg := range file.MessageType { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.FileMessagesTag, int32(i)) + } + if err := w.walkDescriptorProto(prefix, p, msg); err != nil { + return err + } + } + for i, en := range file.EnumType { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.FileEnumsTag, int32(i)) + } + if err := w.walkEnumDescriptorProto(prefix, p, en); err != nil { + return err + } + } + for i, ext := range file.Extension { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.FileExtensionsTag, int32(i)) + } + fqn := prefix + ext.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, ext); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, ext); err != nil { + return err + } + } + } + for i, svc := range file.Service { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.FileServicesTag, int32(i)) + } + fqn := prefix + svc.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, svc); err != nil { + return err + } + for j, mtd := range svc.Method { + var mp protoreflect.SourcePath + if w.usePath { + mp = p + mp = append(mp, internal.ServiceMethodsTag, int32(j)) + } + mtdFqn := fqn + "." + mtd.GetName() + if err := w.enter(protoreflect.FullName(mtdFqn), mp, mtd); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(mtdFqn), mp, mtd); err != nil { + return err + } + } + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, svc); err != nil { + return err + } + } + } + return nil +} + +func (w *protoWalker) walkDescriptorProto(prefix string, path protoreflect.SourcePath, msg *descriptorpb.DescriptorProto) error { + fqn := prefix + msg.GetName() + if err := w.enter(protoreflect.FullName(fqn), path, msg); err != nil { + return err + } + prefix = fqn + "." + for i, fld := range msg.Field { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.MessageFieldsTag, int32(i)) + } + fqn := prefix + fld.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, fld); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, fld); err != nil { + return err + } + } + } + for i, oo := range msg.OneofDecl { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.MessageOneofsTag, int32(i)) + } + fqn := prefix + oo.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, oo); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, oo); err != nil { + return err + } + } + } + for i, nested := range msg.NestedType { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.MessageNestedMessagesTag, int32(i)) + } + if err := w.walkDescriptorProto(prefix, p, nested); err != nil { + return err + } + } + for i, en := range msg.EnumType { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.MessageEnumsTag, int32(i)) + } + if err := w.walkEnumDescriptorProto(prefix, p, en); err != nil { + return err + } + } + for i, ext := range msg.Extension { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.MessageExtensionsTag, int32(i)) + } + fqn := prefix + ext.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, ext); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, ext); err != nil { + return err + } + } + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), path, msg); err != nil { + return err + } + } + return nil +} + +func (w *protoWalker) walkEnumDescriptorProto(prefix string, path protoreflect.SourcePath, en *descriptorpb.EnumDescriptorProto) error { + fqn := prefix + en.GetName() + if err := w.enter(protoreflect.FullName(fqn), path, en); err != nil { + return err + } + for i, val := range en.Value { + var p protoreflect.SourcePath + if w.usePath { + p = path + p = append(p, internal.EnumValuesTag, int32(i)) + } + fqn := prefix + val.GetName() + if err := w.enter(protoreflect.FullName(fqn), p, val); err != nil { + return err + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), p, val); err != nil { + return err + } + } + } + if w.exit != nil { + if err := w.exit(protoreflect.FullName(fqn), path, en); err != nil { + return err + } + } + return nil +} |
