snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
159
cmd/client/grpc_client.go
Normal file
159
cmd/client/grpc_client.go
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/ory/x/flagx"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/credentials/oauth"
|
||||
)
|
||||
|
||||
type contextKeys string
|
||||
|
||||
const (
|
||||
FlagReadRemote = "read-remote"
|
||||
FlagWriteRemote = "write-remote"
|
||||
FlagOplRemote = "syntax-remote"
|
||||
|
||||
FlagInsecureNoTransportSecurity = "insecure-disable-transport-security"
|
||||
FlagInsecureSkipHostVerification = "insecure-skip-hostname-verification"
|
||||
FlagAuthority = "authority"
|
||||
FlagBlock = "block"
|
||||
|
||||
EnvReadRemote = "KETO_READ_REMOTE"
|
||||
EnvWriteRemote = "KETO_WRITE_REMOTE"
|
||||
EnvAuthToken = "KETO_BEARER_TOKEN" //nolint:gosec // just the key, not the value
|
||||
EnvAuthority = "KETO_AUTHORITY"
|
||||
|
||||
ContextKeyTimeout contextKeys = "timeout"
|
||||
ContextKeyDialFunc contextKeys = "dial"
|
||||
)
|
||||
|
||||
type connectionDetails struct {
|
||||
token, authority string
|
||||
skipHostVerification bool
|
||||
noTransportSecurity bool
|
||||
block bool
|
||||
}
|
||||
|
||||
func (d *connectionDetails) dialOptions() (opts []grpc.DialOption) {
|
||||
if d.token != "" {
|
||||
opts = append(opts,
|
||||
grpc.WithPerRPCCredentials(
|
||||
oauth.TokenSource{TokenSource: oauth2.StaticTokenSource(&oauth2.Token{AccessToken: d.token})},
|
||||
))
|
||||
}
|
||||
if d.authority != "" {
|
||||
opts = append(opts, grpc.WithAuthority(d.authority))
|
||||
}
|
||||
|
||||
// TLS settings
|
||||
switch {
|
||||
case d.noTransportSecurity:
|
||||
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
case d.skipHostVerification:
|
||||
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
|
||||
//nolint:gosec // explicity set through scary flag
|
||||
InsecureSkipVerify: true,
|
||||
})))
|
||||
default:
|
||||
// Defaults to the default host root CA bundle
|
||||
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(nil)))
|
||||
}
|
||||
if d.block {
|
||||
opts = append(opts, grpc.WithBlock()) //nolint:staticcheck // SA1019 grpc.WithBlock is deprecated, but we actually want to block here until the connection is up.
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func getRemote(cmd *cobra.Command, flagRemote, envRemote string) (remote string) {
|
||||
defer (func() {
|
||||
if strings.HasPrefix(remote, "http://") || strings.HasPrefix(remote, "https://") {
|
||||
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "remote %q seems to be an http URL instead of a remote address\n", remote)
|
||||
}
|
||||
})()
|
||||
|
||||
if cmd.Flags().Changed(flagRemote) {
|
||||
return flagx.MustGetString(cmd, flagRemote)
|
||||
} else if remote, isSet := os.LookupEnv(envRemote); isSet {
|
||||
return remote
|
||||
}
|
||||
|
||||
// no value is set, use fallback from the flag and warn about that
|
||||
remote = flagx.MustGetString(cmd, flagRemote)
|
||||
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "neither flag --%s nor env var %s are set, falling back to %s\n", flagRemote, envRemote, remote)
|
||||
return remote
|
||||
}
|
||||
|
||||
func getAuthority(cmd *cobra.Command) string {
|
||||
if cmd.Flags().Changed(FlagAuthority) {
|
||||
return flagx.MustGetString(cmd, FlagAuthority)
|
||||
}
|
||||
return os.Getenv(EnvAuthority)
|
||||
}
|
||||
|
||||
func getConnectionDetails(cmd *cobra.Command) connectionDetails {
|
||||
return connectionDetails{
|
||||
token: os.Getenv(EnvAuthToken),
|
||||
authority: getAuthority(cmd),
|
||||
skipHostVerification: flagx.MustGetBool(cmd, FlagInsecureSkipHostVerification),
|
||||
noTransportSecurity: flagx.MustGetBool(cmd, FlagInsecureNoTransportSecurity),
|
||||
block: flagx.MustGetBool(cmd, "block"),
|
||||
}
|
||||
}
|
||||
|
||||
func GetReadConn(cmd *cobra.Command) (*grpc.ClientConn, error) {
|
||||
return Conn(cmd.Context(),
|
||||
getRemote(cmd, FlagReadRemote, EnvReadRemote),
|
||||
getConnectionDetails(cmd),
|
||||
)
|
||||
}
|
||||
|
||||
func GetWriteConn(cmd *cobra.Command) (*grpc.ClientConn, error) {
|
||||
return Conn(cmd.Context(),
|
||||
getRemote(cmd, FlagWriteRemote, EnvWriteRemote),
|
||||
getConnectionDetails(cmd),
|
||||
)
|
||||
}
|
||||
|
||||
func Conn(ctx context.Context, remote string, details connectionDetails) (*grpc.ClientConn, error) {
|
||||
if d, ok := ctx.Value(ContextKeyTimeout).(time.Duration); ok {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, d)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if dial, ok := ctx.Value(ContextKeyDialFunc).(func(context.Context, string) (*grpc.ClientConn, error)); ok {
|
||||
return dial(ctx, remote)
|
||||
}
|
||||
|
||||
return grpc.DialContext( // nolint:staticcheck // SA1019 grpc.DialContext is deprecated, but we actually want to connect here right away.
|
||||
ctx,
|
||||
remote,
|
||||
details.dialOptions()...,
|
||||
)
|
||||
}
|
||||
|
||||
func RegisterRemoteURLFlags(flags *pflag.FlagSet) {
|
||||
flags.String(FlagReadRemote, "127.0.0.1:4466", "Remote address of the read API endpoint.")
|
||||
flags.String(FlagWriteRemote, "127.0.0.1:4467", "Remote address of the write API endpoint.")
|
||||
flags.String(FlagAuthority, "", "Set the authority header for the remote gRPC server.")
|
||||
flags.Bool(FlagInsecureNoTransportSecurity, false, "Disables transport security. Do not use this in production.")
|
||||
flags.Bool(FlagInsecureSkipHostVerification, false, "Disables hostname verification. Do not use this in production.")
|
||||
flags.Bool(FlagBlock, false, "Block until the connection is up.")
|
||||
}
|
||||
Reference in New Issue
Block a user