Skip to content

Commit

Permalink
Add audit events for spaces (elastic#86343) (elastic#86620)
Browse files Browse the repository at this point in the history
* Add audit events for spaces

* fix eslint error
  • Loading branch information
thomheymann authored Dec 21, 2020
1 parent b1bc258 commit 20d9ae2
Show file tree
Hide file tree
Showing 8 changed files with 501 additions and 81 deletions.
58 changes: 37 additions & 21 deletions docs/user/security/audit-logging.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ authorization checks have passed, but before the response from {es} is received.
Refer to the corresponding {es} logs for potential write errors.
============================================================================


[cols="3*<"]
|======
3+a|
Expand Down Expand Up @@ -89,9 +88,12 @@ Refer to the corresponding {es} logs for potential write errors.
| `failure` | User is not authorized to create a connector.

.2+| `alert_create`
| `unknown` | User is creating an alert rule.
| `failure` | User is not authorized to create an alert rule.
| `unknown` | User is creating an alert.
| `failure` | User is not authorized to create an alert.

.2+| `space_create`
| `unknown` | User is creating a space.
| `failure` | User is not authorized to create a space.

3+a|
====== Type: change
Expand Down Expand Up @@ -121,28 +123,28 @@ Refer to the corresponding {es} logs for potential write errors.
| `failure` | User is not authorized to update a connector.

.2+| `alert_update`
| `unknown` | User is updating an alert rule.
| `failure` | User is not authorized to update an alert rule.
| `unknown` | User is updating an alert.
| `failure` | User is not authorized to update an alert.

.2+| `alert_update_api_key`
| `unknown` | User is updating the API key of an alert rule.
| `failure` | User is not authorized to update the API key of an alert rule.
| `unknown` | User is updating the API key of an alert.
| `failure` | User is not authorized to update the API key of an alert.

.2+| `alert_enable`
| `unknown` | User is enabling an alert rule.
| `failure` | User is not authorized to enable an alert rule.
| `unknown` | User is enabling an alert.
| `failure` | User is not authorized to enable an alert.

.2+| `alert_disable`
| `unknown` | User is disabling an alert rule.
| `failure` | User is not authorized to disable an alert rule.
| `unknown` | User is disabling an alert.
| `failure` | User is not authorized to disable an alert.

.2+| `alert_mute`
| `unknown` | User is muting an alert rule.
| `failure` | User is not authorized to mute an alert rule.
| `unknown` | User is muting an alert.
| `failure` | User is not authorized to mute an alert.

.2+| `alert_unmute`
| `unknown` | User is unmuting an alert rule.
| `failure` | User is not authorized to unmute an alert rule.
| `unknown` | User is unmuting an alert.
| `failure` | User is not authorized to unmute an alert.

.2+| `alert_instance_mute`
| `unknown` | User is muting an alert instance.
Expand All @@ -152,6 +154,9 @@ Refer to the corresponding {es} logs for potential write errors.
| `unknown` | User is unmuting an alert instance.
| `failure` | User is not authorized to unmute an alert instance.

.2+| `space_update`
| `unknown` | User is updating a space.
| `failure` | User is not authorized to update a space.

3+a|
====== Type: deletion
Expand All @@ -169,8 +174,12 @@ Refer to the corresponding {es} logs for potential write errors.
| `failure` | User is not authorized to delete a connector.

.2+| `alert_delete`
| `unknown` | User is deleting an alert rule.
| `failure` | User is not authorized to delete an alert rule.
| `unknown` | User is deleting an alert.
| `failure` | User is not authorized to delete an alert.

.2+| `space_delete`
| `unknown` | User is deleting a space.
| `failure` | User is not authorized to delete a space.

3+a|
====== Type: access
Expand All @@ -196,13 +205,20 @@ Refer to the corresponding {es} logs for potential write errors.
| `failure` | User is not authorized to search for connectors.

.2+| `alert_get`
| `success` | User has accessed an alert rule.
| `failure` | User is not authorized to access an alert rule.
| `success` | User has accessed an alert.
| `failure` | User is not authorized to access an alert.

.2+| `alert_find`
| `success` | User has accessed an alert rule as part of a search operation.
| `failure` | User is not authorized to search for alert rules.
| `success` | User has accessed an alert as part of a search operation.
| `failure` | User is not authorized to search for alerts.

.2+| `space_get`
| `success` | User has accessed a space.
| `failure` | User is not authorized to access a space.

.2+| `space_find`
| `success` | User has accessed a space as part of a search operation.
| `failure` | User is not authorized to search for spaces.

3+a|
===== Category: web
Expand Down
87 changes: 87 additions & 0 deletions x-pack/plugins/security/server/audit/audit_events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
savedObjectEvent,
userLoginEvent,
httpRequestEvent,
spaceAuditEvent,
SpaceAuditAction,
} from './audit_events';
import { AuthenticationResult } from '../authentication';
import { mockAuthenticatedUser } from '../../common/model/authenticated_user.mock';
Expand Down Expand Up @@ -325,3 +327,88 @@ describe('#httpRequestEvent', () => {
`);
});
});

describe('#spaceAuditEvent', () => {
test('creates event with `unknown` outcome', () => {
expect(
spaceAuditEvent({
action: SpaceAuditAction.CREATE,
outcome: EventOutcome.UNKNOWN,
savedObject: { type: 'space', id: 'SPACE_ID' },
})
).toMatchInlineSnapshot(`
Object {
"error": undefined,
"event": Object {
"action": "space_create",
"category": "database",
"outcome": "unknown",
"type": "creation",
},
"kibana": Object {
"saved_object": Object {
"id": "SPACE_ID",
"type": "space",
},
},
"message": "User is creating space [id=SPACE_ID]",
}
`);
});

test('creates event with `success` outcome', () => {
expect(
spaceAuditEvent({
action: SpaceAuditAction.CREATE,
savedObject: { type: 'space', id: 'SPACE_ID' },
})
).toMatchInlineSnapshot(`
Object {
"error": undefined,
"event": Object {
"action": "space_create",
"category": "database",
"outcome": "success",
"type": "creation",
},
"kibana": Object {
"saved_object": Object {
"id": "SPACE_ID",
"type": "space",
},
},
"message": "User has created space [id=SPACE_ID]",
}
`);
});

test('creates event with `failure` outcome', () => {
expect(
spaceAuditEvent({
action: SpaceAuditAction.CREATE,
savedObject: { type: 'space', id: 'SPACE_ID' },
error: new Error('ERROR_MESSAGE'),
})
).toMatchInlineSnapshot(`
Object {
"error": Object {
"code": "Error",
"message": "ERROR_MESSAGE",
},
"event": Object {
"action": "space_create",
"category": "database",
"outcome": "failure",
"type": "creation",
},
"kibana": Object {
"saved_object": Object {
"id": "SPACE_ID",
"type": "space",
},
},
"message": "Failed attempt to create space [id=SPACE_ID]",
}
`);
});
});
74 changes: 69 additions & 5 deletions x-pack/plugins/security/server/audit/audit_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface AuditEvent {
* Human readable message describing action, outcome and user.
*
* @example
* User [jdoe] logged in using basic provider [name=basic1]
* Failed attempt to login using basic provider [name=basic1]
*/
message: string;
event: {
Expand Down Expand Up @@ -208,7 +208,7 @@ export enum SavedObjectAction {

type VerbsTuple = [string, string, string];

const eventVerbs: Record<SavedObjectAction, VerbsTuple> = {
const savedObjectAuditVerbs: Record<SavedObjectAction, VerbsTuple> = {
saved_object_create: ['create', 'creating', 'created'],
saved_object_get: ['access', 'accessing', 'accessed'],
saved_object_update: ['update', 'updating', 'updated'],
Expand All @@ -223,7 +223,7 @@ const eventVerbs: Record<SavedObjectAction, VerbsTuple> = {
],
};

const eventTypes: Record<SavedObjectAction, EventType> = {
const savedObjectAuditTypes: Record<SavedObjectAction, EventType> = {
saved_object_create: EventType.CREATION,
saved_object_get: EventType.ACCESS,
saved_object_update: EventType.CHANGE,
Expand Down Expand Up @@ -252,13 +252,13 @@ export function savedObjectEvent({
error,
}: SavedObjectEventParams): AuditEvent | undefined {
const doc = savedObject ? `${savedObject.type} [id=${savedObject.id}]` : 'saved objects';
const [present, progressive, past] = eventVerbs[action];
const [present, progressive, past] = savedObjectAuditVerbs[action];
const message = error
? `Failed attempt to ${present} ${doc}`
: outcome === EventOutcome.UNKNOWN
? `User is ${progressive} ${doc}`
: `User has ${past} ${doc}`;
const type = eventTypes[action];
const type = savedObjectAuditTypes[action];

if (
type === EventType.ACCESS &&
Expand Down Expand Up @@ -287,3 +287,67 @@ export function savedObjectEvent({
},
};
}

export enum SpaceAuditAction {
CREATE = 'space_create',
GET = 'space_get',
UPDATE = 'space_update',
DELETE = 'space_delete',
FIND = 'space_find',
}

const spaceAuditVerbs: Record<SpaceAuditAction, VerbsTuple> = {
space_create: ['create', 'creating', 'created'],
space_get: ['access', 'accessing', 'accessed'],
space_update: ['update', 'updating', 'updated'],
space_delete: ['delete', 'deleting', 'deleted'],
space_find: ['access', 'accessing', 'accessed'],
};

const spaceAuditTypes: Record<SpaceAuditAction, EventType> = {
space_create: EventType.CREATION,
space_get: EventType.ACCESS,
space_update: EventType.CHANGE,
space_delete: EventType.DELETION,
space_find: EventType.ACCESS,
};

export interface SpacesAuditEventParams {
action: SpaceAuditAction;
outcome?: EventOutcome;
savedObject?: NonNullable<AuditEvent['kibana']>['saved_object'];
error?: Error;
}

export function spaceAuditEvent({
action,
savedObject,
outcome,
error,
}: SpacesAuditEventParams): AuditEvent {
const doc = savedObject ? `space [id=${savedObject.id}]` : 'spaces';
const [present, progressive, past] = spaceAuditVerbs[action];
const message = error
? `Failed attempt to ${present} ${doc}`
: outcome === EventOutcome.UNKNOWN
? `User is ${progressive} ${doc}`
: `User has ${past} ${doc}`;
const type = spaceAuditTypes[action];

return {
message,
event: {
action,
category: EventCategory.DATABASE,
type,
outcome: outcome ?? (error ? EventOutcome.FAILURE : EventOutcome.SUCCESS),
},
kibana: {
saved_object: savedObject,
},
error: error && {
code: error.name,
message: error.message,
},
};
}
2 changes: 2 additions & 0 deletions x-pack/plugins/security/server/audit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export {
userLoginEvent,
httpRequestEvent,
savedObjectEvent,
spaceAuditEvent,
SavedObjectAction,
SpaceAuditAction,
} from './audit_events';
export { SecurityAuditLogger } from './security_audit_logger';
Loading

0 comments on commit 20d9ae2

Please sign in to comment.