@@ -5,16 +5,12 @@ import (
55 "crypto/tls"
66 "crypto/x509"
77 "fmt"
8- "os"
9- "sync"
10-
118 "google.golang.org/grpc"
129 "google.golang.org/grpc/credentials"
1310 "google.golang.org/grpc/keepalive"
11+ "k8s.io/apimachinery/pkg/util/errors"
12+ "os"
1413
15- "k8s.io/klog/v2"
16-
17- pbv1 "open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/protobuf/v1"
1814 "open-cluster-management.io/sdk-go/pkg/cloudevents/generic/types"
1915 "open-cluster-management.io/sdk-go/pkg/cloudevents/server"
2016 grpcserver "open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc"
@@ -29,11 +25,12 @@ type PreStartHook interface {
2925}
3026
3127type Server struct {
32- options * GRPCServerOptions
33- authenticators []authn.Authenticator
34- authorizers []authz.Authorizer
35- services map [types.CloudEventsDataType ]server.Service
36- hooks []PreStartHook
28+ options * GRPCServerOptions
29+ authenticators []authn.Authenticator
30+ unarayAuthorizers []authz.UnaryAuthorizer
31+ streamAuthorizers []authz.StreamAuthorizer
32+ services map [types.CloudEventsDataType ]server.Service
33+ hooks []PreStartHook
3734}
3835
3936func NewServer (opt * GRPCServerOptions ) * Server {
@@ -45,8 +42,13 @@ func (s *Server) WithAuthenticator(authenticator authn.Authenticator) *Server {
4542 return s
4643}
4744
48- func (s * Server ) WithAuthorizer (authorizer authz.Authorizer ) * Server {
49- s .authorizers = append (s .authorizers , authorizer )
45+ func (s * Server ) WithUnarayAuthorizer (authorizer authz.UnaryAuthorizer ) * Server {
46+ s .unarayAuthorizers = append (s .unarayAuthorizers , authorizer )
47+ return s
48+ }
49+
50+ func (s * Server ) WithStreamAuthorizer (authorizer authz.StreamAuthorizer ) * Server {
51+ s .streamAuthorizers = append (s .streamAuthorizers , authorizer )
5052 return s
5153}
5254
@@ -110,10 +112,10 @@ func (s *Server) Run(ctx context.Context) error {
110112 grpcServerOptions = append (grpcServerOptions ,
111113 grpc .ChainUnaryInterceptor (
112114 newAuthnUnaryInterceptor (s .authenticators ... ),
113- newAuthzUnaryInterceptor (s .authorizers ... )),
115+ newAuthzUnaryInterceptor (s .unarayAuthorizers ... )),
114116 grpc .ChainStreamInterceptor (
115117 newAuthnStreamInterceptor (s .authenticators ... ),
116- newAuthzStreamInterceptor (s .authorizers ... )))
118+ newAuthzStreamInterceptor (s .streamAuthorizers ... )))
117119
118120 grpcServer := grpc .NewServer (grpcServerOptions ... )
119121 grpcEventServer := grpcserver .NewGRPCBroker (grpcServer )
@@ -155,37 +157,27 @@ func newAuthnUnaryInterceptor(authenticators ...authn.Authenticator) grpc.UnaryS
155157 }
156158}
157159
158- func newAuthzUnaryInterceptor (authorizers ... authz.Authorizer ) grpc.UnaryServerInterceptor {
160+ func newAuthzUnaryInterceptor (authorizers ... authz.UnaryAuthorizer ) grpc.UnaryServerInterceptor {
159161 return func (
160162 ctx context.Context ,
161163 req interface {},
162164 info * grpc.UnaryServerInfo ,
163165 handler grpc.UnaryHandler ,
164166 ) (interface {}, error ) {
167+ var errs []error
165168 for _ , authorizer := range authorizers {
166- pReq , ok := req .(* pbv1.PublishRequest )
167- if ! ok {
168- return nil , fmt .Errorf ("unsupported request type %T" , req )
169- }
170-
171- eventsType , err := types .ParseCloudEventsType (pReq .Event .Type )
172- if err != nil {
173- return nil , err
174- }
175-
176- // the event of grpc publish request is the original cloudevent data, we need a `ce-` prefix
177- // to get the event attribute
178- clusterAttr , ok := pReq .Event .Attributes [fmt .Sprintf ("ce-%s" , types .ExtensionClusterName )]
179- if ! ok {
180- return nil , fmt .Errorf ("missing ce-clustername in event attributes, %v" , pReq .Event .Attributes )
169+ if err := authorizer .AuthorizeRequest (ctx , req ); err == nil {
170+ return handler (ctx , req )
171+ } else {
172+ errs = append (errs , err )
181173 }
174+ }
182175
183- if err := authorizer .Authorize (ctx , clusterAttr .GetCeString (), * eventsType ); err != nil {
184- return nil , err
185- }
176+ if len (errs ) > 0 {
177+ return nil , errors .NewAggregate (errs )
186178 }
187179
188- return handler ( ctx , req )
180+ return nil , fmt . Errorf ( "no authorizer found for %s" , info . FullMethod )
189181 }
190182}
191183
@@ -236,32 +228,8 @@ func newAuthnStreamInterceptor(authenticators ...authn.Authenticator) grpc.Strea
236228 }
237229}
238230
239- // wrappedAuthorizedStream caches the subscription request that is already read.
240- type wrappedAuthorizedStream struct {
241- sync.Mutex
242-
243- grpc.ServerStream
244- authorizedReq * pbv1.SubscriptionRequest
245- }
246-
247- // RecvMsg set the msg from the cache.
248- func (c * wrappedAuthorizedStream ) RecvMsg (m any ) error {
249- c .Lock ()
250- defer c .Unlock ()
251-
252- msg , ok := m .(* pbv1.SubscriptionRequest )
253- if ! ok {
254- return fmt .Errorf ("unsupported request type %T" , m )
255- }
256-
257- msg .ClusterName = c .authorizedReq .ClusterName
258- msg .Source = c .authorizedReq .Source
259- msg .DataType = c .authorizedReq .DataType
260- return nil
261- }
262-
263- // newAuthzStreamInterceptor is a stream interceptor that authorizes the subscription request.
264- func newAuthzStreamInterceptor (authorizers ... authz.Authorizer ) grpc.StreamServerInterceptor {
231+ // newAuthzStreamInterceptor is a stream interceptor that authorizes the stream request.
232+ func newAuthzStreamInterceptor (authorizers ... authz.StreamAuthorizer ) grpc.StreamServerInterceptor {
265233 return func (
266234 srv interface {},
267235 ss grpc.ServerStream ,
@@ -272,32 +240,19 @@ func newAuthzStreamInterceptor(authorizers ...authz.Authorizer) grpc.StreamServe
272240 return handler (srv , ss )
273241 }
274242
275- var req pbv1.SubscriptionRequest
276- if err := ss .RecvMsg (& req ); err != nil {
277- return err
278- }
279-
280- eventDataType , err := types .ParseCloudEventsDataType (req .DataType )
281- if err != nil {
282- return err
283- }
284-
285- eventsType := types.CloudEventsType {
286- CloudEventsDataType : * eventDataType ,
287- SubResource : types .SubResourceSpec ,
288- Action : types .WatchRequestAction ,
289- }
243+ var errs []error
290244 for _ , authorizer := range authorizers {
291- if err := authorizer .Authorize (ss .Context (), req .ClusterName , eventsType ); err != nil {
292- return err
245+ if authorizedStream , err := authorizer .AuthorizeStream (ss .Context (), ss , info ); err == nil {
246+ return handler (srv , authorizedStream )
247+ } else {
248+ errs = append (errs , err )
293249 }
294250 }
295251
296- if err := handler (srv , & wrappedAuthorizedStream {ServerStream : ss , authorizedReq : & req }); err != nil {
297- klog .Error (err )
298- return err
252+ if len (errs ) > 0 {
253+ return errors .NewAggregate (errs )
299254 }
300255
301- return nil
256+ return fmt . Errorf ( "no authorizer found for %s" , info . FullMethod )
302257 }
303258}
0 commit comments