mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Enterprise Search] Fix cloudId decoding on index detail (#137478)
* Fix cloudId decoding on index detail * Add filepaths Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ec15a9ce53
commit
8bd2c273f8
3 changed files with 177 additions and 11 deletions
|
@ -21,6 +21,8 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { useCloudDetails } from '../../../shared/cloud_details/cloud_details';
|
||||
import { decodeCloudId } from '../../utils/decode_cloud_id';
|
||||
|
||||
import { DOCUMENTS_API_JSON_EXAMPLE } from '../new_index/constants';
|
||||
|
||||
import { ClientLibrariesPopover } from './components/client_libraries_popover/popover';
|
||||
|
@ -29,21 +31,15 @@ import { ManageKeysPopover } from './components/manage_api_keys_popover/popover'
|
|||
|
||||
import { OverviewLogic } from './overview.logic';
|
||||
|
||||
const getDeploymentUrls = (cloudId: string) => {
|
||||
const [host, kibanaHost, elasticHost] = window.atob(cloudId);
|
||||
return {
|
||||
elasticUrl: `https://${elasticHost}.${host}`,
|
||||
kibanaUrl: `https://${kibanaHost}.${host}`,
|
||||
};
|
||||
};
|
||||
export const GenerateApiKeyPanel: React.FC = () => {
|
||||
const { apiKey, isGenerateModalOpen, indexData } = useValues(OverviewLogic);
|
||||
const { closeGenerateModal } = useActions(OverviewLogic);
|
||||
|
||||
const cloudContext = useCloudDetails();
|
||||
const searchIndexApiUrl = cloudContext.cloudId
|
||||
? getDeploymentUrls(cloudContext.cloudId).elasticUrl
|
||||
: '<elasticsearch-host>:<elasticsearch-port>/';
|
||||
|
||||
const DEFAULT_URL = '<ELASTICSEARCH-HOST>:<ELASTICSEARCH-PORT>';
|
||||
const searchIndexApiUrl =
|
||||
(cloudContext.cloudId && decodeCloudId(cloudContext.cloudId)?.elasticsearchUrl) || DEFAULT_URL;
|
||||
|
||||
const apiKeyExample = apiKey || '<Create an API Key>';
|
||||
|
||||
|
@ -88,7 +84,7 @@ export const GenerateApiKeyPanel: React.FC = () => {
|
|||
<EuiFlexItem>
|
||||
<EuiCodeBlock language="bash" fontSize="m" isCopyable>
|
||||
{`\
|
||||
curl -X POST '${searchIndexApiUrl}${indexData?.name}/_doc' \\
|
||||
curl -X POST '${searchIndexApiUrl}/${indexData?.name}/_doc' \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-H 'Authorization: ApiKey ${apiKeyExample}' \\
|
||||
-d '${JSON.stringify(DOCUMENTS_API_JSON_EXAMPLE, null, 2)}'
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { decodeCloudId } from './decode_cloud_id';
|
||||
|
||||
// Copied from Fleet's solution
|
||||
// x-pack/fleet/common/services/decode_cloud_id.test.ts
|
||||
describe('Enterprise Search - decodeCloudId', () => {
|
||||
it('parses various CloudID formats', () => {
|
||||
const tests = [
|
||||
{
|
||||
cloudID:
|
||||
'staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==',
|
||||
expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443',
|
||||
expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==',
|
||||
expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443',
|
||||
expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
':dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==',
|
||||
expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443',
|
||||
expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'gcp-cluster:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZmNlJDBjZDVjZDU2OGVlYmU1M2M4OWViN2NhZTViYWM4YjM3',
|
||||
expectedEsURL: 'https://8a0283af041f195f7729bc04c66a0fce.us-central1.gcp.cloud.es.io:443',
|
||||
expectedKibanaURL:
|
||||
'https://0cd5cd568eebe53c89eb7cae5bac8b37.us-central1.gcp.cloud.es.io:443',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'custom-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA=',
|
||||
expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243',
|
||||
expectedKibanaURL:
|
||||
'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9243',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'different-es-kb-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==',
|
||||
expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243',
|
||||
expectedKibanaURL:
|
||||
'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'only-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwOjkyNDQ=',
|
||||
expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443',
|
||||
expectedKibanaURL:
|
||||
'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'host-and-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==',
|
||||
expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243',
|
||||
expectedKibanaURL:
|
||||
'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244',
|
||||
},
|
||||
{
|
||||
cloudID:
|
||||
'extra-items:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwJGFub3RoZXJpZCRhbmRhbm90aGVy',
|
||||
expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443',
|
||||
expectedKibanaURL:
|
||||
'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:443',
|
||||
},
|
||||
];
|
||||
|
||||
for (const test of tests) {
|
||||
const decoded = decodeCloudId(test.cloudID);
|
||||
expect(decoded).toBeTruthy();
|
||||
expect(decoded?.elasticsearchUrl === test.expectedEsURL).toBe(true);
|
||||
expect(decoded?.kibanaUrl === test.expectedKibanaURL).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns undefined for invalid formats', () => {
|
||||
const tests = [
|
||||
{
|
||||
cloudID:
|
||||
'staging:garbagedXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==',
|
||||
errorMsg: 'base64 decoding failed',
|
||||
},
|
||||
{
|
||||
cloudID: 'dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZg==',
|
||||
errorMsg: 'Expected at least 3 parts',
|
||||
},
|
||||
];
|
||||
|
||||
for (const test of tests) {
|
||||
const decoded = decodeCloudId(test.cloudID);
|
||||
expect(decoded).toBe(undefined);
|
||||
// decodeCloudId currently only logs; not throws errors
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
// copied this solution from fleet due to time constraints
|
||||
// x-pack/fleet/common/services/decode_cloud_id.ts
|
||||
// decodeCloudId decodes the c.id into c.esURL and c.kibURL
|
||||
export function decodeCloudId(cid: string):
|
||||
| {
|
||||
defaultPort: string;
|
||||
elasticsearchUrl: string;
|
||||
host: string;
|
||||
kibanaUrl: string;
|
||||
}
|
||||
| undefined {
|
||||
// 1. Ignore anything before `:`.
|
||||
const id = cid.split(':').pop();
|
||||
if (!id) {
|
||||
// throw new Error(`Unable to decode ${id}`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(`Unable to decode ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. base64 decode
|
||||
let decoded: string | undefined;
|
||||
try {
|
||||
decoded = Buffer.from(id, 'base64').toString('utf8');
|
||||
} catch {
|
||||
// throw new Error(`base64 decoding failed on ${id}`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(`base64 decoding failed on ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. separate based on `$`
|
||||
const words = decoded.split('$');
|
||||
if (words.length < 3) {
|
||||
// throw new Error(`Expected at least 3 parts in ${decoded}`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(`Expected at least 3 parts in ${decoded}`);
|
||||
return;
|
||||
}
|
||||
// 4. extract port from the ES and Kibana host
|
||||
const [host, defaultPort] = extractPortFromName(words[0]);
|
||||
const [esId, esPort] = extractPortFromName(words[1], defaultPort);
|
||||
const [kbId, kbPort] = extractPortFromName(words[2], defaultPort);
|
||||
// 5. form the URLs
|
||||
const esUrl = `https://${esId}.${host}:${esPort}`;
|
||||
const kbUrl = `https://${kbId}.${host}:${kbPort}`;
|
||||
return {
|
||||
defaultPort,
|
||||
elasticsearchUrl: esUrl,
|
||||
host,
|
||||
kibanaUrl: kbUrl,
|
||||
};
|
||||
}
|
||||
// extractPortFromName takes a string in the form `id:port` and returns the
|
||||
// Id and the port. If there's no `:`, the default port is returned
|
||||
function extractPortFromName(word: string, defaultPort = '443') {
|
||||
const [host, port = defaultPort] = word.split(':');
|
||||
return [host, port];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue