diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b47d78ea6d691..e0608128f71be 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -332,6 +332,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib # Security Intelligence And Analytics /x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules @elastic/security-intelligence-analytics +# Security Asset Management +/x-pack/plugins/osquery @elastic/security-asset-management + # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design #CC# /packages/kbn-ui-framework/ @elastic/kibana-design diff --git a/x-pack/plugins/osquery/.i18nrc.json b/x-pack/plugins/osquery/.i18nrc.json deleted file mode 100644 index fddcf98f4e73c..0000000000000 --- a/x-pack/plugins/osquery/.i18nrc.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "paths": { - "osquery": "." - }, - "prefix": "osquery", - "translations": [ - "translations/ja-JP.json" - ] -} diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts index 261b9ba0c36b3..e1fff1713c740 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts @@ -4,23 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ +import { SearchResponse } from 'elasticsearch'; import { IEsSearchResponse } from '../../../../../../../src/plugins/data/common'; -import { CursorType, Inspect, Maybe, PageInfoPaginated } from '../../common'; +import { Inspect, Maybe, PageInfoPaginated } from '../../common'; import { RequestOptions, RequestOptionsPaginated } from '../..'; -export interface ActionEdge { - node: any[]; - cursor: CursorType; -} - -export interface ActionResultEdge { - node: any[]; - cursor: CursorType; -} +export type ActionEdge = SearchResponse['hits']['hits']; +export type ActionResultEdge = SearchResponse['hits']['hits']; export interface ActionsStrategyResponse extends IEsSearchResponse { - edges: ActionEdge[]; + edges: ActionEdge; totalCount: number; pageInfo: PageInfoPaginated; inspect?: Maybe; @@ -38,7 +32,7 @@ export interface ActionDetailsRequestOptions extends RequestOptions { } export interface ActionResultsStrategyResponse extends IEsSearchResponse { - edges: ActionResultEdge[]; + edges: ActionResultEdge; totalCount: number; pageInfo: PageInfoPaginated; inspect?: Maybe; diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/agents/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/agents/index.ts index 5c085214aeeac..64a570ef5525b 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/agents/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/agents/index.ts @@ -6,16 +6,12 @@ import { IEsSearchResponse } from '../../../../../../../src/plugins/data/common'; -import { CursorType, Inspect, Maybe, PageInfoPaginated } from '../../common'; +import { Inspect, Maybe, PageInfoPaginated } from '../../common'; import { RequestOptionsPaginated } from '../..'; - -export interface AgentEdge { - node: any[]; - cursor: CursorType; -} +import { Agent } from '../../../shared_imports'; export interface AgentsStrategyResponse extends IEsSearchResponse { - edges: AgentEdge[]; + edges: Agent[]; totalCount: number; pageInfo: PageInfoPaginated; inspect?: Maybe; diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts index 7d8aa4a6be555..d6365062c8dff 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts @@ -4,18 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import { SearchResponse } from 'elasticsearch'; import { IEsSearchResponse } from '../../../../../../../src/plugins/data/common'; -import { CursorType, Inspect, Maybe, PageInfoPaginated } from '../../common'; +import { Inspect, Maybe, PageInfoPaginated } from '../../common'; import { RequestOptionsPaginated } from '../..'; -export interface ResultEdge { - node: any[]; - cursor: CursorType; -} +export type ResultEdge = SearchResponse['hits']['hits']; export interface ResultsStrategyResponse extends IEsSearchResponse { - edges: ResultEdge[]; + edges: ResultEdge; totalCount: number; pageInfo: PageInfoPaginated; inspect?: Maybe; diff --git a/x-pack/plugins/osquery/common/shared_imports.ts b/x-pack/plugins/osquery/common/shared_imports.ts new file mode 100644 index 0000000000000..58133db6aa1b0 --- /dev/null +++ b/x-pack/plugins/osquery/common/shared_imports.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { Agent } from '../../fleet/common'; diff --git a/x-pack/plugins/osquery/public/action_results/action_results_table.tsx b/x-pack/plugins/osquery/public/action_results/action_results_table.tsx index 6ecc952b29b64..513f73c8b351f 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_table.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_table.tsx @@ -58,7 +58,7 @@ const ActionResultsTableComponent: React.FC = ({ action () => ({ rowIndex, columnId, setCellProps }) => { // eslint-disable-next-line react-hooks/rules-of-hooks const data = useContext(DataContext); - + // @ts-expect-error const value = data[rowIndex].fields[columnId]; return !isEmpty(value) ? value : '-'; @@ -82,6 +82,7 @@ const ActionResultsTableComponent: React.FC = ({ action ); useEffect(() => { + // @ts-expect-error const newColumns = keys(results[0]?.fields) .sort() .map((fieldName) => ({ diff --git a/x-pack/plugins/osquery/public/actions/actions_table.tsx b/x-pack/plugins/osquery/public/actions/actions_table.tsx index ad73615dd5a97..e24f7adcea924 100644 --- a/x-pack/plugins/osquery/public/actions/actions_table.tsx +++ b/x-pack/plugins/osquery/public/actions/actions_table.tsx @@ -5,7 +5,7 @@ */ import { isEmpty, isEqual, keys, map } from 'lodash/fp'; -import { EuiDataGrid, EuiDataGridProps, EuiDataGridColumn } from '@elastic/eui'; +import { EuiDataGrid, EuiDataGridProps, EuiDataGridColumn, EuiDataGridSorting } from '@elastic/eui'; import React, { createContext, useEffect, useState, useCallback, useContext, useMemo } from 'react'; import { useAllActions } from './use_all_actions'; @@ -14,7 +14,6 @@ import { ActionEdge, Direction } from '../../common/search_strategy'; const DataContext = createContext([]); const ActionsTableComponent = () => { - // ** Pagination config const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 50 }); const onChangeItemsPerPage = useCallback( (pageSize) => @@ -33,7 +32,7 @@ const ActionsTableComponent = () => { const [columns, setColumns] = useState([]); // ** Sorting config - const [sortingColumns, setSortingColumns] = useState([]); + const [sortingColumns, setSortingColumns] = useState([]); const [, { actions, totalCount }] = useAllActions({ activePage: pagination.pageIndex, @@ -55,16 +54,17 @@ const ActionsTableComponent = () => { // eslint-disable-next-line react-hooks/rules-of-hooks const data = useContext(DataContext); + // @ts-expect-error const value = data[rowIndex].fields[columnId]; return !isEmpty(value) ? value : '-'; }; }, []); - const tableSorting = useMemo(() => ({ columns: sortingColumns, onSort: setSortingColumns }), [ - setSortingColumns, - sortingColumns, - ]); + const tableSorting: EuiDataGridSorting = useMemo( + () => ({ columns: sortingColumns, onSort: setSortingColumns }), + [setSortingColumns, sortingColumns] + ); const tablePagination = useMemo( () => ({ @@ -77,6 +77,7 @@ const ActionsTableComponent = () => { ); useEffect(() => { + // @ts-expect-error const newColumns = keys(actions[0]?.fields) .sort() .map((fieldName) => ({ diff --git a/x-pack/plugins/osquery/public/agents/agents_table.tsx b/x-pack/plugins/osquery/public/agents/agents_table.tsx index 33fb739681098..e43f93be918bd 100644 --- a/x-pack/plugins/osquery/public/agents/agents_table.tsx +++ b/x-pack/plugins/osquery/public/agents/agents_table.tsx @@ -6,10 +6,17 @@ import { find } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; -import { EuiBasicTable, EuiBasicTableProps, EuiTableSelectionType, EuiHealth } from '@elastic/eui'; +import { + EuiBasicTable, + EuiBasicTableColumn, + EuiBasicTableProps, + EuiTableSelectionType, + EuiHealth, +} from '@elastic/eui'; import { useAllAgents } from './use_all_agents'; -import { AgentEdge, Direction } from '../../common/search_strategy'; +import { Direction } from '../../common/search_strategy'; +import { Agent } from '../shared_imports'; interface AgentsTableProps { selectedAgents: string[]; @@ -19,12 +26,12 @@ interface AgentsTableProps { const AgentsTableComponent: React.FC = ({ selectedAgents, onChange }) => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(5); - const [sortField, setSortField] = useState('firstName'); + const [sortField, setSortField] = useState('id'); const [sortDirection, setSortDirection] = useState(Direction.asc); const [selectedItems, setSelectedItems] = useState([]); - const tableRef = useRef>(null); + const tableRef = useRef>(null); - const onTableChange: EuiBasicTableProps<{}>['onChange'] = useCallback( + const onTableChange: EuiBasicTableProps['onChange'] = useCallback( ({ page = {}, sort = {} }) => { const { index: newPageIndex, size: newPageSize } = page; @@ -41,6 +48,7 @@ const AgentsTableComponent: React.FC = ({ selectedAgents, onCh const onSelectionChange: EuiTableSelectionType<{}>['onSelectionChange'] = useCallback( (newSelectedItems) => { setSelectedItems(newSelectedItems); + // @ts-expect-error onChange(newSelectedItems.map((item) => item._id)); }, [onChange] @@ -59,7 +67,7 @@ const AgentsTableComponent: React.FC = ({ selectedAgents, onCh sortField, }); - const columns = useMemo( + const columns: Array> = useMemo( () => [ { field: 'local_metadata.elastic.agent.id', @@ -103,11 +111,10 @@ const AgentsTableComponent: React.FC = ({ selectedAgents, onCh [sortDirection, sortField] ); - const selection = useMemo( + const selection: EuiBasicTableProps['selection'] = useMemo( () => ({ - selectable: (agent: AgentEdge) => agent.active, - selectableMessage: (selectable: boolean) => - !selectable ? 'User is currently offline' : undefined, + selectable: (agent: Agent) => agent.active, + selectableMessage: (selectable: boolean) => (!selectable ? 'User is currently offline' : ''), onSelectionChange, initialSelected: selectedItems, }), @@ -117,13 +124,14 @@ const AgentsTableComponent: React.FC = ({ selectedAgents, onCh useEffect(() => { if (selectedAgents?.length && agents.length && selectedItems.length !== selectedAgents.length) { tableRef?.current?.setSelection( + // @ts-expect-error selectedAgents.map((agentId) => find({ _id: agentId }, agents)) ); } }, [selectedAgents, agents, selectedItems.length]); return ( - + ref={tableRef} items={agents} itemId="_id" diff --git a/x-pack/plugins/osquery/public/agents/use_all_agents.ts b/x-pack/plugins/osquery/public/agents/use_all_agents.ts index 09410b5a95356..f700f7775ddaf 100644 --- a/x-pack/plugins/osquery/public/agents/use_all_agents.ts +++ b/x-pack/plugins/osquery/public/agents/use_all_agents.ts @@ -10,7 +10,6 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { createFilter } from '../common/helpers'; import { useKibana } from '../common/lib/kibana'; import { - AgentEdge, PageInfoPaginated, DocValueFields, OsqueryQueries, @@ -19,6 +18,7 @@ import { Direction, } from '../../common/search_strategy'; import { ESTermQuery } from '../../common/typed_json'; +import { Agent } from '../shared_imports'; import * as i18n from './translations'; import { isCompleteResponse, isErrorResponse } from '../../../../../src/plugins/data/common'; @@ -28,7 +28,7 @@ import { generateTablePaginationOptions, getInspectResponse, InspectResponse } f const ID = 'agentsAllQuery'; export interface AgentsArgs { - agents: AgentEdge[]; + agents: Agent[]; id: string; inspect: InspectResponse; isInspected: boolean; @@ -97,6 +97,7 @@ export const useAllAgents = ({ next: (response) => { if (isCompleteResponse(response)) { if (!didCancel) { + console.error('agents', response.edges); setLoading(false); setAgentsResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/osquery/public/live_query/edit/index.tsx b/x-pack/plugins/osquery/public/live_query/edit/index.tsx index 214d3c214361f..5626e78069d01 100644 --- a/x-pack/plugins/osquery/public/live_query/edit/index.tsx +++ b/x-pack/plugins/osquery/public/live_query/edit/index.tsx @@ -6,7 +6,7 @@ import { isEmpty } from 'lodash/fp'; import { EuiSpacer } from '@elastic/eui'; -import React from 'react'; +import React, { useCallback } from 'react'; import { useParams } from 'react-router-dom'; import { useActionDetails } from '../../actions/use_action_details'; @@ -17,13 +17,17 @@ const EditLiveQueryPageComponent = () => { const { actionId } = useParams<{ actionId: string }>(); const [loading, { actionDetails }] = useActionDetails({ actionId }); + const handleSubmit = useCallback(() => Promise.resolve(), []); + if (loading) { return <>{'Loading...'}; } return ( <> - {!isEmpty(actionDetails) && } + {!isEmpty(actionDetails) && ( + + )} diff --git a/x-pack/plugins/osquery/public/results/results_table.tsx b/x-pack/plugins/osquery/public/results/results_table.tsx index 4135169d21082..5336583122b16 100644 --- a/x-pack/plugins/osquery/public/results/results_table.tsx +++ b/x-pack/plugins/osquery/public/results/results_table.tsx @@ -87,6 +87,7 @@ const ResultsTableComponent: React.FC = ({ actionId ); useEffect(() => { + // @ts-expect-error const newColumns: EuiDataGridColumn[] = keys(results[0]?.fields) .sort() .map((fieldName) => ({ diff --git a/x-pack/plugins/osquery/public/results/use_all_results.ts b/x-pack/plugins/osquery/public/results/use_all_results.ts index 02541ba6f29ec..49d042cad2fc8 100644 --- a/x-pack/plugins/osquery/public/results/use_all_results.ts +++ b/x-pack/plugins/osquery/public/results/use_all_results.ts @@ -10,7 +10,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { createFilter } from '../common/helpers'; import { useKibana } from '../common/lib/kibana'; import { - ResultEdges, + ResultEdge, PageInfoPaginated, DocValueFields, OsqueryQueries, @@ -28,7 +28,7 @@ import { generateTablePaginationOptions, getInspectResponse, InspectResponse } f const ID = 'resultsAllQuery'; export interface ResultsArgs { - results: ResultEdges[]; + results: ResultEdge[]; id: string; inspect: InspectResponse; isInspected: boolean; diff --git a/x-pack/plugins/osquery/server/config.ts b/x-pack/plugins/osquery/server/config.ts index 8c65d20c7fc39..633a95b8f91a7 100644 --- a/x-pack/plugins/osquery/server/config.ts +++ b/x-pack/plugins/osquery/server/config.ts @@ -7,7 +7,7 @@ import { TypeOf, schema } from '@kbn/config-schema'; export const ConfigSchema = schema.object({ - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), }); export type ConfigType = TypeOf; diff --git a/x-pack/plugins/osquery/server/index.ts b/x-pack/plugins/osquery/server/index.ts index 95cf6cf037210..c74ef6c95a2e7 100644 --- a/x-pack/plugins/osquery/server/index.ts +++ b/x-pack/plugins/osquery/server/index.ts @@ -8,7 +8,12 @@ import { PluginInitializerContext } from '../../../../src/core/server'; import { OsqueryPlugin } from './plugin'; import { ConfigSchema } from './config'; -export const config = { schema: ConfigSchema }; +export const config = { + schema: ConfigSchema, + exposeToBrowser: { + enabled: true, + }, +}; export function plugin(initializerContext: PluginInitializerContext) { return new OsqueryPlugin(initializerContext); } diff --git a/x-pack/plugins/osquery/server/plugin.ts b/x-pack/plugins/osquery/server/plugin.ts index 6b9f2716585f2..3e59faa55d057 100644 --- a/x-pack/plugins/osquery/server/plugin.ts +++ b/x-pack/plugins/osquery/server/plugin.ts @@ -13,7 +13,6 @@ import { Logger, } from '../../../../src/core/server'; -import { ConfigType } from './config'; import { createConfig$ } from './create_config'; import { OsqueryPluginSetup, OsqueryPluginStart, SetupPlugins, StartPlugins } from './types'; import { defineRoutes } from './routes'; @@ -21,7 +20,6 @@ import { osquerySearchStrategyProvider } from './search_strategy/osquery'; export class OsqueryPlugin implements Plugin { private readonly logger: Logger; - private config: ConfigType | undefined | null; constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = this.initializerContext.logger.get(); @@ -30,9 +28,8 @@ export class OsqueryPlugin implements Plugin, plugins: SetupPlugins) { this.logger.debug('osquery: Setup'); const config = await createConfig$(this.initializerContext).pipe(first()).toPromise(); - this.config = config; - if (!this.config.enabled) { + if (!config.enabled) { return {}; } @@ -51,7 +48,7 @@ export class OsqueryPlugin implements Plugin { - return response.ok({ - body: { - time: new Date().toISOString(), - }, - }); - } - ); - router.post( { path: '/api/osquery/queries', @@ -43,11 +29,13 @@ export function defineRoutes(router: IRouter) { expiration: moment().add(2, 'days').toISOString(), type: 'APP_ACTION', input_id: 'osquery', + // @ts-expect-error agents: request.body.agents, data: { commands: [ { id: uuid.v4(), + // @ts-expect-error query: request.body.command.query, }, ], diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/index.ts index c4a8f2fbca2bc..4a049ca670cc6 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/index.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/index.ts @@ -25,7 +25,7 @@ export const actionResults: OsqueryFactory = { }, parse: async ( options: ActionResultsRequestOptions, - response: IEsSearchResponse + response: IEsSearchResponse ): Promise => { const { activePage } = options.pagination; const inspect = { diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts index dd186334c7cbe..615343c738d78 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts @@ -12,6 +12,7 @@ import { OsqueryQueries, } from '../../../../../common/search_strategy/osquery'; +import { Agent } from '../../../../../common/shared_imports'; import { inspectStringifyObject } from '../../../../../common/utils/build_query'; import { OsqueryFactory } from '../types'; import { buildAgentsQuery } from './query.all_agents.dsl'; @@ -25,7 +26,7 @@ export const allAgents: OsqueryFactory = { }, parse: async ( options: AgentsRequestOptions, - response: IEsSearchResponse + response: IEsSearchResponse ): Promise => { const { activePage } = options.pagination; const inspect = {