mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-11 22:49:54 +00:00
Add audit events for CreatePairedDeviceEnrollToken (#68835)
* Add audit events for CreatePairedDeviceEnrollToken * Add Web UI formatter for new audit events * Update audit events reference * Use `OSType` from generated protos
This commit is contained in:
@@ -5,6 +5,7 @@ inputs:
|
||||
paths:
|
||||
- api/proto/teleport/userpreferences/
|
||||
- api/proto/teleport/desktop/
|
||||
- api/proto/teleport/devicetrust/v1/os_type.proto
|
||||
- proto/prehog/
|
||||
- proto/teleport/lib/teleterm/
|
||||
- proto/teleport/lib/vnet/diag/
|
||||
|
||||
@@ -3633,6 +3633,58 @@ Example:
|
||||
}
|
||||
```
|
||||
|
||||
## device.enroll_pairing.request
|
||||
|
||||
There are multiple events with the `device.enroll_pairing.request` type.
|
||||
|
||||
### TV010I
|
||||
|
||||
Device Enroll Pairing Requested
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"cluster_name": "im-a-cluster-name",
|
||||
"code": "TV010I",
|
||||
"device": {
|
||||
"asset_tag": "M2CQVQV64R",
|
||||
"device_id": "",
|
||||
"os_type": 4
|
||||
},
|
||||
"ei": 0,
|
||||
"event": "device.enroll_pairing.request",
|
||||
"success": true,
|
||||
"time": "2024-04-08T19:37:48.1Z",
|
||||
"uid": "a7b3e9f1-4d5c-6a8b-9012-def345678901",
|
||||
"user": "llama"
|
||||
}
|
||||
```
|
||||
|
||||
### TV010W
|
||||
|
||||
Device Enroll Pairing Request Failed
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"cluster_name": "im-a-cluster-name",
|
||||
"code": "TV010W",
|
||||
"device": {
|
||||
"asset_tag": "M2CQVQV64R",
|
||||
"device_id": "",
|
||||
"os_type": 4
|
||||
},
|
||||
"ei": 0,
|
||||
"error": "invalid pairing token",
|
||||
"event": "device.enroll_pairing.request",
|
||||
"success": false,
|
||||
"time": "2024-04-08T19:38:48.1Z",
|
||||
"uid": "a7b3e9f1-4d5c-6a8b-9012-def345678902"
|
||||
}
|
||||
```
|
||||
|
||||
## device.token.create
|
||||
|
||||
Device Enroll Token Created
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/* eslint-disable */
|
||||
// @generated by protobuf-ts 2.9.3 with parameter add_pb_suffix,eslint_disable,generate_dependencies,server_grpc1,ts_nocheck
|
||||
// @generated from protobuf file "teleport/devicetrust/v1/os_type.proto" (package "teleport.devicetrust.v1", syntax proto3)
|
||||
// tslint:disable
|
||||
// @ts-nocheck
|
||||
//
|
||||
// Copyright 2022 Gravitational, Inc
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
/**
|
||||
* OSType represents the operating system of a device.
|
||||
*
|
||||
* @generated from protobuf enum teleport.devicetrust.v1.OSType
|
||||
*/
|
||||
export enum OSType {
|
||||
/**
|
||||
* @generated from protobuf enum value: OS_TYPE_UNSPECIFIED = 0;
|
||||
*/
|
||||
OS_TYPE_UNSPECIFIED = 0,
|
||||
/**
|
||||
* Linux.
|
||||
*
|
||||
* @generated from protobuf enum value: OS_TYPE_LINUX = 1;
|
||||
*/
|
||||
OS_TYPE_LINUX = 1,
|
||||
/**
|
||||
* macOS.
|
||||
*
|
||||
* @generated from protobuf enum value: OS_TYPE_MACOS = 2;
|
||||
*/
|
||||
OS_TYPE_MACOS = 2,
|
||||
/**
|
||||
* Windows.
|
||||
*
|
||||
* @generated from protobuf enum value: OS_TYPE_WINDOWS = 3;
|
||||
*/
|
||||
OS_TYPE_WINDOWS = 3,
|
||||
/**
|
||||
* iOS.
|
||||
*
|
||||
* @generated from protobuf enum value: OS_TYPE_IOS = 4;
|
||||
*/
|
||||
OS_TYPE_IOS = 4,
|
||||
/**
|
||||
* iPadOS.
|
||||
*
|
||||
* @generated from protobuf enum value: OS_TYPE_IPADOS = 5;
|
||||
*/
|
||||
OS_TYPE_IPADOS = 5
|
||||
}
|
||||
@@ -707,6 +707,11 @@ const (
|
||||
// A confirmed web authentication means the WebSession itself now holds
|
||||
// augmented TLS and SSH certificates.
|
||||
DeviceAuthenticateConfirmEvent = "device.authenticate.confirm"
|
||||
// DeviceEnrollPairingRequestEvent is emitted when a device presents an enroll
|
||||
// pairing token to request enrollment. On success the pairing transitions to
|
||||
// awaiting approval. It is also emitted on failure (e.g. an invalid token),
|
||||
// before any transition, in which case there is no associated user.
|
||||
DeviceEnrollPairingRequestEvent = "device.enroll_pairing.request"
|
||||
|
||||
// BotJoinEvent is emitted when a bot joins
|
||||
BotJoinEvent = "bot.join"
|
||||
|
||||
@@ -525,6 +525,11 @@ const (
|
||||
DeviceWebTokenCreateCode = "TV008I"
|
||||
// DeviceAuthenticateConfirmCode is the device authentication confirm code.
|
||||
DeviceAuthenticateConfirmCode = "TV009I"
|
||||
// DeviceEnrollPairingRequestCode is the device enroll pairing request code.
|
||||
DeviceEnrollPairingRequestCode = "TV010I"
|
||||
// DeviceEnrollPairingRequestFailureCode is the device enroll pairing request
|
||||
// failure code.
|
||||
DeviceEnrollPairingRequestFailureCode = "TV010W"
|
||||
|
||||
// LoginRuleCreateCode is the login rule create code.
|
||||
LoginRuleCreateCode = "TLR00I"
|
||||
|
||||
@@ -296,7 +296,8 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) {
|
||||
DeviceAuthenticateEvent,
|
||||
DeviceEnrollTokenCreateEvent,
|
||||
DeviceWebTokenCreateEvent,
|
||||
DeviceAuthenticateConfirmEvent:
|
||||
DeviceAuthenticateConfirmEvent,
|
||||
DeviceEnrollPairingRequestEvent:
|
||||
e = &events.DeviceEvent2{}
|
||||
case LockCreatedEvent:
|
||||
e = &events.LockCreate{}
|
||||
|
||||
@@ -155,6 +155,7 @@ var eventsMap = map[string]apievents.AuditEvent{
|
||||
DeviceEnrollTokenCreateEvent: &apievents.DeviceEvent2{},
|
||||
DeviceWebTokenCreateEvent: &apievents.DeviceEvent2{},
|
||||
DeviceAuthenticateConfirmEvent: &apievents.DeviceEvent2{},
|
||||
DeviceEnrollPairingRequestEvent: &apievents.DeviceEvent2{},
|
||||
LockCreatedEvent: &apievents.LockCreate{},
|
||||
LockDeletedEvent: &apievents.LockDelete{},
|
||||
RecoveryCodeGeneratedEvent: &apievents.RecoveryCodeGenerate{},
|
||||
|
||||
@@ -206,6 +206,8 @@ export const EventIconMap: Record<EventCode, any> = {
|
||||
[eventCodes.DEVICE_UPDATE]: Icons.Info,
|
||||
[eventCodes.DEVICE_WEB_TOKEN_CREATE]: Icons.Info,
|
||||
[eventCodes.DEVICE_AUTHENTICATE_CONFIRM]: Icons.Info,
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST]: Icons.Info,
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST_FAILURE]: Icons.Info,
|
||||
[eventCodes.MFA_DEVICE_ADD]: Icons.Info,
|
||||
[eventCodes.MFA_DEVICE_DELETE]: Icons.Info,
|
||||
[eventCodes.BILLING_CARD_CREATE]: Icons.CreditCard,
|
||||
|
||||
@@ -3291,6 +3291,36 @@ export const events = [
|
||||
user: 'llama',
|
||||
user_kind: 1,
|
||||
},
|
||||
{
|
||||
cluster_name: 'im-a-cluster-name',
|
||||
code: 'TV010I',
|
||||
device: {
|
||||
asset_tag: 'M2CQVQV64R',
|
||||
device_id: '',
|
||||
os_type: 4,
|
||||
},
|
||||
ei: 0,
|
||||
event: 'device.enroll_pairing.request',
|
||||
success: true,
|
||||
time: '2024-04-08T19:37:48.1Z',
|
||||
uid: 'a7b3e9f1-4d5c-6a8b-9012-def345678901',
|
||||
user: 'llama',
|
||||
},
|
||||
{
|
||||
cluster_name: 'im-a-cluster-name',
|
||||
code: 'TV010W',
|
||||
device: {
|
||||
asset_tag: 'M2CQVQV64R',
|
||||
device_id: '',
|
||||
os_type: 4,
|
||||
},
|
||||
ei: 0,
|
||||
error: 'invalid pairing token',
|
||||
event: 'device.enroll_pairing.request',
|
||||
success: false,
|
||||
time: '2024-04-08T19:38:48.1Z',
|
||||
uid: 'a7b3e9f1-4d5c-6a8b-9012-def345678902',
|
||||
},
|
||||
{
|
||||
cluster_name: 'im-a-cluster-name',
|
||||
code: 'TLR00I',
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
import { PagerPosition } from 'design/DataTable/types';
|
||||
import { OSType } from 'gen-proto-ts/teleport/devicetrust/v1/os_type_pb';
|
||||
|
||||
export type TrustedDevice = {
|
||||
id: string;
|
||||
@@ -56,6 +57,28 @@ export type DeviceSource = {
|
||||
*/
|
||||
export type TrustedDeviceOSType = TrustedDevice['osType'];
|
||||
|
||||
export function osTypeLabel(
|
||||
osType: OSType
|
||||
): TrustedDevice['osType'] | undefined {
|
||||
switch (osType) {
|
||||
case OSType.OS_TYPE_LINUX:
|
||||
return 'Linux';
|
||||
case OSType.OS_TYPE_MACOS:
|
||||
return 'macOS';
|
||||
case OSType.OS_TYPE_WINDOWS:
|
||||
return 'Windows';
|
||||
case OSType.OS_TYPE_IOS:
|
||||
return 'iOS';
|
||||
case OSType.OS_TYPE_IPADOS:
|
||||
return 'iPadOS';
|
||||
case OSType.OS_TYPE_UNSPECIFIED:
|
||||
return undefined;
|
||||
default:
|
||||
osType satisfies never;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export type TrustedDeviceResponse = {
|
||||
items: TrustedDevice[];
|
||||
startKey: string;
|
||||
|
||||
@@ -20,6 +20,8 @@ import { formatDistanceStrict } from 'date-fns';
|
||||
|
||||
import { pluralize } from 'shared/utils/text';
|
||||
|
||||
import { osTypeLabel } from 'teleport/DeviceTrust/types';
|
||||
|
||||
import {
|
||||
Event,
|
||||
EventCode,
|
||||
@@ -1491,6 +1493,20 @@ export const formatters: Formatters = {
|
||||
? `User [${user}] has confirmed device web authentication`
|
||||
: `User [${user}] has failed to confirm device web authentication`,
|
||||
},
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST]: {
|
||||
type: 'device.enroll_pairing.request',
|
||||
desc: 'Device Enroll Pairing Requested',
|
||||
format: ({ user, device }) =>
|
||||
`Device enrollment was requested for user [${user}]${formatDevice(device)}`,
|
||||
},
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST_FAILURE]: {
|
||||
type: 'device.enroll_pairing.request',
|
||||
desc: 'Device Enroll Pairing Request Failed',
|
||||
format: ({ device, error }) =>
|
||||
error
|
||||
? `Device enrollment request failed${formatDevice(device)}: ${error}`
|
||||
: `Device enrollment request failed${formatDevice(device)}`,
|
||||
},
|
||||
[eventCodes.X11_FORWARD]: {
|
||||
type: 'x11-forward',
|
||||
desc: 'X11 Forwarding Requested',
|
||||
@@ -2989,3 +3005,22 @@ export function formatSqn({
|
||||
}
|
||||
return `${scope}::${name}`;
|
||||
}
|
||||
|
||||
// formatDevice renders the OS type and serial number (carried as asset_tag) of a device audit
|
||||
// event's device metadata, e.g. " (OS [iOS], serial number [ABC123])". Returns an empty string when
|
||||
// neither is present.
|
||||
const formatDevice = (device?: {
|
||||
asset_tag?: string;
|
||||
os_type?: number;
|
||||
}): string => {
|
||||
const parts: string[] = [];
|
||||
// Account for os_type possibly being 0 (UNSPECIFIED) with os_type != null.
|
||||
const os = device?.os_type != null ? osTypeLabel(device.os_type) : undefined;
|
||||
if (os) {
|
||||
parts.push(`OS [${os}]`);
|
||||
}
|
||||
if (device?.asset_tag) {
|
||||
parts.push(`serial number [${device.asset_tag}]`);
|
||||
}
|
||||
return parts.length ? ` (${parts.join(', ')})` : '';
|
||||
};
|
||||
|
||||
@@ -30,6 +30,7 @@ export const eventGroupTypes = {
|
||||
subsystem: 'Subsystem Request',
|
||||
'user.login': 'User Logins',
|
||||
'spiffe.svid.issued': 'SPIFFE SVID Issuance',
|
||||
'device.enroll_pairing.request': 'Device Enroll Pairing Request',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,6 @@ export const eventGroupTypes = {
|
||||
* These duplicated event types needs to be defined in `eventGroupTypes` object
|
||||
* 3: Define icons for events under `EventTypeCell.tsx` file
|
||||
* 4: Add an actual JSON event to the fixtures file in `src/Audit/fixtures/index.ts`.
|
||||
* 5: Check fixture is rendered in storybook, then update snapshot for `Audit.story.test.tsx`
|
||||
*/
|
||||
export const eventCodes = {
|
||||
ACCESS_REQUEST_CREATED: 'T5000I',
|
||||
@@ -138,6 +138,8 @@ export const eventCodes = {
|
||||
DEVICE_UPDATE: 'TV007I',
|
||||
DEVICE_WEB_TOKEN_CREATE: 'TV008I',
|
||||
DEVICE_AUTHENTICATE_CONFIRM: 'TV009I',
|
||||
DEVICE_ENROLL_PAIRING_REQUEST: 'TV010I',
|
||||
DEVICE_ENROLL_PAIRING_REQUEST_FAILURE: 'TV010W',
|
||||
EXEC_FAILURE: 'T3002E',
|
||||
EXEC: 'T3002I',
|
||||
GITHUB_CONNECTOR_CREATED: 'T8000I',
|
||||
@@ -1445,6 +1447,15 @@ export type RawEvents = {
|
||||
[eventCodes.DEVICE_AUTHENTICATE_CONFIRM]: RawDeviceEvent<
|
||||
typeof eventCodes.DEVICE_AUTHENTICATE_CONFIRM
|
||||
>;
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST]: RawDeviceEvent<
|
||||
typeof eventCodes.DEVICE_ENROLL_PAIRING_REQUEST
|
||||
>;
|
||||
// The failure event carries no user (the pairing lookup that resolves the user
|
||||
// is what failed) and surfaces the failure reason via the error field.
|
||||
[eventCodes.DEVICE_ENROLL_PAIRING_REQUEST_FAILURE]: RawEvent<
|
||||
typeof eventCodes.DEVICE_ENROLL_PAIRING_REQUEST_FAILURE,
|
||||
Merge<DeviceEventFields, { error?: string }>
|
||||
>;
|
||||
[eventCodes.UNKNOWN]: RawEvent<
|
||||
typeof eventCodes.UNKNOWN,
|
||||
{
|
||||
@@ -2597,16 +2608,15 @@ type RawEventData<T extends EventCode> = RawEvent<
|
||||
}
|
||||
>;
|
||||
|
||||
type RawDeviceEvent<T extends EventCode> = RawEvent<
|
||||
T,
|
||||
{
|
||||
device: { asset_tag: string; device_id: string; os_type: number };
|
||||
success?: boolean;
|
||||
user?: string;
|
||||
// status from "legacy" event format.
|
||||
status?: { success: boolean };
|
||||
}
|
||||
>;
|
||||
type DeviceEventFields = {
|
||||
device: { asset_tag: string; device_id: string; os_type: number };
|
||||
success?: boolean;
|
||||
user?: string;
|
||||
// status from "legacy" event format.
|
||||
status?: { success: boolean };
|
||||
};
|
||||
|
||||
type RawDeviceEvent<T extends EventCode> = RawEvent<T, DeviceEventFields>;
|
||||
|
||||
type RawEventCommand<T extends EventCode> = RawEvent<
|
||||
T,
|
||||
|
||||
Reference in New Issue
Block a user