mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Added was-authorized auditd renderer (#33470)
* Added was-authorized auditd renderer * https://github.com/elastic/ingest-dev/issues/301
This commit is contained in:
parent
664a74b6af
commit
e390ed5ddc
11 changed files with 1099 additions and 2 deletions
|
@ -1637,6 +1637,70 @@ Can be one or multiple IPv4 or IPv6 addresses.",
|
|||
},
|
||||
"zeek": null,
|
||||
},
|
||||
Object {
|
||||
"_id": "26",
|
||||
"auditd": Object {
|
||||
"data": Object {
|
||||
"acct": null,
|
||||
"op": null,
|
||||
"terminal": "/dev/pts/0",
|
||||
},
|
||||
"result": "success",
|
||||
"session": "338",
|
||||
"summary": Object {
|
||||
"actor": Object {
|
||||
"primary": "root",
|
||||
"secondary": "alice",
|
||||
},
|
||||
"how": "/sbin/pam_tally2",
|
||||
"message_type": null,
|
||||
"object": Object {
|
||||
"primary": "/dev/pts/0",
|
||||
"secondary": null,
|
||||
"type": "user-session",
|
||||
},
|
||||
"sequence": null,
|
||||
},
|
||||
},
|
||||
"destination": null,
|
||||
"event": Object {
|
||||
"action": "was-authorized",
|
||||
"category": "user-login",
|
||||
"dataset": null,
|
||||
"id": null,
|
||||
"module": "auditd",
|
||||
"severity": null,
|
||||
},
|
||||
"geo": null,
|
||||
"host": Object {
|
||||
"id": "0a63559c1acf4c419d979c4b4d8b83ff",
|
||||
"ip": Array [
|
||||
"139.59.11.147",
|
||||
"10.47.0.5",
|
||||
"fe80::ec0b:1bff:fe29:80bd",
|
||||
],
|
||||
"name": "suricata-bangalore",
|
||||
},
|
||||
"http": null,
|
||||
"network": null,
|
||||
"process": Object {
|
||||
"args": null,
|
||||
"executable": "/sbin/pam_tally2",
|
||||
"name": null,
|
||||
"pid": 21170,
|
||||
"ppid": null,
|
||||
"title": null,
|
||||
"working_directory": null,
|
||||
},
|
||||
"source": null,
|
||||
"suricata": null,
|
||||
"timestamp": "2019-03-13T03:34:08.890Z",
|
||||
"url": null,
|
||||
"user": Object {
|
||||
"name": "alice",
|
||||
},
|
||||
"zeek": null,
|
||||
},
|
||||
]
|
||||
}
|
||||
eventIdToNoteIds={Object {}}
|
||||
|
@ -1691,6 +1755,10 @@ Can be one or multiple IPv4 or IPv6 addresses.",
|
|||
"isInstance": [Function],
|
||||
"renderRow": [Function],
|
||||
},
|
||||
Object {
|
||||
"isInstance": [Function],
|
||||
"renderRow": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
sort={
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AuditAcquiredCredsDetails rendering it renders the default AuditAcquiredCredsDetails 1`] = `
|
||||
<Component
|
||||
intl={
|
||||
Object {
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"formatDate": [Function],
|
||||
"formatHTMLMessage": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelative": [Function],
|
||||
"formatTime": [Function],
|
||||
"formats": Object {
|
||||
"date": Object {
|
||||
"full": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"weekday": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"long": Object {
|
||||
"day": "numeric",
|
||||
"month": "long",
|
||||
"year": "numeric",
|
||||
},
|
||||
"medium": Object {
|
||||
"day": "numeric",
|
||||
"month": "short",
|
||||
"year": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"day": "numeric",
|
||||
"month": "numeric",
|
||||
"year": "2-digit",
|
||||
},
|
||||
},
|
||||
"number": Object {
|
||||
"currency": Object {
|
||||
"style": "currency",
|
||||
},
|
||||
"percent": Object {
|
||||
"style": "percent",
|
||||
},
|
||||
},
|
||||
"relative": Object {
|
||||
"days": Object {
|
||||
"units": "day",
|
||||
},
|
||||
"hours": Object {
|
||||
"units": "hour",
|
||||
},
|
||||
"minutes": Object {
|
||||
"units": "minute",
|
||||
},
|
||||
"months": Object {
|
||||
"units": "month",
|
||||
},
|
||||
"seconds": Object {
|
||||
"units": "second",
|
||||
},
|
||||
"years": Object {
|
||||
"units": "year",
|
||||
},
|
||||
},
|
||||
"time": Object {
|
||||
"full": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"long": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
"timeZoneName": "short",
|
||||
},
|
||||
"medium": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
"second": "numeric",
|
||||
},
|
||||
"short": Object {
|
||||
"hour": "numeric",
|
||||
"minute": "numeric",
|
||||
},
|
||||
},
|
||||
},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralFormat": [Function],
|
||||
"getRelativeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"now": [Function],
|
||||
"onError": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": null,
|
||||
}
|
||||
}
|
||||
>
|
||||
<pure(Component)
|
||||
browserFields={Object {}}
|
||||
data={
|
||||
Object {
|
||||
"_id": "22",
|
||||
"auditd": Object {
|
||||
"data": Object {
|
||||
"acct": "alice",
|
||||
"op": "PAM:setcred",
|
||||
"terminal": "ssh",
|
||||
},
|
||||
"result": "success",
|
||||
"session": "340",
|
||||
"summary": Object {
|
||||
"actor": Object {
|
||||
"primary": "alice",
|
||||
"secondary": "alice",
|
||||
},
|
||||
"how": "/usr/sbin/sshd",
|
||||
"message_type": null,
|
||||
"object": Object {
|
||||
"primary": "ssh",
|
||||
"secondary": "8.42.77.171",
|
||||
"type": "user-session",
|
||||
},
|
||||
"sequence": null,
|
||||
},
|
||||
},
|
||||
"destination": null,
|
||||
"event": Object {
|
||||
"action": "disposed-credentials",
|
||||
"category": "user-login",
|
||||
"dataset": null,
|
||||
"id": null,
|
||||
"module": "auditd",
|
||||
"severity": null,
|
||||
},
|
||||
"geo": null,
|
||||
"host": Object {
|
||||
"id": "0a63559c1acf4c419d979c4b4d8b83ff",
|
||||
"ip": Array [
|
||||
"139.59.11.147",
|
||||
"10.47.0.5",
|
||||
"fe80::ec0b:1bff:fe29:80bd",
|
||||
],
|
||||
"name": "suricata-bangalore",
|
||||
},
|
||||
"http": null,
|
||||
"network": null,
|
||||
"process": Object {
|
||||
"args": null,
|
||||
"executable": "/usr/sbin/sshd",
|
||||
"name": null,
|
||||
"pid": 21202,
|
||||
"ppid": null,
|
||||
"title": null,
|
||||
"working_directory": null,
|
||||
},
|
||||
"source": null,
|
||||
"suricata": null,
|
||||
"timestamp": "2019-03-13T03:35:21.614Z",
|
||||
"url": null,
|
||||
"user": Object {
|
||||
"name": "root",
|
||||
},
|
||||
"zeek": null,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</Component>
|
||||
`;
|
|
@ -0,0 +1,84 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`auditWasAuthorizedRowRenderer renders correctly against snapshot 1`] = `
|
||||
<span>
|
||||
<styled.div>
|
||||
<span>
|
||||
some children
|
||||
</span>
|
||||
<styled.div
|
||||
width={100}
|
||||
>
|
||||
<pure(Component)
|
||||
browserFields={Object {}}
|
||||
data={
|
||||
Object {
|
||||
"_id": "26",
|
||||
"auditd": Object {
|
||||
"data": Object {
|
||||
"acct": null,
|
||||
"op": null,
|
||||
"terminal": "/dev/pts/0",
|
||||
},
|
||||
"result": "success",
|
||||
"session": "338",
|
||||
"summary": Object {
|
||||
"actor": Object {
|
||||
"primary": "root",
|
||||
"secondary": "alice",
|
||||
},
|
||||
"how": "/sbin/pam_tally2",
|
||||
"message_type": null,
|
||||
"object": Object {
|
||||
"primary": "/dev/pts/0",
|
||||
"secondary": null,
|
||||
"type": "user-session",
|
||||
},
|
||||
"sequence": null,
|
||||
},
|
||||
},
|
||||
"destination": null,
|
||||
"event": Object {
|
||||
"action": "was-authorized",
|
||||
"category": "user-login",
|
||||
"dataset": null,
|
||||
"id": null,
|
||||
"module": "auditd",
|
||||
"severity": null,
|
||||
},
|
||||
"geo": null,
|
||||
"host": Object {
|
||||
"id": "0a63559c1acf4c419d979c4b4d8b83ff",
|
||||
"ip": Array [
|
||||
"139.59.11.147",
|
||||
"10.47.0.5",
|
||||
"fe80::ec0b:1bff:fe29:80bd",
|
||||
],
|
||||
"name": "suricata-bangalore",
|
||||
},
|
||||
"http": null,
|
||||
"network": null,
|
||||
"process": Object {
|
||||
"args": null,
|
||||
"executable": "/sbin/pam_tally2",
|
||||
"name": null,
|
||||
"pid": 21170,
|
||||
"ppid": null,
|
||||
"title": null,
|
||||
"working_directory": null,
|
||||
},
|
||||
"source": null,
|
||||
"suricata": null,
|
||||
"timestamp": "2019-03-13T03:34:08.890Z",
|
||||
"url": null,
|
||||
"user": Object {
|
||||
"name": "alice",
|
||||
},
|
||||
"zeek": null,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</styled.div>
|
||||
</styled.div>
|
||||
</span>
|
||||
`;
|
|
@ -379,7 +379,7 @@ describe('AuditdStartedSessionDetails', () => {
|
|||
<TestProviders>
|
||||
<AuditdStartedSessionLine
|
||||
id="hello-i-am-an-id"
|
||||
args="arg1 arg 2 arg 3"
|
||||
args="arg1 arg2 arg 3"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
|
@ -391,7 +391,7 @@ describe('AuditdStartedSessionDetails', () => {
|
|||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessionarg1 arg 2 arg 3');
|
||||
expect(wrapper.text()).toEqual('Sessionarg1 arg2 arg 3');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* 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 toJson from 'enzyme-to-json';
|
||||
import * as React from 'react';
|
||||
import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import { BrowserFields } from 'x-pack/plugins/secops/public/containers/source';
|
||||
|
||||
import { mockBrowserFields } from '../../../../containers/source/mock';
|
||||
import { mockEcsData, TestProviders } from '../../../../mock';
|
||||
|
||||
import {
|
||||
AuditdWasAuthorizedDetails,
|
||||
AuditdWasAuthorizedLine,
|
||||
} from './auditd_was_authorized_details';
|
||||
|
||||
describe('AuditAcquiredCredsDetails', () => {
|
||||
describe('rendering', () => {
|
||||
test('it renders the default AuditAcquiredCredsDetails', () => {
|
||||
// I cannot and do not want to use the BrowserFields mocks for the snapshot tests as they are too heavy
|
||||
const browserFields: BrowserFields = {};
|
||||
const wrapper = shallowWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedDetails browserFields={browserFields} data={mockEcsData[21]} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('it returns auditd if the data does contain auditd data', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedDetails browserFields={mockBrowserFields} data={mockEcsData[19]} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionjohnson@zeek-sanfranin/was authorized to use/usr/bin/gpgconf--list-dirs agent-socket'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns null for text if the data contains no auditd data', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedDetails browserFields={mockBrowserFields} data={mockEcsData[0]} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// NOTE: It's best if all the arguments are sent into this function and they typically should be otherwise
|
||||
// you have something wrong with your beats. These tests are to ensure the function does not
|
||||
// crash. If you need to format things prettier because not all the data is there, then update
|
||||
// these tests with those changes
|
||||
describe('#AuditdWasAuthorizedLine', () => {
|
||||
test('it returns pretty output if you send in all your happy path data', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
userName="username-1"
|
||||
session="session-1"
|
||||
primary="username-1"
|
||||
secondary="username-1"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1username-1@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with username if username, primary, and secondary all equal each other ', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
userName="username-1"
|
||||
primary="username-1"
|
||||
secondary="username-1"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1username-1@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with username if primary and secondary equal unset', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
userName="username-1"
|
||||
primary="unset"
|
||||
secondary="unset"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1username-1@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with username if primary and secondary equal unset with different casing', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
userName="username-1"
|
||||
session="session-1"
|
||||
primary="Unset"
|
||||
secondary="uNseT"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1username-1@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with username if primary and secondary are undefined', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
primary={undefined}
|
||||
secondary={undefined}
|
||||
userName="username-1"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1username-1@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with "as" wording if username, primary, and secondary are all different', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
userName="[username-1]"
|
||||
primary="[username-2]"
|
||||
secondary="[username-3]"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1[username-2]as[username-3]@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with "as" wording if username and primary are the same but secondary is different', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
userName="[username-1]"
|
||||
primary="[username-1]"
|
||||
secondary="[username-2]"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1[username-1]as[username-2]@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with primary if username and secondary are unset with different casing', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
userName="unseT"
|
||||
session="session-1"
|
||||
primary="[username-primary]"
|
||||
secondary="unset"
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1[username-primary]@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns a session with primary if username and secondary are undefined', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="host-1"
|
||||
session="session-1"
|
||||
primary="[username-primary]"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
processExecutable="process-1"
|
||||
processTitle="process-title-1"
|
||||
workingDirectory="working-directory-1"
|
||||
args="arg1 arg2 arg3"
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual(
|
||||
'Sessionsession-1[username-primary]@host-1inworking-directory-1was authorized to useprocess-1arg1 arg2 arg3'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns just a session if only given an id', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
processTitle={undefined}
|
||||
workingDirectory={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Session');
|
||||
});
|
||||
|
||||
test('it returns only session and hostName if only hostname and an id is given', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
hostName="some-host-name"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
processTitle={undefined}
|
||||
workingDirectory={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Session@some-host-name');
|
||||
});
|
||||
|
||||
test('it returns only a session and user name if only a user name and id is given', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
userName="some-user-name"
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
processTitle={undefined}
|
||||
workingDirectory={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessionsome-user-name');
|
||||
});
|
||||
|
||||
test('it returns only a process name if only given a process name and id', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
userName={undefined}
|
||||
processExecutable="some-process-name"
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processTitle={undefined}
|
||||
workingDirectory={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessionwas authorized to usesome-process-name');
|
||||
});
|
||||
|
||||
test('it returns only session if process title with id is given', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
processTitle="some-process-title"
|
||||
userName="some-user-name"
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
workingDirectory={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessionsome-user-name');
|
||||
});
|
||||
|
||||
test('it returns only a working directory if that is all that is given with a id', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id={'hello-i-am-an-id'}
|
||||
workingDirectory="some-working-directory"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
processTitle={undefined}
|
||||
args={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessioninsome-working-directory');
|
||||
});
|
||||
|
||||
test('it returns only the session args with id if that is all that is given (very unlikely situation)', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<TestProviders>
|
||||
<AuditdWasAuthorizedLine
|
||||
id="hello-i-am-an-id"
|
||||
args="arg1 arg2 arg 3"
|
||||
userName={undefined}
|
||||
secondary={undefined}
|
||||
session={undefined}
|
||||
hostName={undefined}
|
||||
primary={undefined}
|
||||
processExecutable={undefined}
|
||||
processTitle={undefined}
|
||||
workingDirectory={undefined}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('Sessionarg1 arg2 arg 3');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { get } from 'lodash/fp';
|
||||
import * as React from 'react';
|
||||
import { pure } from 'recompose';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { BrowserFields } from '../../../../containers/source';
|
||||
import { Ecs } from '../../../../graphql/types';
|
||||
import { DraggableBadge } from '../../../draggables';
|
||||
|
||||
import { PrimarySecondaryUserInfo } from './primary_secondary_user_info';
|
||||
import { SourceDest } from './source_dest_ip';
|
||||
|
||||
import * as i18n from './translations';
|
||||
|
||||
const Details = styled.div`
|
||||
margin: 10px 0px 10px 10px;
|
||||
`;
|
||||
|
||||
const TokensFlexItem = styled(EuiFlexItem)`
|
||||
margin-left: 3px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
hostName: string | null | undefined;
|
||||
userName: string | null | undefined;
|
||||
primary: string | null | undefined;
|
||||
secondary: string | null | undefined;
|
||||
processExecutable: string | null | undefined;
|
||||
processTitle: string | null | undefined;
|
||||
workingDirectory: string | null | undefined;
|
||||
args: string | null | undefined;
|
||||
session: string | null | undefined;
|
||||
}
|
||||
|
||||
export const AuditdWasAuthorizedLine = pure<Props>(
|
||||
({
|
||||
id,
|
||||
hostName,
|
||||
userName,
|
||||
primary,
|
||||
secondary,
|
||||
processExecutable,
|
||||
processTitle,
|
||||
workingDirectory,
|
||||
args,
|
||||
session,
|
||||
}) => (
|
||||
<EuiFlexGroup justifyContent="center" gutterSize="none" wrap={true}>
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
{i18n.SESSION}
|
||||
</TokensFlexItem>
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
<DraggableBadge
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
field="auditd.session"
|
||||
value={session}
|
||||
iconType="number"
|
||||
/>
|
||||
</TokensFlexItem>
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
<PrimarySecondaryUserInfo
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
userName={userName}
|
||||
primary={primary}
|
||||
secondary={secondary}
|
||||
/>
|
||||
</TokensFlexItem>
|
||||
{hostName != null && (
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
@
|
||||
</TokensFlexItem>
|
||||
)}
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
<DraggableBadge
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
field="host.name"
|
||||
value={hostName}
|
||||
/>
|
||||
</TokensFlexItem>
|
||||
{workingDirectory != null && (
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
{i18n.IN}
|
||||
</TokensFlexItem>
|
||||
)}
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
<DraggableBadge
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
field="process.working_directory"
|
||||
value={workingDirectory}
|
||||
iconType="folderOpen"
|
||||
/>
|
||||
</TokensFlexItem>
|
||||
{processExecutable != null && (
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
{i18n.WAS_AUTHORIZED_TO_USE}
|
||||
</TokensFlexItem>
|
||||
)}
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
<DraggableBadge
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
field="process.executable"
|
||||
value={processExecutable}
|
||||
iconType="console"
|
||||
/>
|
||||
</TokensFlexItem>
|
||||
<TokensFlexItem grow={false} component="span">
|
||||
{args !== '' && (
|
||||
<DraggableBadge
|
||||
contextId="auditd-acquired-creds"
|
||||
eventId={id}
|
||||
field="process.title"
|
||||
queryValue={processTitle != null ? processTitle : ''}
|
||||
value={args}
|
||||
/>
|
||||
)}
|
||||
</TokensFlexItem>
|
||||
</EuiFlexGroup>
|
||||
)
|
||||
);
|
||||
|
||||
export const AuditdWasAuthorizedDetails = pure<{ browserFields: BrowserFields; data: Ecs }>(
|
||||
({ browserFields, data }) => {
|
||||
const id = data._id;
|
||||
const session: string | null | undefined = get('auditd.session', data);
|
||||
const hostName: string | null | undefined = get('host.name', data);
|
||||
const userName: string | null | undefined = get('user.name', data);
|
||||
const processExecutable: string | null | undefined = get('process.executable', data);
|
||||
const processTitle: string | null | undefined = get('process.title', data);
|
||||
const workingDirectory: string | null | undefined = get('process.working_directory', data);
|
||||
const primary: string | null | undefined = get('auditd.summary.actor.primary', data);
|
||||
const secondary: string | null | undefined = get('auditd.summary.actor.secondary', data);
|
||||
const rawArgs: string[] | null | undefined = get('process.args', data);
|
||||
const args: string = rawArgs != null ? rawArgs.slice(1).join(' ') : '';
|
||||
if (data.process != null) {
|
||||
return (
|
||||
<Details>
|
||||
<AuditdWasAuthorizedLine
|
||||
id={id}
|
||||
hostName={hostName}
|
||||
userName={userName}
|
||||
processExecutable={processExecutable}
|
||||
processTitle={processTitle}
|
||||
workingDirectory={workingDirectory}
|
||||
args={args}
|
||||
session={session}
|
||||
primary={primary}
|
||||
secondary={secondary}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
<SourceDest data={data} browserFields={browserFields} />
|
||||
</Details>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 { mount, shallow } from 'enzyme';
|
||||
import toJson from 'enzyme-to-json';
|
||||
import { cloneDeep } from 'lodash/fp';
|
||||
import * as React from 'react';
|
||||
import { BrowserFields } from 'x-pack/plugins/secops/public/containers/source';
|
||||
|
||||
import { mockBrowserFields } from '../../../../containers/source/mock';
|
||||
import { Ecs } from '../../../../graphql/types';
|
||||
import { mockEcsData, TestProviders } from '../../../../mock';
|
||||
|
||||
import { auditdWasAuthorizedRowRenderer } from '.';
|
||||
|
||||
describe('auditWasAuthorizedRowRenderer', () => {
|
||||
let nonAuditd: Ecs;
|
||||
let auditd: Ecs;
|
||||
|
||||
beforeEach(() => {
|
||||
nonAuditd = cloneDeep(mockEcsData[0]);
|
||||
auditd = cloneDeep(mockEcsData[25]);
|
||||
});
|
||||
|
||||
test('renders correctly against snapshot', () => {
|
||||
// I cannot and do not want to use the BrowserFields mocks for the snapshot tests as they are too heavy
|
||||
const browserFields: BrowserFields = {};
|
||||
const children = auditdWasAuthorizedRowRenderer.renderRow({
|
||||
browserFields,
|
||||
data: auditd,
|
||||
width: 100,
|
||||
children: <span>some children</span>,
|
||||
});
|
||||
|
||||
const wrapper = shallow(<span>{children}</span>);
|
||||
expect(toJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should return false if not a auditd datum', () => {
|
||||
expect(auditdWasAuthorizedRowRenderer.isInstance(nonAuditd)).toBe(false);
|
||||
});
|
||||
|
||||
test('should return true if it is a auditd datum', () => {
|
||||
expect(auditdWasAuthorizedRowRenderer.isInstance(auditd)).toBe(true);
|
||||
});
|
||||
|
||||
test('should return false when action is set to some other value', () => {
|
||||
auditd.event != null
|
||||
? (auditd.event.action = 'some other value')
|
||||
: expect(auditd.event).toBeDefined();
|
||||
expect(auditdWasAuthorizedRowRenderer.isInstance(auditd)).toBe(false);
|
||||
});
|
||||
|
||||
test('should render children normally if it does not have a auditd object', () => {
|
||||
const children = auditdWasAuthorizedRowRenderer.renderRow({
|
||||
browserFields: mockBrowserFields,
|
||||
data: nonAuditd,
|
||||
width: 100,
|
||||
children: <span>some children</span>,
|
||||
});
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<span>{children}</span>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toEqual('some children');
|
||||
});
|
||||
|
||||
test('should render a auditd row', () => {
|
||||
const children = auditdWasAuthorizedRowRenderer.renderRow({
|
||||
browserFields: mockBrowserFields,
|
||||
data: auditd,
|
||||
width: 100,
|
||||
children: <span>some children </span>,
|
||||
});
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<span>{children}</span>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.text()).toContain(
|
||||
'some children Session338rootasalice@suricata-bangalorewas authorized to use/sbin/pam_tally2'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { get } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { RowRenderer, RowRendererContainer } from '.';
|
||||
import { AuditdWasAuthorizedDetails } from './auditd_was_authorized_details';
|
||||
|
||||
const AuditdWasAuthorizedRow = styled.div`
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
&:hover {
|
||||
background-color: ${props => props.theme.eui.euiTableHoverColor};
|
||||
}
|
||||
`;
|
||||
|
||||
export const auditdWasAuthorizedRowRenderer: RowRenderer = {
|
||||
isInstance: ecs => {
|
||||
const module: string | null | undefined = get('event.module', ecs);
|
||||
const action: string | null | undefined = get('event.action', ecs);
|
||||
return (
|
||||
module != null &&
|
||||
module.toLowerCase() === 'auditd' &&
|
||||
action != null &&
|
||||
action.toLowerCase() === 'was-authorized'
|
||||
);
|
||||
},
|
||||
renderRow: ({ browserFields, data, width, children }) => (
|
||||
<AuditdWasAuthorizedRow>
|
||||
{children}
|
||||
<RowRendererContainer width={width}>
|
||||
<AuditdWasAuthorizedDetails browserFields={browserFields} data={data} />
|
||||
</RowRendererContainer>
|
||||
</AuditdWasAuthorizedRow>
|
||||
),
|
||||
};
|
|
@ -10,6 +10,7 @@ import { auditdEndedSessionRowRenderer } from './auditd_ended_session_row_render
|
|||
import { auditdExecutedRowRenderer } from './auditd_executed_row_renderer';
|
||||
import { auditdLoggedinRowRenderer } from './auditd_loggedin_row_renderer';
|
||||
import { auditdStartedSessionRowRenderer } from './auditd_started_session_row_renderer';
|
||||
import { auditdWasAuthorizedRowRenderer } from './auditd_was_authorized_row_renderer';
|
||||
import { ColumnRenderer } from './column_renderer';
|
||||
import { emptyColumnRenderer } from './empty_column_renderer';
|
||||
import { plainColumnRenderer } from './plain_column_renderer';
|
||||
|
@ -25,6 +26,7 @@ export * from './auditd_disposed_creds_row_renderer';
|
|||
export * from './auditd_executed_row_renderer';
|
||||
export * from './auditd_started_session_row_renderer';
|
||||
export * from './auditd_loggedin_row_renderer';
|
||||
export * from './auditd_was_authorized_row_renderer';
|
||||
export * from './column_renderer';
|
||||
export * from './row_renderer';
|
||||
export * from './empty_column_renderer';
|
||||
|
@ -41,6 +43,7 @@ export const rowRenderers: RowRenderer[] = [
|
|||
suricataRowRenderer,
|
||||
auditdExecutedRowRenderer,
|
||||
auditdLoggedinRowRenderer,
|
||||
auditdWasAuthorizedRowRenderer,
|
||||
auditAcquiredCredsRowRenderer,
|
||||
auditdEndedSessionRowRenderer,
|
||||
auditDisposedCredsRowRenderer,
|
||||
|
|
|
@ -87,6 +87,13 @@ export const IN = i18n.translate('xpack.secops.auditd.disposed.inDescription', {
|
|||
defaultMessage: 'in',
|
||||
});
|
||||
|
||||
export const WAS_AUTHORIZED_TO_USE = i18n.translate(
|
||||
'xpack.secops.auditd.wasauthorized.wasAuthorizedToUseDescription',
|
||||
{
|
||||
defaultMessage: 'was authorized to use',
|
||||
}
|
||||
);
|
||||
|
||||
export const ACQUIRED_CREDENTIALS_TO = i18n.translate(
|
||||
'xpack.secops.auditd.acquired.credentialsDescription',
|
||||
{
|
||||
|
|
|
@ -1086,4 +1086,64 @@ export const mockEcsData: Ecs[] = [
|
|||
},
|
||||
zeek: null,
|
||||
},
|
||||
{
|
||||
_id: '26',
|
||||
timestamp: '2019-03-13T03:34:08.890Z',
|
||||
event: {
|
||||
action: 'was-authorized',
|
||||
severity: null,
|
||||
module: 'auditd',
|
||||
category: 'user-login',
|
||||
id: null,
|
||||
dataset: null,
|
||||
},
|
||||
auditd: {
|
||||
result: 'success',
|
||||
session: '338',
|
||||
data: {
|
||||
acct: null,
|
||||
terminal: '/dev/pts/0',
|
||||
op: null,
|
||||
},
|
||||
summary: {
|
||||
actor: {
|
||||
primary: 'root',
|
||||
secondary: 'alice',
|
||||
},
|
||||
object: {
|
||||
primary: '/dev/pts/0',
|
||||
secondary: null,
|
||||
type: 'user-session',
|
||||
},
|
||||
how: '/sbin/pam_tally2',
|
||||
message_type: null,
|
||||
sequence: null,
|
||||
},
|
||||
},
|
||||
host: {
|
||||
id: '0a63559c1acf4c419d979c4b4d8b83ff',
|
||||
name: 'suricata-bangalore',
|
||||
ip: ['139.59.11.147', '10.47.0.5', 'fe80::ec0b:1bff:fe29:80bd'],
|
||||
},
|
||||
source: null,
|
||||
destination: null,
|
||||
geo: null,
|
||||
suricata: null,
|
||||
network: null,
|
||||
http: null,
|
||||
url: null,
|
||||
user: {
|
||||
name: 'alice',
|
||||
},
|
||||
process: {
|
||||
pid: 21170,
|
||||
name: null,
|
||||
ppid: null,
|
||||
args: null,
|
||||
executable: '/sbin/pam_tally2',
|
||||
title: null,
|
||||
working_directory: null,
|
||||
},
|
||||
zeek: null,
|
||||
},
|
||||
];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue