kibana/test/interactive_setup_api_integration/tests/enrollment_flow.ts
Alejandro Fernández Haro 52ab19db2d
Upgrade ES client to 9.0.0-alpha.3 (#208776)
## Summary

Updating the ES client to 9.0. 

Resolves #116102

## What changes?

**Breaking change**: `body` has been removed.

Most of the changes are about bringing all the content inside the body
as a root attribute to the API params:

```diff
const response = await client.search({
  index: 'test',
-  body: {
    query: {
      match_all: {}
    }
-  }
})
```

For this reason, enabling the "Hide whitespace changes" option when
reviewing is recommended.

Some exceptions to this rule:

* Bulk APIs replace the `body` array with `operations` array (direct
replacement)
* Index Put Settings API replace `body` array with `settings` (direct
replacement)
* Msearch replaces the `body` array with `searches` array (direct
replacement)
* Document Index API replaces `body` with `document` (direct
replacement)
* Create Repository replaces `body` with `repository` (direct
replacement)

Because of a known issue in the client
(https://github.com/elastic/elasticsearch-js/issues/2584), there's still
an escape hatch to send data in the body in case the specific use case
requires it via `// @ts-expect-error elasticsearch@9.0.0
https://github.com/elastic/elasticsearch-js/issues/2584`, but it
shouldn't be abused because we lose types. In this PR we've used it in
those scenarios where we reuse the response of a GET as the body of a
PUT/POST.

### Other changes

* `estypes` can be imported from the root of the library as `import type
{ estypes } from '@elastic/elasticsearch';`
* `estypesWithBody` have been removed
* `requestTimeout`'s 30s default has been removed in the client. This PR
explicitly adds the setting in all client usages.


### Identify risks

- [x] The client places unknown properties as querystring, risking body
params leaking there, and causing 400 errors from ES => Solved by
forcing `body` usage there via `// @ts-expect-error elasticsearch@9.0.0
https://github.com/elastic/elasticsearch-js/issues/2584`. The next
version of the client will address this.
- [x] We need to run the MKI tests to make sure that we're not breaking
anything there =>
https://elastic.slack.com/archives/C04HT4P1YS3/p1739528112482629?thread_ts=1739480136.231439&cid=C04HT4P1YS3

---------

Co-authored-by: Gloria Hornero <gloria.hornero@elastic.co>
2025-02-25 14:37:23 +00:00

150 lines
5.2 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import expect from '@kbn/expect';
import { getUrl } from '@kbn/test';
import { hasKibanaBooted } from '../fixtures/test_helpers';
import { getElasticsearchCaCertificate } from '../fixtures/tls_tools';
import type { FtrProviderContext } from '../ftr_provider_context';
export default function (context: FtrProviderContext) {
const supertest = context.getService('supertest');
const es = context.getService('es');
const log = context.getService('log');
const config = context.getService('config');
describe('Interactive setup APIs - Enrollment flow', function () {
this.tags(['skipCloud', 'skipFIPS']);
let kibanaVerificationCode: string;
let elasticsearchCaFingerprint: string;
before(async () => {
const esServerConfig = config.get('servers.elasticsearch');
elasticsearchCaFingerprint = (
await getElasticsearchCaCertificate(esServerConfig.host, esServerConfig.port)
).fingerprint256.replace(/:/g, '');
kibanaVerificationCode = (
await supertest.get('/test_endpoints/verification_code').expect(200)
).body.verificationCode;
});
let enrollmentAPIKey: string;
beforeEach(async () => {
const apiResponse = await es.security.createApiKey({ name: 'enrollment_api_key' });
enrollmentAPIKey = Buffer.from(`${apiResponse.id}:${apiResponse.api_key}`).toString('base64');
});
afterEach(async () => {
await es.security.invalidateApiKey({ name: 'enrollment_api_key' });
});
it('fails to enroll with invalid authentication code', async () => {
const esHost = getUrl.baseUrl(config.get('servers.elasticsearch'));
const enrollPayload = {
apiKey: enrollmentAPIKey,
code: '000000',
caFingerprint: elasticsearchCaFingerprint,
hosts: [esHost],
};
log.debug(`Enroll payload ${JSON.stringify(enrollPayload)}`);
await supertest
.post('/internal/interactive_setup/enroll')
.set('kbn-xsrf', 'xxx')
.send(enrollPayload)
.expect(403, { statusCode: 403, error: 'Forbidden', message: 'Forbidden' });
});
it('fails to enroll with invalid CA fingerprint', async () => {
const esHost = getUrl.baseUrl(config.get('servers.elasticsearch'));
const enrollPayload = {
apiKey: enrollmentAPIKey,
code: kibanaVerificationCode,
caFingerprint: '3FDAEE71A3604070E6AE6B01412D19772DE5AE129F69C413F0453B293D9BE65D',
hosts: [esHost],
};
log.debug(`Enroll payload ${JSON.stringify(enrollPayload)}`);
await supertest
.post('/internal/interactive_setup/enroll')
.set('kbn-xsrf', 'xxx')
.send(enrollPayload)
.expect(500, {
statusCode: 500,
error: 'Internal Server Error',
message: 'Failed to enroll.',
attributes: { type: 'enroll_failure' },
});
});
it('fails to enroll with invalid api key', async function () {
const esServerConfig = config.get('servers.elasticsearch');
const enrollPayload = {
apiKey: enrollmentAPIKey,
code: kibanaVerificationCode,
caFingerprint: elasticsearchCaFingerprint,
hosts: [getUrl.baseUrl(esServerConfig)],
};
log.debug(`Enroll payload ${JSON.stringify(enrollPayload)}`);
// Invalidate API key.
await es.security.invalidateApiKey({ name: 'enrollment_api_key' });
await supertest
.post('/internal/interactive_setup/enroll')
.set('kbn-xsrf', 'xxx')
.send(enrollPayload)
.expect(500, {
statusCode: 500,
error: 'Internal Server Error',
message: 'Failed to enroll.',
attributes: { type: 'enroll_failure' },
});
});
it('should be able to enroll with valid authentication code', async function () {
this.timeout(60000);
const esServerConfig = config.get('servers.elasticsearch');
const enrollPayload = {
apiKey: enrollmentAPIKey,
code: kibanaVerificationCode,
caFingerprint: elasticsearchCaFingerprint,
hosts: [getUrl.baseUrl(esServerConfig)],
};
log.debug(`Enroll payload ${JSON.stringify(enrollPayload)}`);
await supertest
.post('/internal/interactive_setup/enroll')
.set('kbn-xsrf', 'xxx')
.send(enrollPayload)
.expect(204, {});
// Enroll should no longer accept requests.
await supertest
.post('/internal/interactive_setup/enroll')
.set('kbn-xsrf', 'xxx')
.send(enrollPayload)
.expect(400, {
error: 'Bad Request',
message: 'Cannot process request outside of preboot stage.',
statusCode: 400,
attributes: { type: 'outside_preboot_stage' },
});
expect(await hasKibanaBooted(context)).to.be(true);
});
});
}