From e6968e1c2c38f7fff8729e21e989703efe042965 Mon Sep 17 00:00:00 2001 From: Dan Fuhry Date: Wed, 19 Nov 2025 09:26:04 -0500 Subject: [PATCH] [grpc] make PeerIdentity take a context instead of peer.Peer; break out cert retrieval into new PeerCertificate helper --- attestation/internal/attestation/BUILD.bazel | 1 - .../internal/attestation/rpc_server.go | 16 +------ echo/BUILD.bazel | 1 - echo/server.go | 8 +--- ephs/servicer/servicer.go | 2 +- grpc/imports.go | 1 + grpc/internal/server/context.go | 2 +- grpc/internal/server/server.go | 48 ++++++++++++++----- 8 files changed, 43 insertions(+), 36 deletions(-) diff --git a/attestation/internal/attestation/BUILD.bazel b/attestation/internal/attestation/BUILD.bazel index 5fd6332..ccc655e 100644 --- a/attestation/internal/attestation/BUILD.bazel +++ b/attestation/internal/attestation/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "//utils/log", "@com_github_google_certificate_transparency_go//x509", "@com_github_google_go_attestation//attest", - "@org_golang_google_grpc//peer", "@org_golang_google_protobuf//encoding/protojson", "@org_golang_google_protobuf//reflect/protoreflect", ], diff --git a/attestation/internal/attestation/rpc_server.go b/attestation/internal/attestation/rpc_server.go index 62e6344..d3b1104 100644 --- a/attestation/internal/attestation/rpc_server.go +++ b/attestation/internal/attestation/rpc_server.go @@ -8,8 +8,6 @@ import ( "net/url" "time" - "google.golang.org/grpc/peer" - "go.fuhry.dev/runtime/grpc" attest_pb "go.fuhry.dev/runtime/proto/service/attest" "google.golang.org/protobuf/encoding/protojson" @@ -44,12 +42,7 @@ func NewAttestationServer() attest_pb.AttestServer { } func (s *AttestServer) GetActivationChallenge(ctx context.Context, req *attest_pb.GetActivationChallengeRequest) (*attest_pb.GetActivationChallengeResponse, error) { - peer, ok := peer.FromContext(ctx) - if !ok { - return nil, fmt.Errorf("provided context did not contain peer anything") - } - - spiffe, err := grpc.PeerIdentity(peer) + spiffe, err := grpc.PeerIdentity(ctx) if err != nil { return nil, err } @@ -96,12 +89,7 @@ func (s *AttestServer) GetActivationChallenge(ctx context.Context, req *attest_p } func (s *AttestServer) AttestPlatform(ctx context.Context, req *attest_pb.AttestPlatformRequest) (*attest_pb.AttestPlatformResponse, error) { - peer, ok := peer.FromContext(ctx) - if !ok { - return nil, fmt.Errorf("provided context did not contain peer anything") - } - - spiffe, err := grpc.PeerIdentity(peer) + spiffe, err := grpc.PeerIdentity(ctx) if err != nil { return nil, err } diff --git a/echo/BUILD.bazel b/echo/BUILD.bazel index 9992ff0..2d34dd0 100644 --- a/echo/BUILD.bazel +++ b/echo/BUILD.bazel @@ -8,7 +8,6 @@ go_library( deps = [ "//grpc", "//proto/service/echo", - "@org_golang_google_grpc//peer", "@org_golang_x_text//cases", "@org_golang_x_text//language", ], diff --git a/echo/server.go b/echo/server.go index bafcf50..69cae01 100644 --- a/echo/server.go +++ b/echo/server.go @@ -6,7 +6,6 @@ import ( "golang.org/x/text/cases" "golang.org/x/text/language" - "google.golang.org/grpc/peer" grpc_lib "go.fuhry.dev/runtime/grpc" echo_pb "go.fuhry.dev/runtime/proto/service/echo" @@ -29,12 +28,7 @@ func (s *EchoServer) Echo(ctx context.Context, req *echo_pb.EchoRequest) (*echo_ } func (s *EchoServer) Greet(ctx context.Context, req *echo_pb.GreetRequest) (*echo_pb.GreetReply, error) { - peer, ok := peer.FromContext(ctx) - if !ok { - return nil, fmt.Errorf("provided context did not contain peer anything") - } - - spiffe, err := grpc_lib.PeerIdentity(peer) + spiffe, err := grpc_lib.PeerIdentity(ctx) if err != nil { return nil, err } diff --git a/ephs/servicer/servicer.go b/ephs/servicer/servicer.go index d1f47c7..eccb51b 100644 --- a/ephs/servicer/servicer.go +++ b/ephs/servicer/servicer.go @@ -681,7 +681,7 @@ func identityFromContext(ctx context.Context) (string, error) { return "", status.Error(codes.Unauthenticated, "who are you??") } - ident, err := grpc.PeerIdentity(peer) + ident, err := grpc.PeerIdentity(ctx) if err != nil { return "", status.Errorf(codes.PermissionDenied, "cannot determine your identity from peer info: %v", peer.AuthInfo) } diff --git a/grpc/imports.go b/grpc/imports.go index 6c2de64..5fdef20 100644 --- a/grpc/imports.go +++ b/grpc/imports.go @@ -36,5 +36,6 @@ var NewGrpcClient = client.NewGrpcClient var RandomPort = server.RandomPort var NewGrpcServer = server.NewGrpcServer var NewGrpcServerWithPort = server.NewGrpcServerWithPort +var PeerCertificate = server.PeerCertificate var PeerIdentity = server.PeerIdentity var NewHealthCheckServicer = server.NewHealthCheckServicer diff --git a/grpc/internal/server/context.go b/grpc/internal/server/context.go index 4a92d58..4ceabe4 100644 --- a/grpc/internal/server/context.go +++ b/grpc/internal/server/context.go @@ -30,7 +30,7 @@ func SessionFromContext(ctx context.Context) Session { return nil } - if peerSpiffe, err := PeerIdentity(peer); err == nil { + if peerSpiffe, err := PeerIdentity(ctx); err == nil { sessionKey := fmt.Sprintf("%s:%s:%s", peerSpiffe.String(), peer.Addr.Network(), peer.Addr.String()) log.Default().V(3).Debugf("peer session key: %s", sessionKey) server := ctx.Value(kServer).(*Server) diff --git a/grpc/internal/server/server.go b/grpc/internal/server/server.go index 7ce5aef..d5a3739 100644 --- a/grpc/internal/server/server.go +++ b/grpc/internal/server/server.go @@ -164,11 +164,7 @@ func (s *Server) handleConnection(ctx context.Context, req interface{}, info *gr return handler(ctx, req) } - peer, ok := peer.FromContext(ctx) - if !ok { - return nil, status.Errorf(codes.PermissionDenied, "client did not authenticate") - } - spiffe, err := PeerIdentity(peer) + spiffe, err := PeerIdentity(ctx) if err != nil { return nil, err } @@ -188,11 +184,7 @@ func (s *Server) handleStreamConnection(srv interface{}, ss grpc.ServerStream, i } ctx := ss.Context() - peer, ok := peer.FromContext(ctx) - if !ok { - return status.Errorf(codes.PermissionDenied, "client did not authenticate") - } - spiffe, err := PeerIdentity(peer) + spiffe, err := PeerIdentity(ctx) if err != nil { return err } @@ -204,7 +196,41 @@ func (s *Server) handleStreamConnection(srv interface{}, ss grpc.ServerStream, i return handler(srv, ss) } -func PeerIdentity(peer *peer.Peer) (*url.URL, error) { +func PeerCertificate(ctx context.Context) (*x509.Certificate, error) { + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, status.Errorf(codes.PermissionDenied, "client did not authenticate") + } + + if peer.AuthInfo == nil { + return nil, status.Errorf(codes.PermissionDenied, "no AuthInfo present in peer information") + } + + var tlsState tls.ConnectionState + + switch ai := peer.AuthInfo.(type) { + case credentials.TLSInfo: + tlsState = ai.State + case *grpc_quic.Info: + conn := ai.Conn() + tlsState = conn.(*grpc_quic.Conn).TLSState() + default: + return nil, status.Errorf(codes.PermissionDenied, "unhandled type of peer.AuthInfo: %T", peer.AuthInfo) + } + + if len(tlsState.PeerCertificates) == 0 { + return nil, errors.New("no peer certificate provided") + } + + return tlsState.PeerCertificates[0], nil +} + +func PeerIdentity(ctx context.Context) (*url.URL, error) { + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, status.Errorf(codes.PermissionDenied, "client did not authenticate") + } + if peer.AuthInfo == nil { return nil, status.Errorf(codes.PermissionDenied, "no AuthInfo present in peer information") } -- 2.50.1