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

[Telemetry] Check permissions when requesting telemetry #126238

Merged
merged 27 commits into from
Mar 7, 2022

Conversation

afharo
Copy link
Member

@afharo afharo commented Feb 23, 2022

Summary

POST /api/telemetry/v2/clusters/_stats now checks that the user has the permissions decryptedTelemetry added in #96571 to only allow admins to retrieve telemetry. It returns 403 otherwise.

Adding security as a dependency to telemetry created a circular dependency because home relies on telemetry to set decide on whether to show the telemetry notice. I moved that logic to the telemetry plugin and registered the "renderer" via a new API exposed by the home plugin.

Resolves #96538.

Side wins

As we no longer need to scope the requests, I removed the kibanaRequest from the fetch context. Simplifying a lot the types in the usageCollection plugin.

Resolves #84183.

How to test

Locally

Create a user with a role that has read-only access to all spaces. Then, log in with that user and head to Advanced Settings > Usage Data (at the bottom), and attempt to retrieve the telemetry sample. You'll see it gets a 403.

Cloud

Using the auto-deployed Kibana 🧡

Since Cloud hides the section Advanced Settings > Usage Data, we need to curl the deployment to test this feature:

  • "admin" requesting unencrypted telemetry should get 200
$ curl -s -o /dev/null -w "%{http_code}" --request POST 'https://kibana-pr-126238.kb.us-west2.gcp.elastic-cloud.com:9243/api/telemetry/v2/clusters/_stats' \
--header 'Content-Type: application/json' \
--header 'kbn-xsrf: test' \
--header 'Authorization: Basic xxxxxx' \
--data-raw '{"unencrypted": true}'

200%
  • read-only user (access to all spaces but in read-only mode), requesting unencrypted telemetry should get 403
$ curl -s -o /dev/null -w "%{http_code}" --request POST 'https://kibana-pr-126238.kb.us-west2.gcp.elastic-cloud.com:9243/api/telemetry/v2/clusters/_stats' \
--header 'Content-Type: application/json' \
--header 'kbn-xsrf: test' \
--header 'Authorization: Basic xxxxxx' \
--data-raw '{"unencrypted": true}'

403%
  • any of the users above, requesting encrypted telemetry should get 200
$ curl -s -o /dev/null -w "%{http_code}" --request POST 'https://kibana-pr-126238.kb.us-west2.gcp.elastic-cloud.com:9243/api/telemetry/v2/clusters/_stats' \
--header 'Content-Type: application/json' \
--header 'kbn-xsrf: test' \
--header 'Authorization: Basic xxxxxx' \
--data-raw '{"unencrypted": false}'

200%

Checklist

Delete any items that are not applicable to this PR.

For maintainers

src/plugins/home/kibana.json Show resolved Hide resolved
@@ -126,11 +126,10 @@ export class TelemetryCollectionManagerPlugin
const esClient = this.getElasticsearchClient(config);
const soClient = this.getSavedObjectsClient(config);
// Provide the kibanaRequest so opted-in plugins can scope their custom clients only if the request is not encrypted
const kibanaRequest = config.unencrypted ? config.request : void 0;
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the main reason for allowing admin only to retrieve the sampled data. There's no longer a need to scope the requests. It may also help us with #84183 because kibanaRequest won't be needed in the context anymore.

return config.unencrypted
? this.elasticsearchClient?.asScoped(config.request).asCurrentUser
: this.elasticsearchClient?.asInternalUser;
return this.elasticsearchClient?.asInternalUser;
Copy link
Member Author

Choose a reason for hiding this comment

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

We can now rely on the internal user only 🎉

constructor(
log: Logger,
// Needed because it doesn't affect on anything here but being explicit creates a lot of pain down the line
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing anys 🥳

@@ -9,7 +9,7 @@ import { merge } from 'lodash';
import { loggingSystemMock } from 'src/core/server/mocks';
import {
Collector,
createCollectorFetchContextWithKibanaMock,
Copy link
Member Author

Choose a reason for hiding this comment

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

I looked at the collector and they don't require the KibanaRequest mock.

@afharo afharo added backport:skip This commit does not require backporting release_note:skip Skip the PR/issue when compiling release notes v8.2.0 labels Feb 23, 2022
@afharo afharo changed the title [Telemetry] Include security dependency [Telemetry] Check permissions when requesting telemetry Feb 23, 2022
@@ -24,6 +24,7 @@
{ "path": "../navigation/tsconfig.json" },
{ "path": "../saved_objects_tagging_oss/tsconfig.json" },
{ "path": "../saved_objects/tsconfig.json" },
{ "path": "../screenshot_mode/tsconfig.json" },
Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure why it failed in this PR. But dashboard is importing types from screenshot_mode and it was missing this line.

@elastic/kibana-operations probably a bug in the type_check script that didn't catch it earlier in main?

Copy link
Contributor

Choose a reason for hiding this comment

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

We're not totally sure how TypeScript validates that projects have the references they need, it seems to validate it most of the time but there are edge cases where you can import from another project even when it's not listed in the projects deps. We are on the cusp of moving away from relative plugin imports to imported based on global module IDs for packages which will make this a non-problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a strange situation, but I'm glad we'll be moving away from it in the future. Thanks for adding the project to our tsconfig though!

@@ -47,7 +37,7 @@ export class Welcome extends React.Component<Props> {
}
};

private redirecToAddData() {
private redirectToAddData() {
Copy link
Member Author

@afharo afharo Feb 24, 2022

Choose a reason for hiding this comment

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

Just fixing a typo here 😇

Comment on lines 40 to 42
const { hasAllRequested } = await security.authz
.checkPrivilegesWithRequest(req)
.globally({ kibana: 'decryptedTelemetry' });
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to check the serialized privilege string here. I'd suggest adding a comment to clarify this design decision for future maintainers, too 😄

Suggested change
const { hasAllRequested } = await security.authz
.checkPrivilegesWithRequest(req)
.globally({ kibana: 'decryptedTelemetry' });
// Normally we would use `options: { tags: ['access:decryptedTelemetry'] }` in the route definition to check authorization for an
// API action, however, we want to check this conditionally based on the `unencrypted` parameter. In this case we need to use the
// security API directly to check privileges for this action. Note that the 'decryptedTelemetry' API privilege string is only
// granted to users that have "Global All" or "Global Read" privileges in Kibana.
const { checkPrivilegesWithRequest, actions } = security.authz;
const privileges = { kibana: actions.api.get('decryptedTelemetry') };
const { hasAllRequested } = await checkPrivilegesWithRequest(req).globally(privileges);

Copy link
Member Author

Choose a reason for hiding this comment

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

It works! Thank you! Is there any documentation I could have gone to earlier so I wouldn't bother you with this wrong usage?

Copy link
Contributor

Choose a reason for hiding this comment

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

You're welcome!

Here's where we have an example of securing an HTTP route with an API privilege string via an access: tag: https://www.elastic.co/guide/en/kibana/current/development-security.html#example-2-dev-tools

Unfortunately you couldn't use an access: tag here.
AFAIK we don't really have any dev docs or TS docs that explain how to use the Security plugin's API to check privileges directly. The only TS docs I could find is this snippet:

/** Actions are used to create the "actions" that are associated with Elasticsearch's
* application privileges, and are used to perform the authorization checks implemented
* by the various `checkPrivilegesWithRequest` derivatives.
*/

That's not too helpful 😅

I added an issue for us to add docs for the authorization service: #126355

@afharo afharo marked this pull request as ready for review February 24, 2022 14:59
@afharo afharo requested review from a team as code owners February 24, 2022 14:59
@afharo
Copy link
Member Author

afharo commented Feb 27, 2022

@elasticmachine merge upstream

Copy link
Contributor

@gmmorris gmmorris left a comment

Choose a reason for hiding this comment

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

TM changes LGTM :)

Copy link
Contributor

@ThomThomson ThomThomson left a comment

Choose a reason for hiding this comment

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

Presentation team changes LGTM

@@ -24,6 +24,7 @@
{ "path": "../navigation/tsconfig.json" },
{ "path": "../saved_objects_tagging_oss/tsconfig.json" },
{ "path": "../saved_objects/tsconfig.json" },
{ "path": "../screenshot_mode/tsconfig.json" },
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a strange situation, but I'm glad we'll be moving away from it in the future. Thanks for adding the project to our tsconfig though!

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

Some nits and comments, but overall LGTM

@afharo afharo requested a review from a team as a code owner March 4, 2022 19:01
@afharo
Copy link
Member Author

afharo commented Mar 7, 2022

@elasticmachine merge upstream

Copy link
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

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

VisEditors changes LGTM, code review only

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
home 62 64 +2
telemetry 30 31 +1
total +3

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
home 97 102 +5
telemetryCollectionManager 33 32 -1
total +4

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
home 77.4KB 75.8KB -1.6KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
usageCollection 2 1 -1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
home 9.8KB 10.6KB +830.0B
telemetry 25.2KB 26.9KB +1.7KB
total +2.5KB
Unknown metric groups

API count

id before after diff
home 133 140 +7
telemetryCollectionManager 33 32 -1
total +6

ESLint disabled line counts

id before after diff
home 26 28 +2
usageCollection 4 2 -2
total -0

Total ESLint disabled count

id before after diff
home 27 29 +2
usageCollection 5 3 -2
total -0

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Contributor

@miltonhultgren miltonhultgren left a comment

Choose a reason for hiding this comment

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

Infra changes LGTM 👍🏼

@afharo afharo merged commit cb70888 into elastic:main Mar 7, 2022
@afharo afharo deleted the telemetry-depending-on-security branch March 7, 2022 20:29
jloleysens added a commit to jloleysens/kibana that referenced this pull request Mar 8, 2022
…ed-unexpectedly-error

* 'main' of github.com:elastic/kibana: (46 commits)
  Fix copy and pasted renderer user_name test (elastic#126663)
  [Gauge] Vis editors gauge legacy percent mode. (elastic#126318)
  Remove all cases related code from timelines (elastic#127003)
  Hide Enterprise search panel when no nodes are present (elastic#127100)
  [Lens] Fixed flakiness on runtime fields' appearance on the list (elastic#126945)
  [Security Solution][Lists] - Add missing privileges callout to exception lists page (elastic#126874)
  [Security Solution][Lists] - Updates exception flyout edit error messages (elastic#126875)
  [Security Solution][Rules] - Remove rule selection for read only users (elastic#126827)
  Fix session cleanup test (elastic#126966)
  [ftr] implement support for accessing ES through CCS (elastic#126547)
  [type-summarizer] always use normalized paths, fix windows compat (elastic#127055)
  Revert "[ci] Configure hourly pipeline for a small spot instance trial (elastic#126824)"
  Revert "[CI] Expand spot instance trial a bit (elastic#126928)"
  [Alerting] Adding functional tests for alerting and actions telemetry (elastic#126528)
  [Telemetry] Check permissions when requesting telemetry (elastic#126238)
  Don't submit empty seed_urls or sitemap_urls when making a partial crawl request (elastic#126972)
  Remove License Requirement for Enterprise Search App Search Meta Engines (elastic#127046)
  [ML] Adding data recognizer module config cache (elastic#126338)
  skip flaky suite (elastic#126027)
  [Reporting] Improve error logging for rescheduled jobs (elastic#126737)
  ...

# Conflicts:
#	x-pack/plugins/reporting/server/core.ts
#	x-pack/plugins/reporting/server/lib/tasks/execute_report.ts
jloleysens added a commit to jloleysens/kibana that referenced this pull request Mar 8, 2022
…re-browser-errors

* 'main' of github.com:elastic/kibana: (46 commits)
  Fix copy and pasted renderer user_name test (elastic#126663)
  [Gauge] Vis editors gauge legacy percent mode. (elastic#126318)
  Remove all cases related code from timelines (elastic#127003)
  Hide Enterprise search panel when no nodes are present (elastic#127100)
  [Lens] Fixed flakiness on runtime fields' appearance on the list (elastic#126945)
  [Security Solution][Lists] - Add missing privileges callout to exception lists page (elastic#126874)
  [Security Solution][Lists] - Updates exception flyout edit error messages (elastic#126875)
  [Security Solution][Rules] - Remove rule selection for read only users (elastic#126827)
  Fix session cleanup test (elastic#126966)
  [ftr] implement support for accessing ES through CCS (elastic#126547)
  [type-summarizer] always use normalized paths, fix windows compat (elastic#127055)
  Revert "[ci] Configure hourly pipeline for a small spot instance trial (elastic#126824)"
  Revert "[CI] Expand spot instance trial a bit (elastic#126928)"
  [Alerting] Adding functional tests for alerting and actions telemetry (elastic#126528)
  [Telemetry] Check permissions when requesting telemetry (elastic#126238)
  Don't submit empty seed_urls or sitemap_urls when making a partial crawl request (elastic#126972)
  Remove License Requirement for Enterprise Search App Search Meta Engines (elastic#127046)
  [ML] Adding data recognizer module config cache (elastic#126338)
  skip flaky suite (elastic#126027)
  [Reporting] Improve error logging for rescheduled jobs (elastic#126737)
  ...

# Conflicts:
#	x-pack/plugins/reporting/server/lib/tasks/execute_report.ts
lucasfcosta pushed a commit to lucasfcosta/kibana that referenced this pull request Mar 8, 2022
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
@tylersmalley tylersmalley added ci:cloud-deploy Create or update a Cloud deployment and removed ci:deploy-cloud labels Aug 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting ci:cloud-deploy Create or update a Cloud deployment release_note:skip Skip the PR/issue when compiling release notes v8.2.0
Projects
None yet