From 2c424004f499c665a7308057f7b9acabfce1d945 Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Wed, 5 Feb 2025 14:51:43 +0000 Subject: [PATCH 1/4] feat: add opa allowlisting support Signed-off-by: Arjun Raja Yogidas --- api/router/router.go | 65 +++++++++++++++++++- api/router/router_test.go | 71 +++++++++++++++++++++- cmd/finch-daemon/main.go | 99 +++++++++++++++++++++++++++++- cmd/finch-daemon/router_utils.go | 2 + go.mod | 40 +++++++++--- go.sum | 101 ++++++++++++++++++++++++++----- sample.rego | 15 +++++ 7 files changed, 363 insertions(+), 30 deletions(-) create mode 100644 sample.rego diff --git a/api/router/router.go b/api/router/router.go index 65066929..02217d0d 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -5,6 +5,7 @@ package router import ( "context" + "errors" "fmt" "net/http" "os" @@ -15,6 +16,7 @@ import ( "github.com/moby/moby/api/server/httputils" "github.com/moby/moby/api/types/versions" + "github.com/open-policy-agent/opa/v1/rego" "github.com/runfinch/finch-daemon/api/handlers/builder" "github.com/runfinch/finch-daemon/api/handlers/container" "github.com/runfinch/finch-daemon/api/handlers/distribution" @@ -30,6 +32,14 @@ import ( "github.com/runfinch/finch-daemon/version" ) +var errRego = errors.New("error in rego policy file") +var errInput = errors.New("error in HTTP request") + +type inputRegoRequest struct { + Method string + Path string +} + // Options defines the router options to be passed into the handlers. type Options struct { Config *config.Config @@ -41,6 +51,7 @@ type Options struct { VolumeService volume.Service ExecService exec.Service DistributionService distribution.Service + RegoFilePath string // NerdctlWrapper wraps the interactions with nerdctl to build NerdctlWrapper *backend.NerdctlWrapper @@ -48,9 +59,16 @@ type Options struct { // New creates a new router and registers the handlers to it. Returns a handler object // The struct definitions of the HTTP responses come from https://github.com/moby/moby/tree/master/api/types. -func New(opts *Options) http.Handler { +func New(opts *Options) (http.Handler, error) { r := mux.NewRouter() r.Use(VersionMiddleware) + if opts.RegoFilePath != "" { + regoMiddleware, err := CreateRegoMiddleware(opts.RegoFilePath) + if err != nil { + return nil, err + } + r.Use(regoMiddleware) + } vr := types.VersionedRouter{Router: r} logger := flog.NewLogrus() @@ -62,7 +80,7 @@ func New(opts *Options) http.Handler { volume.RegisterHandlers(vr, opts.VolumeService, opts.Config, logger) exec.RegisterHandlers(vr, opts.ExecService, opts.Config, logger) distribution.RegisterHandlers(vr, opts.DistributionService, opts.Config, logger) - return ghandlers.LoggingHandler(os.Stderr, r) + return ghandlers.LoggingHandler(os.Stderr, r), nil } // VersionMiddleware checks for the requested version of the api and makes sure it falls within the bounds @@ -90,3 +108,46 @@ func VersionMiddleware(next http.Handler) http.Handler { next.ServeHTTP(w, newReq) }) } + +// CreateRegoMiddleware dynamically parses the rego file at the path specified in options +// and allows or denies the request based on the policy. +// Will return a nil function and an error if the given file path is blank or invalid. +func CreateRegoMiddleware(regoFilePath string) (func(next http.Handler) http.Handler, error) { + if regoFilePath == "" { + return nil, errRego + } + + query := "data.finch.authz.allow" + nr := rego.New( + rego.Load([]string{regoFilePath}, nil), + rego.Query(query), + ) + + preppedQuery, err := nr.PrepareForEval(context.Background()) + if err != nil { + return nil, err + } + + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + input := inputRegoRequest{ + Method: r.Method, + Path: r.URL.Path, + } + + rs, err := preppedQuery.Eval(r.Context(), rego.EvalInput(input)) + if err != nil { + response.SendErrorResponse(w, http.StatusInternalServerError, errInput) + return + } + + if !rs.Allowed() { + response.SendErrorResponse(w, http.StatusForbidden, + fmt.Errorf("method %s not allowed for path %s", r.Method, r.URL.Path)) + return + } + newReq := r.WithContext(r.Context()) + next.ServeHTTP(w, newReq) + }) + }, nil +} diff --git a/api/router/router_test.go b/api/router/router_test.go index df4f69f8..1d05cd27 100644 --- a/api/router/router_test.go +++ b/api/router/router_test.go @@ -8,6 +8,8 @@ import ( "fmt" "net/http" "net/http/httptest" + "os" + "path/filepath" "testing" "github.com/containerd/nerdctl/v2/pkg/config" @@ -51,8 +53,9 @@ var _ = Describe("version middleware test", func() { BuilderService: nil, VolumeService: nil, NerdctlWrapper: nil, + RegoFilePath: "", } - h = New(opts) + h, _ = New(opts) rr = httptest.NewRecorder() expected = types.VersionInfo{ Platform: struct { @@ -126,3 +129,69 @@ var _ = Describe("version middleware test", func() { Expect(v).Should(Equal(expected)) }) }) + +// Unit tests for the rego handler. +var _ = Describe("rego middleware test", func() { + var ( + opts *Options + rr *httptest.ResponseRecorder + expected types.VersionInfo + sysSvc *mocks_system.MockService + regoFilePath string + ) + + BeforeEach(func() { + mockCtrl := gomock.NewController(GinkgoT()) + defer mockCtrl.Finish() + + tempDirPath := GinkgoT().TempDir() + regoFilePath = filepath.Join(tempDirPath, "authz.rego") + os.Create(regoFilePath) + + c := config.Config{} + sysSvc = mocks_system.NewMockService(mockCtrl) + opts = &Options{ + Config: &c, + SystemService: sysSvc, + } + rr = httptest.NewRecorder() + expected = types.VersionInfo{} + sysSvc.EXPECT().GetVersion(gomock.Any()).Return(&expected, nil).AnyTimes() + }) + It("should return a 200 error for calls by default", func() { + h, err := New(opts) + Expect(err).Should(BeNil()) + + req, _ := http.NewRequest(http.MethodGet, "/version", nil) + h.ServeHTTP(rr, req) + + Expect(rr).Should(HaveHTTPStatus(http.StatusOK)) + }) + + It("should return a 400 error for disallowed calls", func() { + regoPolicy := `package finch.authz +import rego.v1 + +default allow = false` + + os.WriteFile(regoFilePath, []byte(regoPolicy), 0644) + opts.RegoFilePath = regoFilePath + h, err := New(opts) + Expect(err).Should(BeNil()) + + req, _ := http.NewRequest(http.MethodGet, "/version", nil) + h.ServeHTTP(rr, req) + + Expect(rr).Should(HaveHTTPStatus(http.StatusForbidden)) + }) + + It("should return an error for poorly formed rego files", func() { + regoPolicy := `poorly formed rego file` + + os.WriteFile(regoFilePath, []byte(regoPolicy), 0644) + opts.RegoFilePath = regoFilePath + _, err := New(opts) + + Expect(err).Should(Not(BeNil())) + }) +}) diff --git a/cmd/finch-daemon/main.go b/cmd/finch-daemon/main.go index 314a83f8..55c1a9c2 100644 --- a/cmd/finch-daemon/main.go +++ b/cmd/finch-daemon/main.go @@ -49,6 +49,9 @@ type DaemonOptions struct { debugAddress string configPath string pidFile string + regoFilePath string + enableOpa bool + regoFileLock *flock.Flock } var options = new(DaemonOptions) @@ -67,6 +70,8 @@ func main() { rootCmd.Flags().StringVar(&options.debugAddress, "debug-addr", "", "") rootCmd.Flags().StringVar(&options.configPath, "config-file", defaultConfigPath, "Daemon Config Path") rootCmd.Flags().StringVar(&options.pidFile, "pidfile", defaultPidFile, "pid file location") + rootCmd.Flags().StringVar(&options.regoFilePath, "rego-file", "", "Rego Policy Path") + rootCmd.Flags().BoolVar(&options.enableOpa, "enable-opa", false, "turn on opa allowlisting") if err := rootCmd.Execute(); err != nil { log.Printf("got error: %v", err) log.Fatal(err) @@ -193,6 +198,16 @@ func run(options *DaemonOptions) error { } }() + defer func() { + if options.regoFileLock != nil { + if err := options.regoFileLock.Unlock(); err != nil { + logrus.Errorf("failed to unlock Rego file: %v", err) + } + logger.Infof("rego file unlocked") + // todo : chmod to read-write permissions + } + }() + sdNotify(daemon.SdNotifyReady, logger) serverWg.Wait() logger.Debugln("Server stopped. Exiting...") @@ -215,8 +230,20 @@ func newRouter(options *DaemonOptions, logger *flog.Logrus) (http.Handler, error return nil, err } - opts := createRouterOptions(conf, clientWrapper, ncWrapper, logger) - return router.New(opts), nil + var regoFilePath string + if options.enableOpa { + regoFilePath, err = sanitizeRegoFile(options) + if err != nil { + return nil, err + } + } + + opts := createRouterOptions(conf, clientWrapper, ncWrapper, logger, regoFilePath) + newRouter, err := router.New(opts) + if err != nil { + return nil, err + } + return newRouter, nil } func handleSignal(socket string, server *http.Server, logger *flog.Logrus) { @@ -265,3 +292,71 @@ func defineDockerConfig(uid int) error { return true }) } + +func checkRegoFileValidity(filePath string) error { + fmt.Println("checking file validity.....") + if _, err := os.Stat(filePath); os.IsNotExist(err) { + return fmt.Errorf("provided Rego file path does not exist: %s", filePath) + } + + // Check if the file has a valid extension (.rego, .yaml, or .json) + // validExtensions := []string{".rego", ".yaml", ".yml", ".json"} + fileExt := strings.ToLower(filepath.Ext(options.regoFilePath)) + + if fileExt != ".rego" { + return fmt.Errorf("invalid file extension for Rego file. Only .rego files are supported") + } + + // isValidExtension := false + // for _, ext := range validExtensions { + // if fileExt == ext { + // isValidExtension = true + // break + // } + // } + + // if !isValidExtension { + // return fmt.Errorf("Invalid file extension for Rego file. Allowed extensions are: %v", validExtensions) + // } + + fmt.Println(" file valid!") + return nil +} + +// todo : rename this function to be more descriptve +func sanitizeRegoFile(options *DaemonOptions) (string, error) { + fmt.Println("sanitizeRegoFile called.....") + if options.regoFilePath != "" { + if !options.enableOpa { + return "", fmt.Errorf("rego file path was provided without the --enable-opa flag, please provide the --enable-opa flag") // todo, can we default to setting this flag ourselves is this better UX? + } + + if err := checkRegoFileValidity(options.regoFilePath); err != nil { + return "", err + } + } + + if options.enableOpa && options.regoFilePath == "" { + return "", fmt.Errorf("rego file path not provided, please provide the policy file path using the --rego-file flag") + } + + fileLock := flock.New(options.regoFilePath) + + locked, err := fileLock.TryLock() + if err != nil { + return "", fmt.Errorf("error acquiring lock on rego file: %v", err) + } + if !locked { + return "", fmt.Errorf("unable to acquire lock on rego file, it may be in use by another process") + } + + // Change file permissions to read-only + err = os.Chmod(options.regoFilePath, 0444) // read-only for all users + if err != nil { + fileLock.Unlock() + return "", fmt.Errorf("error changing rego file permissions: %v", err) + } + options.regoFileLock = fileLock + + return options.regoFilePath, nil +} diff --git a/cmd/finch-daemon/router_utils.go b/cmd/finch-daemon/router_utils.go index 0261f4c4..3aa4175e 100644 --- a/cmd/finch-daemon/router_utils.go +++ b/cmd/finch-daemon/router_utils.go @@ -96,6 +96,7 @@ func createRouterOptions( clientWrapper *backend.ContainerdClientWrapper, ncWrapper *backend.NerdctlWrapper, logger *flog.Logrus, + regoFilePath string, ) *router.Options { fs := afero.NewOsFs() tarCreator := archive.NewTarCreator(ecc.NewExecCmdCreator(), logger) @@ -112,5 +113,6 @@ func createRouterOptions( ExecService: exec.NewService(clientWrapper, logger), DistributionService: distribution.NewService(clientWrapper, ncWrapper, logger), NerdctlWrapper: ncWrapper, + RegoFilePath: regoFilePath, } } diff --git a/go.mod b/go.mod index 394368fb..cb8809af 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,29 @@ require ( google.golang.org/protobuf v1.36.4 ) +require ( + github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/agnivade/levenshtein v1.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/go-ini/ini v1.67.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/tchap/go-patricia/v2 v2.3.2 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/yashtewari/glob-intersection v0.2.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/sdk v1.34.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect @@ -115,11 +138,11 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect + github.com/open-policy-agent/opa v1.1.0 github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/selinux v1.11.1 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rootless-containers/bypass4netns v0.4.1 // indirect github.com/rootless-containers/rootlesskit/v2 v2.3.2 // indirect github.com/smallstep/pkcs7 v0.1.1 // indirect @@ -131,23 +154,22 @@ require ( github.com/vbatts/tar-split v0.11.6 // indirect github.com/yuchanns/srslog v1.1.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect golang.org/x/crypto v0.32.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/term v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.28.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.68.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/grpc v1.70.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index b0622014..b09a56ba 100644 --- a/go.sum +++ b/go.sum @@ -14,11 +14,25 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= +github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= +github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= +github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -88,6 +102,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -102,6 +122,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -112,12 +134,18 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= +github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/getlantern/httptest v0.0.0-20161025015934-4b40f4c7e590 h1:OhyiFx+yBN30O3IHrIq+9LAEhy6o7fin21wUQxF8NiE= github.com/getlantern/httptest v0.0.0-20161025015934-4b40f4c7e590/go.mod h1:rE/jidqqHHG9sjSxC24Gd5YCfZ1AT91C2wjJ28TAOfA= github.com/getlantern/mockconn v0.0.0-20200818071412-cb30d065a848 h1:2MhMMVBTnaHrst6HyWFDhwQCaJ05PZuOv1bE2gN8WFY= github.com/getlantern/mockconn v0.0.0-20200818071412-cb30d065a848/go.mod h1:+F5GJ7qGpQ03DBtcOEyQpM30ix4BLswdaojecFtsdy8= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -131,6 +159,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -156,6 +186,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -169,10 +201,14 @@ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/Z github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -202,6 +238,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/ github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -252,10 +290,14 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/open-policy-agent/opa v1.1.0 h1:HMz2evdEMTyNqtdLjmu3Vyx06BmhNYAx67Yz3Ll9q2s= +github.com/open-policy-agent/opa v1.1.0/go.mod h1:T1pASQ1/vwfTa+e2fYcfpLCvWgYtqtiUv+IuA/dLPQs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -277,11 +319,19 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= github.com/rootless-containers/rootlesskit/v2 v2.3.2 h1:QZk7sKU3+B8UHretEeIg6NSTTpj0o4iHGNhNbJBnHOU= @@ -319,6 +369,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM= +github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -336,6 +388,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg= +github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk= github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -344,14 +398,26 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= @@ -462,8 +528,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -488,15 +554,18 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= -google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/sample.rego b/sample.rego new file mode 100644 index 00000000..750c9783 --- /dev/null +++ b/sample.rego @@ -0,0 +1,15 @@ +package finch.authz + +import future.keywords.if +import rego.v1 + +default allow = false + +allow if { + not is_container_create +} + +is_container_create if { + input.Method == "POST" + input.Path == "/v1.43/containers/create" +} \ No newline at end of file From dc08628eca41a037990b1530231e45fbbb75da4e Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Thu, 6 Feb 2025 22:33:15 +0000 Subject: [PATCH 2/4] chore: add e2e tests Signed-off-by: Arjun Raja Yogidas --- .github/workflows/ci.yaml | 10 ++++ Makefile | 8 +++ cmd/finch-daemon/main.go | 32 +++++------ e2e/e2e_test.go | 38 ++++++++++++-- e2e/tests/opa_middleware.go | 102 ++++++++++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+), 23 deletions(-) create mode 100644 e2e/tests/opa_middleware.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0740b590..0fd41371 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -109,3 +109,13 @@ jobs: run: sudo bin/finch-daemon --debug --socket-owner $UID & - name: Run e2e test run: sudo make test-e2e + - name: Clean up Daemon socket + run: sudo rm /var/run/finch.sock && sudo rm /run/finch.pid + - name: Verify Rego file presence + run: ls -l ${{ github.workspace }}/sample.rego + - name: Set Rego file path + run: echo "REGO_FILE_PATH=${{ github.workspace }}/sample.rego" >> $GITHUB_ENV + - name: Start finch-daemon with opa Authz + run: sudo bin/finch-daemon --debug --enable-opa --rego-file ${{ github.workspace }}/sample.rego --socket-owner $UID & + - name: Run opa e2e tests + run: sudo -E make test-e2e-opa diff --git a/Makefile b/Makefile index 7a1dbf22..70a62e21 100644 --- a/Makefile +++ b/Makefile @@ -114,6 +114,14 @@ test-e2e: linux TEST_E2E=1 \ $(GINKGO) $(GFLAGS) ./e2e/... +.PHONY: test-e2e-opa +test-e2e-opa: linux + DOCKER_HOST="unix:///run/finch.sock" \ + DOCKER_API_VERSION="v1.43" \ + OPA_E2E=1 \ + TEST_E2E=1 \ + $(GINKGO) $(GFLAGS) ./e2e/... + .PHONY: licenses licenses: PATH=$(BIN):$(PATH) go-licenses report --template="scripts/third-party-license.tpl" --ignore github.com/runfinch ./... > THIRD_PARTY_LICENSES diff --git a/cmd/finch-daemon/main.go b/cmd/finch-daemon/main.go index 55c1a9c2..f201fef5 100644 --- a/cmd/finch-daemon/main.go +++ b/cmd/finch-daemon/main.go @@ -200,11 +200,16 @@ func run(options *DaemonOptions) error { defer func() { if options.regoFileLock != nil { + // unlock the rego file upon daemon exit if err := options.regoFileLock.Unlock(); err != nil { logrus.Errorf("failed to unlock Rego file: %v", err) } logger.Infof("rego file unlocked") - // todo : chmod to read-write permissions + + // make rego file editable upon daemon exit + if err := os.Chmod(options.regoFilePath, 0600); err != nil { + logrus.Errorf("failed to change file permissions of rego file: %v", err) + } } }() @@ -293,39 +298,26 @@ func defineDockerConfig(uid int) error { }) } +// checkRegoFileValidity verifies that the given rego file exists and has the right file extension func checkRegoFileValidity(filePath string) error { - fmt.Println("checking file validity.....") if _, err := os.Stat(filePath); os.IsNotExist(err) { return fmt.Errorf("provided Rego file path does not exist: %s", filePath) } - // Check if the file has a valid extension (.rego, .yaml, or .json) - // validExtensions := []string{".rego", ".yaml", ".yml", ".json"} + // Check if the file has a valid extension (.rego) fileExt := strings.ToLower(filepath.Ext(options.regoFilePath)) if fileExt != ".rego" { return fmt.Errorf("invalid file extension for Rego file. Only .rego files are supported") } - // isValidExtension := false - // for _, ext := range validExtensions { - // if fileExt == ext { - // isValidExtension = true - // break - // } - // } - - // if !isValidExtension { - // return fmt.Errorf("Invalid file extension for Rego file. Allowed extensions are: %v", validExtensions) - // } - - fmt.Println(" file valid!") return nil } -// todo : rename this function to be more descriptve +// sanitizeRegoFile validates and prepares the Rego policy file for use. +// It checks validates the file, acquires a file lock, +// and sets rego file to be read-only. func sanitizeRegoFile(options *DaemonOptions) (string, error) { - fmt.Println("sanitizeRegoFile called.....") if options.regoFilePath != "" { if !options.enableOpa { return "", fmt.Errorf("rego file path was provided without the --enable-opa flag, please provide the --enable-opa flag") // todo, can we default to setting this flag ourselves is this better UX? @@ -351,7 +343,7 @@ func sanitizeRegoFile(options *DaemonOptions) (string, error) { } // Change file permissions to read-only - err = os.Chmod(options.regoFilePath, 0444) // read-only for all users + err = os.Chmod(options.regoFilePath, 0400) if err != nil { fileLock.Unlock() return "", fmt.Errorf("error changing rego file permissions: %v", err) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 20f97c2b..6deb463a 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -4,6 +4,7 @@ package e2e import ( + "fmt" "os" "testing" @@ -16,10 +17,41 @@ import ( ) func TestRun(t *testing.T) { - if os.Getenv("TEST_E2E") != "1" { - t.Skip("E2E tests skipped. Set TEST_E2E=1 to run these tests") + if os.Getenv("OPA_E2E") == "1" { + runOPATests(t) + } else if os.Getenv("TEST_E2E") == "1" { + runE2ETests(t) + } else { + t.Skip("E2E tests skipped. Set TEST_E2E=1 to run regular E2E tests or OPA_E2E=1 to run OPA middleware tests") } - // TODO : Make this configurable +} + +func runOPATests(t *testing.T) { + runtimeExe := "nerdctl" + opt, _ := option.New([]string{runtimeExe, "-n", "finch"}) + + ginkgo.SynchronizedBeforeSuite(func() []byte { + tests.SetupLocalRegistry(opt) + return nil + }, func(bytes []byte) {}) + + ginkgo.SynchronizedAfterSuite(func() { + tests.CleanupLocalRegistry(opt) + // clean up everything after the local registry is cleaned up + command.RemoveAll(opt) + }, func() {}) + + const description = "Finch Daemon OPA E2E Tests" + ginkgo.Describe(description, func() { + tests.OpaMiddlewareTest(opt) + fmt.Print(opt) + }) + + gomega.RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, description) +} + +func runE2ETests(t *testing.T) { runtimeExe := "nerdctl" opt, _ := option.New([]string{runtimeExe, "-n", "finch"}) diff --git a/e2e/tests/opa_middleware.go b/e2e/tests/opa_middleware.go new file mode 100644 index 00000000..db9cca7d --- /dev/null +++ b/e2e/tests/opa_middleware.go @@ -0,0 +1,102 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package tests + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "os" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/runfinch/common-tests/command" + "github.com/runfinch/common-tests/option" + + "github.com/runfinch/finch-daemon/api/types" + "github.com/runfinch/finch-daemon/e2e/client" +) + +// OpaMiddlewareTest tests the OPA functionality. +func OpaMiddlewareTest(opt *option.Option) { + Describe("test opa middleware functionality", func() { + var ( + uClient *http.Client + version string + wantContainerName string + options types.ContainerCreateRequest + createUrl string + ) + BeforeEach(func() { + // create a custom client to use http over unix sockets + uClient = client.NewClient(GetDockerHostUrl()) + // get the docker api version that will be tested + version = GetDockerApiVersion() + wantContainerName = fmt.Sprintf("/%s", testContainerName) + // set default container options + options = types.ContainerCreateRequest{} + options.Image = defaultImage + createUrl = client.ConvertToFinchUrl(version, "/containers/create") + }) + AfterEach(func() { + command.RemoveAll(opt) + }) + It("should allow GET version API request", func() { + res, err := uClient.Get(client.ConvertToFinchUrl("", "/version")) + Expect(err).ShouldNot(HaveOccurred()) + jd := json.NewDecoder(res.Body) + var v types.VersionInfo + err = jd.Decode(&v) + Expect(err).ShouldNot(HaveOccurred()) + Expect(v.Version).ShouldNot(BeNil()) + Expect(v.ApiVersion).Should(Equal("1.43")) + fmt.Println(version) + }) + + It("shold allow GET containers API request", func() { + id := command.StdoutStr(opt, "run", "-d", "--name", testContainerName, defaultImage, "sleep", "infinity") + want := []types.ContainerListItem{ + { + Id: id[:12], + Names: []string{wantContainerName}, + }, + } + + res, err := uClient.Get(client.ConvertToFinchUrl(version, "/containers/json")) + Expect(err).Should(BeNil()) + Expect(res.StatusCode).Should(Equal(http.StatusOK)) + var got []types.ContainerListItem + err = json.NewDecoder(res.Body).Decode(&got) + Expect(err).Should(BeNil()) + Expect(len(got)).Should(Equal(2)) + got = filterContainerList(got) + Expect(got).Should(ContainElements(want)) + }) + + It("shold disallow POST containers/create API request", func() { + options.Cmd = []string{"echo", "hello world"} + + reqBody, err := json.Marshal(options) + Expect(err).Should(BeNil()) + + fmt.Println("createUrl = ", createUrl) + res, _ := uClient.Post(createUrl, "application/json", bytes.NewReader(reqBody)) + + Expect(res.StatusCode).Should(Equal(http.StatusForbidden)) + }) + + It("should not allow updates to the rego file", func() { + regoFilePath := os.Getenv("REGO_FILE_PATH") + Expect(regoFilePath).NotTo(BeEmpty(), "REGO_FILE_PATH environment variable should be set") + + fileInfo, err := os.Stat(regoFilePath) + Expect(err).NotTo(HaveOccurred(), "Failed to get Rego file info") + + // Check file permissions + mode := fileInfo.Mode() + Expect(mode.Perm()).To(Equal(os.FileMode(0400)), "Rego file should be read-only (0400)") + }) + }) +} From dec3efac94b8f75ee7823e17b5d39accaaae390f Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Fri, 7 Feb 2025 21:48:56 +0000 Subject: [PATCH 3/4] docs: update opa middleware docs Signed-off-by: Arjun Raja Yogidas --- cmd/finch-daemon/main.go | 2 +- docs/opa-middleware.md | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 docs/opa-middleware.md diff --git a/cmd/finch-daemon/main.go b/cmd/finch-daemon/main.go index f201fef5..ceaecbd1 100644 --- a/cmd/finch-daemon/main.go +++ b/cmd/finch-daemon/main.go @@ -298,7 +298,7 @@ func defineDockerConfig(uid int) error { }) } -// checkRegoFileValidity verifies that the given rego file exists and has the right file extension +// checkRegoFileValidity verifies that the given rego file exists and has the right file extension. func checkRegoFileValidity(filePath string) error { if _, err := os.Stat(filePath); os.IsNotExist(err) { return fmt.Errorf("provided Rego file path does not exist: %s", filePath) diff --git a/docs/opa-middleware.md b/docs/opa-middleware.md new file mode 100644 index 00000000..3c3d237d --- /dev/null +++ b/docs/opa-middleware.md @@ -0,0 +1,42 @@ +# Applying OPA authz policies + +This guide provides instructions for setting up [OPA](https://github.com/open-policy-agent/opa) authz policies with the finch-daemon. Authz policies allow users to allowlist or deny certain resources based on policy rules. + +## What Is OPA Authz implementation +Open Policy Agent (OPA) is an open-source, general-purpose policy engine that enables unified, context-aware policy enforcement across the entire stack. OPA provides a high-level declarative language, Rego, for specifying policy as code and simple APIs to offload policy decision-making from your software. + +In the current implementation, users can use OPA Rego policies to filter API requests at the Daemon level. It's important to note that the current implementation only supports allowlisting of requests. This means you can specify which requests should be allowed, and all others will be denied by default. + +## Setting up a policy + +Use the [sample rego](../sample.rego) policy template to build your policy rules. + +The package name must be `finch.authz`, the daemon middleware will look for the result of the `allow` key on each API call to determine wether to allow/deny the request. +An approved request will go through without any events, a rejected request will fail with status code 403 + +Example: + +The following policy blocks all API requests made to the daemon. +``` +package finch.authz + +default allow = false + +``` +`allow` can be modified based on the business requirements for example we can prevent users from creating new containers by preventing them from accessing the create API + +``` +allow if { + not (input.Method == "POST" and input.Path == "/v1.43/containers/create") +} +``` +Use the [Rego playground](https://play.openpolicyagent.org/) to fine tune your rego policies + +## Enable OPA Middleware + +Once you are ready with your policy document, use the `--enable-opa` flag to tell the finch-daemon to enable the OPA middleware. The daemon will then look for the policy document provided by the `--rego-file` flag. + +Note: The `--rego-file` flag is required when `--enable-opa` is set. + +Example: +`sudo bin/finch-daemon --debug --socket-owner $UID --socket-addr /run/finch-test.sock --pidfile /run/finch-test.pid --enable-opa --rego-file //finch-daemon/sample.rego &` \ No newline at end of file From 641bdea1c7720ac481e72ff9c635b6e01b557371 Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Fri, 7 Feb 2025 23:28:24 +0000 Subject: [PATCH 4/4] chore: update variable names Signed-off-by: Arjun Raja Yogidas --- .github/workflows/ci.yaml | 2 +- Makefile | 2 +- cmd/finch-daemon/main.go | 28 ++++++++++++++-------------- docs/opa-middleware.md | 6 +++--- e2e/e2e_test.go | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0fd41371..59115f20 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -116,6 +116,6 @@ jobs: - name: Set Rego file path run: echo "REGO_FILE_PATH=${{ github.workspace }}/sample.rego" >> $GITHUB_ENV - name: Start finch-daemon with opa Authz - run: sudo bin/finch-daemon --debug --enable-opa --rego-file ${{ github.workspace }}/sample.rego --socket-owner $UID & + run: sudo bin/finch-daemon --debug --enable-middleware --rego-file ${{ github.workspace }}/sample.rego --socket-owner $UID & - name: Run opa e2e tests run: sudo -E make test-e2e-opa diff --git a/Makefile b/Makefile index 70a62e21..2f09af51 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ test-e2e: linux test-e2e-opa: linux DOCKER_HOST="unix:///run/finch.sock" \ DOCKER_API_VERSION="v1.43" \ - OPA_E2E=1 \ + MIDDLEWARE_E2E=1 \ TEST_E2E=1 \ $(GINKGO) $(GFLAGS) ./e2e/... diff --git a/cmd/finch-daemon/main.go b/cmd/finch-daemon/main.go index ceaecbd1..c048a15f 100644 --- a/cmd/finch-daemon/main.go +++ b/cmd/finch-daemon/main.go @@ -43,15 +43,15 @@ const ( ) type DaemonOptions struct { - debug bool - socketAddr string - socketOwner int - debugAddress string - configPath string - pidFile string - regoFilePath string - enableOpa bool - regoFileLock *flock.Flock + debug bool + socketAddr string + socketOwner int + debugAddress string + configPath string + pidFile string + regoFilePath string + enableMiddleware bool + regoFileLock *flock.Flock } var options = new(DaemonOptions) @@ -71,7 +71,7 @@ func main() { rootCmd.Flags().StringVar(&options.configPath, "config-file", defaultConfigPath, "Daemon Config Path") rootCmd.Flags().StringVar(&options.pidFile, "pidfile", defaultPidFile, "pid file location") rootCmd.Flags().StringVar(&options.regoFilePath, "rego-file", "", "Rego Policy Path") - rootCmd.Flags().BoolVar(&options.enableOpa, "enable-opa", false, "turn on opa allowlisting") + rootCmd.Flags().BoolVar(&options.enableMiddleware, "enable-middleware", false, "turn on middleware for allowlisting") if err := rootCmd.Execute(); err != nil { log.Printf("got error: %v", err) log.Fatal(err) @@ -236,7 +236,7 @@ func newRouter(options *DaemonOptions, logger *flog.Logrus) (http.Handler, error } var regoFilePath string - if options.enableOpa { + if options.enableMiddleware { regoFilePath, err = sanitizeRegoFile(options) if err != nil { return nil, err @@ -319,8 +319,8 @@ func checkRegoFileValidity(filePath string) error { // and sets rego file to be read-only. func sanitizeRegoFile(options *DaemonOptions) (string, error) { if options.regoFilePath != "" { - if !options.enableOpa { - return "", fmt.Errorf("rego file path was provided without the --enable-opa flag, please provide the --enable-opa flag") // todo, can we default to setting this flag ourselves is this better UX? + if !options.enableMiddleware { + return "", fmt.Errorf("rego file path was provided without the --enable-middleware flag, please provide the --enable-middleware flag") // todo, can we default to setting this flag ourselves is this better UX? } if err := checkRegoFileValidity(options.regoFilePath); err != nil { @@ -328,7 +328,7 @@ func sanitizeRegoFile(options *DaemonOptions) (string, error) { } } - if options.enableOpa && options.regoFilePath == "" { + if options.enableMiddleware && options.regoFilePath == "" { return "", fmt.Errorf("rego file path not provided, please provide the policy file path using the --rego-file flag") } diff --git a/docs/opa-middleware.md b/docs/opa-middleware.md index 3c3d237d..77bfec78 100644 --- a/docs/opa-middleware.md +++ b/docs/opa-middleware.md @@ -34,9 +34,9 @@ Use the [Rego playground](https://play.openpolicyagent.org/) to fine tune your r ## Enable OPA Middleware -Once you are ready with your policy document, use the `--enable-opa` flag to tell the finch-daemon to enable the OPA middleware. The daemon will then look for the policy document provided by the `--rego-file` flag. +Once you are ready with your policy document, use the `--enable-middleware` flag to tell the finch-daemon to enable the OPA middleware. The daemon will then look for the policy document provided by the `--rego-file` flag. -Note: The `--rego-file` flag is required when `--enable-opa` is set. +Note: The `--rego-file` flag is required when `--enable-middleware` is set. Example: -`sudo bin/finch-daemon --debug --socket-owner $UID --socket-addr /run/finch-test.sock --pidfile /run/finch-test.pid --enable-opa --rego-file //finch-daemon/sample.rego &` \ No newline at end of file +`sudo bin/finch-daemon --debug --socket-owner $UID --socket-addr /run/finch-test.sock --pidfile /run/finch-test.pid --enable-middleware --rego-file //finch-daemon/sample.rego &` \ No newline at end of file diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 6deb463a..9def32fe 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -17,12 +17,12 @@ import ( ) func TestRun(t *testing.T) { - if os.Getenv("OPA_E2E") == "1" { + if os.Getenv("MIDDLEWARE_E2E") == "1" { runOPATests(t) } else if os.Getenv("TEST_E2E") == "1" { runE2ETests(t) } else { - t.Skip("E2E tests skipped. Set TEST_E2E=1 to run regular E2E tests or OPA_E2E=1 to run OPA middleware tests") + t.Skip("E2E tests skipped. Set TEST_E2E=1 to run regular E2E tests or MIDDLEWARE_E2E=1 to run OPA middleware tests") } }