1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-09-27 04:03:00 +02:00

[PM-166] [PM-198] - Add Event Logs for CLI Actions (#6527)

* Added the DeviceType changes for windows CLI

* Event logging for CLI commands

* Changing the icons to cli icons
This commit is contained in:
ttalty 2023-11-09 15:17:25 -05:00 committed by GitHub
parent 4446c09fd2
commit 801141f90e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 93 additions and 14 deletions

View File

@ -4,6 +4,8 @@ import * as path from "path";
import * as program from "commander";
import * as jsdom from "jsdom";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
@ -44,6 +46,8 @@ import { MemoryStorageService } from "@bitwarden/common/platform/services/memory
import { NoopMessagingService } from "@bitwarden/common/platform/services/noop-messaging.service";
import { StateService } from "@bitwarden/common/platform/services/state.service";
import { AuditService } from "@bitwarden/common/services/audit.service";
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
import { SearchService } from "@bitwarden/common/services/search.service";
import { SettingsService } from "@bitwarden/common/services/settings.service";
import { TotpService } from "@bitwarden/common/services/totp.service";
@ -116,6 +120,8 @@ export class Main {
vaultTimeoutService: VaultTimeoutService;
vaultTimeoutSettingsService: VaultTimeoutSettingsService;
syncService: SyncService;
eventCollectionService: EventCollectionServiceAbstraction;
eventUploadService: EventUploadServiceAbstraction;
passwordGenerationService: PasswordGenerationServiceAbstraction;
passwordStrengthService: PasswordStrengthServiceAbstraction;
totpService: TotpService;
@ -452,6 +458,19 @@ export class Main {
this.sendProgram = new SendProgram(this);
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
this.eventUploadService = new EventUploadService(
this.apiService,
this.stateService,
this.logService
);
this.eventCollectionService = new EventCollectionService(
this.cipherService,
this.stateService,
this.organizationService,
this.eventUploadService
);
}
async run() {

View File

@ -1,9 +1,11 @@
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { EventType } from "@bitwarden/common/enums";
import { CardExport } from "@bitwarden/common/models/export/card.export";
import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
@ -53,7 +55,8 @@ export class GetCommand extends DownloadCommand {
private stateService: StateService,
private searchService: SearchService,
private apiService: ApiService,
private organizationService: OrganizationService
private organizationService: OrganizationService,
private eventCollectionService: EventCollectionService
) {
super(cryptoService);
}
@ -137,6 +140,14 @@ export class GetCommand extends DownloadCommand {
return Response.multipleResults(decCipher.map((c) => c.id));
}
}
this.eventCollectionService.collect(
EventType.Cipher_ClientViewed,
id,
true,
decCipher.organizationId
);
const res = new CipherResponse(decCipher);
return Response.success(res);
}

View File

@ -1,7 +1,9 @@
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { EventType } from "@bitwarden/common/enums";
import { ListResponse as ApiListResponse } from "@bitwarden/common/models/response/list.response";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@ -32,7 +34,8 @@ export class ListCommand {
private organizationService: OrganizationService,
private searchService: SearchService,
private organizationUserService: OrganizationUserService,
private apiService: ApiService
private apiService: ApiService,
private eventCollectionService: EventCollectionService
) {}
async run(object: string, cmdOptions: Record<string, any>): Promise<Response> {
@ -123,6 +126,17 @@ export class ListCommand {
ciphers = this.searchService.searchCiphersBasic(ciphers, options.search, options.trash);
}
ciphers.forEach((c, index) => {
// Set upload immediately on the last item in the ciphers collection to avoid the event collection
// service from uploading each time.
this.eventCollectionService.collect(
EventType.Cipher_ClientViewed,
c.id,
index === ciphers.length - 1,
c.organizationId
);
});
const res = new ListResponse(ciphers.map((o) => new CipherResponse(o)));
return Response.success(res);
}

View File

@ -66,7 +66,8 @@ export class ServeCommand {
this.main.stateService,
this.main.searchService,
this.main.apiService,
this.main.organizationService
this.main.organizationService,
this.main.eventCollectionService
);
this.listCommand = new ListCommand(
this.main.cipherService,
@ -75,7 +76,8 @@ export class ServeCommand {
this.main.organizationService,
this.main.searchService,
this.main.organizationUserService,
this.main.apiService
this.main.apiService,
this.main.eventCollectionService
);
this.createCommand = new CreateCommand(
this.main.cipherService,

View File

@ -19,14 +19,14 @@ export class CliPlatformUtilsService implements PlatformUtilsService {
if (!this.deviceCache) {
switch (process.platform) {
case "win32":
this.deviceCache = DeviceType.WindowsDesktop;
this.deviceCache = DeviceType.WindowsCLI;
break;
case "darwin":
this.deviceCache = DeviceType.MacOsDesktop;
this.deviceCache = DeviceType.MacOsCLI;
break;
case "linux":
default:
this.deviceCache = DeviceType.LinuxDesktop;
this.deviceCache = DeviceType.LinuxCLI;
break;
}
}
@ -36,7 +36,7 @@ export class CliPlatformUtilsService implements PlatformUtilsService {
getDeviceString(): string {
const device = DeviceType[this.getDevice()].toLowerCase();
return device.replace("desktop", "");
return device.replace("cli", "");
}
getClientType() {

View File

@ -1,8 +1,10 @@
import * as program from "commander";
import * as inquirer from "inquirer";
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { EventType } from "@bitwarden/common/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import {
ExportFormat,
@ -16,7 +18,8 @@ import { CliUtils } from "../utils";
export class ExportCommand {
constructor(
private exportService: VaultExportServiceAbstraction,
private policyService: PolicyService
private policyService: PolicyService,
private eventCollectionService: EventCollectionService
) {}
async run(options: program.OptionValues): Promise<Response> {
@ -48,6 +51,11 @@ export class ExportCommand {
format === "encrypted_json"
? await this.getProtectedExport(options.password, options.organizationid)
: await this.getUnprotectedExport(format, options.organizationid);
const eventType = options.organizationid
? EventType.Organization_ClientExportedVault
: EventType.User_ClientExportedVault;
this.eventCollectionService.collect(eventType, null, true, options.organizationid);
} catch (e) {
return Response.error(e);
}

View File

@ -156,7 +156,8 @@ export class SendProgram extends Program {
this.main.stateService,
this.main.searchService,
this.main.apiService,
this.main.organizationService
this.main.organizationService,
this.main.eventCollectionService
);
const response = await cmd.run("template", object, null);
this.processResponse(response);

View File

@ -116,7 +116,8 @@ export class VaultProgram extends Program {
this.main.organizationService,
this.main.searchService,
this.main.organizationUserService,
this.main.apiService
this.main.apiService,
this.main.eventCollectionService
);
const response = await command.run(object, cmd);
@ -189,7 +190,8 @@ export class VaultProgram extends Program {
this.main.stateService,
this.main.searchService,
this.main.apiService,
this.main.organizationService
this.main.organizationService,
this.main.eventCollectionService
);
const response = await command.run(object, id, cmd);
this.processResponse(response);
@ -489,7 +491,11 @@ export class VaultProgram extends Program {
})
.action(async (options) => {
await this.exitIfLocked();
const command = new ExportCommand(this.main.exportService, this.main.policyService);
const command = new ExportCommand(
this.main.exportService,
this.main.policyService,
this.main.eventCollectionService
);
const response = await command.run(options);
this.processResponse(response);
});

View File

@ -486,6 +486,12 @@ export class EventService {
return ["bwi-globe", this.i18nService.t("webVault") + " - IE"];
case DeviceType.Server:
return ["bwi-server", this.i18nService.t("server")];
case DeviceType.WindowsCLI:
return ["bwi-cli", this.i18nService.t("cli") + " - Windows"];
case DeviceType.MacOsCLI:
return ["bwi-cli", this.i18nService.t("cli") + " - macOS"];
case DeviceType.LinuxCLI:
return ["bwi-cli", this.i18nService.t("cli") + " - Linux"];
case DeviceType.UnknownBrowser:
return [
"bwi-globe",

View File

@ -2762,6 +2762,9 @@
"webVault": {
"message": "Web vault"
},
"cli": {
"message": "CLI"
},
"bitWebVault": {
"message": "Bitwarden Web vault"
},

View File

@ -22,6 +22,9 @@ export enum DeviceType {
SafariExtension = 20,
SDK = 21,
Server = 22,
WindowsCLI = 23,
MacOsCLI = 24,
LinuxCLI = 25,
}
export const MobileDeviceTypes: Set<DeviceType> = new Set([
@ -35,4 +38,7 @@ export const DesktopDeviceTypes: Set<DeviceType> = new Set([
DeviceType.MacOsDesktop,
DeviceType.LinuxDesktop,
DeviceType.UWP,
DeviceType.WindowsCLI,
DeviceType.MacOsCLI,
DeviceType.LinuxCLI,
]);

View File

@ -171,7 +171,10 @@ export class ApiService implements ApiServiceAbstraction {
this.isDesktopClient =
this.device === DeviceType.WindowsDesktop ||
this.device === DeviceType.MacOsDesktop ||
this.device === DeviceType.LinuxDesktop;
this.device === DeviceType.LinuxDesktop ||
this.device === DeviceType.WindowsCLI ||
this.device === DeviceType.MacOsCLI ||
this.device === DeviceType.LinuxCLI;
}
// Auth APIs