Skip to content

Report Connect usage events#19564

Merged
gzdunek merged 33 commits intomasterfrom
gzdunek/add-usage-reporter-to-connect
Jan 10, 2023
Merged

Report Connect usage events#19564
gzdunek merged 33 commits intomasterfrom
gzdunek/add-usage-reporter-to-connect

Conversation

@gzdunek
Copy link
Copy Markdown
Contributor

@gzdunek gzdunek commented Dec 21, 2022

Part of #19000
Requires #19378 to be merged first. ✅
Requires #19774 to be merged first (see #19564 (comment)) ✅

This PR adds actual events sending mechanism, it receives events from Electron, converts them to prehog model anonyzmies them and then sends in batches.

EDIT:
In the first attempt I had separate definitions for prehog events in tshd. It was ineffective approach and resulted in quite a lot of boilerplate (maintaining two, very similar protos and then having to convert one model to another). After a discussion with Rafał, we decided to use prehog protos directly in tshd protos.

@gzdunek
Copy link
Copy Markdown
Contributor Author

gzdunek commented Dec 21, 2022

My thoughts about this PR:
Anonymizing and converting tshd events to prehog events introduces quite a lot of boilerplate (the events have almost the same properties and I need manually convert each of them). I’m considering getting rid of tshd's usage_events.proto and instead operating only prehog's events.
It would require:

  • Performing anonymization before event leaves electron - shouldn’t be difficult, I can add a gRPC call that will run our anonymizer against the provided value
  • Importing prehog's connect.proto to teleterm's service.proto - for some reason it doesn’t work, I get an error saying that imported proto doesn't exist
  • Generating JS files for connect.proto

What do you think about it? Do you like the current solution, where we send authClusterId with every event that needs to be anonymized? I'm afraid it can be confusing, as we create almost complete events in Electron and then we perform one more thing in tshd :/

@gzdunek gzdunek requested review from avatus and ravicious December 21, 2022 18:02
Copy link
Copy Markdown
Contributor

@avatus avatus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only had a chance to look at the types today. Will finish my review tomorrow. Super neat so far tho!

}
}

message SubmitConnectEventResponse {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can reuse our EmptyResponse for this in service.proto instead of creating a new empty response here. Like this here

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use google.protobuf.Empty here, as long as it doesn't return linter errors (I'm not sure about this).

Historically, I haven't been consistent with it inside lib/teleterm. tshd_events_service.proto explicitly defines custom empty messages in order to keep backwards compatibility.

But I did a quick search right now and it turns out reusing google.protobuf.Empty (or something similar) is not a problem for backwards compatibility. Eric Anderson from the gRPC team says that old clients will not have a problem with this and the only thing it breaks is the generated types.

So I think going forward we could use google.protobuf.Empty, as we already do in the project. Unless the linter is now set up to require you to define a custom message for each RPC.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .proto is imported from gravitational/prehog, which enforces the default Buf lint rules RPC_REQUEST_STANDARD_NAME and RPC_RESPONSE_STANDARD_NAME.

ConnectUsageEventOneOf event = 3;
}

message EventReportedResponse {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can also be an EmptyResponse

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I think it's ok to use our common EmptyResponse instead of google.protobuf.Empty.

Comment thread lib/teleterm/daemon/usagereporter.go Outdated
Comment on lines +101 to +106
// Note: this results in retrying the entire batch, which probably
// isn't ideal.
req := connect.NewRequest(event.Event)
if _, err := client.SubmitConnectEvent(ctx, req); err != nil {
errors = append(errors, err)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to address this before merging?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it works this way for Teleport events too, we can fix it later.

Comment thread lib/teleterm/api/proto/v1/usage_events.proto Outdated

option go_package = "github.com/gravitational/teleport/lib/teleterm/v1";

message ReportEventRequest {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m considering getting rid of tshd's usage_events.proto and instead operating only prehog's events. It would require:

  • Performing anonymization before event leaves electron - shouldn’t be difficult, I can add a gRPC call that will run our anonymizer against the provided value

  • Importing prehog's connect.proto to teleterm's service.proto - for some reason it doesn’t work, I get an error saying that imported proto doesn't exist

  • Generating JS files for connect.proto

What do you think about it? Do you like the current solution, where we send authClusterId with every event that needs to be anonymized? I'm afraid it can be confusing, as we create almost complete events in Electron and then we perform one more thing in tshd :/

For me it's not confusing as much as it's just a lot of boilerplate.

From the side of the Electron app, I think the API looks pretty much alright – the Electron app should just send events and I don't think it wants to care about anonymization, especially since it's unable to anonymize anything on its own.


Could the Electron app send prehog's events to tshd through TerminalService and then tshd would anonymize the required fields before passing the events further?

If that would be possible, theoretically we could then do the minimal amount of work possible instead of having to rewrap every event.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for importing connect.proto to service.proto:

The protocol compiler searches for imported files in a set of directories specified on the protocol compiler command line using the -I/--proto_path flag. If no flag was given, it looks in the directory in which the compiler was invoked. In general you should set the --proto_path flag to the root of your project and use fully qualified names for all imports.

https://developers.google.com/protocol-buffers/docs/proto3#importing_definitions

AFAIK we now use buf instead of protoc, so maybe enabling that requires changes to buf's config.

Copy link
Copy Markdown
Contributor Author

@gzdunek gzdunek Dec 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the Electron app send prehog's events to tshd through TerminalService and then tshd would anonymize the required fields before passing the events further?

Unfortunately, it is not possible as tshd events (the ones that need to be anonymized) have one additional field - auth_cluster_id. It is needed to create the anonymizer. The prehog events don't have this field.

EDIT: we can send event + auth cluster id

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed the changes, so we don't have tshd usage events anymore and there is much less boilerplate.

We should merge changes to the protobuf generation first, @ravicious promised to create a PR for that :)

@gzdunek gzdunek force-pushed the gzdunek/add-usage-reporter-to-connect branch from f140eff to 00769c1 Compare December 30, 2022 15:56
Base automatically changed from gzdunek/make-usage-reporter-reusable to master December 30, 2022 17:24
@ravicious
Copy link
Copy Markdown
Member

ravicious commented Jan 2, 2023

I opened #19774 which reorganizes protos into a single workspace.

I made a couple of small changes compared to #19700. Once #19774 is merged, you will need to do the following in this PR:

  • Add lib/prehog/buf-teleterm.gen.yaml
lib/prehog/buf-teleterm.gen.yaml
# buf-teleterm.gen.yaml is identical to buf.gen.yaml,
# with the exception of three addidiotal JS plugins.
version: v1
managed:
  enabled: true
  go_package_prefix:
    default: github.com/gravitational/teleport/lib/prehog/gen
plugins:
  - name: go
    path: lib/prehog/bin/protoc-gen-go
    out: lib/prehog/gen
    opt:
      - paths=source_relative
  - name: connect-go
    path: lib/prehog/bin/protoc-gen-connect-go
    out: lib/prehog/gen
    opt:
      - paths=source_relative

  - name: js
    out: lib/prehog/gen-js
    opt:
      - import_style=commonjs,binary
  - name: grpc
    out: lib/prehog/gen-js
    opt: grpc_js
    path: grpc_tools_node_protoc_plugin
  - name: ts
    out: lib/prehog/gen-js
    opt: "service=grpc-node"
  • Extend grpc-teleterm/host to generate prehog protos as well.
grpc-teleterm/host: protos/all
	$(BUF) generate --template=lib/prehog/buf-teleterm.gen.yaml lib/prehog/proto
	$(BUF) generate --template=lib/teleterm/buf.gen.yaml lib/teleterm/api/proto
  • Add go_package in lib/prehog/proto/prehog/v1alpha/teleport.proto
option go_package = "github.com/gravitational/teleport/lib/prehog/gen/prehog/v1alpha";

@gzdunek
Copy link
Copy Markdown
Contributor Author

gzdunek commented Jan 3, 2023

License check was failing on the following files:

lib/prehog/gen-js/prehog/v1alpha/teleport_grpc_pb.d.ts
lib/prehog/gen-js/prehog/v1alpha/connect_grpc_pb.d.ts
lib/prehog/gen-js/prehog/v1alpha/connect_pb.d.ts
lib/prehog/gen-js/prehog/v1alpha/teleport_pb.d.ts

I added lib/prehog/gen-js/** to the ignored files list.

@gzdunek gzdunek marked this pull request as ready for review January 3, 2023 16:57
@github-actions github-actions Bot requested review from hatched and nklaassen January 3, 2023 16:57
@gzdunek gzdunek force-pushed the gzdunek/add-usage-reporter-to-connect branch from 805c4ec to c7b59a0 Compare January 3, 2023 17:06
@github-actions github-actions Bot removed the request for review from hatched January 10, 2023 00:50
@gzdunek
Copy link
Copy Markdown
Contributor Author

gzdunek commented Jan 10, 2023

I updated the PR:

  • updated connect.proto to match the final version from prehog
  • added changes related to JS files generation (from Report Connect usage events #19564 (comment))
  • removed hardcoded prehog address, instead it will be passed from Electron (similarly to other runtime values)

@ravicious ravicious self-requested a review January 10, 2023 11:56
string cluster_name = 1;
// anonymized
string user_name = 2;
bool is_upload = 3;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the advantage of doing it this way vs using a string with "upload"/"download"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed Edoardo suggestion, I think isUpload is easier to understand than direction.

Comment thread tool/tsh/tsh.go Outdated
Comment on lines 184 to 185
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put it below DaemonCertsDir and above DatabaseService.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I meant to put it like that.

@gzdunek gzdunek merged commit 584e96e into master Jan 10, 2023
@gzdunek gzdunek deleted the gzdunek/add-usage-reporter-to-connect branch March 20, 2023 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants