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

migrate xsrf / version-check / custom-headers handlers to NP #53684

Merged

Conversation

pgayvallet
Copy link
Contributor

Summary

Fix #50656

Checklist

Use strikethroughs to remove checklist items you don't feel are applicable to this PR.

For maintainers

Comment on lines +70 to +72
customResponseHeaders: schema.recordOf(schema.string(), schema.string(), {
defaultValue: {},
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I kept the same name. It's quite long but I don't really have a better idea. If someone comes with a better name, we could deprecates this one now that deprecations can be handled in NP configs

Comment on lines +97 to +99

registerCoreHandlers(serverContract, config, this.env);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did not add a test that ensure this is properly invoked during the service setup phase as the feature is heavily integration-tested. Tell we if we want to still add a test.

Comment on lines 35 to 46
describe('core lifecycle handlers', () => {
let root: ReturnType<typeof kbnTestServer.createRoot>;

beforeEach(async () => {
root = kbnTestServer.createRoot({
server: {
name: kibanaName,
customResponseHeaders: {
'some-header': 'some-value',
},
xsrf: { disableProtection: false, whitelist: [whitelistedTestPath] },
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm doing all three handlers integration tests in the same file, so the root creation has settings for all the 3 handlers. Not sure if I should split/isolate per file

import { OnPreAuthToolkit } from './on_pre_auth';
import { LifecycleResponseFactory } from '../router';

type MockToolkit = jest.Mocked<OnPreResponseToolkit & OnPostAuthToolkit & OnPreAuthToolkit>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All these toolkits have very similar API, in a mock point of view. I generalised this type that can be used on for testing any of the lifecycle handler types.

@@ -71,19 +71,6 @@ export default () =>
server: Joi.object({
name: Joi.string().default(os.hostname()),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

HANDLED_IN_NEW_PLATFORM states This key is handled in the new platform ONLY, however server.name is still used in legacy in some places such as

serverName: config.get('server.name'),

so I kept it as is. should I change it to name: HANDLED_IN_NEW_PLATFORM ?

Copy link
Contributor

Choose a reason for hiding this comment

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

The validation is handled in the new platform, so I'd remove this. The legacy platform can continue using config.get('server.name'), but validation will be delegated to the NP.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TIL we can't. Some plugins are still accessing it from the legacy config, and as we are constructing the legacy config from the raw configuration values, any default from our NP schemas are ignored. had to keep it for now.

@pgayvallet pgayvallet added release_note:skip Skip the PR/issue when compiling release notes v7.6.0 v8.0.0 labels Dec 20, 2019
@pgayvallet pgayvallet added Feature:New Platform Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc labels Dec 20, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

@pgayvallet pgayvallet marked this pull request as ready for review December 20, 2019 15:45
@pgayvallet pgayvallet requested a review from a team as a code owner December 20, 2019 15:45
Comment on lines +26 to +28
const VERSION_HEADER = 'kbn-version';
const XSRF_HEADER = 'kbn-xsrf';
const KIBANA_NAME_HEADER = 'kbn-name';
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about adding a file for these constants that can be shared across public and server?

While I was implementing the System API behavior, I was considering adding a src/core/utils/constants file for the kbn-system-api and kbn-version header names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I though about it and was not sure where I was supposed to put the constants file. should it be src/core/utils or src/core/types? Constants are not exactly one or the other.

I could also exports these from src/core/server/http (and src/core/server) and then expose them in src/core/server/types to be eventually used by the client-side?

Copy link
Contributor

@mshustov mshustov Dec 23, 2019

Choose a reason for hiding this comment

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

Do we need this? What benefits does it provide? I don't see a problem to inline them in both server & client within the same domain because:

  • it simplifies search (Cmd + F) and improves DX. I cannot just copy an error message Request must contain a kbn-xsrf header. and find the place where a request was rejected.
  • it doesn't clutter code with unnecessary import/export expressions
  • it makes this API truly private and prevents accidental importing from the plugin code.

The main benefit of sharing that we can easily to audit all internal Kibana headers. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Other benefit is that if we need to change the header name in the future, we only have to edit it in a single place and don't risk missing a string that needs to be updated (or a string from a yet-to-be-merged PR not getting updated).

That said, I don't imagine these changing often (if at all) or them being used in many more places (if any).

Kind of a toss up on benefits here. I'm fine leaving as-is in this PR and removing my shared module in #53734.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will keep them as-is for now. Can easily be refactored later on if the benefits appear more significants at some point.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

History

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

Comment on lines +26 to +28
const VERSION_HEADER = 'kbn-version';
const XSRF_HEADER = 'kbn-xsrf';
const KIBANA_NAME_HEADER = 'kbn-name';
Copy link
Contributor

@mshustov mshustov Dec 23, 2019

Choose a reason for hiding this comment

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

Do we need this? What benefits does it provide? I don't see a problem to inline them in both server & client within the same domain because:

  • it simplifies search (Cmd + F) and improves DX. I cannot just copy an error message Request must contain a kbn-xsrf header. and find the place where a request was rejected.
  • it doesn't clutter code with unnecessary import/export expressions
  • it makes this API truly private and prevents accidental importing from the plugin code.

The main benefit of sharing that we can easily to audit all internal Kibana headers. 🤔

const testRoute = '/version_check/test/route';

beforeEach(() => {
kbnTestServer.getKbnServer(root).server.route({
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather avoid using raw hapi API in the platform tests.

const { server: innerServer, createRouter } = await server.setup(setupDeps);

This allows us to reduce noize in tests when updating hapi version / removing hapi

await kbnTestServer.request
.get(root, testRoute)
.set(versionHeader, 'invalid-version')
.expect(400, /"Browser client is out of date/);
Copy link
Contributor

Choose a reason for hiding this comment

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

optional nit: /Browser client is out of date/


const createConfig = (partial: Partial<HttpConfig>): HttpConfig => partial as HttpConfig;

const forgeRequest = ({
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason not to use already existing fixtures ?

function createRawRequestMock(customization: DeepPartial<Request> = {}) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, just forget we already had a mock request fixture. Will adapt.

responseFactory = httpServerMock.createLifecycleResponseFactory();
});

it('forward the request to the next interceptor if header matches', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect this functionality is covered by the integration tests. Isn't it? If yes, I'd remove the unit tests because it's hard to write them due to coupling with hapi.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's tested in integration tests. However I don't think we are really tightly coupled with hapi here, as all used interfaces/types are from core (even if we mimic hapi's types for some of them). I'm leaning to keep them as this is the only place we can really test them unitarily (integ test have all interceptors registered)

@@ -71,19 +71,6 @@ export default () =>
server: Joi.object({
name: Joi.string().default(os.hostname()),
Copy link
Contributor

Choose a reason for hiding this comment

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

The validation is handled in the new platform, so I'd remove this. The legacy platform can continue using config.get('server.name'), but validation will be delegated to the NP.

);
});

it('adds the custom headers', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

could you add a test that custom headers are present in error responses as well?

Copy link
Contributor

@mshustov mshustov 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, looks good & clean 💯

@pgayvallet
Copy link
Contributor Author

retest

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

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

@pgayvallet pgayvallet merged commit 205fbce into elastic:master Jan 6, 2020
pgayvallet added a commit to pgayvallet/kibana that referenced this pull request Jan 6, 2020
…#53684)

* migrate xsrf / version-check / custom-headers handlers to NP

* export lifecycleMock to be used by plugins

* move toolkit mock to http_server mock

* remove legacy config tests on xsrf

* fix integration_test http configuration

* remove direct HAPI usages from integration tests

* nits and comments

* add custom headers test in case of server returning error

* resolve merge conflicts

* restore `server.name` to legacy config
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jan 6, 2020
* master:
  allows Alerts to recover gracefully from Executor errors (elastic#53688)
  [Console] Fix OSS build (elastic#53885)
  migrate xsrf / version-check / custom-headers handlers to NP (elastic#53684)
  use NP deprecations in uiSettings (elastic#53755)
  adds strict types to Alerting Client (elastic#53821)
  [Dashboard] Empty screen redesign (elastic#53681)
  Migrate config deprecations and `ShieldUser` functionality to the New Platform (elastic#53768)
pgayvallet added a commit that referenced this pull request Jan 6, 2020
…53684) (#54016)

* migrate xsrf / version-check / custom-headers handlers to NP (#53684)

* migrate xsrf / version-check / custom-headers handlers to NP

* export lifecycleMock to be used by plugins

* move toolkit mock to http_server mock

* remove legacy config tests on xsrf

* fix integration_test http configuration

* remove direct HAPI usages from integration tests

* nits and comments

* add custom headers test in case of server returning error

* resolve merge conflicts

* restore `server.name` to legacy config

* update snapshots
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:New Platform release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.6.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Migrate Kibana specific headers checks.
5 participants