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

[Ingest] Add additional attributes to the Datasources Saved Object #66127

Merged
5 changes: 5 additions & 0 deletions x-pack/plugins/endpoint/common/generate_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,15 @@ export class EndpointDocGenerator {
* Generates an Ingest `datasource` that includes the Endpoint Policy data
*/
public generatePolicyDatasource(): PolicyData {
const created = new Date(Date.now() - 8.64e7).toISOString(); // 24h ago
Copy link
Member

Choose a reason for hiding this comment

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

I imagine is just for testing purpose?

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, test purposes to mock up data,

return {
id: this.seededUUIDv4(),
name: 'Endpoint Policy',
description: 'Policy to protect the worlds data',
created_at: created,
created_by: 'elastic',
updated_at: new Date().toISOString(),
updated_by: 'elastic',
config_id: this.seededUUIDv4(),
enabled: true,
output_id: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ describe('policy details: ', () => {
id: '',
name: '',
description: '',
created_at: '',
created_by: '',
updated_at: '',
updated_by: '',
config_id: '',
enabled: true,
output_id: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
*/

import { ImmutableMiddlewareFactory, PolicyDetailsState, UpdatePolicyResponse } from '../../types';
import { policyIdFromParams, isOnPolicyDetailsPage, policyDetails } from './selectors';
import {
policyIdFromParams,
isOnPolicyDetailsPage,
policyDetails,
policyDetailsForUpdate,
} from './selectors';
import {
sendGetDatasource,
sendGetFleetAgentStatusForConfig,
sendPutDatasource,
} from '../policy_list/services/ingest';
import { PolicyData } from '../../../../../common/types';
import { NewPolicyData, PolicyData } from '../../../../../common/types';
import { factory as policyConfigFactory } from '../../../../../common/models/policy_config';

export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDetailsState> = coreStart => {
Expand Down Expand Up @@ -71,7 +76,8 @@ export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDe
});
}
} else if (action.type === 'userClickedPolicyDetailsSaveButton') {
const { id, revision, ...updatedPolicyItem } = policyDetails(state) as PolicyData;
const { id } = policyDetails(state) as PolicyData;
const updatedPolicyItem = policyDetailsForUpdate(state) as NewPolicyData;

let apiResponse: UpdatePolicyResponse;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,29 @@

import { createSelector } from 'reselect';
import { PolicyDetailsState } from '../../types';
import { Immutable, PolicyConfig, UIPolicyConfig } from '../../../../../common/types';
import {
Immutable,
NewPolicyData,
PolicyConfig,
UIPolicyConfig,
} from '../../../../../common/types';
import { factory as policyConfigFactory } from '../../../../../common/models/policy_config';

/** Returns the policy details */
export const policyDetails = (state: Immutable<PolicyDetailsState>) => state.policyItem;

/**
* Return only the policy structure accepted for update/create
*/
export const policyDetailsForUpdate: (
state: Immutable<PolicyDetailsState>
) => Immutable<NewPolicyData> | undefined = createSelector(policyDetails, policy => {
if (policy) {
const { id, revision, created_by, created_at, updated_by, updated_at, ...newPolicy } = policy;
return newPolicy;
}
});

/** Returns a boolean of whether the user is on the policy details page or not */
export const isOnPolicyDetailsPage = (state: Immutable<PolicyDetailsState>) => {
if (state.location) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ describe('Ingest Manager - storedDatasourceToAgentDatasource', () => {
id: 'some-uuid',
name: 'mock-datasource',
description: '',
created_at: '',
created_by: '',
updated_at: '',
updated_by: '',
config_id: '',
enabled: true,
output_id: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ export interface Datasource extends Omit<NewDatasource, 'inputs'> {
id: string;
inputs: DatasourceInput[];
revision: number;
updated_at: string;
updated_by: string;
created_at: string;
created_by: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,16 @@ export const EditDatasourcePage: React.FunctionComponent = () => {
setAgentConfig(agentConfigData.item);
}
if (datasourceData?.item) {
const { id, revision, inputs, ...restOfDatasource } = datasourceData.item;
const {
id,
revision,
inputs,
created_by,
created_at,
updated_by,
updated_at,
...restOfDatasource
} = datasourceData.item;
// Remove `agent_stream` from all stream info, we assign this after saving
const newDatasource = {
...restOfDatasource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ export const createAgentConfigHandler: RequestHandler<
TypeOf<typeof CreateAgentConfigRequestSchema.body>
> = async (context, request, response) => {
const soClient = context.core.savedObjects.client;
const user = await appContextService.getSecurity()?.authc.getCurrentUser(request);
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const withSysMonitoring = request.query.sys_monitoring ?? false;
try {
// eslint-disable-next-line prefer-const
let [agentConfig, newSysDatasource] = await Promise.all<AgentConfig, NewDatasource | undefined>(
[
agentConfigService.create(soClient, request.body, {
user: user || undefined,
user,
}),
// If needed, retrieve System package information and build a new Datasource for the system package
// NOTE: we ignore failures in attempting to create datasource, since config might have been created
Expand All @@ -123,7 +123,7 @@ export const createAgentConfigHandler: RequestHandler<
// Create the system monitoring datasource and add it to config.
if (withSysMonitoring && newSysDatasource !== undefined && agentConfig !== undefined) {
newSysDatasource.config_id = agentConfig.id;
const sysDatasource = await datasourceService.create(soClient, newSysDatasource);
const sysDatasource = await datasourceService.create(soClient, newSysDatasource, { user });

if (sysDatasource) {
agentConfig = await agentConfigService.assignDatasources(soClient, agentConfig.id, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import { SavedObjectsServiceSetup, SavedObjectsType } from 'kibana/server';
import { EncryptedSavedObjectsPluginSetup } from '../../encrypted_saved_objects/server';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import {
OUTPUT_SAVED_OBJECT_TYPE,
AGENT_CONFIG_SAVED_OBJECT_TYPE,
Expand All @@ -16,7 +16,8 @@ import {
AGENT_ACTION_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
GLOBAL_SETTINGS_SAVED_OBJET_TYPE,
} from './constants';
} from '../constants';
import { migrateDatasourcesToV790 } from './migrations/datasources_v790';

/*
* Saved object types and mappings
Expand Down Expand Up @@ -218,8 +219,15 @@ const savedObjectTypes: { [key: string]: SavedObjectsType } = {
},
},
revision: { type: 'integer' },
updated_at: { type: 'date' },
updated_by: { type: 'keyword' },
created_at: { type: 'date' },
created_by: { type: 'keyword' },
},
},
migrations: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Even though I don't expect users to migrate from 7.8 to 7.9 I like that we get into the habit of providing a migration path! 👍

'7.9.0': migrateDatasourcesToV790,
},
},
[PACKAGES_SAVED_OBJECT_TYPE]: {
name: PACKAGES_SAVED_OBJECT_TYPE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { SavedObjectMigrationFn } from 'kibana/server';
import { cloneDeep } from 'lodash';
import { Datasource } from '../../types/models';

type Pre790Datasource = Exclude<
Datasource,
'created_at' | 'created_by' | 'updated_at' | 'updated_by'
>;

export const migrateDatasourcesToV790: SavedObjectMigrationFn<
Pre790Datasource,
Datasource
> = doc => {
const updatedDatasource = cloneDeep(doc);
const defDate = new Date().toISOString();

updatedDatasource.attributes.created_by = 'system';
updatedDatasource.attributes.created_at = updatedDatasource?.updated_at ?? defDate;
updatedDatasource.attributes.updated_by = 'system';
updatedDatasource.attributes.updated_at = updatedDatasource?.updated_at ?? defDate;

return updatedDatasource;
};
7 changes: 7 additions & 0 deletions x-pack/plugins/ingest_manager/server/services/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ class DatasourceService {
datasource: NewDatasource,
options?: { id?: string; user?: AuthenticatedUser }
): Promise<Datasource> {
const isoDate = new Date().toISOString();
const newSo = await soClient.create<Omit<Datasource, 'id'>>(
SAVED_OBJECT_TYPE,
{
...datasource,
revision: 1,
created_at: isoDate,
created_by: options?.user?.username ?? 'system',
updated_at: isoDate,
updated_by: options?.user?.username ?? 'system',
},
options
);
Expand Down Expand Up @@ -134,6 +139,8 @@ class DatasourceService {
await soClient.update<Datasource>(SAVED_OBJECT_TYPE, id, {
...datasource,
revision: oldDatasource.revision + 1,
updated_at: new Date().toISOString(),
updated_by: options?.user?.username ?? 'system',
});

// Bump revision of associated agent config
Expand Down