summaryrefslogtreecommitdiff
path: root/vendor/github.com/authzed/grpcutil/dial_opts.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/authzed/grpcutil/dial_opts.go')
-rw-r--r--vendor/github.com/authzed/grpcutil/dial_opts.go149
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 0000000..68369d4
--- /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})
+}