diff --git a/examples/features/csm_observability/client/main.go b/examples/features/csm_observability/client/main.go index cf33e6cb641d..c5b81ff0beb7 100644 --- a/examples/features/csm_observability/client/main.go +++ b/examples/features/csm_observability/client/main.go @@ -30,7 +30,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" xdscreds "google.golang.org/grpc/credentials/xds" - "google.golang.org/grpc/examples/features/proto/echo" + pb "google.golang.org/grpc/examples/helloworld/helloworld" "google.golang.org/grpc/stats/opentelemetry" "google.golang.org/grpc/stats/opentelemetry/csm" _ "google.golang.org/grpc/xds" // To install the xds resolvers and balancers. @@ -40,9 +40,12 @@ import ( "go.opentelemetry.io/otel/sdk/metric" ) +const defaultName = "world" + var ( target = flag.String("target", "xds:///helloworld:50051", "the server address to connect to") prometheusEndpoint = flag.String("prometheus_endpoint", ":9464", "the Prometheus exporter endpoint") + name = flag.String("name", defaultName, "Name to greet") ) func main() { @@ -68,15 +71,15 @@ func main() { log.Fatalf("Failed to start NewClient: %v", err) } defer cc.Close() - c := echo.NewEchoClient(cc) + c := pb.NewGreeterClient(cc) // Make an RPC every second. This should trigger telemetry to be emitted from // the client and the server. for { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - r, err := c.UnaryEcho(ctx, &echo.EchoRequest{Message: "this is examples/opentelemetry"}) + r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name}) if err != nil { - log.Printf("UnaryEcho failed: %v", err) + log.Fatalf("Could not greet: %v", err) } fmt.Println(r) time.Sleep(time.Second) diff --git a/examples/features/csm_observability/server/main.go b/examples/features/csm_observability/server/main.go index 7a87517cbde6..3c4c7a328e0c 100644 --- a/examples/features/csm_observability/server/main.go +++ b/examples/features/csm_observability/server/main.go @@ -22,7 +22,6 @@ package main import ( "context" "flag" - "fmt" "log" "net" "net/http" @@ -30,7 +29,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" xdscreds "google.golang.org/grpc/credentials/xds" - pb "google.golang.org/grpc/examples/features/proto/echo" + pb "google.golang.org/grpc/examples/helloworld/helloworld" "google.golang.org/grpc/stats/opentelemetry" "google.golang.org/grpc/stats/opentelemetry/csm" "google.golang.org/grpc/xds" @@ -45,13 +44,15 @@ var ( prometheusEndpoint = flag.String("prometheus_endpoint", ":9464", "the Prometheus exporter endpoint") ) -type echoServer struct { - pb.UnimplementedEchoServer +// server is used to implement helloworld.GreeterServer. +type server struct { + pb.UnimplementedGreeterServer addr string } -func (s *echoServer) UnaryEcho(_ context.Context, req *pb.EchoRequest) (*pb.EchoResponse, error) { - return &pb.EchoResponse{Message: fmt.Sprintf("%s (from %s)", req.Message, s.addr)}, nil +// SayHello implements helloworld.GreeterServer +func (s *server) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { + return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil } func main() { @@ -80,7 +81,7 @@ func main() { if err != nil { log.Fatalf("Failed to start xDS Server: %v", err) } - pb.RegisterEchoServer(s, &echoServer{addr: ":" + *port}) + pb.RegisterGreeterServer(s, &server{addr: ":" + *port}) log.Printf("Serving on %s\n", *port) diff --git a/internal/xds/rbac/rbac_engine.go b/internal/xds/rbac/rbac_engine.go index 344052cb04fd..8f376c400333 100644 --- a/internal/xds/rbac/rbac_engine.go +++ b/internal/xds/rbac/rbac_engine.go @@ -219,6 +219,9 @@ func newRPCData(ctx context.Context) (*rpcData, error) { if !ok { return nil, errors.New("missing method in incoming context") } + // gRPC-Go strips :path from the headers given to the application, but RBAC should be + // able to match against it. + md[":path"] = []string{mn} // The connection is needed in order to find the destination address and // port of the incoming RPC Call. diff --git a/test/xds/xds_server_rbac_test.go b/test/xds/xds_server_rbac_test.go index 831f2512a96a..f05cd05e5fd9 100644 --- a/test/xds/xds_server_rbac_test.go +++ b/test/xds/xds_server_rbac_test.go @@ -478,6 +478,30 @@ func (s) TestRBACHTTPFilter(t *testing.T) { wantStatusEmptyCall: codes.PermissionDenied, wantStatusUnaryCall: codes.OK, }, + // This test tests an RBAC HTTP Filter which is configured to allow only + // RPC's with certain paths ("UnaryCall") via the ":path" header. Only + // unary calls passing through this RBAC HTTP Filter should proceed as + // normal, and any others should be denied. + { + name: "allow-certain-path-by-header", + rbacCfg: &rpb.RBAC{ + Rules: &v3rbacpb.RBAC{ + Action: v3rbacpb.RBAC_ALLOW, + Policies: map[string]*v3rbacpb.Policy{ + "certain-path": { + Permissions: []*v3rbacpb.Permission{ + {Rule: &v3rbacpb.Permission_Header{Header: &v3routepb.HeaderMatcher{Name: ":path", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_ExactMatch{ExactMatch: "/grpc.testing.TestService/UnaryCall"}}}}, + }, + Principals: []*v3rbacpb.Principal{ + {Identifier: &v3rbacpb.Principal_Any{Any: true}}, + }, + }, + }, + }, + }, + wantStatusEmptyCall: codes.PermissionDenied, + wantStatusUnaryCall: codes.OK, + }, // This test that a RBAC Config with nil rules means that every RPC is // allowed. This maps to the line "If absent, no enforcing RBAC policy // will be applied" from the RBAC Proto documentation for the Rules