diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/github.com/authzed/grpcutil/dial_opts.go | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/github.com/authzed/grpcutil/dial_opts.go')
| -rw-r--r-- | vendor/github.com/authzed/grpcutil/dial_opts.go | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/grpcutil/dial_opts.go b/vendor/github.com/authzed/grpcutil/dial_opts.go new file mode 100644 index 00000000..68369d40 --- /dev/null +++ b/vendor/github.com/authzed/grpcutil/dial_opts.go @@ -0,0 +1,149 @@ +// Package grpcutil implements various utilities to simplify common gRPC APIs. +package grpcutil + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "io/fs" + "os" + + "github.com/certifi/gocertifi" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type verification int + +const ( + // SkipVerifyCA is a constant that improves the readability of functions + // with the insecureSkipVerify parameter. + SkipVerifyCA verification = iota + + // VerifyCA is a constant that improves the readability of functions + // with the insecureSkipVerify parameter. + VerifyCA +) + +func (v verification) asInsecureSkipVerify() bool { + switch v { + case SkipVerifyCA: + return true + case VerifyCA: + return false + default: + panic("unknown verification") + } +} + +// WithSystemCerts returns a grpc.DialOption that uses the system-provided +// certificate authority chain to verify the connection. +// +// If one cannot be found, this falls back to using a vendored version of +// Mozilla's collection of root certificate authorities. +func WithSystemCerts(v verification) (grpc.DialOption, error) { + certPool, err := x509.SystemCertPool() + if err != nil { + // Fall back to Mozilla collection of root CAs. + certPool, err = gocertifi.CACerts() + if err != nil { + // This library promises that this should never occur. + return nil, fmt.Errorf("gocertifi returned an error: %w", err) + } + } + + return grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: certPool, + InsecureSkipVerify: v.asInsecureSkipVerify(), // nolint + })), nil +} + +func forEachFileContents(dirPath string, fn func(contents []byte)) error { + dirFS := os.DirFS(dirPath) + return fs.WalkDir(dirFS, ".", func(path string, d fs.DirEntry, err error) error { + if !d.IsDir() { + contents, err := fs.ReadFile(dirFS, d.Name()) + if err != nil { + return err + } + fn(contents) + } + return nil + }) +} + +// WithCustomCerts returns a grpc.DialOption for requiring TLS that is +// authenticated using a certificate authority chain provided as a path on disk. +// +// If the path is a directory, all files are loaded. +func WithCustomCerts(v verification, certPaths ...string) (grpc.DialOption, error) { + var caFiles [][]byte + for _, certPath := range certPaths { + fi, err := os.Stat(certPath) + if err != nil { + return nil, fmt.Errorf("failed to find certificate: %w", err) + } + + if fi.IsDir() { + if err = forEachFileContents(certPath, func(contents []byte) { + caFiles = append(caFiles, contents) + }); err != nil { + return nil, err + } + } else { + contents, err := os.ReadFile(certPath) + if err != nil { + return nil, err + } + caFiles = append(caFiles, contents) + } + } + + return WithCustomCertBytes(v, caFiles...) +} + +// WithCustomCertBytes returns a grpc.DialOption for requiring TLS that is +// authenticated using a certificate authority chain provided in bytes. +func WithCustomCertBytes(v verification, certsContents ...[]byte) (grpc.DialOption, error) { + certPool := x509.NewCertPool() + for _, certContents := range certsContents { + if ok := certPool.AppendCertsFromPEM(certContents); !ok { + return nil, errors.New("failed to append certs from CA PEM") + } + } + + return grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: certPool, + InsecureSkipVerify: v.asInsecureSkipVerify(), // nolint:gosec + })), nil +} + +type secureMetadataCreds map[string]string + +func (c secureMetadataCreds) RequireTransportSecurity() bool { return true } +func (c secureMetadataCreds) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { + return c, nil +} + +// WithBearerToken returns a grpc.DialOption that adds a standard HTTP Bearer +// token to all requests sent from a client. +func WithBearerToken(token string) grpc.DialOption { + return grpc.WithPerRPCCredentials(secureMetadataCreds{"authorization": "Bearer " + token}) +} + +type insecureMetadataCreds map[string]string + +func (c insecureMetadataCreds) RequireTransportSecurity() bool { return false } +func (c insecureMetadataCreds) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) { + return c, nil +} + +// WithInsecureBearerToken returns a grpc.DialOption that adds a standard HTTP +// Bearer token to all requests sent from an insecure client. +// +// Must be used in conjunction with `insecure.NewCredentials()`. +func WithInsecureBearerToken(token string) grpc.DialOption { + return grpc.WithPerRPCCredentials(insecureMetadataCreds{"authorization": "Bearer " + token}) +} |
