[SIEM] Add TLS to Newtowrk overview page (#48062) (#48386)

* add TLS table to network overview page

* isolate TLS parser

* add unit test

* add integration test

* fix types

* revert not necessary change

* remove variables for domains table

* fix for review

* fix tlsSelector

* update tls selector

* apply updateTlsLimit

* update selected property for tls selector

* add networkType as the 2nd param of updateTlsSort

* correcting pagetype

* check the page type for updateTableActivePage

* hard coded the targeting table name

* remove tls table param as property

* fix types
This commit is contained in:
Angela Chuang 2019-10-16 13:50:05 +01:00 committed by GitHub
parent 6113f648fa
commit 168f4d6223
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1929 additions and 863 deletions

View file

@ -13,7 +13,6 @@ import { RedirectToNetworkPage } from './redirect_to_network';
import { RedirectToOverviewPage } from './redirect_to_overview';
import { RedirectToTimelinesPage } from './redirect_to_timelines';
import { HostsTableType } from '../../store/hosts/model';
interface LinkToPageProps {
match: RouteMatch<{}>;
}

View file

@ -36,10 +36,14 @@ interface TlsTableReduxProps {
}
interface TlsTableDispatchProps {
updateTableActivePage: ActionCreator<{
updateIpDetailsTableActivePage: ActionCreator<{
activePage: number;
tableType: networkModel.IpDetailsTableType;
}>;
updateNetworkPageTableActivePage: ActionCreator<{
activePage: number;
tableType: networkModel.NetworkTableType;
}>;
updateTlsLimit: ActionCreator<{
limit: number;
networkType: networkModel.NetworkType;
@ -80,9 +84,18 @@ class TlsTableComponent extends React.PureComponent<TlsTableProps> {
tlsSortField,
totalCount,
type,
updateTableActivePage,
updateIpDetailsTableActivePage,
updateNetworkPageTableActivePage,
updateTlsLimit,
} = this.props;
const updateTableActivePage: ActionCreator<{
activePage: number;
tableType: networkModel.NetworkTableType | networkModel.IpDetailsTableType;
}> =
type === networkModel.NetworkType.page
? updateNetworkPageTableActivePage
: updateIpDetailsTableActivePage;
return (
<PaginatedTable
activePage={activePage}
@ -130,17 +143,14 @@ class TlsTableComponent extends React.PureComponent<TlsTableProps> {
};
}
const makeMapStateToProps = () => {
const getTlsSelector = networkSelectors.tlsSelector();
return (state: State) => ({
...getTlsSelector(state),
});
};
const makeMapStateToProps = (state: State, ownProps: OwnProps) =>
networkSelectors.tlsSelector(ownProps.type);
export const TlsTable = connect(
makeMapStateToProps,
{
updateTableActivePage: networkActions.updateIpDetailsTableActivePage,
updateNetworkPageTableActivePage: networkActions.updateNetworkPageTableActivePage,
updateIpDetailsTableActivePage: networkActions.updateIpDetailsTableActivePage,
updateTlsLimit: networkActions.updateTlsLimit,
updateTlsSort: networkActions.updateTlsSort,
}

View file

@ -10,7 +10,7 @@ export const tlsQuery = gql`
query GetTlsQuery(
$sourceId: ID!
$filterQuery: String
$flowTarget: FlowTarget!
$flowTarget: FlowTargetSourceDest!
$ip: String!
$pagination: PaginationInputPaginated!
$sort: TlsSortField!

View file

@ -12,11 +12,11 @@ import { connect } from 'react-redux';
import chrome from 'ui/chrome';
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
import {
FlowTarget,
PageInfoPaginated,
TlsEdges,
TlsSortField,
GetTlsQuery,
FlowTargetSourceDest,
} from '../../graphql/types';
import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store';
import { createFilter, getDefaultFetchPolicy } from '../helpers';
@ -40,7 +40,7 @@ export interface TlsArgs {
export interface OwnProps extends QueryTemplatePaginatedProps {
children: (args: TlsArgs) => React.ReactNode;
flowTarget: FlowTarget;
flowTarget: FlowTargetSourceDest;
ip: string;
type: networkModel.NetworkType;
}
@ -139,18 +139,15 @@ class TlsComponentQuery extends QueryTemplatePaginated<
}
}
const makeMapStateToProps = () => {
const getTlsSelector = networkSelectors.tlsSelector();
const mapStateToProps = (state: State, { id = ID, type }: OwnProps) => {
const getTlsSelector = networkSelectors.tlsSelector(type);
const getQuery = inputsSelectors.globalQueryByIdSelector();
const mapStateToProps = (state: State, { id = ID }: OwnProps) => {
const { isInspected } = getQuery(state, id);
return {
...getTlsSelector(state),
isInspected,
};
};
const { isInspected } = getQuery(state, id);
return mapStateToProps;
return {
...getTlsSelector(state),
isInspected,
};
};
export const TlsQuery = connect(makeMapStateToProps)(TlsComponentQuery);
export const TlsQuery = connect(mapStateToProps)(TlsComponentQuery);

View file

@ -1193,103 +1193,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "Tls",
"description": "",
"args": [
{
"name": "filterQuery",
"description": "",
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"defaultValue": null
},
{
"name": "id",
"description": "",
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"defaultValue": null
},
{
"name": "ip",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
},
"defaultValue": null
},
{
"name": "pagination",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "PaginationInputPaginated",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "sort",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "INPUT_OBJECT", "name": "TlsSortField", "ofType": null }
},
"defaultValue": null
},
{
"name": "flowTarget",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "FlowTarget", "ofType": null }
},
"defaultValue": null
},
{
"name": "timerange",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }
},
"defaultValue": null
},
{
"name": "defaultIndex",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
}
},
"defaultValue": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsData", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "Users",
"description": "",
@ -1925,6 +1828,103 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "Tls",
"description": "",
"args": [
{
"name": "filterQuery",
"description": "",
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"defaultValue": null
},
{
"name": "id",
"description": "",
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"defaultValue": null
},
{
"name": "ip",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
},
"defaultValue": null
},
{
"name": "pagination",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "PaginationInputPaginated",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "sort",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "INPUT_OBJECT", "name": "TlsSortField", "ofType": null }
},
"defaultValue": null
},
{
"name": "flowTarget",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null }
},
"defaultValue": null
},
{
"name": "timerange",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }
},
"defaultValue": null
},
{
"name": "defaultIndex",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
}
},
"defaultValue": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsData", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "UncommonProcesses",
"description": "Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified",
@ -6378,274 +6378,6 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "TlsSortField",
"description": "",
"fields": null,
"inputFields": [
{
"name": "field",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "TlsFields", "ofType": null }
},
"defaultValue": null
},
{
"name": "direction",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "Direction", "ofType": null }
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "TlsFields",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{ "name": "_id", "description": "", "isDeprecated": false, "deprecationReason": null }
],
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "FlowTarget",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{ "name": "client", "description": "", "isDeprecated": false, "deprecationReason": null },
{
"name": "destination",
"description": "",
"isDeprecated": false,
"deprecationReason": null
},
{ "name": "server", "description": "", "isDeprecated": false, "deprecationReason": null },
{ "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null }
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsData",
"description": "",
"fields": [
{
"name": "edges",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsEdges", "ofType": null }
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "totalCount",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "inspect",
"description": "",
"args": [],
"type": { "kind": "OBJECT", "name": "Inspect", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsEdges",
"description": "",
"fields": [
{
"name": "node",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsNode", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "cursor",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsNode",
"description": "",
"fields": [
{
"name": "_id",
"description": "",
"args": [],
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "timestamp",
"description": "",
"args": [],
"type": { "kind": "SCALAR", "name": "Date", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "alternativeNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "notAfter",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "commonNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ja3",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issuerNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "UsersSortField",
@ -6690,6 +6422,26 @@
],
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "FlowTarget",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{ "name": "client", "description": "", "isDeprecated": false, "deprecationReason": null },
{
"name": "destination",
"description": "",
"isDeprecated": false,
"deprecationReason": null
},
{ "name": "server", "description": "", "isDeprecated": false, "deprecationReason": null },
{ "name": "source", "description": "", "isDeprecated": false, "deprecationReason": null }
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "UsersData",
@ -8424,6 +8176,254 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "TlsSortField",
"description": "",
"fields": null,
"inputFields": [
{
"name": "field",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "TlsFields", "ofType": null }
},
"defaultValue": null
},
{
"name": "direction",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "ENUM", "name": "Direction", "ofType": null }
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "TlsFields",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{ "name": "_id", "description": "", "isDeprecated": false, "deprecationReason": null }
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsData",
"description": "",
"fields": [
{
"name": "edges",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsEdges", "ofType": null }
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "totalCount",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "inspect",
"description": "",
"args": [],
"type": { "kind": "OBJECT", "name": "Inspect", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsEdges",
"description": "",
"fields": [
{
"name": "node",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "TlsNode", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "cursor",
"description": "",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null }
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "TlsNode",
"description": "",
"fields": [
{
"name": "_id",
"description": "",
"args": [],
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "timestamp",
"description": "",
"args": [],
"type": { "kind": "SCALAR", "name": "Date", "ofType": null },
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "alternativeNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "notAfter",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "commonNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ja3",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issuerNames",
"description": "",
"args": [],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "UncommonProcessesData",

View file

@ -67,12 +67,6 @@ export interface HostsSortField {
direction: Direction;
}
export interface TlsSortField {
field: TlsFields;
direction: Direction;
}
export interface UsersSortField {
field: UsersFields;
@ -91,6 +85,12 @@ export interface NetworkDnsSortField {
direction: Direction;
}
export interface TlsSortField {
field: TlsFields;
direction: Direction;
}
export interface PageInfoTimeline {
pageIndex: number;
@ -239,8 +239,9 @@ export enum HostsFields {
lastSeen = 'lastSeen',
}
export enum TlsFields {
_id = '_id',
export enum UsersFields {
name = 'name',
count = 'count',
}
export enum FlowTarget {
@ -250,11 +251,6 @@ export enum FlowTarget {
source = 'source',
}
export enum UsersFields {
name = 'name',
count = 'count',
}
export enum FlowTargetSourceDest {
destination = 'destination',
source = 'source',
@ -276,6 +272,10 @@ export enum NetworkDnsFields {
dnsBytesOut = 'dnsBytesOut',
}
export enum TlsFields {
_id = '_id',
}
export enum SortFieldTimeline {
title = 'title',
description = 'description',
@ -417,8 +417,6 @@ export interface Source {
IpOverview?: Maybe<IpOverviewData>;
Tls: TlsData;
Users: UsersData;
KpiNetwork?: Maybe<KpiNetworkData>;
@ -436,6 +434,8 @@ export interface Source {
OverviewNetwork?: Maybe<OverviewNetworkData>;
OverviewHost?: Maybe<OverviewHostData>;
Tls: TlsData;
/** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */
UncommonProcesses: UncommonProcessesData;
/** Just a simple example to get the app name */
@ -1314,38 +1314,6 @@ export interface AutonomousSystemOrganization {
name?: Maybe<string>;
}
export interface TlsData {
edges: TlsEdges[];
totalCount: number;
pageInfo: PageInfoPaginated;
inspect?: Maybe<Inspect>;
}
export interface TlsEdges {
node: TlsNode;
cursor: CursorType;
}
export interface TlsNode {
_id?: Maybe<string>;
timestamp?: Maybe<string>;
alternativeNames?: Maybe<string[]>;
notAfter?: Maybe<string[]>;
commonNames?: Maybe<string[]>;
ja3?: Maybe<string[]>;
issuerNames?: Maybe<string[]>;
}
export interface UsersData {
edges: UsersEdges[];
@ -1666,6 +1634,38 @@ export interface OverviewHostData {
inspect?: Maybe<Inspect>;
}
export interface TlsData {
edges: TlsEdges[];
totalCount: number;
pageInfo: PageInfoPaginated;
inspect?: Maybe<Inspect>;
}
export interface TlsEdges {
node: TlsNode;
cursor: CursorType;
}
export interface TlsNode {
_id?: Maybe<string>;
timestamp?: Maybe<string>;
alternativeNames?: Maybe<string[]>;
notAfter?: Maybe<string[]>;
commonNames?: Maybe<string[]>;
ja3?: Maybe<string[]>;
issuerNames?: Maybe<string[]>;
}
export interface UncommonProcessesData {
edges: UncommonProcessesEdges[];
@ -2052,23 +2052,6 @@ export interface IpOverviewSourceArgs {
defaultIndex: string[];
}
export interface TlsSourceArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTarget;
timerange: TimerangeInput;
defaultIndex: string[];
}
export interface UsersSourceArgs {
filterQuery?: Maybe<string>;
@ -2180,6 +2163,23 @@ export interface OverviewHostSourceArgs {
defaultIndex: string[];
}
export interface TlsSourceArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTargetSourceDest;
timerange: TimerangeInput;
defaultIndex: string[];
}
export interface UncommonProcessesSourceArgs {
timerange: TimerangeInput;
@ -5113,7 +5113,7 @@ export namespace GetTlsQuery {
export type Variables = {
sourceId: string;
filterQuery?: Maybe<string>;
flowTarget: FlowTarget;
flowTarget: FlowTargetSourceDest;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;

View file

@ -91,6 +91,11 @@ export const mockGlobalState: State = {
dnsSortField: { field: NetworkDnsFields.queryCount, direction: Direction.desc },
isPtrIncluded: false,
},
[networkModel.NetworkTableType.tls]: {
activePage: 0,
limit: 10,
tlsSortField: { field: TlsFields._id, direction: Direction.desc },
},
},
},
details: {

View file

@ -357,7 +357,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
<TlsQuery
endDate={to}
filterQuery={filterQuery}
flowTarget={flowTarget}
flowTarget={(flowTarget as unknown) as FlowTargetSourceDest}
ip={ip}
skip={isInitializing}
sourceId="default"

View file

@ -33,6 +33,13 @@ export const navTabsNetwork = (hasMlUserPermissions: boolean): NetworkNavTab =>
disabled: false,
urlKey: 'network',
},
[NetworkRouteType.tls]: {
id: NetworkRouteType.tls,
name: i18n.NAVIGATION_TLS_TITLE,
href: getTabsOnNetworkUrl(NetworkRouteType.tls),
disabled: false,
urlKey: 'network',
},
[NetworkRouteType.anomalies]: {
id: NetworkRouteType.anomalies,
name: i18n.NAVIGATION_ANOMALIES_TITLE,

View file

@ -17,6 +17,7 @@ import { AnomaliesQueryTabBody } from './anomalies_query_tab_body';
import { DnsQueryTabBody } from './dns_query_tab_body';
import { ConditionalFlexGroup } from './conditional_flex_group';
import { NetworkRoutesProps, NetworkRouteType } from './types';
import { TlsQueryTabBody } from './tls_query_tab_body';
export const NetworkRoutes = ({
networkPagePath,
@ -80,6 +81,10 @@ export const NetworkRoutes = ({
</ConditionalFlexGroup>
)}
/>
<Route
path={`${networkPagePath}/:tabName(${NetworkRouteType.tls})`}
render={() => <TlsQueryTabBody {...tabProps} flowTarget={FlowTargetSourceDest.source} />}
/>
<Route
path={`${networkPagePath}/:tabName(${NetworkRouteType.countries})`}
render={() => (

View file

@ -0,0 +1,52 @@
/*
* 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 React from 'react';
import { getOr } from 'lodash/fp';
import { manageQuery } from '../../../components/page/manage_query';
import { TlsQuery } from '../../../containers/tls';
import { TlsTable } from '../../../components/page/network/tls_table';
import { TlsQueryTabBodyProps } from './types';
const TlsTableManage = manageQuery(TlsTable);
export const TlsQueryTabBody = ({
to,
filterQuery,
flowTarget,
ip = '',
setQuery,
isInitializing,
from,
type,
}: TlsQueryTabBodyProps) => (
<TlsQuery
endDate={to}
filterQuery={filterQuery}
flowTarget={flowTarget}
ip={ip}
skip={isInitializing}
sourceId="default"
startDate={from}
type={type}
>
{({ id, inspect, isInspected, tls, totalCount, pageInfo, loading, loadPage, refetch }) => (
<TlsTableManage
data={tls}
id={id}
inspect={inspect}
isInspect={isInspected}
fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)}
loading={loading}
loadPage={loadPage}
showMorePagesIndicator={getOr(false, 'showMorePagesIndicator', pageInfo)}
refetch={refetch}
setQuery={setQuery}
totalCount={totalCount}
type={type}
/>
)}
</TlsQuery>
);

View file

@ -28,6 +28,12 @@ export type IPsQueryTabBodyProps = QueryTabBodyProps &
flowTarget: FlowTargetSourceDest;
};
export type TlsQueryTabBodyProps = QueryTabBodyProps &
GlobalTimeArgs & {
flowTarget: FlowTargetSourceDest;
ip?: string;
};
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps &
Pick<GlobalTimeArgs, 'to' | 'from' | 'isInitializing'> & {
narrowDateRange: NarrowDateRange;
@ -43,7 +49,8 @@ export type NetworkRoutesProps = GlobalTimeArgs & {
export type KeyNetworkNavTabWithoutMlPermission = NetworkRouteType.countries &
NetworkRouteType.dns &
NetworkRouteType.ips;
NetworkRouteType.ips &
NetworkRouteType.tls;
type KeyNetworkNavTabWithMlPermission = KeyNetworkNavTabWithoutMlPermission &
NetworkRouteType.anomalies;
@ -57,6 +64,7 @@ export enum NetworkRouteType {
countries = 'countries',
dns = 'dns',
anomalies = 'anomalies',
tls = 'tls',
}
export type GetNetworkRoutePath = (

View file

@ -12,7 +12,7 @@ export const getNetworkRoutePath: GetNetworkRoutePath = (
hasMlUserPermission
) => {
if (capabilitiesFetched && !hasMlUserPermission) {
return `${pagePath}/:tabName(${NetworkRouteType.ips}|${NetworkRouteType.dns}|${NetworkRouteType.countries})`;
return `${pagePath}/:tabName(${NetworkRouteType.ips}|${NetworkRouteType.dns}|${NetworkRouteType.countries}|${NetworkRouteType.tls})`;
}
return (
@ -20,6 +20,7 @@ export const getNetworkRoutePath: GetNetworkRoutePath = (
`${NetworkRouteType.ips}|` +
`${NetworkRouteType.dns}|` +
`${NetworkRouteType.countries}|` +
`${NetworkRouteType.anomalies})`
`${NetworkRouteType.anomalies}|` +
`${NetworkRouteType.tls})`
);
};

View file

@ -42,6 +42,10 @@ export const NAVIGATION_DNS_TITLE = i18n.translate('xpack.siem.network.navigatio
defaultMessage: 'DNS',
});
export const NAVIGATION_TLS_TITLE = i18n.translate('xpack.siem.network.navigation.tlsTitle', {
defaultMessage: 'TLS',
});
export const NAVIGATION_ANOMALIES_TITLE = i18n.translate(
'xpack.siem.network.navigation.anomaliesTitle',
{

View file

@ -81,10 +81,12 @@ export const updateIpDetailsFlowTarget = actionCreator<{
// TLS Table Actions
export const updateTlsSort = actionCreator<{
tlsSortField: TlsSortField;
networkType: networkModel.NetworkType;
}>('UPDATE_TLS_SORT');
export const updateTlsLimit = actionCreator<{
limit: number;
networkType: networkModel.NetworkType;
}>('UPDATE_TLS_LIMIT');
// Users Table Actions

View file

@ -60,6 +60,14 @@ export const mockNetworkState: NetworkModel = {
},
isPtrIncluded: false,
},
[NetworkTableType.tls]: {
activePage: 2,
limit: DEFAULT_TABLE_LIMIT,
tlsSortField: {
field: TlsFields._id,
direction: Direction.desc,
},
},
},
},
details: {
@ -137,6 +145,14 @@ describe('Network redux store', () => {
dnsSortField: { field: 'uniqueDomains', direction: 'desc' },
isPtrIncluded: false,
},
[NetworkTableType.tls]: {
activePage: 0,
limit: 10,
tlsSortField: {
direction: 'desc',
field: '_id',
},
},
[NetworkTableType.topCountriesDestination]: {
activePage: 0,
limit: 10,

View file

@ -36,6 +36,10 @@ export const setNetworkPageQueriesActivePageToZero = (state: NetworkModel): Netw
...state.page.queries[NetworkTableType.dns],
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
},
[NetworkTableType.tls]: {
...state.page.queries[NetworkTableType.tls],
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
},
});
export const setNetworkDetailsQueriesActivePageToZero = (

View file

@ -23,6 +23,7 @@ export enum NetworkTableType {
topCountriesSource = 'topCountriesSource',
topNFlowDestination = 'topNFlowDestination',
topNFlowSource = 'topNFlowSource',
tls = 'tls',
}
export type TopNTableType =
@ -65,24 +66,23 @@ export interface DnsQuery extends BasicQueryPaginated {
isPtrIncluded: boolean;
}
export interface TlsQuery extends BasicQueryPaginated {
tlsSortField: TlsSortField;
}
export interface NetworkQueries {
[NetworkTableType.dns]: DnsQuery;
[NetworkTableType.topCountriesDestination]: TopCountriesQuery;
[NetworkTableType.topCountriesSource]: TopCountriesQuery;
[NetworkTableType.topNFlowDestination]: TopNFlowQuery;
[NetworkTableType.topNFlowSource]: TopNFlowQuery;
[NetworkTableType.tls]: TlsQuery;
}
export interface NetworkPageModel {
queries: NetworkQueries;
}
// IP Details Models
export interface TlsQuery extends BasicQueryPaginated {
tlsSortField: TlsSortField;
}
export interface UsersQuery extends BasicQueryPaginated {
usersSortField: UsersSortField;
}
@ -101,7 +101,6 @@ export interface NetworkDetailsModel {
queries: IpOverviewQueries;
}
// Network Model
export interface NetworkModel {
[NetworkType.page]: NetworkPageModel;
[NetworkType.details]: NetworkDetailsModel;

View file

@ -69,6 +69,14 @@ export const initialNetworkState: NetworkState = {
},
isPtrIncluded: false,
},
[NetworkTableType.tls]: {
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
limit: DEFAULT_TABLE_LIMIT,
tlsSortField: {
field: TlsFields._id,
direction: Direction.desc,
},
},
[NetworkTableType.topCountriesSource]: {
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
limit: DEFAULT_TABLE_LIMIT,
@ -382,27 +390,27 @@ export const networkReducer = reducerWithInitialState(initialNetworkState)
flowTarget,
},
}))
.case(updateTlsLimit, (state, { limit }) => ({
.case(updateTlsLimit, (state, { limit, networkType }) => ({
...state,
[NetworkType.details]: {
...state[NetworkType.details],
[networkType]: {
...state[networkType],
queries: {
...state[NetworkType.details].queries,
[IpDetailsTableType.tls]: {
...state[NetworkType.details].queries.tls,
...state[networkType].queries,
tls: {
...state[networkType].queries.tls,
limit,
},
},
},
}))
.case(updateTlsSort, (state, { tlsSortField }) => ({
.case(updateTlsSort, (state, { tlsSortField, networkType }) => ({
...state,
[NetworkType.details]: {
...state[NetworkType.details],
[networkType]: {
...state[networkType],
queries: {
...state[NetworkType.details].queries,
[IpDetailsTableType.tls]: {
...state[NetworkType.details].queries.tls,
...state[networkType].queries,
tls: {
...state[networkType].queries.tls,
tlsSortField,
},
},

View file

@ -22,12 +22,14 @@ export const dnsSelector = () =>
network => network.queries.dns
);
export enum NetworkTableType {
tls = 'tls',
dns = 'dns',
topCountriesDestination = 'topCountriesDestination',
topCountriesSource = 'topCountriesSource',
topNFlowDestination = 'topNFlowDestination',
topNFlowSource = 'topNFlowSource',
}
export const topNFlowSelector = (flowTarget: FlowTargetSourceDest, networkType: NetworkType) => {
if (networkType === NetworkType.page) {
return createSelector(
@ -47,6 +49,20 @@ export const topNFlowSelector = (flowTarget: FlowTargetSourceDest, networkType:
);
};
export const tlsSelector = (networkType: NetworkType) => {
if (networkType === NetworkType.page) {
return createSelector(
selectNetworkPage,
network => network.queries[NetworkTableType.tls]
);
}
return createSelector(
selectNetworkDetails,
network => network.queries[IpDetailsTableType.tls]
);
};
export const topCountriesSelector = (
flowTarget: FlowTargetSourceDest,
networkType: NetworkType
@ -76,12 +92,6 @@ export const ipDetailsFlowTargetSelector = () =>
network => network.flowTarget
);
export const tlsSelector = () =>
createSelector(
selectNetworkDetails,
network => network.queries.tls
);
export const usersSelector = () =>
createSelector(
selectNetworkDetails,

View file

@ -25,6 +25,7 @@ import { toNumberSchema } from './scalar_to_number_array';
import { sourceStatusSchema } from './source_status';
import { sourcesSchema } from './sources';
import { timelineSchema } from './timeline';
import { tlsSchema } from './tls';
import { uncommonProcessesSchema } from './uncommon_processes';
import { whoAmISchema } from './who_am_i';
export const schemas = [
@ -48,6 +49,7 @@ export const schemas = [
sourceStatusSchema,
sharedSchema,
timelineSchema,
tlsSchema,
uncommonProcessesSchema,
whoAmISchema,
];

View file

@ -6,7 +6,7 @@
import { SourceResolvers } from '../../graphql/types';
import { AppResolverOf, ChildResolverOf } from '../../lib/framework';
import { IpDetails, TlsRequestOptions, UsersRequestOptions } from '../../lib/ip_details';
import { IpDetails, UsersRequestOptions } from '../../lib/ip_details';
import { createOptions, createOptionsPaginated } from '../../utils/build_query/create_options';
import { QuerySourceResolver } from '../sources/resolvers';
@ -15,11 +15,6 @@ export type QueryIpOverviewResolver = ChildResolverOf<
QuerySourceResolver
>;
export type QueryTlsResolver = ChildResolverOf<
AppResolverOf<SourceResolvers.TlsResolver>,
QuerySourceResolver
>;
export type QueryUsersResolver = ChildResolverOf<
AppResolverOf<SourceResolvers.UsersResolver>,
QuerySourceResolver
@ -34,7 +29,6 @@ export const createIpDetailsResolvers = (
): {
Source: {
IpOverview: QueryIpOverviewResolver;
Tls: QueryTlsResolver;
Users: QueryUsersResolver;
};
} => ({
@ -43,15 +37,6 @@ export const createIpDetailsResolvers = (
const options = { ...createOptions(source, args, info), ip: args.ip };
return libs.ipDetails.getIpOverview(req, options);
},
async Tls(source, args, { req }, info) {
const options: TlsRequestOptions = {
...createOptionsPaginated(source, args, info),
ip: args.ip,
tlsSortField: args.sort,
flowTarget: args.flowTarget,
};
return libs.ipDetails.getTls(req, options);
},
async Users(source, args, { req }, info) {
const options: UsersRequestOptions = {
...createOptionsPaginated(source, args, info),

View file

@ -42,47 +42,6 @@ const ipOverviewSchema = gql`
}
`;
const tlsSchema = gql`
enum TlsFields {
_id
}
type TlsNode {
_id: String
timestamp: Date
alternativeNames: [String!]
notAfter: [String!]
commonNames: [String!]
ja3: [String!]
issuerNames: [String!]
}
input TlsSortField {
field: TlsFields!
direction: Direction!
}
type TlsEdges {
node: TlsNode!
cursor: CursorType!
}
type TlsData {
edges: [TlsEdges!]!
totalCount: Float!
pageInfo: PageInfoPaginated!
inspect: Inspect
}
extend type Source {
Tls(
filterQuery: String
id: String
ip: String!
pagination: PaginationInputPaginated!
sort: TlsSortField!
flowTarget: FlowTarget!
timerange: TimerangeInput!
defaultIndex: [String!]!
): TlsData!
}
`;
const usersSchema = gql`
enum UsersFields {
name
@ -134,4 +93,4 @@ const usersSchema = gql`
}
`;
export const ipDetailsSchemas = [ipOverviewSchema, tlsSchema, usersSchema];
export const ipDetailsSchemas = [ipOverviewSchema, usersSchema];

View file

@ -0,0 +1,8 @@
/*
* 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 { createTlsResolvers } from './resolvers';
export { tlsSchema } from './schema.gql';

View file

@ -0,0 +1,40 @@
/*
* 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 { SourceResolvers } from '../../graphql/types';
import { AppResolverOf, ChildResolverOf } from '../../lib/framework';
import { TLS, TlsRequestOptions } from '../../lib/tls';
import { createOptionsPaginated } from '../../utils/build_query/create_options';
import { QuerySourceResolver } from '../sources/resolvers';
export type QueryTlsResolver = ChildResolverOf<
AppResolverOf<SourceResolvers.TlsResolver>,
QuerySourceResolver
>;
export interface TlsResolversDeps {
tls: TLS;
}
export const createTlsResolvers = (
libs: TlsResolversDeps
): {
Source: {
Tls: QueryTlsResolver;
};
} => ({
Source: {
async Tls(source, args, { req }, info) {
const options: TlsRequestOptions = {
...createOptionsPaginated(source, args, info),
ip: args.ip,
tlsSortField: args.sort,
flowTarget: args.flowTarget,
};
return libs.tls.getTls(req, options);
},
},
});

View file

@ -0,0 +1,48 @@
/*
* 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 gql from 'graphql-tag';
export const tlsSchema = gql`
enum TlsFields {
_id
}
type TlsNode {
_id: String
timestamp: Date
alternativeNames: [String!]
notAfter: [String!]
commonNames: [String!]
ja3: [String!]
issuerNames: [String!]
}
input TlsSortField {
field: TlsFields!
direction: Direction!
}
type TlsEdges {
node: TlsNode!
cursor: CursorType!
}
type TlsData {
edges: [TlsEdges!]!
totalCount: Float!
pageInfo: PageInfoPaginated!
inspect: Inspect
}
extend type Source {
Tls(
filterQuery: String
id: String
ip: String!
pagination: PaginationInputPaginated!
sort: TlsSortField!
flowTarget: FlowTargetSourceDest!
timerange: TimerangeInput!
defaultIndex: [String!]!
): TlsData!
}
`;

View file

@ -69,12 +69,6 @@ export interface HostsSortField {
direction: Direction;
}
export interface TlsSortField {
field: TlsFields;
direction: Direction;
}
export interface UsersSortField {
field: UsersFields;
@ -93,6 +87,12 @@ export interface NetworkDnsSortField {
direction: Direction;
}
export interface TlsSortField {
field: TlsFields;
direction: Direction;
}
export interface PageInfoTimeline {
pageIndex: number;
@ -241,8 +241,9 @@ export enum HostsFields {
lastSeen = 'lastSeen',
}
export enum TlsFields {
_id = '_id',
export enum UsersFields {
name = 'name',
count = 'count',
}
export enum FlowTarget {
@ -252,11 +253,6 @@ export enum FlowTarget {
source = 'source',
}
export enum UsersFields {
name = 'name',
count = 'count',
}
export enum FlowTargetSourceDest {
destination = 'destination',
source = 'source',
@ -278,6 +274,10 @@ export enum NetworkDnsFields {
dnsBytesOut = 'dnsBytesOut',
}
export enum TlsFields {
_id = '_id',
}
export enum SortFieldTimeline {
title = 'title',
description = 'description',
@ -419,8 +419,6 @@ export interface Source {
IpOverview?: Maybe<IpOverviewData>;
Tls: TlsData;
Users: UsersData;
KpiNetwork?: Maybe<KpiNetworkData>;
@ -438,6 +436,8 @@ export interface Source {
OverviewNetwork?: Maybe<OverviewNetworkData>;
OverviewHost?: Maybe<OverviewHostData>;
Tls: TlsData;
/** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */
UncommonProcesses: UncommonProcessesData;
/** Just a simple example to get the app name */
@ -1316,38 +1316,6 @@ export interface AutonomousSystemOrganization {
name?: Maybe<string>;
}
export interface TlsData {
edges: TlsEdges[];
totalCount: number;
pageInfo: PageInfoPaginated;
inspect?: Maybe<Inspect>;
}
export interface TlsEdges {
node: TlsNode;
cursor: CursorType;
}
export interface TlsNode {
_id?: Maybe<string>;
timestamp?: Maybe<string>;
alternativeNames?: Maybe<string[]>;
notAfter?: Maybe<string[]>;
commonNames?: Maybe<string[]>;
ja3?: Maybe<string[]>;
issuerNames?: Maybe<string[]>;
}
export interface UsersData {
edges: UsersEdges[];
@ -1668,6 +1636,38 @@ export interface OverviewHostData {
inspect?: Maybe<Inspect>;
}
export interface TlsData {
edges: TlsEdges[];
totalCount: number;
pageInfo: PageInfoPaginated;
inspect?: Maybe<Inspect>;
}
export interface TlsEdges {
node: TlsNode;
cursor: CursorType;
}
export interface TlsNode {
_id?: Maybe<string>;
timestamp?: Maybe<string>;
alternativeNames?: Maybe<string[]>;
notAfter?: Maybe<string[]>;
commonNames?: Maybe<string[]>;
ja3?: Maybe<string[]>;
issuerNames?: Maybe<string[]>;
}
export interface UncommonProcessesData {
edges: UncommonProcessesEdges[];
@ -2054,23 +2054,6 @@ export interface IpOverviewSourceArgs {
defaultIndex: string[];
}
export interface TlsSourceArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTarget;
timerange: TimerangeInput;
defaultIndex: string[];
}
export interface UsersSourceArgs {
filterQuery?: Maybe<string>;
@ -2182,6 +2165,23 @@ export interface OverviewHostSourceArgs {
defaultIndex: string[];
}
export interface TlsSourceArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTargetSourceDest;
timerange: TimerangeInput;
defaultIndex: string[];
}
export interface UncommonProcessesSourceArgs {
timerange: TimerangeInput;
@ -2602,8 +2602,6 @@ export namespace SourceResolvers {
IpOverview?: IpOverviewResolver<Maybe<IpOverviewData>, TypeParent, TContext>;
Tls?: TlsResolver<TlsData, TypeParent, TContext>;
Users?: UsersResolver<UsersData, TypeParent, TContext>;
KpiNetwork?: KpiNetworkResolver<Maybe<KpiNetworkData>, TypeParent, TContext>;
@ -2625,6 +2623,8 @@ export namespace SourceResolvers {
OverviewNetwork?: OverviewNetworkResolver<Maybe<OverviewNetworkData>, TypeParent, TContext>;
OverviewHost?: OverviewHostResolver<Maybe<OverviewHostData>, TypeParent, TContext>;
Tls?: TlsResolver<TlsData, TypeParent, TContext>;
/** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */
UncommonProcesses?: UncommonProcessesResolver<UncommonProcessesData, TypeParent, TContext>;
/** Just a simple example to get the app name */
@ -2784,30 +2784,6 @@ export namespace SourceResolvers {
defaultIndex: string[];
}
export type TlsResolver<R = TlsData, Parent = Source, TContext = SiemContext> = Resolver<
R,
Parent,
TContext,
TlsArgs
>;
export interface TlsArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTarget;
timerange: TimerangeInput;
defaultIndex: string[];
}
export type UsersResolver<R = UsersData, Parent = Source, TContext = SiemContext> = Resolver<
R,
Parent,
@ -2974,6 +2950,30 @@ export namespace SourceResolvers {
defaultIndex: string[];
}
export type TlsResolver<R = TlsData, Parent = Source, TContext = SiemContext> = Resolver<
R,
Parent,
TContext,
TlsArgs
>;
export interface TlsArgs {
filterQuery?: Maybe<string>;
id?: Maybe<string>;
ip: string;
pagination: PaginationInputPaginated;
sort: TlsSortField;
flowTarget: FlowTargetSourceDest;
timerange: TimerangeInput;
defaultIndex: string[];
}
export type UncommonProcessesResolver<
R = UncommonProcessesData,
Parent = Source,
@ -5879,112 +5879,6 @@ export namespace AutonomousSystemOrganizationResolvers {
> = Resolver<R, Parent, TContext>;
}
export namespace TlsDataResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsData> {
edges?: EdgesResolver<TlsEdges[], TypeParent, TContext>;
totalCount?: TotalCountResolver<number, TypeParent, TContext>;
pageInfo?: PageInfoResolver<PageInfoPaginated, TypeParent, TContext>;
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
}
export type EdgesResolver<R = TlsEdges[], Parent = TlsData, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type TotalCountResolver<R = number, Parent = TlsData, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type PageInfoResolver<
R = PageInfoPaginated,
Parent = TlsData,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type InspectResolver<
R = Maybe<Inspect>,
Parent = TlsData,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
}
export namespace TlsEdgesResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsEdges> {
node?: NodeResolver<TlsNode, TypeParent, TContext>;
cursor?: CursorResolver<CursorType, TypeParent, TContext>;
}
export type NodeResolver<R = TlsNode, Parent = TlsEdges, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type CursorResolver<R = CursorType, Parent = TlsEdges, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
}
export namespace TlsNodeResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsNode> {
_id?: _IdResolver<Maybe<string>, TypeParent, TContext>;
timestamp?: TimestampResolver<Maybe<string>, TypeParent, TContext>;
alternativeNames?: AlternativeNamesResolver<Maybe<string[]>, TypeParent, TContext>;
notAfter?: NotAfterResolver<Maybe<string[]>, TypeParent, TContext>;
commonNames?: CommonNamesResolver<Maybe<string[]>, TypeParent, TContext>;
ja3?: Ja3Resolver<Maybe<string[]>, TypeParent, TContext>;
issuerNames?: IssuerNamesResolver<Maybe<string[]>, TypeParent, TContext>;
}
export type _IdResolver<R = Maybe<string>, Parent = TlsNode, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type TimestampResolver<
R = Maybe<string>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type AlternativeNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type NotAfterResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type CommonNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type Ja3Resolver<R = Maybe<string[]>, Parent = TlsNode, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type IssuerNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
}
export namespace UsersDataResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = UsersData> {
edges?: EdgesResolver<UsersEdges[], TypeParent, TContext>;
@ -7095,6 +6989,112 @@ export namespace OverviewHostDataResolvers {
> = Resolver<R, Parent, TContext>;
}
export namespace TlsDataResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsData> {
edges?: EdgesResolver<TlsEdges[], TypeParent, TContext>;
totalCount?: TotalCountResolver<number, TypeParent, TContext>;
pageInfo?: PageInfoResolver<PageInfoPaginated, TypeParent, TContext>;
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
}
export type EdgesResolver<R = TlsEdges[], Parent = TlsData, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type TotalCountResolver<R = number, Parent = TlsData, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type PageInfoResolver<
R = PageInfoPaginated,
Parent = TlsData,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type InspectResolver<
R = Maybe<Inspect>,
Parent = TlsData,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
}
export namespace TlsEdgesResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsEdges> {
node?: NodeResolver<TlsNode, TypeParent, TContext>;
cursor?: CursorResolver<CursorType, TypeParent, TContext>;
}
export type NodeResolver<R = TlsNode, Parent = TlsEdges, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type CursorResolver<R = CursorType, Parent = TlsEdges, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
}
export namespace TlsNodeResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = TlsNode> {
_id?: _IdResolver<Maybe<string>, TypeParent, TContext>;
timestamp?: TimestampResolver<Maybe<string>, TypeParent, TContext>;
alternativeNames?: AlternativeNamesResolver<Maybe<string[]>, TypeParent, TContext>;
notAfter?: NotAfterResolver<Maybe<string[]>, TypeParent, TContext>;
commonNames?: CommonNamesResolver<Maybe<string[]>, TypeParent, TContext>;
ja3?: Ja3Resolver<Maybe<string[]>, TypeParent, TContext>;
issuerNames?: IssuerNamesResolver<Maybe<string[]>, TypeParent, TContext>;
}
export type _IdResolver<R = Maybe<string>, Parent = TlsNode, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type TimestampResolver<
R = Maybe<string>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type AlternativeNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type NotAfterResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type CommonNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
export type Ja3Resolver<R = Maybe<string[]>, Parent = TlsNode, TContext = SiemContext> = Resolver<
R,
Parent,
TContext
>;
export type IssuerNamesResolver<
R = Maybe<string[]>,
Parent = TlsNode,
TContext = SiemContext
> = Resolver<R, Parent, TContext>;
}
export namespace UncommonProcessesDataResolvers {
export interface Resolvers<TContext = SiemContext, TypeParent = UncommonProcessesData> {
edges?: EdgesResolver<UncommonProcessesEdges[], TypeParent, TContext>;
@ -8173,9 +8173,6 @@ export type IResolvers<TContext = SiemContext> = {
Overview?: OverviewResolvers.Resolvers<TContext>;
AutonomousSystem?: AutonomousSystemResolvers.Resolvers<TContext>;
AutonomousSystemOrganization?: AutonomousSystemOrganizationResolvers.Resolvers<TContext>;
TlsData?: TlsDataResolvers.Resolvers<TContext>;
TlsEdges?: TlsEdgesResolvers.Resolvers<TContext>;
TlsNode?: TlsNodeResolvers.Resolvers<TContext>;
UsersData?: UsersDataResolvers.Resolvers<TContext>;
UsersEdges?: UsersEdgesResolvers.Resolvers<TContext>;
UsersNode?: UsersNodeResolvers.Resolvers<TContext>;
@ -8203,6 +8200,9 @@ export type IResolvers<TContext = SiemContext> = {
NetworkDnsItem?: NetworkDnsItemResolvers.Resolvers<TContext>;
OverviewNetworkData?: OverviewNetworkDataResolvers.Resolvers<TContext>;
OverviewHostData?: OverviewHostDataResolvers.Resolvers<TContext>;
TlsData?: TlsDataResolvers.Resolvers<TContext>;
TlsEdges?: TlsEdgesResolvers.Resolvers<TContext>;
TlsNode?: TlsNodeResolvers.Resolvers<TContext>;
UncommonProcessesData?: UncommonProcessesDataResolvers.Resolvers<TContext>;
UncommonProcessesEdges?: UncommonProcessesEdgesResolvers.Resolvers<TContext>;
UncommonProcessItem?: UncommonProcessItemResolvers.Resolvers<TContext>;

View file

@ -28,6 +28,7 @@ import { createUncommonProcessesResolvers } from './graphql/uncommon_processes';
import { createWhoAmIResolvers } from './graphql/who_am_i';
import { AppBackendLibs } from './lib/types';
import { Logger } from './utils/logger';
import { createTlsResolvers } from './graphql/tls';
export interface Config {
mocking: boolean;
@ -56,6 +57,7 @@ export const initServer = (libs: AppBackendLibs, config: Config) => {
createSourcesResolvers(libs) as IResolvers,
createSourceStatusResolvers(libs) as IResolvers,
createTimelineResolvers(libs) as IResolvers,
createTlsResolvers(libs) as IResolvers,
createUncommonProcessesResolvers(libs) as IResolvers,
createWhoAmIResolvers() as IResolvers,
createKpiHostsResolvers(libs) as IResolvers,

View file

@ -16,7 +16,9 @@ import { KpiHosts } from '../kpi_hosts';
import { ElasticsearchKpiHostsAdapter } from '../kpi_hosts/elasticsearch_adapter';
import { ElasticsearchIndexFieldAdapter, IndexFields } from '../index_fields';
import { ElasticsearchIpOverviewAdapter, IpDetails } from '../ip_details';
import { ElasticsearchIpDetailsAdapter, IpDetails } from '../ip_details';
import { ElasticsearchTlsAdapter, TLS } from '../tls';
import { KpiNetwork } from '../kpi_network';
import { ElasticsearchKpiNetworkAdapter } from '../kpi_network/elasticsearch_adapter';
import { ElasticsearchNetworkAdapter, Network } from '../network';
@ -45,7 +47,8 @@ export function compose(server: Server): AppBackendLibs {
events: new Events(new ElasticsearchEventsAdapter(framework)),
fields: new IndexFields(new ElasticsearchIndexFieldAdapter(framework)),
hosts: new Hosts(new ElasticsearchHostsAdapter(framework)),
ipDetails: new IpDetails(new ElasticsearchIpOverviewAdapter(framework)),
ipDetails: new IpDetails(new ElasticsearchIpDetailsAdapter(framework)),
tls: new TLS(new ElasticsearchTlsAdapter(framework)),
kpiHosts: new KpiHosts(new ElasticsearchKpiHostsAdapter(framework)),
kpiNetwork: new KpiNetwork(new ElasticsearchKpiNetworkAdapter(framework)),
network: new Network(new ElasticsearchNetworkAdapter(framework)),

View file

@ -11,8 +11,6 @@ import {
GeoEcsFields,
HostEcsFields,
IpOverviewData,
TlsData,
TlsEdges,
UsersData,
UsersEdges,
} from '../../graphql/types';
@ -20,22 +18,19 @@ import { inspectStringifyObject } from '../../utils/build_query';
import { DatabaseSearchResponse, FrameworkAdapter, FrameworkRequest } from '../framework';
import { TermAggregation } from '../types';
import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants';
import { IpOverviewRequestOptions, TlsRequestOptions, UsersRequestOptions } from './index';
import { IpOverviewRequestOptions, UsersRequestOptions } from './index';
import { buildOverviewQuery } from './query_overview.dsl';
import { buildUsersQuery } from './query_users.dsl';
import {
IpDetailsAdapter,
IpOverviewHit,
OverviewHit,
OverviewHostHit,
TlsBuckets,
UsersBucketsItem,
} from './types';
import { buildTlsQuery } from './query_tls.dsl';
import { buildUsersQuery } from './query_users.dsl';
export class ElasticsearchIpOverviewAdapter implements IpDetailsAdapter {
export class ElasticsearchIpDetailsAdapter implements IpDetailsAdapter {
constructor(private readonly framework: FrameworkAdapter) {}
public async getIpDetails(
@ -62,39 +57,6 @@ export class ElasticsearchIpOverviewAdapter implements IpDetailsAdapter {
};
}
public async getTls(request: FrameworkRequest, options: TlsRequestOptions): Promise<TlsData> {
if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
}
const dsl = buildTlsQuery(options);
const response = await this.framework.callWithRequest<TlsData, TermAggregation>(
request,
'search',
dsl
);
const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
const totalCount = getOr(0, 'aggregations.count.value', response);
const tlsEdges: TlsEdges[] = getTlsEdges(response, options);
const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
const edges = tlsEdges.splice(cursorStart, querySize - cursorStart);
const inspect = {
dsl: [inspectStringifyObject(dsl)],
response: [inspectStringifyObject(response)],
};
const showMorePagesIndicator = totalCount > fakeTotalCount;
return {
edges,
inspect,
pageInfo: {
activePage: activePage ? activePage : 0,
fakeTotalCount,
showMorePagesIndicator,
},
totalCount,
};
}
public async getUsers(
request: FrameworkRequest,
options: UsersRequestOptions
@ -173,34 +135,6 @@ export const getIpOverviewHostAgg = (overviewHostHit: OverviewHostHit | {}) => {
};
};
const getTlsEdges = (
response: DatabaseSearchResponse<TlsData, TermAggregation>,
options: TlsRequestOptions
): TlsEdges[] => {
return formatTlsEdges(getOr([], 'aggregations.sha1.buckets', response));
};
export const formatTlsEdges = (buckets: TlsBuckets[]): TlsEdges[] => {
return buckets.map((bucket: TlsBuckets) => {
const edge: TlsEdges = {
node: {
_id: bucket.key,
alternativeNames: bucket.alternative_names.buckets.map(({ key }) => key),
commonNames: bucket.common_names.buckets.map(({ key }) => key),
ja3: bucket.ja3.buckets.map(({ key }) => key),
issuerNames: bucket.issuer_names.buckets.map(({ key }) => key),
// eslint-disable-next-line @typescript-eslint/camelcase
notAfter: bucket.not_after.buckets.map(({ key_as_string }) => key_as_string),
},
cursor: {
value: bucket.key,
tiebreaker: null,
},
};
return edge;
});
};
export const getUsersEdges = (
response: DatabaseSearchResponse<UsersData, TermAggregation>
): UsersEdges[] =>

View file

@ -4,14 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import {
FlowTarget,
IpOverviewData,
TlsSortField,
TlsData,
UsersData,
UsersSortField,
} from '../../graphql/types';
import { FlowTarget, IpOverviewData, UsersData, UsersSortField } from '../../graphql/types';
import { FrameworkRequest, RequestOptions, RequestOptionsPaginated } from '../framework';
import { IpDetailsAdapter } from './types';
@ -22,11 +15,6 @@ export interface IpOverviewRequestOptions extends RequestOptions {
ip: string;
}
export interface TlsRequestOptions extends RequestOptionsPaginated {
ip: string;
tlsSortField: TlsSortField;
flowTarget: FlowTarget;
}
export interface UsersRequestOptions extends RequestOptionsPaginated {
ip: string;
usersSortField: UsersSortField;
@ -43,10 +31,6 @@ export class IpDetails {
return this.adapter.getIpDetails(req, options);
}
public async getTls(req: FrameworkRequest, options: TlsRequestOptions): Promise<TlsData> {
return this.adapter.getTls(req, options);
}
public async getUsers(req: FrameworkRequest, options: UsersRequestOptions): Promise<UsersData> {
return this.adapter.getUsers(req, options);
}

View file

@ -4,13 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { TlsData, IpOverviewData, UsersData } from '../../graphql/types';
import { IpOverviewData, UsersData } from '../../graphql/types';
import { FrameworkRequest, RequestBasicOptions } from '../framework';
import { Hit, ShardsResponse, TotalValue } from '../types';
export interface IpDetailsAdapter {
getIpDetails(request: FrameworkRequest, options: RequestBasicOptions): Promise<IpOverviewData>;
getTls(request: FrameworkRequest, options: RequestBasicOptions): Promise<TlsData>;
getUsers(request: FrameworkRequest, options: RequestBasicOptions): Promise<UsersData>;
}
@ -81,34 +80,6 @@ export interface IpOverviewHit {
timeout: number;
}
export interface TlsBuckets {
key: string;
timestamp?: {
value: number;
value_as_string: string;
};
alternative_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
common_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
ja3: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
issuer_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
not_after: {
buckets: Readonly<Array<{ key: number; key_as_string: string; doc_count: number }>>;
};
}
// Users Table
export interface UsersResponse {

View file

@ -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;
* you may not use this file except in compliance with the Elastic License.
*/
import { buildTlsQuery } from './query_tls.dsl';
import { ElasticsearchTlsAdapter } from './elasticsearch_adapter';
import expect from '@kbn/expect';
import { FrameworkRequest, FrameworkAdapter } from '../framework';
import { mockRequest, mockResponse, mockOptions, expectedTlsEdges, mockTlsQuery } from './mock';
import { TlsData } from '../../graphql/types';
jest.mock('./query_tls.dsl', () => {
return {
buildTlsQuery: jest.fn(),
};
});
describe('elasticsearch_adapter', () => {
describe('#getTls', () => {
let data: TlsData;
const mockCallWithRequest = jest.fn();
const mockFramework: FrameworkAdapter = {
version: 'mock',
callWithRequest: mockCallWithRequest,
exposeStaticDir: jest.fn(),
registerGraphQLEndpoint: jest.fn(),
getIndexPatternsService: jest.fn(),
getSavedObjectsService: jest.fn(),
};
beforeAll(async () => {
(buildTlsQuery as jest.Mock).mockReset();
(buildTlsQuery as jest.Mock).mockReturnValue(mockTlsQuery);
mockCallWithRequest.mockResolvedValue(mockResponse);
jest.doMock('../framework', () => ({
callWithRequest: mockCallWithRequest,
}));
const EsTls = new ElasticsearchTlsAdapter(mockFramework);
data = await EsTls.getTls(mockRequest as FrameworkRequest, mockOptions);
});
afterAll(() => {
mockCallWithRequest.mockRestore();
(buildTlsQuery as jest.Mock).mockClear();
});
test('buildTlsQuery', () => {
expect((buildTlsQuery as jest.Mock).mock.calls[0][0]).to.eql(mockOptions);
});
test('will return tlsEdges correctly', () => {
expect(data.edges).to.eql(expectedTlsEdges);
});
test('will return inspect data', () => {
expect(data.inspect).to.eql({
dsl: [JSON.stringify(mockTlsQuery, null, 2)],
response: [JSON.stringify(mockResponse, null, 2)],
});
});
});
});

View file

@ -0,0 +1,83 @@
/*
* 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 { getOr } from 'lodash/fp';
import { TlsData, TlsEdges } from '../../graphql/types';
import { inspectStringifyObject } from '../../utils/build_query';
import { DatabaseSearchResponse, FrameworkAdapter, FrameworkRequest } from '../framework';
import { TermAggregation } from '../types';
import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants';
import { TlsRequestOptions } from './index';
import { TlsAdapter, TlsBuckets } from './types';
import { buildTlsQuery } from './query_tls.dsl';
export class ElasticsearchTlsAdapter implements TlsAdapter {
constructor(private readonly framework: FrameworkAdapter) {}
public async getTls(request: FrameworkRequest, options: TlsRequestOptions): Promise<TlsData> {
if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) {
throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`);
}
const dsl = buildTlsQuery(options);
const response = await this.framework.callWithRequest<TlsData, TermAggregation>(
request,
'search',
dsl
);
const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination;
const totalCount = getOr(0, 'aggregations.count.value', response);
const tlsEdges: TlsEdges[] = getTlsEdges(response, options);
const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount;
const edges = tlsEdges.splice(cursorStart, querySize - cursorStart);
const inspect = {
dsl: [inspectStringifyObject(dsl)],
response: [inspectStringifyObject(response)],
};
const showMorePagesIndicator = totalCount > fakeTotalCount;
return {
edges,
inspect,
pageInfo: {
activePage: activePage ? activePage : 0,
fakeTotalCount,
showMorePagesIndicator,
},
totalCount,
};
}
}
const getTlsEdges = (
response: DatabaseSearchResponse<TlsData, TermAggregation>,
options: TlsRequestOptions
): TlsEdges[] => {
return formatTlsEdges(getOr([], 'aggregations.sha1.buckets', response));
};
export const formatTlsEdges = (buckets: TlsBuckets[]): TlsEdges[] => {
return buckets.map((bucket: TlsBuckets) => {
const edge: TlsEdges = {
node: {
_id: bucket.key,
alternativeNames: bucket.alternative_names.buckets.map(({ key }) => key),
commonNames: bucket.common_names.buckets.map(({ key }) => key),
ja3: bucket.ja3.buckets.map(({ key }) => key),
issuerNames: bucket.issuer_names.buckets.map(({ key }) => key),
// eslint-disable-next-line @typescript-eslint/camelcase
notAfter: bucket.not_after.buckets.map(({ key_as_string }) => key_as_string),
},
cursor: {
value: bucket.key,
tiebreaker: null,
},
};
return edge;
});
};

View file

@ -0,0 +1,26 @@
/*
* 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 { FlowTargetSourceDest, TlsSortField, TlsData } from '../../graphql/types';
import { FrameworkRequest, RequestOptionsPaginated } from '../framework';
import { TlsAdapter } from './types';
export * from './elasticsearch_adapter';
export interface TlsRequestOptions extends RequestOptionsPaginated {
ip?: string;
tlsSortField: TlsSortField;
flowTarget: FlowTargetSourceDest;
}
export class TLS {
constructor(private readonly adapter: TlsAdapter) {}
public async getTls(req: FrameworkRequest, options: TlsRequestOptions): Promise<TlsData> {
return this.adapter.getTls(req, options);
}
}

View file

@ -0,0 +1,663 @@
/*
* 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 { Direction, TlsFields, FlowTargetSourceDest } from '../../graphql/types';
export const mockTlsQuery = {
allowNoIndices: true,
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
ignoreUnavailable: true,
body: {
aggs: {
count: { cardinality: { field: 'tls.server_certificate.fingerprint.sha1' } },
sha1: {
terms: {
field: 'tls.server_certificate.fingerprint.sha1',
size: 10,
order: { _key: 'desc' },
},
aggs: {
issuer_names: { terms: { field: 'tls.server_certificate.issuer.common_name' } },
common_names: { terms: { field: 'tls.server_certificate.subject.common_name' } },
alternative_names: { terms: { field: 'tls.server_certificate.alternative_names' } },
not_after: { terms: { field: 'tls.server_certificate.not_after' } },
ja3: { terms: { field: 'tls.fingerprints.ja3.hash' } },
},
},
},
query: {
bool: { filter: [{ range: { '@timestamp': { gte: 1570719927430, lte: 1570806327431 } } }] },
},
size: 0,
track_total_hits: false,
},
};
export const expectedTlsEdges = [
{
cursor: {
tiebreaker: null,
value: 'fff8dc95436e0e25ce46b1526a1a547e8cf3bb82',
},
node: {
_id: 'fff8dc95436e0e25ce46b1526a1a547e8cf3bb82',
alternativeNames: [
'*.1.nflxso.net',
'*.a.nflxso.net',
'assets.nflxext.com',
'cast.netflix.com',
'codex.nflxext.com',
'tvui.netflix.com',
],
commonNames: ['*.1.nflxso.net'],
issuerNames: ['DigiCert SHA2 Secure Server CA'],
ja3: ['95d2dd53a89b334cddd5c22e81e7fe61'],
notAfter: ['2019-10-27T12:00:00.000Z'],
},
},
{
cursor: {
tiebreaker: null,
value: 'fd8440c4b20978b173e0910e2639d114f0d405c5',
},
node: {
_id: 'fd8440c4b20978b173e0910e2639d114f0d405c5',
alternativeNames: ['*.cogocast.net', 'cogocast.net'],
commonNames: ['cogocast.net'],
issuerNames: ['Amazon'],
ja3: ['a111d93cdf31f993c40a8a9ef13e8d7e'],
notAfter: ['2020-02-01T12:00:00.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fcdc16645ebb3386adc96e7ba735c4745709b9dd' },
node: {
_id: 'fcdc16645ebb3386adc96e7ba735c4745709b9dd',
alternativeNames: [
'player-devintever2-imperva.mountain.siriusxm.com',
'player-devintever2.mountain.siriusxm.com',
],
commonNames: ['player-devintever2.mountain.siriusxm.com'],
issuerNames: ['Trustwave Organization Validation SHA256 CA, Level 1'],
ja3: ['6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2020-03-06T21:57:09.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fccf375789cb7e671502a7b0cc969f218a4b2c70' },
node: {
_id: 'fccf375789cb7e671502a7b0cc969f218a4b2c70',
alternativeNames: [
'appleid-nc-s.apple.com',
'appleid-nwk-s.apple.com',
'appleid-prn-s.apple.com',
'appleid-rno-s.apple.com',
'appleid.apple.com',
],
commonNames: ['appleid.apple.com'],
issuerNames: ['DigiCert SHA2 Extended Validation Server CA'],
ja3: ['6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2020-07-04T12:00:00.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fc4a296b706fa18ac50b96f5c0327c69db4a8981' },
node: {
_id: 'fc4a296b706fa18ac50b96f5c0327c69db4a8981',
alternativeNames: [
'api.itunes.apple.com',
'appsto.re',
'ax.init.itunes.apple.com',
'bag.itunes.apple.com',
'bookkeeper.itunes.apple.com',
'c.itunes.apple.com',
'carrierbundle.itunes.apple.com',
'client-api.itunes.apple.com',
'cma.itunes.apple.com',
'courses.apple.com',
],
commonNames: ['itunes.apple.com'],
issuerNames: ['DigiCert SHA2 Extended Validation Server CA'],
ja3: ['a441a33aaee795f498d6b764cc78989a'],
notAfter: ['2020-03-24T12:00:00.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fc2cbc41f6a0e9c0118de4fe40f299f7207b797e' },
node: {
_id: 'fc2cbc41f6a0e9c0118de4fe40f299f7207b797e',
alternativeNames: [
'*.adlercasino.com',
'*.allaustraliancasino.com',
'*.alletf.com',
'*.appareldesignpartners.com',
'*.atmosfir.net',
'*.cityofboston.gov',
'*.cp.mytoyotaentune.com',
'*.decathlon.be',
'*.decathlon.co.uk',
'*.decathlon.de',
],
commonNames: ['incapsula.com'],
issuerNames: ['GlobalSign CloudSSL CA - SHA256 - G3'],
ja3: ['6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2020-04-04T14:05:06.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fb70d78ffa663a3a4374d841b3288d2de9759566' },
node: {
_id: 'fb70d78ffa663a3a4374d841b3288d2de9759566',
alternativeNames: ['*.siriusxm.com', 'siriusxm.com'],
commonNames: ['*.siriusxm.com'],
issuerNames: ['DigiCert Baltimore CA-2 G2'],
ja3: ['535aca3d99fc247509cd50933cd71d37', '6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2021-10-27T12:00:00.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'fb59038dcec33ab3a01a6ae60d0835ad0e04ccf0' },
node: {
_id: 'fb59038dcec33ab3a01a6ae60d0835ad0e04ccf0',
alternativeNames: [
'photos.amazon.co.uk',
'photos.amazon.de',
'photos.amazon.es',
'photos.amazon.eu',
'photos.amazon.fr',
'photos.amazon.it',
],
commonNames: ['photos.amazon.eu'],
issuerNames: ['Amazon'],
ja3: ['6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2020-04-23T12:00:00.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'f9815293c883a6006f0b2d95a4895bdc501fd174' },
node: {
_id: 'f9815293c883a6006f0b2d95a4895bdc501fd174',
alternativeNames: [
'*.api.cdn.hbo.com',
'*.artist.cdn.hbo.com',
'*.cdn.hbo.com',
'*.lv3.cdn.hbo.com',
'artist.api.cdn.hbo.com',
'artist.api.lv3.cdn.hbo.com',
'artist.staging.cdn.hbo.com',
'artist.staging.hurley.lv3.cdn.hbo.com',
'atv.api.lv3.cdn.hbo.com',
'atv.staging.hurley.lv3.cdn.hbo.com',
],
commonNames: ['cdn.hbo.com'],
issuerNames: ['Sectigo RSA Organization Validation Secure Server CA'],
ja3: ['6fa3244afc6bb6f9fad207b6b52af26b'],
notAfter: ['2021-02-10T23:59:59.000Z'],
},
},
{
cursor: { tiebreaker: null, value: 'f8db6a69797e383dca2529727369595733123386' },
node: {
_id: 'f8db6a69797e383dca2529727369595733123386',
alternativeNames: ['www.google.com'],
commonNames: ['www.google.com'],
issuerNames: ['GTS CA 1O1'],
ja3: ['a111d93cdf31f993c40a8a9ef13e8d7e'],
notAfter: ['2019-12-10T13:32:54.000Z'],
},
},
];
export const mockRequest = {
params: {},
payload: {
operationName: 'GetTlsQuery',
variables: {
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
filterQuery: '',
flowTarget: 'source',
inspect: false,
ip: '',
pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 },
sort: { field: '_id', direction: 'desc' },
sourceId: 'default',
timerange: { interval: '12h', from: 1570716261267, to: 1570802661267 },
},
query:
'query GetTlsQuery($sourceId: ID!, $filterQuery: String, $flowTarget: FlowTarget!, $ip: String!, $pagination: PaginationInputPaginated!, $sort: TlsSortField!, $timerange: TimerangeInput!, $defaultIndex: [String!]!, $inspect: Boolean!) {\n source(id: $sourceId) {\n id\n Tls(filterQuery: $filterQuery, flowTarget: $flowTarget, ip: $ip, pagination: $pagination, sort: $sort, timerange: $timerange, defaultIndex: $defaultIndex) {\n totalCount\n edges {\n node {\n _id\n alternativeNames\n commonNames\n ja3\n issuerNames\n notAfter\n __typename\n }\n cursor {\n value\n __typename\n }\n __typename\n }\n pageInfo {\n activePage\n fakeTotalCount\n showMorePagesIndicator\n __typename\n }\n inspect @include(if: $inspect) {\n dsl\n response\n __typename\n }\n __typename\n }\n __typename\n }\n}\n',
},
query: {},
};
export const mockResponse = {
took: 92,
timed_out: false,
_shards: { total: 33, successful: 33, skipped: 0, failed: 0 },
hits: { max_score: null, hits: [] },
aggregations: {
sha1: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 4597,
buckets: [
{
key: 'fff8dc95436e0e25ce46b1526a1a547e8cf3bb82',
doc_count: 1,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1572177600000, key_as_string: '2019-10-27T12:00:00.000Z', doc_count: 1 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'DigiCert SHA2 Secure Server CA', doc_count: 1 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '*.1.nflxso.net', doc_count: 1 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: '*.1.nflxso.net', doc_count: 1 },
{ key: '*.a.nflxso.net', doc_count: 1 },
{ key: 'assets.nflxext.com', doc_count: 1 },
{ key: 'cast.netflix.com', doc_count: 1 },
{ key: 'codex.nflxext.com', doc_count: 1 },
{ key: 'tvui.netflix.com', doc_count: 1 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '95d2dd53a89b334cddd5c22e81e7fe61', doc_count: 1 }],
},
},
{
key: 'fd8440c4b20978b173e0910e2639d114f0d405c5',
doc_count: 1,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1580558400000, key_as_string: '2020-02-01T12:00:00.000Z', doc_count: 1 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'Amazon', doc_count: 1 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'cogocast.net', doc_count: 1 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: '*.cogocast.net', doc_count: 1 },
{ key: 'cogocast.net', doc_count: 1 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'a111d93cdf31f993c40a8a9ef13e8d7e', doc_count: 1 }],
},
},
{
key: 'fcdc16645ebb3386adc96e7ba735c4745709b9dd',
doc_count: 1,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1583531829000, key_as_string: '2020-03-06T21:57:09.000Z', doc_count: 1 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'Trustwave Organization Validation SHA256 CA, Level 1', doc_count: 1 },
],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'player-devintever2.mountain.siriusxm.com', doc_count: 1 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'player-devintever2-imperva.mountain.siriusxm.com', doc_count: 1 },
{ key: 'player-devintever2.mountain.siriusxm.com', doc_count: 1 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 1 }],
},
},
{
key: 'fccf375789cb7e671502a7b0cc969f218a4b2c70',
doc_count: 1,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1593864000000, key_as_string: '2020-07-04T12:00:00.000Z', doc_count: 1 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'DigiCert SHA2 Extended Validation Server CA', doc_count: 1 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'appleid.apple.com', doc_count: 1 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'appleid-nc-s.apple.com', doc_count: 1 },
{ key: 'appleid-nwk-s.apple.com', doc_count: 1 },
{ key: 'appleid-prn-s.apple.com', doc_count: 1 },
{ key: 'appleid-rno-s.apple.com', doc_count: 1 },
{ key: 'appleid.apple.com', doc_count: 1 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 1 }],
},
},
{
key: 'fc4a296b706fa18ac50b96f5c0327c69db4a8981',
doc_count: 2,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1585051200000, key_as_string: '2020-03-24T12:00:00.000Z', doc_count: 2 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'DigiCert SHA2 Extended Validation Server CA', doc_count: 2 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'itunes.apple.com', doc_count: 2 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 156,
buckets: [
{ key: 'api.itunes.apple.com', doc_count: 2 },
{ key: 'appsto.re', doc_count: 2 },
{ key: 'ax.init.itunes.apple.com', doc_count: 2 },
{ key: 'bag.itunes.apple.com', doc_count: 2 },
{ key: 'bookkeeper.itunes.apple.com', doc_count: 2 },
{ key: 'c.itunes.apple.com', doc_count: 2 },
{ key: 'carrierbundle.itunes.apple.com', doc_count: 2 },
{ key: 'client-api.itunes.apple.com', doc_count: 2 },
{ key: 'cma.itunes.apple.com', doc_count: 2 },
{ key: 'courses.apple.com', doc_count: 2 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'a441a33aaee795f498d6b764cc78989a', doc_count: 2 }],
},
},
{
key: 'fc2cbc41f6a0e9c0118de4fe40f299f7207b797e',
doc_count: 1,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1586009106000, key_as_string: '2020-04-04T14:05:06.000Z', doc_count: 1 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'GlobalSign CloudSSL CA - SHA256 - G3', doc_count: 1 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'incapsula.com', doc_count: 1 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 110,
buckets: [
{ key: '*.adlercasino.com', doc_count: 1 },
{ key: '*.allaustraliancasino.com', doc_count: 1 },
{ key: '*.alletf.com', doc_count: 1 },
{ key: '*.appareldesignpartners.com', doc_count: 1 },
{ key: '*.atmosfir.net', doc_count: 1 },
{ key: '*.cityofboston.gov', doc_count: 1 },
{ key: '*.cp.mytoyotaentune.com', doc_count: 1 },
{ key: '*.decathlon.be', doc_count: 1 },
{ key: '*.decathlon.co.uk', doc_count: 1 },
{ key: '*.decathlon.de', doc_count: 1 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 1 }],
},
},
{
key: 'fb70d78ffa663a3a4374d841b3288d2de9759566',
doc_count: 325,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1635336000000, key_as_string: '2021-10-27T12:00:00.000Z', doc_count: 325 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'DigiCert Baltimore CA-2 G2', doc_count: 325 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '*.siriusxm.com', doc_count: 325 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: '*.siriusxm.com', doc_count: 325 },
{ key: 'siriusxm.com', doc_count: 325 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: '535aca3d99fc247509cd50933cd71d37', doc_count: 284 },
{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 39 },
],
},
},
{
key: 'fb59038dcec33ab3a01a6ae60d0835ad0e04ccf0',
doc_count: 5,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1587643200000, key_as_string: '2020-04-23T12:00:00.000Z', doc_count: 5 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'Amazon', doc_count: 5 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'photos.amazon.eu', doc_count: 5 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'photos.amazon.co.uk', doc_count: 5 },
{ key: 'photos.amazon.de', doc_count: 5 },
{ key: 'photos.amazon.es', doc_count: 5 },
{ key: 'photos.amazon.eu', doc_count: 5 },
{ key: 'photos.amazon.fr', doc_count: 5 },
{ key: 'photos.amazon.it', doc_count: 5 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 5 }],
},
},
{
key: 'f9815293c883a6006f0b2d95a4895bdc501fd174',
doc_count: 29,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1613001599000, key_as_string: '2021-02-10T23:59:59.000Z', doc_count: 29 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 'Sectigo RSA Organization Validation Secure Server CA', doc_count: 29 },
],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'cdn.hbo.com', doc_count: 29 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 29,
buckets: [
{ key: '*.api.cdn.hbo.com', doc_count: 29 },
{ key: '*.artist.cdn.hbo.com', doc_count: 29 },
{ key: '*.cdn.hbo.com', doc_count: 29 },
{ key: '*.lv3.cdn.hbo.com', doc_count: 29 },
{ key: 'artist.api.cdn.hbo.com', doc_count: 29 },
{ key: 'artist.api.lv3.cdn.hbo.com', doc_count: 29 },
{ key: 'artist.staging.cdn.hbo.com', doc_count: 29 },
{ key: 'artist.staging.hurley.lv3.cdn.hbo.com', doc_count: 29 },
{ key: 'atv.api.lv3.cdn.hbo.com', doc_count: 29 },
{ key: 'atv.staging.hurley.lv3.cdn.hbo.com', doc_count: 29 },
],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: '6fa3244afc6bb6f9fad207b6b52af26b', doc_count: 26 }],
},
},
{
key: 'f8db6a69797e383dca2529727369595733123386',
doc_count: 5,
not_after: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [
{ key: 1575984774000, key_as_string: '2019-12-10T13:32:54.000Z', doc_count: 5 },
],
},
issuer_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'GTS CA 1O1', doc_count: 5 }],
},
common_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'www.google.com', doc_count: 5 }],
},
alternative_names: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'www.google.com', doc_count: 5 }],
},
ja3: {
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
buckets: [{ key: 'a111d93cdf31f993c40a8a9ef13e8d7e', doc_count: 5 }],
},
},
],
},
count: { value: 364 },
},
};
export const mockOptions = {
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
sourceConfiguration: {
fields: {
container: 'docker.container.name',
host: 'beat.hostname',
message: ['message', '@message'],
pod: 'kubernetes.pod.name',
tiebreaker: '_doc',
timestamp: '@timestamp',
},
},
timerange: { interval: '12h', to: 1570801871626, from: 1570715471626 },
pagination: { activePage: 0, cursorStart: 0, fakePossibleCount: 50, querySize: 10 },
filterQuery: {},
fields: [
'totalCount',
'_id',
'alternativeNames',
'commonNames',
'ja3',
'issuerNames',
'notAfter',
'edges.cursor.value',
'pageInfo.activePage',
'pageInfo.fakeTotalCount',
'pageInfo.showMorePagesIndicator',
'inspect.dsl',
'inspect.response',
],
ip: '',
tlsSortField: { field: TlsFields._id, direction: Direction.desc },
flowTarget: FlowTargetSourceDest.source,
};

View file

@ -65,12 +65,13 @@ export const buildTlsQuery = ({
},
timerange: { from, to },
}: TlsRequestOptions) => {
const filter = [
const defaultFilter = [
...createQueryFilterClauses(filterQuery),
{ range: { [timestamp]: { gte: from, lte: to } } },
{ term: { [`${flowTarget}.ip`]: ip } },
];
const filter = ip ? [...defaultFilter, { term: { [`${flowTarget}.ip`]: ip } }] : defaultFilter;
const dslQuery = {
allowNoIndices: true,
index: defaultIndex,

View file

@ -0,0 +1,40 @@
/*
* 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 { FrameworkRequest, RequestBasicOptions } from '../framework';
import { TlsData } from '../../../public/graphql/types';
export interface TlsAdapter {
getTls(request: FrameworkRequest, options: RequestBasicOptions): Promise<TlsData>;
}
export interface TlsBuckets {
key: string;
timestamp?: {
value: number;
value_as_string: string;
};
alternative_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
common_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
ja3: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
issuer_names: {
buckets: Readonly<Array<{ key: string; doc_count: number }>>;
};
not_after: {
buckets: Readonly<Array<{ key: number; key_as_string: string; doc_count: number }>>;
};
}

View file

@ -21,6 +21,7 @@ import { UncommonProcesses } from './uncommon_processes';
import { Note } from './note/saved_object';
import { PinnedEvent } from './pinned_event/saved_object';
import { Timeline } from './timeline/saved_object';
import { TLS } from './tls';
export * from './hosts';
@ -35,6 +36,7 @@ export interface AppDomainLibs {
overview: Overview;
uncommonProcesses: UncommonProcesses;
kpiHosts: KpiHosts;
tls: TLS;
}
export interface AppBackendLibs extends AppDomainLibs {

View file

@ -29,11 +29,68 @@ const expectedResult = {
notAfter: ['2019-05-22T12:00:00.000Z'],
};
const expectedOverviewDestinationResult = {
__typename: 'TlsData',
edges: [
{
__typename: 'TlsEdges',
cursor: {
__typename: 'CursorType',
value: '61749734b3246f1584029deb4f5276c64da00ada',
},
node: {
__typename: 'TlsNode',
_id: '61749734b3246f1584029deb4f5276c64da00ada',
alternativeNames: ['api.snapcraft.io'],
commonNames: ['api.snapcraft.io'],
issuerNames: ['DigiCert SHA2 Secure Server CA'],
ja3: ['839868ad711dc55bde0d37a87f14740d'],
notAfter: ['2019-05-22T12:00:00.000Z'],
},
},
],
pageInfo: {
__typename: 'PageInfoPaginated',
activePage: 0,
fakeTotalCount: 1,
showMorePagesIndicator: false,
},
totalCount: 1,
};
const expectedOverviewSourceResult = {
__typename: 'TlsData',
edges: [
{
__typename: 'TlsEdges',
cursor: {
__typename: 'CursorType',
value: '61749734b3246f1584029deb4f5276c64da00ada',
},
node: {
__typename: 'TlsNode',
_id: '61749734b3246f1584029deb4f5276c64da00ada',
alternativeNames: ['api.snapcraft.io'],
commonNames: ['api.snapcraft.io'],
issuerNames: ['DigiCert SHA2 Secure Server CA'],
ja3: ['839868ad711dc55bde0d37a87f14740d'],
notAfter: ['2019-05-22T12:00:00.000Z'],
},
},
],
pageInfo: {
__typename: 'PageInfoPaginated',
activePage: 0,
fakeTotalCount: 1,
showMorePagesIndicator: false,
},
totalCount: 1,
};
export default function({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const client = getService('siemGraphQLClient');
describe('Tls Test', () => {
describe('With packetbeat', () => {
describe('Tls Test with Packetbeat', () => {
describe('Tls Test', () => {
before(() => esArchiver.load('packetbeat/default'));
after(() => esArchiver.unload('packetbeat/default'));
@ -101,5 +158,70 @@ export default function({ getService }: FtrProviderContext) {
});
});
});
describe('Tls Overview Test', () => {
before(() => esArchiver.load('packetbeat/default'));
after(() => esArchiver.unload('packetbeat/default'));
it('Ensure data is returned for FlowTarget.Source', () => {
return client
.query<GetTlsQuery.Query>({
query: tlsQuery,
variables: {
sourceId: 'default',
timerange: {
interval: '12h',
to: TO,
from: FROM,
},
ip: '',
flowTarget: FlowTarget.source,
sort: { field: TlsFields._id, direction: Direction.desc },
pagination: {
activePage: 0,
cursorStart: 0,
fakePossibleCount: 30,
querySize: 10,
},
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
inspect: false,
},
})
.then(resp => {
const tls = resp.data.source.Tls;
expect(tls).to.eql(expectedOverviewSourceResult);
});
});
it('Ensure data is returned for FlowTarget.Destination', () => {
return client
.query<GetTlsQuery.Query>({
query: tlsQuery,
variables: {
sourceId: 'default',
timerange: {
interval: '12h',
to: TO,
from: FROM,
},
ip: '',
flowTarget: FlowTarget.destination,
sort: { field: TlsFields._id, direction: Direction.desc },
pagination: {
activePage: 0,
cursorStart: 0,
fakePossibleCount: 30,
querySize: 10,
},
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
inspect: false,
},
})
.then(resp => {
const tls = resp.data.source.Tls;
expect(tls).to.eql(expectedOverviewDestinationResult);
});
});
});
});
}