package server import ( "context" "log" "net" "testing" "time" apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac" spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" eventservice "code.fbi.h-da.de/danet/gosdn/controller/eventService" "code.fbi.h-da.de/danet/gosdn/controller/nucleus" "code.fbi.h-da.de/danet/gosdn/controller/rbac" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/grpc/test/bufconn" ) func getTestAuthInterceptorServer(t *testing.T) (*AuthInterceptor, *UserServer, *RoleServer, *SbiServer) { initUUIDs(t) jwtManager := rbac.NewJWTManager("test", time.Minute) eventService := eventservice.NewMockEventService() userStore := rbac.NewMemoryUserStore() userService := rbac.NewUserService(userStore, eventService) roleStore := rbac.NewMemoryRoleStore() roleService := rbac.NewRoleService(roleStore, eventService) mockPnd := getMockPnd(t) pndStore := nucleus.NewMemoryPndStore() if err := pndStore.Add(mockPnd); err != nil { t.Fatal(err) } s := NewAuthInterceptor(jwtManager, userService, roleService) u := NewUserServer(jwtManager, userService) r := NewRoleServer(jwtManager, roleService) sbiServer := NewSbiServer(pndStore) clearAndCreateAuthTestSetup(userService, roleService) return s, u, r, sbiServer } func dialer(interceptorServer *AuthInterceptor, userServer *UserServer, roleServer *RoleServer, sbiServer *SbiServer) func(context.Context, string) (net.Conn, error) { listener := bufconn.Listen(1024 * 1024) interceptor := interceptorServer server := grpc.NewServer(grpc.UnaryInterceptor(interceptor.Unary()), grpc.StreamInterceptor(interceptor.Stream())) apb.RegisterUserServiceServer(server, userServer) spb.RegisterSbiServiceServer(server, sbiServer) go func() { if err := server.Serve(listener); err != nil { log.Fatal(err) } }() return func(context.Context, string) (net.Conn, error) { return listener.Dial() } } func TestAuthInterceptor_Unary(t *testing.T) { authServer, userServer, roleServer, sbiServer := getTestAuthInterceptorServer(t) validToken, err := createTestUserToken("testAdmin", true, authServer.userService, authServer.jwtManager) if err != nil { t.Fatal(err) } wrongUserToken, err := createTestUserToken("foo", false, authServer.userService, authServer.jwtManager) if err != nil { t.Fatal(err) } ctx := context.Background() conn, err := grpc.DialContext( ctx, "", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialer(authServer, userServer, roleServer, sbiServer)), ) if err != nil { t.Fatal(err) } defer conn.Close() client := apb.NewUserServiceClient(conn) type args struct { ctx context.Context request *apb.GetUsersRequest } tests := []struct { name string args args want *apb.GetUsersResponse wantErr bool }{ { name: "default unary interceptor", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorize", validToken)), request: &apb.GetUsersRequest{}, }, want: &apb.GetUsersResponse{ Status: apb.Status_STATUS_OK, }, wantErr: false, }, { name: "error unary invalid user token", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorize", wrongUserToken)), request: &apb.GetUsersRequest{}, }, want: nil, wantErr: true, }, { name: "error unary invalid token string", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorize", "foo")), request: &apb.GetUsersRequest{}, }, want: nil, wantErr: true, }, { name: "error unary no token in metadata", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("foo", "foo")), request: &apb.GetUsersRequest{}, }, want: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := client.GetUsers(tt.args.ctx, tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("AuthInterceptor.Unary() = %v, wantErr %v", err, tt.wantErr) return } if got != nil && got.Status != tt.want.Status { t.Errorf("AuthInterceptor.Unary() = %v, wantErr %v", err, tt.wantErr) return } }) } } func TestAuthInterceptor_Stream(t *testing.T) { authServer, userServer, roleServer, sbiServer := getTestAuthInterceptorServer(t) validToken, err := createTestUserToken("testAdmin", true, authServer.userService, authServer.jwtManager) if err != nil { t.Fatal(err) } ctx := context.Background() conn, err := grpc.DialContext( ctx, "", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialer(authServer, userServer, roleServer, sbiServer)), ) if err != nil { t.Fatal(err) } defer conn.Close() client := spb.NewSbiServiceClient(conn) type args struct { ctx context.Context request *spb.GetSchemaRequest } tests := []struct { name string args args want bool }{ { name: "default stream interceptor", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorize", validToken)), request: &spb.GetSchemaRequest{ Pid: pndID, Sid: sbiID, }, }, want: true, }, { name: "error stream interceptor", args: args{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorize", "foo")), request: &spb.GetSchemaRequest{ Pid: pndID, Sid: sbiID, }, }, want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := client.GetSchema(tt.args.ctx, tt.args.request) if err != nil { t.Errorf("AuthInterceptor.Stream() = %v", err) return } payload, _ := got.Recv() if (payload != nil) != tt.want { t.Errorf("AuthInterceptor.Stream() = %v", tt.want) return } }) } } func TestAuthInterceptor_authorize(t *testing.T) { authServer, _, _, _ := getTestAuthInterceptorServer(t) validToken, err := createTestUserToken("testAdmin", true, authServer.userService, authServer.jwtManager) if err != nil { t.Fatal(err) } wrongUserToken, err := createTestUserToken("foo", false, authServer.userService, authServer.jwtManager) if err != nil { t.Fatal(err) } type args struct { ctx context.Context method string } tests := []struct { name string args args wantErr bool }{ { name: "default authorize", args: args{ ctx: metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorize", validToken)), method: "/gosdn.rbac.UserService/GetUsers", }, wantErr: false, }, { name: "error invalid token", args: args{ ctx: metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorize", wrongUserToken)), method: "/gosdn.rbac.UserService/GetUsers", }, wantErr: true, }, { name: "error no permission for request", args: args{ ctx: metadata.NewIncomingContext(context.Background(), metadata.Pairs("authorize", validToken)), method: "/gosdn.pnd.PndService/DeleteOnd", }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := authServer.authorize(tt.args.ctx, tt.args.method); (err != nil) != tt.wantErr { t.Errorf("AuthInterceptor.authorize() error = %v, wantErr %v", err, tt.wantErr) } }) } }