Lädt...


🔧 Use RBAC to protect your gRPC service right on proto definition


Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to

We have a simple gRPC service:

message GetUserRequest {
  string id = 1;
}

message GetUserResponse {
  string id = 1;
  string name = 2;
  string email = 3;
}

service UsersService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
}

gRPC is great in many ways, its performance is great, its ecosystem cannot be compared.

But imho, top over all of that is a typed contract its provide.

I'm a backend engineer, I and my mobile and web friends can sit down, discuss, come up with an agreement then we generate the stub client code in flutter and es for mock implementation, regroup after 3 days.

A good and performance day!

But wait, we're missing something!

What exactly user role can call this API?

service UsersService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
}

GetUser method almost have everything, but still not enough for describing the authorization requirement.

  • Get: this is the verb, the action
  • User: this is the resource

And we only missing the Role part to describe a RBAC rule.

Tooooo bad, we come so close, just if we can do something, something type-safe, something generic... 😢

Your wish will come true, with the help of proto descriptor

First, extend the google.protobuf.MethodOptions to describe your policy

enum Role {
  ROLE_UNSPECIFIED = 0;
  ROLE_CUSTOMER = 1;
  ROLE_ADMIN = 2;
}

message RoleBasedAccessControl {
  repeated Role allowed_roles = 1;
  bool allow_unauthenticated = 2;
}

extend google.protobuf.MethodOptions {
  optional RoleBasedAccessControl access_control = 90000; // I don't know about this 90000, seem as long as it's unique
}

Then, use the new MethodOptions in your Methods definition (mind the import path)

service UsersService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse) {
    option (components.rbac.v1.access_control) = {
      allowed_roles: [
        ROLE_CUSTOMER,
        ROLE_ADMIN
      ]
      allow_unauthenticated: false
    };
  }

  rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) {
    option (components.rbac.v1.access_control) = {
      allowed_roles: [ROLE_ADMIN]
      allow_unauthenticated: false
    };
  }
}

Then fork and modify the grpc-go proto generator command

Just kidding, the night is late and I need to be in the office before 08:00 AM 😢

Solution: write an interceptor and use it with your server

Load the methods descriptor:

func RBACUnaryInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
    // the info give us: /components.users.v1.UsersService/GetUser
    // we need to convert it to components.users.v1.UsersService.GetUser
    methodName := strings.Replace(strings.TrimPrefix(info.FullMethod, "/"), "/", ".", -1)
    desc, err := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(methodName))
    if err != nil {
        return nil, status.Errorf(codes.Internal, "method not found descriptor")
    }

    method, ok := desc.(protoreflect.MethodDescriptor)
    if !ok {
        return nil, status.Errorf(codes.Internal, "some hoe this is not a method")
    }

Find our access_control option:

    var policy *rbacv1.RoleBasedAccessControl
    method.Options().ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
        if fd.FullName() != rbacv1.E_AccessControl.TypeDescriptor().FullName() {
            // continue finding the AccessControl field
            return true
        }

        b, err := proto.Marshal(v.Message().Interface())
        if err != nil {
            // TODO: better handle this as an Internal error
            // but for now, just return PermissionDenied
            return false
        }

        policy = &rbacv1.RoleBasedAccessControl{}
        if err := proto.Unmarshal(b, policy); err != nil {
            // same as above, better handle this as an Internal error
            return false
        }

        // btw I think this policy can be cached

        return false
    })

    if policy == nil {
        // secure by default, DENY_ALL if no control policy is found
        return nil, status.Errorf(codes.PermissionDenied, "permission denied")
    }

Example:

Add or append the newly created interceptor to your backend

func newUsersServer() *grpc.Server {
    svc := grpc.NewServer(grpc.UnaryInterceptor(interceptors.RBACUnaryInterceptor))
    usersv1.RegisterUsersServiceServer(svc, &usersServer{})
    return svc
}

Then test it:

    peasantCtx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("role", "ROLE_CUSTOMER"))
    _, err = client.GetUser(peasantCtx, &usersv1.GetUserRequest{})
    fmt.Println(status.Code(err))

    _, err = client.DeleteUser(peasantCtx, &usersv1.DeleteUserRequest{})
    fmt.Println(status.Code(err))

    knightlyAdminCtx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("role", "ROLE_ADMIN"))
    _, err = client.GetUser(knightlyAdminCtx, &usersv1.GetUserRequest{})
    fmt.Println(status.Code(err))

    _, err = client.DeleteUser(knightlyAdminCtx, &usersv1.DeleteUserRequest{})
    fmt.Println(status.Code(err))
    // Output:
    // OK
    // PermissionDenied
    // OK
    // OK

Finally, example code with testable Example published here https://github.com/nvcnvn/grpc-methods-descriptor-example

...

🔧 Use RBAC to protect your gRPC service right on proto definition


📈 88.85 Punkte
🔧 Programmierung

🔧 Browser Client to gRPC Server Routing options: Connect, gRPC-web, gRPC-gateway and more!


📈 49.16 Punkte
🔧 Programmierung

🔧 angular-rbac the RBAC lightweight library for your next Angular projects


📈 37.87 Punkte
🔧 Programmierung

🕵️ grpc/grpc-js Prototype loadPackageDefinition code injection


📈 32.77 Punkte
🕵️ Sicherheitslücken

🔧 ASP.NET Community Standup - June 4th, 2019 - gRPC with the gRPC Team | .NET Community Standups


📈 32.77 Punkte
🔧 Programmierung

📰 What Is RBAC? Role-Based Access Control Definition, Benefits, Best Practices, and Examples


📈 29.23 Punkte
📰 IT Security Nachrichten

📰 What Is RBAC? Role-Based Access Control Definition, Benefits, Best Practices, and Examples


📈 29.23 Punkte
📰 IT Security Nachrichten

🔧 Android Proto DataStore – Should You Use It?


📈 23.53 Punkte
🔧 Programmierung

🔧 tRPC, gRPC, GraphQL or REST: Choosing the Right API Technology


📈 23.35 Punkte
🔧 Programmierung

🔧 Choosing the Right API Architecture - A Deep Dive into RESTful API & gRPC Protocols


📈 23.35 Punkte
🔧 Programmierung

🕵️ Sandstorm Cap'n Proto up to 0.5.3.0 Compiler Optimization denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark up to 1.12.10/2.0.2 epan/proto.c denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 2.6.1 MMSE Dissector epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ PBC bis 2017-03-02 proto.c _pbcP_message_default Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ protobufjs auf Node.js proto File Regular Expression Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 2.6.0 RRC Dissector epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Sandstorm Cap'n Proto bis 0.4.1.0/0.5.1.0 Element CPU Exhaustion Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Sandstorm Cap'n Proto bis 0.4.1.0/0.5.1.0 Incomplete Fix totalSize Application Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Cap'n Proto: Eine Schwachstelle ermöglicht einen Denial-of-Service-Angriff


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Sandstorm Cap'n Proto bis 0.5.3.0 Compiler Optimization Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark up to 2.6.1 MMSE Dissector epan/proto.c denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 1.12.12/2.0.4 OpenFlow Dissector epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ PBC up to 2017-03-02 proto.c _pbcP_message_default denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 1.12.10/2.0.2 epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ protobufjs on Node.js proto File Regular Expression denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 1.12.12/2.0.4 OpenFlow Dissector epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark bis 1.12.10/2.0.2 epan/proto.c Denial of Service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Wireshark up to 2.6.0 RRC Dissector epan/proto.c denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Sandstorm Cap'n Proto up to 0.4.1.0/0.5.1.0 Element CPU Exhaustion denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

🕵️ Sandstorm Cap'n Proto up to 0.4.1.0/0.5.1.0 Incomplete Fix totalSize Application denial of service


📈 22.06 Punkte
🕵️ Sicherheitslücken

matomo