From a751446811511b913935c68f145cd57030093dd0 Mon Sep 17 00:00:00 2001 From: Steven Rhodes Date: Mon, 13 Nov 2023 09:10:54 -0800 Subject: [PATCH] Add an optional TargetConn to RPCAuthInput (#361) We're finding cases where we want the sansshell proxy to make gRPC calls to the target sansshell server as part of gathering input for policy evaluation. For example, for MPA we want the proxy to call out to the server to check if there's any MPA approval for a request. The ways of doing this in RPCAuthzHook without adding it to RPCAuthInput get very hacky. It's possible to pull out the hosts's address and dial it, but then you're establishing a separate redundant connection and you need to replicate dial options around things like authentication and metrics. We can't change the hook interface, so our two options are adding a new field to RPCAuthInput or putting the connection into the context. Putting it into the context is possible but we should be putting "request-scoped data that transits processes and API boundaries" in there and a grpc connection doesn't fit that model. We're left with the new RPCAuthInput field as the best option. This PR introduces the first field in RPCAuthInput that's meant purely for use by RPCAuthzHooks and not for policy evaluation. Part of https://github.com/Snowflake-Labs/sansshell/issues/346 --- auth/opa/rpcauth/input.go | 8 ++++++++ proxy/server/target.go | 1 + 2 files changed, 9 insertions(+) diff --git a/auth/opa/rpcauth/input.go b/auth/opa/rpcauth/input.go index bbb7bdc2..81d2bc82 100644 --- a/auth/opa/rpcauth/input.go +++ b/auth/opa/rpcauth/input.go @@ -22,6 +22,7 @@ import ( "encoding/json" "net" + "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" @@ -60,6 +61,13 @@ type RPCAuthInput struct { // Implementation specific extensions. Extensions json.RawMessage `json:"extensions"` + + // TargetConn is a connection to the target under evaluation. It is only non-nil when + // the policy evaluation is being performed by some entity other than the host and + // can be used in rpcauth hooks to gather information by making RPC calls to the + // host. + // TargetConn is not exposed to policy evaluation. + TargetConn grpc.ClientConnInterface `json:"-"` } // EnvironmentInput contains information about the environment in which the policy evaluation is diff --git a/proxy/server/target.go b/proxy/server/target.go index 314e938b..54784968 100644 --- a/proxy/server/target.go +++ b/proxy/server/target.go @@ -289,6 +289,7 @@ func (s *TargetStream) Run(nonce uint32, replyChan chan *pb.ProxyReply) { authinput.Environment = &rpcauth.EnvironmentInput{ NonHostPolicyCheck: true, } + authinput.TargetConn = grpcConn // If authz fails, close immediately with an error if err := s.authorizer.Eval(ctx, authinput); err != nil {