Page MenuHomePhabricator

[services] Tunnelbroker - Adding of gRPC `NewSession` wrapper implementation
ClosedPublic

Authored by max on Oct 27 2022, 6:15 AM.
Tags
None
Referenced Files
F2169559: D5490.id17954.diff
Tue, Jul 2, 12:07 PM
Unknown Object (File)
Mon, Jul 1, 3:23 AM
Unknown Object (File)
Sat, Jun 29, 11:34 PM
Unknown Object (File)
Sat, Jun 29, 2:09 AM
Unknown Object (File)
Thu, Jun 27, 12:47 AM
Unknown Object (File)
Wed, Jun 26, 3:26 AM
Unknown Object (File)
Tue, Jun 25, 11:48 PM
Unknown Object (File)
Tue, Jun 25, 12:13 PM

Details

Summary

This diff introduces the implementation of NewSession gRPC handler using the Rust Tonic gRPC server by calling the newSessionHandler C++ handler wrapper function.
The new implementation is a wrapper of the current NewSession C++ handler for using and calling from Rust gRPC server codebase.

Linear task: ENG-2059

Test Plan

1. Building:
The service was successfully built with the CI process or can be built manually using the cargo build command in services/tunnelbroker directory.

2. gRPC testings:
First, run the service using the cargo run command.

Open the gRPC client and call the SessionSignature request with the valid deviceID.
For example:

{
  "deviceID": "mobile:foS4IBADcn3uUNF8DEoH2jj6b8hujMsKUtNAKhJID4U50oalGWyg9rdLpgJwlmRy"
}

The expected result should be the toSign generated string from the server:

{
  "toSign": "7u1iiQNBlrsn0qy9BhlX8BJxttS6cBNnuCtJR1N9Mp8up56Qc4BEZWc9OvJYjlou"
}

Generate a key pair and sign the toSign string by the private key. Then call NewSession gRPC request with the following data:

{
"deviceID" = "mobile:foS4IBADcn3uUNF8DEoH2jj6b8hujMsKUtNAKhJID4U50oalGWyg9rdLpgJwlmRy"
"publicKey = "Your public key"
"signature" = "Signed `toSign` string by your private key from the previous request"
"notifyToken" = "Notification token you can leave it empty"
"deviceType" = "MOBILE"
"deviceAppVersion" = "You can leave it empty for tests"
deviceOS" = "You can leave it empty for tests"
}

The successful response should be the sessionID with the new client session identification.

In case of the wrong signed toSign string, the server will return an error: "Signature for the verification message is not valid".

Diff Detail

Repository
rCOMM Comm
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

max held this revision as a draft.
max edited the test plan for this revision. (Show Details)
max added reviewers: varun, marcin.
max edited the test plan for this revision. (Show Details)
max published this revision for review.Oct 27 2022, 6:41 AM

Rebasing on a parent changes.

services/tunnelbroker/src/server/mod.rs
45–51 ↗(On Diff #17954)

Unfortunately in Rust, we can't cast from int to enum (but, can do the opposite) and we must use matching ((
Related links: Github issue in Rust repo, rust-lang thread. We can possibly use num-derive crate, but it's not possible to do in the generated gRPC files and CXX because of the impl in the enum which is not supported by CXX.

otherwise LGTM

services/tunnelbroker/src/server/mod.rs
41–44 ↗(On Diff #17954)

if you want to make this a bit smaller

services/tunnelbroker/src/server/mod.rs
45–51 ↗(On Diff #17954)

https://github.com/dtolnay/serde-repr or https://serde.rs/enum-number.html might be of interest, then we can offload the deserialization from our domain of responsibility.

Using of the shorthand of cxx_bridge calls. Using of the unwrap_or instead of matching.

max marked 2 inline comments as done.

Rebasing on master changes.

services/tunnelbroker/src/server/mod.rs
41–44 ↗(On Diff #17954)

if you want to make this a bit smaller

Good catch. Thanks, @jon!

45–51 ↗(On Diff #17954)

https://github.com/dtolnay/serde-repr or https://serde.rs/enum-number.html might be of interest, then we can offload the deserialization from our domain of responsibility.

To use serde_json::from we should wrap the enum into the #[derive..] macro from serde, but the enum is auto-generated from the proto file.
Quick searching shows that we can apply the derive macro only on the declaration and we can't do this on imported things.

Using of the ::prost::Enumeration instead of the string matching for the deviceTypes enum.

services/tunnelbroker/src/server/mod.rs
45–51 ↗(On Diff #17954)

https://github.com/dtolnay/serde-repr or https://serde.rs/enum-number.html might be of interest, then we can offload the deserialization from our domain of responsibility.

I found that the Tonic generated headers for gRPC enums add #[derive(::prost::Enumeration)] and we can use it directly to match the enums by integers.
We can use is_valid() and from_i32() from the ::prost::Enumeration for our needs and no strings match anymore.

The diff is updated with this.

tomek requested changes to this revision.Nov 9 2022, 8:44 AM
tomek added inline comments.
services/tunnelbroker/src/libcpp/Tunnelbroker.cpp
63 ↗(On Diff #18223)

This looks like a new code. Why don't we write it in Rust from the beginning?

78 ↗(On Diff #18223)

Can we avoid using magic number and instead have consts / enums for them?

100–105 ↗(On Diff #18223)

Why do we need to check if the sent keys matches the one from the db? We could simply check the signature against the key from the db instead.

This revision now requires changes to proceed.Nov 9 2022, 8:44 AM
max marked 3 inline comments as done.
max added inline comments.
services/tunnelbroker/src/libcpp/Tunnelbroker.cpp
63 ↗(On Diff #18223)

This looks like a new code. Why don't we write it in Rust from the beginning?

Not exactly. This is not a new code it's a modified gRPC handler from the C++ gRPC server.

The modifications are just to pass the result to the Rust gRPC server. To rewrite gRPC handlers completely we should rewrite the database first into Rust because our database-using approach is not suitable for Rust. In this case, we should expose to Rust using the CXX a lot of the functions and structs including modifications to the C++ side (shared parameters, returns).

The easier and better way in case of productivity here is to make a computation on the C++ side and just pass the result to the gRPC Rust server.

When (in the future maybe) we will start to rewrite the Tunnelbroker completely to Rust, the Database shows be the first.

78 ↗(On Diff #18223)

Can we avoid using magic number and instead have consts / enums for them?

It's a gRPC status code. I don't think we should redefine gRPC codes somewhere as this is a commonly used and variable name is self-describing in this case.

100–105 ↗(On Diff #18223)

Why do we need to check if the sent keys matches the one from the db? We could simply check the signature against the key from the db instead.

It's for better feedback to the user. The user should get the different errors to better solve and know the problem with the signing. If we return the "Signature didn't match" error there are two possible errors on the user side:

  • He has the wrong signature string or something with the signer (the key is ok)
  • The key is don't match.

So it's for better and more precise errors to the client.

Accepting, but please update the diff so that magic numbers are avoided

services/tunnelbroker/src/libcpp/Tunnelbroker.cpp
63 ↗(On Diff #18223)

Ah, now it makes a lot of sense! Thanks for the explanation!

In the future, please try to highlight facts like that and add inline comments explaining the important changes. Ideally, we would have one diff that moves code and one that changes it, but if we want the code to compile, it's not always possible.

78 ↗(On Diff #18223)

The variable name is descriptive, but the value 3 isn't descriptive at all. We should have a place where we define a constant, give it a name and assign 3 to it. (the same for 5 and 7 - how would anyone reading the code know what's their meaning?)

This revision is now accepted and ready to land.Nov 16 2022, 10:03 AM
max marked 3 inline comments as done.

Rebasing on the master and parent diffs changes.

Rebasing and fixing merge.

max added inline comments.
services/tunnelbroker/src/libcpp/Tunnelbroker.cpp
78 ↗(On Diff #18223)

The variable name is descriptive, but the value 3 isn't descriptive at all. We should have a place where we define a constant, give it a name and assign 3 to it. (the same for 5 and 7 - how would anyone reading the code know what's their meaning?)

The parent diffs switched to use an enum instead, this one was rebased to use the enum as well. Marking this as fixed.

max marked an inline comment as done.

Resolving merge.