mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Logs onboarding] Removes dependency on apikey id in saved objects (#159535)
Closes #159381 Makes use of the auto-generated saved object ID to identify observability onboarding state saved objects, so the API key id is never persisted. In this change, the generated API key never has an explicit association with the saved object for the onboarding flow.
This commit is contained in:
parent
85c5b871de
commit
2bab34a8df
8 changed files with 83 additions and 61 deletions
|
@ -120,7 +120,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
|
|||
"ml-module": "2225cbb4bd508ea5f69db4b848be9d8a74b60198",
|
||||
"ml-trained-model": "482195cefd6b04920e539d34d7356d22cb68e4f3",
|
||||
"monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559",
|
||||
"observability-onboarding-state": "c2a7439293913d69cc286a8f8f9885bc2dd9682f",
|
||||
"observability-onboarding-state": "55b112d6a33fedb7c1e4fec4da768d2bcc5fadc2",
|
||||
"osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc",
|
||||
"osquery-pack": "6ab4358ca4304a12dcfc1777c8135b75cffb4397",
|
||||
"osquery-pack-asset": "b14101d3172c4b60eb5404696881ce5275c84152",
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
API_KEY_ENCODED=$1
|
||||
API_ENDPOINT=$2
|
||||
ELASTIC_AGENT_VERSION=$3
|
||||
AUTO_DOWNLOAD_CONFIG=$4
|
||||
ONBOARDING_ID=$4
|
||||
AUTO_DOWNLOAD_CONFIG=$5
|
||||
|
||||
updateStepProgress() {
|
||||
local STEPNAME="$1"
|
||||
local STATUS="$2" # "incomplete" | "complete" | "disabled" | "loading" | "warning" | "danger" | "current"
|
||||
curl --request GET \
|
||||
--url "${API_ENDPOINT}/custom_logs/step/${STEPNAME}?status=${STATUS}" \
|
||||
--url "${API_ENDPOINT}/custom_logs/${ONBOARDING_ID}/step/${STEPNAME}?status=${STATUS}" \
|
||||
--header "Authorization: ApiKey ${API_KEY_ENCODED}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "kbn-xsrf: true" \
|
||||
|
@ -93,7 +94,7 @@ downloadElasticAgentConfig() {
|
|||
echo "Downloading elastic-agent.yml"
|
||||
updateStepProgress "ea-config" "loading"
|
||||
curl --request GET \
|
||||
--url "${API_ENDPOINT}/elastic_agent/config" \
|
||||
--url "${API_ENDPOINT}/elastic_agent/config?id=${ONBOARDING_ID}" \
|
||||
--header "Authorization: ApiKey ${API_KEY_ENCODED}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "kbn-xsrf: true" \
|
||||
|
|
|
@ -43,7 +43,7 @@ export function InstallElasticAgent() {
|
|||
const wizardState = getState();
|
||||
const [elasticAgentPlatform, setElasticAgentPlatform] =
|
||||
useState<ElasticAgentPlatform>('linux-tar');
|
||||
const [apiKeyId, setApiKeyId] = useState('');
|
||||
const [onboardingId, setOnboardingId] = useState('');
|
||||
|
||||
function onInspect() {
|
||||
goToStep('inspect');
|
||||
|
@ -119,11 +119,16 @@ export function InstallElasticAgent() {
|
|||
headers: {
|
||||
authorization: `ApiKey ${installShipperSetup?.apiKeyEncoded}`,
|
||||
},
|
||||
params: {
|
||||
query: { id: installShipperSetup?.id ?? '' },
|
||||
},
|
||||
};
|
||||
|
||||
return callApi(
|
||||
'GET /api/observability_onboarding/elastic_agent/config 2023-05-24',
|
||||
installShipperSetup?.apiKeyEncoded ? options : {}
|
||||
installShipperSetup?.apiKeyEncoded
|
||||
? options
|
||||
: { params: options.params }
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -131,8 +136,8 @@ export function InstallElasticAgent() {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
setApiKeyId(installShipperSetup?.apiKeyId ?? '');
|
||||
}, [installShipperSetup?.apiKeyId]);
|
||||
setOnboardingId(installShipperSetup?.id ?? '');
|
||||
}, [installShipperSetup?.id]);
|
||||
|
||||
const apiKeyEncoded = installShipperSetup?.apiKeyEncoded;
|
||||
|
||||
|
@ -142,16 +147,14 @@ export function InstallElasticAgent() {
|
|||
refetch: refetchProgress,
|
||||
} = useFetcher(
|
||||
(callApi) => {
|
||||
if (CurrentStep === InstallElasticAgent && apiKeyId) {
|
||||
if (CurrentStep === InstallElasticAgent && onboardingId) {
|
||||
return callApi(
|
||||
'GET /internal/observability_onboarding/custom_logs/progress',
|
||||
{
|
||||
params: { query: { apiKeyId } },
|
||||
}
|
||||
'GET /internal/observability_onboarding/custom_logs/{id}/progress',
|
||||
{ params: { path: { id: onboardingId } } }
|
||||
);
|
||||
}
|
||||
},
|
||||
[apiKeyId]
|
||||
[onboardingId]
|
||||
);
|
||||
|
||||
const progressSucceded = progressStatus === FETCH_STATUS.SUCCESS;
|
||||
|
@ -352,6 +355,7 @@ export function InstallElasticAgent() {
|
|||
scriptDownloadUrl: setup?.scriptDownloadUrl,
|
||||
elasticAgentVersion: setup?.elasticAgentVersion,
|
||||
autoDownloadConfig: wizardState.autoDownloadConfig,
|
||||
onboardingId,
|
||||
})}
|
||||
</EuiCodeBlock>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -571,6 +575,7 @@ function getInstallShipperCommand({
|
|||
scriptDownloadUrl = '$SCRIPT_DOWNLOAD_URL',
|
||||
elasticAgentVersion = '$ELASTIC_AGENT_VERSION',
|
||||
autoDownloadConfig = false,
|
||||
onboardingId = '$ONBOARDING_ID',
|
||||
}: {
|
||||
elasticAgentPlatform: ElasticAgentPlatform;
|
||||
apiKeyEncoded: string | undefined;
|
||||
|
@ -578,12 +583,13 @@ function getInstallShipperCommand({
|
|||
scriptDownloadUrl: string | undefined;
|
||||
elasticAgentVersion: string | undefined;
|
||||
autoDownloadConfig: boolean;
|
||||
onboardingId: string | undefined;
|
||||
}) {
|
||||
const setupScriptFilename = 'standalone_agent_setup.sh';
|
||||
const PLATFORM_COMMAND: Record<ElasticAgentPlatform, string> = {
|
||||
'linux-tar': oneLine`
|
||||
curl ${scriptDownloadUrl} -o ${setupScriptFilename} &&
|
||||
sudo bash ${setupScriptFilename} ${apiKeyEncoded} ${apiEndpoint} ${elasticAgentVersion} ${
|
||||
sudo bash ${setupScriptFilename} ${apiKeyEncoded} ${apiEndpoint} ${elasticAgentVersion} ${onboardingId} ${
|
||||
autoDownloadConfig ? 'autoDownloadConfig=1' : ''
|
||||
}
|
||||
`,
|
||||
|
|
|
@ -14,15 +14,15 @@ import {
|
|||
|
||||
export async function getObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId,
|
||||
savedObjectId,
|
||||
}: {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
apiKeyId: string;
|
||||
savedObjectId: string;
|
||||
}): Promise<SavedObservabilityOnboardingState | undefined> {
|
||||
try {
|
||||
const result = await savedObjectsClient.get<ObservabilityOnboardingState>(
|
||||
OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
apiKeyId
|
||||
savedObjectId
|
||||
);
|
||||
const { id, updated_at: updatedAt, attributes } = result;
|
||||
return {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { getAuthenticationAPIKey } from '../../lib/get_authentication_api_key';
|
||||
import { ObservabilityOnboardingState } from '../../saved_objects/observability_onboarding_status';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
import { createShipperApiKey } from './api_key/create_shipper_api_key';
|
||||
|
@ -50,7 +49,9 @@ const installShipperSetupRoute = createObservabilityOnboardingServerRoute({
|
|||
const coreStart = await core.start();
|
||||
|
||||
const kibanaUrl =
|
||||
plugins.cloud?.setup?.kibanaUrl ?? getFallbackUrls(coreStart).kibanaUrl;
|
||||
core.setup.http.basePath.publicBaseUrl ?? // priority given to server.publicBaseUrl
|
||||
plugins.cloud?.setup?.kibanaUrl ?? // then cloud id
|
||||
getFallbackUrls(coreStart).kibanaUrl; // falls back to local network binding
|
||||
const scriptDownloadUrl = `${kibanaUrl}/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`;
|
||||
const apiEndpoint = `${kibanaUrl}/api/observability_onboarding`;
|
||||
|
||||
|
@ -71,10 +72,7 @@ const createApiKeyRoute = createObservabilityOnboardingServerRoute({
|
|||
state: t.record(t.string, t.unknown),
|
||||
}),
|
||||
}),
|
||||
async handler(resources): Promise<{
|
||||
apiKeyId: string;
|
||||
apiKeyEncoded: string;
|
||||
}> {
|
||||
async handler(resources): Promise<{ apiKeyEncoded: string; id: string }> {
|
||||
const {
|
||||
context,
|
||||
params: {
|
||||
|
@ -87,32 +85,29 @@ const createApiKeyRoute = createObservabilityOnboardingServerRoute({
|
|||
const {
|
||||
elasticsearch: { client },
|
||||
} = await context.core;
|
||||
const { id: apiKeyId, encoded: apiKeyEncoded } = await createShipperApiKey(
|
||||
const { encoded: apiKeyEncoded } = await createShipperApiKey(
|
||||
client.asCurrentUser,
|
||||
name
|
||||
);
|
||||
|
||||
const savedObjectsClient = coreStart.savedObjects.getScopedClient(request);
|
||||
|
||||
await saveObservabilityOnboardingState({
|
||||
const { id } = await saveObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId,
|
||||
observabilityOnboardingState: { state } as ObservabilityOnboardingState,
|
||||
});
|
||||
|
||||
return {
|
||||
apiKeyId,
|
||||
apiKeyEncoded,
|
||||
};
|
||||
return { apiKeyEncoded, id };
|
||||
},
|
||||
});
|
||||
|
||||
const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint:
|
||||
'GET /api/observability_onboarding/custom_logs/step/{name} 2023-05-24',
|
||||
'GET /api/observability_onboarding/custom_logs/{id}/step/{name} 2023-05-24',
|
||||
options: { tags: [] },
|
||||
params: t.type({
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
name: t.string,
|
||||
}),
|
||||
query: t.type({
|
||||
|
@ -122,13 +117,11 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
|||
async handler(resources): Promise<object> {
|
||||
const {
|
||||
params: {
|
||||
path: { name },
|
||||
path: { id, name },
|
||||
query: { status },
|
||||
},
|
||||
request,
|
||||
core,
|
||||
} = resources;
|
||||
const authApiKey = getAuthenticationAPIKey(request);
|
||||
const coreStart = await core.start();
|
||||
const savedObjectsClient =
|
||||
coreStart.savedObjects.createInternalRepository();
|
||||
|
@ -136,7 +129,7 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
|||
const savedObservabilityOnboardingState =
|
||||
await getObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId: authApiKey?.apiKeyId as string,
|
||||
savedObjectId: id,
|
||||
});
|
||||
|
||||
if (!savedObservabilityOnboardingState) {
|
||||
|
@ -146,11 +139,15 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
|||
};
|
||||
}
|
||||
|
||||
const { id, updatedAt, ...observabilityOnboardingState } =
|
||||
savedObservabilityOnboardingState;
|
||||
const {
|
||||
id: savedObjectId,
|
||||
updatedAt,
|
||||
...observabilityOnboardingState
|
||||
} = savedObservabilityOnboardingState;
|
||||
|
||||
await saveObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId: authApiKey?.apiKeyId as string,
|
||||
savedObjectId,
|
||||
observabilityOnboardingState: {
|
||||
...observabilityOnboardingState,
|
||||
progress: {
|
||||
|
@ -164,17 +161,17 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({
|
|||
});
|
||||
|
||||
const getProgressRoute = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'GET /internal/observability_onboarding/custom_logs/progress',
|
||||
endpoint: 'GET /internal/observability_onboarding/custom_logs/{id}/progress',
|
||||
options: { tags: [] },
|
||||
params: t.type({
|
||||
query: t.type({
|
||||
apiKeyId: t.string,
|
||||
path: t.type({
|
||||
id: t.string,
|
||||
}),
|
||||
}),
|
||||
async handler(resources): Promise<{ progress: Record<string, string> }> {
|
||||
const {
|
||||
params: {
|
||||
query: { apiKeyId },
|
||||
path: { id },
|
||||
},
|
||||
core,
|
||||
request,
|
||||
|
@ -185,7 +182,7 @@ const getProgressRoute = createObservabilityOnboardingServerRoute({
|
|||
const savedObservabilityOnboardingState =
|
||||
(await getObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId,
|
||||
savedObjectId: id,
|
||||
})) || null;
|
||||
const progress = { ...savedObservabilityOnboardingState?.progress };
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { SavedObjectsClientContract } from '@kbn/core/server';
|
||||
import { SavedObjectsClientContract, SavedObject } from '@kbn/core/server';
|
||||
import {
|
||||
OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
ObservabilityOnboardingState,
|
||||
|
@ -15,26 +15,33 @@ import {
|
|||
interface Options {
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
observabilityOnboardingState: ObservabilityOnboardingState;
|
||||
apiKeyId: string;
|
||||
savedObjectId?: string;
|
||||
}
|
||||
export async function saveObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
observabilityOnboardingState,
|
||||
apiKeyId,
|
||||
savedObjectId,
|
||||
}: Options): Promise<SavedObservabilityOnboardingState> {
|
||||
const {
|
||||
id,
|
||||
attributes,
|
||||
updated_at: updatedAt,
|
||||
} = await savedObjectsClient.update<ObservabilityOnboardingState>(
|
||||
OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
apiKeyId,
|
||||
observabilityOnboardingState,
|
||||
{ upsert: observabilityOnboardingState }
|
||||
);
|
||||
let savedObject: Omit<
|
||||
SavedObject<ObservabilityOnboardingState>,
|
||||
'attributes' | 'references'
|
||||
>;
|
||||
if (savedObjectId) {
|
||||
savedObject = await savedObjectsClient.update<ObservabilityOnboardingState>(
|
||||
OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
savedObjectId,
|
||||
observabilityOnboardingState
|
||||
);
|
||||
} else {
|
||||
savedObject = await savedObjectsClient.create<ObservabilityOnboardingState>(
|
||||
OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
observabilityOnboardingState
|
||||
);
|
||||
}
|
||||
const { id, updated_at: updatedAt } = savedObject;
|
||||
return {
|
||||
id,
|
||||
...(attributes as ObservabilityOnboardingState),
|
||||
...observabilityOnboardingState,
|
||||
updatedAt: updatedAt ? Date.parse(updatedAt) : 0,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import * as t from 'io-ts';
|
||||
import { getAuthenticationAPIKey } from '../../lib/get_authentication_api_key';
|
||||
import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route';
|
||||
import { getObservabilityOnboardingState } from '../custom_logs/get_observability_onboarding_state';
|
||||
|
@ -13,9 +14,19 @@ import { getFallbackUrls } from '../custom_logs/get_fallback_urls';
|
|||
|
||||
const generateConfig = createObservabilityOnboardingServerRoute({
|
||||
endpoint: 'GET /api/observability_onboarding/elastic_agent/config 2023-05-24',
|
||||
params: t.type({
|
||||
query: t.type({ id: t.string }),
|
||||
}),
|
||||
options: { tags: [] },
|
||||
async handler(resources): Promise<string> {
|
||||
const { core, plugins, request } = resources;
|
||||
const {
|
||||
params: {
|
||||
query: { id },
|
||||
},
|
||||
core,
|
||||
plugins,
|
||||
request,
|
||||
} = resources;
|
||||
const authApiKey = getAuthenticationAPIKey(request);
|
||||
|
||||
const coreStart = await core.start();
|
||||
|
@ -28,7 +39,7 @@ const generateConfig = createObservabilityOnboardingServerRoute({
|
|||
|
||||
const savedState = await getObservabilityOnboardingState({
|
||||
savedObjectsClient,
|
||||
apiKeyId: authApiKey?.apiKeyId ?? '',
|
||||
savedObjectId: id,
|
||||
});
|
||||
|
||||
const yaml = generateYml({
|
||||
|
|
|
@ -30,7 +30,7 @@ export interface SavedObservabilityOnboardingState
|
|||
export const observabilityOnboardingState: SavedObjectsType = {
|
||||
name: OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE,
|
||||
hidden: false,
|
||||
namespaceType: 'multiple',
|
||||
namespaceType: 'agnostic',
|
||||
mappings: {
|
||||
properties: {
|
||||
state: { type: 'object', dynamic: false },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue