Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

authz: create interceptors for gRPC security policy API #4664

Merged
merged 14 commits into from Sep 2, 2021
5 changes: 2 additions & 3 deletions authz/rbac_translator.go
Expand Up @@ -285,7 +285,7 @@ func translatePolicy(policyStr string) ([]*v3rbacpb.RBAC, error) {
if len(policy.AllowRules) == 0 {
return nil, fmt.Errorf(`"allow_rules" is not present`)
}
var rbacs []*v3rbacpb.RBAC
rbacs := make([]*v3rbacpb.RBAC, 0, 2)
if len(policy.DenyRules) > 0 {
denyPolicies, err := parseRules(policy.DenyRules, policy.Name)
if err != nil {
Expand All @@ -302,6 +302,5 @@ func translatePolicy(policyStr string) ([]*v3rbacpb.RBAC, error) {
return nil, fmt.Errorf(`"allow_rules" %v`, err)
}
allowRBAC := &v3rbacpb.RBAC{Action: v3rbacpb.RBAC_ALLOW, Policies: allowPolicies}
rbacs = append(rbacs, allowRBAC)
return rbacs, nil
return append(rbacs, allowRBAC), nil
}
53 changes: 16 additions & 37 deletions authz/sdk_end2end_test.go
Expand Up @@ -16,12 +16,6 @@
*
*/

// Package authz_test contains tests for authz.
//
// Experimental
//
// Notice: This package is EXPERIMENTAL and may be changed or removed
// in a later release.
package authz_test

import (
Expand Down Expand Up @@ -107,7 +101,7 @@ func TestSDKEnd2End(t *testing.T) {
}`,
md: metadata.Pairs("key-abc", "val-abc"),
wantStatusCode: codes.PermissionDenied,
wantErr: "Unauthorized RPC request rejected.",
wantErr: "unauthorized RPC request rejected",
},
"DeniesRpcRequestMatchInDenyAndAllow": {
authzPolicy: `{
Expand Down Expand Up @@ -138,7 +132,7 @@ func TestSDKEnd2End(t *testing.T) {
]
}`,
wantStatusCode: codes.PermissionDenied,
wantErr: "Unauthorized RPC request rejected.",
wantErr: "unauthorized RPC request rejected",
},
"AllowsRpcRequestNoMatchInDenyMatchInAllow": {
authzPolicy: `{
Expand Down Expand Up @@ -206,7 +200,7 @@ func TestSDKEnd2End(t *testing.T) {
]
}`,
wantStatusCode: codes.PermissionDenied,
wantErr: "Unauthorized RPC request rejected.",
wantErr: "unauthorized RPC request rejected",
},
"AllowsRpcRequestEmptyDenyMatchInAllow": {
authzPolicy: `{
Expand Down Expand Up @@ -255,51 +249,41 @@ func TestSDKEnd2End(t *testing.T) {
]
}`,
wantStatusCode: codes.PermissionDenied,
wantErr: "Unauthorized RPC request rejected.",
wantErr: "unauthorized RPC request rejected",
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
// Start a gRPC server with SDK unary and stream server interceptors.
i, _ := authz.NewStatic(test.authzPolicy)
serverOpts := []grpc.ServerOption{
grpc.ChainUnaryInterceptor(i.UnaryInterceptor),
grpc.ChainStreamInterceptor(i.StreamInterceptor),
}
lis, err := net.Listen("tcp", ":0")
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("error listening: %v", err)
}
s := grpc.NewServer(serverOpts...)
s := grpc.NewServer(
grpc.ChainUnaryInterceptor(i.UnaryInterceptor),
grpc.ChainStreamInterceptor(i.StreamInterceptor))
pb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)

// Establish a connection to the server.
dialOptions := []grpc.DialOption{
grpc.WithInsecure(),
grpc.WithBlock(),
}
clientConn, err := grpc.Dial(lis.Addr().String(), dialOptions...)
clientConn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure())
if err != nil {
t.Fatalf("grpc.Dial(%v, %v) failed: %v", lis.Addr().String(), dialOptions, err)
t.Fatalf("grpc.Dial(%v) failed: %v", lis.Addr().String(), err)
}
defer clientConn.Close()
client := pb.NewTestServiceClient(clientConn)

ctx := metadata.NewOutgoingContext(context.Background(), test.md)

// Verifying authorization decision for Unary RPC.
_, err = client.UnaryCall(ctx, &pb.SimpleRequest{}, grpc.WaitForReady(true))
gotStatus, _ := status.FromError(err)
if gotStatus.Code() != test.wantStatusCode {
t.Fatalf("[UnaryCall] status code want:%v got:%v", test.wantStatusCode, gotStatus.Code())
}
if gotStatus.Message() != test.wantErr {
t.Fatalf("[UnaryCall] error message want:%v got:%v", test.wantErr, gotStatus.Message())
_, err = client.UnaryCall(ctx, &pb.SimpleRequest{})
dfawley marked this conversation as resolved.
Show resolved Hide resolved
if got := status.Convert(err); got.Code() != test.wantStatusCode || got.Message() != test.wantErr {
t.Fatalf("[UnaryCall] error want:{%v %v} got:{%v %v}", test.wantStatusCode, test.wantErr, got.Code(), got.Message())
}

// Verifying authorization decision for Streaming RPC.
stream, err := client.StreamingInputCall(ctx, grpc.WaitForReady(true))
stream, err := client.StreamingInputCall(ctx)
if err != nil {
t.Fatalf("failed StreamingInputCall err: %v", err)
}
Expand All @@ -312,14 +296,9 @@ func TestSDKEnd2End(t *testing.T) {
t.Fatalf("failed stream.Send err: %v", err)
}
_, err = stream.CloseAndRecv()
gotStatus, _ = status.FromError(err)
if gotStatus.Code() != test.wantStatusCode {
t.Fatalf("[StreamingCall] status code want:%v got:%v", test.wantStatusCode, gotStatus.Code())
}
if gotStatus.Message() != test.wantErr {
t.Fatalf("[StreamingCall] error message want:%v got:%v", test.wantErr, gotStatus.Message())
if got := status.Convert(err); got.Code() != test.wantStatusCode || got.Message() != test.wantErr {
t.Fatalf("[StreamingCall] error want:{%v %v} got:{%v %v}", test.wantStatusCode, test.wantErr, got.Code(), got.Message())
}

})
}
}
4 changes: 2 additions & 2 deletions authz/sdk_server_interceptors.go
Expand Up @@ -55,7 +55,7 @@ func (i *StaticInterceptor) UnaryInterceptor(ctx context.Context, req interface{
return handler(ctx, req)
}
if status.Code(err) == codes.PermissionDenied {
return nil, status.Errorf(codes.PermissionDenied, "Unauthorized RPC request rejected.")
return nil, status.Errorf(codes.PermissionDenied, "unauthorized RPC request rejected")
}
return nil, err
dfawley marked this conversation as resolved.
Show resolved Hide resolved
}
Expand All @@ -69,7 +69,7 @@ func (i *StaticInterceptor) StreamInterceptor(srv interface{}, ss grpc.ServerStr
return handler(srv, ss)
}
if status.Code(err) == codes.PermissionDenied {
return status.Errorf(codes.PermissionDenied, "Unauthorized RPC request rejected.")
return status.Errorf(codes.PermissionDenied, "unauthorized RPC request rejected")
}
return err
}