[SM-389] Event log for service account (#4679)

This commit is contained in:
Oscar Hinton 2023-02-24 16:44:24 +01:00 committed by GitHub
parent 76d6586ff8
commit a643074709
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 65 additions and 9 deletions

View File

@ -139,6 +139,7 @@ export abstract class BaseEventsComponent {
type: r.type, type: r.type,
installationId: r.installationId, installationId: r.installationId,
systemUser: r.systemUser, systemUser: r.systemUser,
serviceAccountId: r.serviceAccountId,
}); });
}) })
); );

View File

@ -36,7 +36,7 @@ export class EventService {
} }
async getEventInfo(ev: EventResponse, options = new EventOptions()): Promise<EventInfo> { async getEventInfo(ev: EventResponse, options = new EventOptions()): Promise<EventInfo> {
const appInfo = this.getAppInfo(ev.deviceType); const appInfo = this.getAppInfo(ev);
const { message, humanReadableMessage } = await this.getEventMessage(ev, options); const { message, humanReadableMessage } = await this.getEventMessage(ev, options);
return { return {
message: message, message: message,
@ -410,6 +410,11 @@ export class EventService {
case EventType.OrganizationDomain_NotVerified: case EventType.OrganizationDomain_NotVerified:
msg = humanReadableMsg = this.i18nService.t("domainNotVerifiedEvent", ev.domainName); msg = humanReadableMsg = this.i18nService.t("domainNotVerifiedEvent", ev.domainName);
break; break;
// Secrets Manager
case EventType.Secret_Retrieved:
msg = this.i18nService.t("accessedSecret", this.formatSecretId(ev));
humanReadableMsg = this.i18nService.t("accessedSecret", this.getShortId(ev.secretId));
break;
default: default:
break; break;
} }
@ -419,8 +424,12 @@ export class EventService {
}; };
} }
private getAppInfo(deviceType: DeviceType): [string, string] { private getAppInfo(ev: EventResponse): [string, string] {
switch (deviceType) { if (ev.serviceAccountId) {
return ["bwi-globe", this.i18nService.t("sdk")];
}
switch (ev.deviceType) {
case DeviceType.Android: case DeviceType.Android:
return ["bwi-android", this.i18nService.t("mobile") + " - Android"]; return ["bwi-android", this.i18nService.t("mobile") + " - Android"];
case DeviceType.iOS: case DeviceType.iOS:
@ -554,6 +563,13 @@ export class EventService {
return a.outerHTML; return a.outerHTML;
} }
formatSecretId(ev: EventResponse): string {
const shortId = this.getShortId(ev.secretId);
const a = this.makeAnchor(shortId);
a.setAttribute("href", "#/sm/" + ev.organizationId + "/secrets?search=" + shortId);
return a.outerHTML;
}
private makeAnchor(shortId: string) { private makeAnchor(shortId: string) {
const a = document.createElement("a"); const a = document.createElement("a");
a.title = this.i18nService.t("view"); a.title = this.i18nService.t("view");

View File

@ -152,9 +152,19 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
} }
} }
if (r.serviceAccountId) {
return {
name: this.i18nService.t("serviceAccount") + " " + this.getShortId(r.serviceAccountId),
};
}
return null; return null;
} }
private getShortId(id: string) {
return id?.substring(0, 8);
}
ngOnDestroy() { ngOnDestroy() {
this.destroy$.next(); this.destroy$.next();
this.destroy$.complete(); this.destroy$.complete();

View File

@ -6420,6 +6420,19 @@
"errorReadingImportFile": { "errorReadingImportFile": {
"message": "An error occurred when trying to read the import file" "message": "An error occurred when trying to read the import file"
}, },
"accessedSecret": {
"message": "Accessed secret $SECRET_ID$.",
"placeholders": {
"secret_id": {
"content": "$1",
"example": "4d34e8a8"
}
}
},
"sdk": {
"message": "SDK",
"description": "Software Development Kit"
},
"createSecret": { "createSecret": {
"message": "Create a secret" "message": "Create a secret"
}, },
@ -6497,9 +6510,6 @@
"weakAndBreachedMasterPasswordDesc": { "weakAndBreachedMasterPasswordDesc": {
"message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?" "message": "Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?"
}, },
"important": {
"message": "Important:"
},
"characterMinimum": { "characterMinimum": {
"message": "$LENGTH$ character minimum", "message": "$LENGTH$ character minimum",
"placeholders": { "placeholders": {

View File

@ -1,5 +1,5 @@
<sm-header> <sm-header>
<input bitInput [placeholder]="'searchSecrets' | i18n" /> <input bitInput [placeholder]="'searchSecrets' | i18n" [(ngModel)]="search" />
<sm-new-menu></sm-new-menu> <sm-new-menu></sm-new-menu>
</sm-header> </sm-header>
<sm-secrets-list <sm-secrets-list
@ -7,4 +7,5 @@
(newSecretEvent)="openNewSecretDialog()" (newSecretEvent)="openNewSecretDialog()"
(editSecretEvent)="openEditSecret($event)" (editSecretEvent)="openEditSecret($event)"
[secrets]="secrets$ | async" [secrets]="secrets$ | async"
[search]="search"
></sm-secrets-list> ></sm-secrets-list>

View File

@ -22,7 +22,8 @@ import { SecretService } from "./secret.service";
templateUrl: "./secrets.component.html", templateUrl: "./secrets.component.html",
}) })
export class SecretsComponent implements OnInit { export class SecretsComponent implements OnInit {
secrets$: Observable<SecretListView[]>; protected secrets$: Observable<SecretListView[]>;
protected search: string;
private organizationId: string; private organizationId: string;
@ -41,6 +42,10 @@ export class SecretsComponent implements OnInit {
return await this.getSecrets(); return await this.getSecrets();
}) })
); );
if (this.route.snapshot.queryParams.search) {
this.search = this.route.snapshot.queryParams.search;
}
} }
private async getSecrets(): Promise<SecretListView[]> { private async getSecrets(): Promise<SecretListView[]> {

View File

@ -24,6 +24,11 @@ export class SecretsListComponent implements OnDestroy {
} }
private _secrets: SecretListView[]; private _secrets: SecretListView[];
@Input()
set search(search: string) {
this.dataSource.filter = search;
}
@Input() trash: boolean; @Input() trash: boolean;
@Output() editSecretEvent = new EventEmitter<string>(); @Output() editSecretEvent = new EventEmitter<string>();

View File

@ -78,4 +78,6 @@ export enum EventType {
OrganizationDomain_Removed = 2001, OrganizationDomain_Removed = 2001,
OrganizationDomain_Verified = 2002, OrganizationDomain_Verified = 2002,
OrganizationDomain_NotVerified = 2003, OrganizationDomain_NotVerified = 2003,
Secret_Retrieved = 2100,
} }

View File

@ -23,6 +23,8 @@ export class EventResponse extends BaseResponse {
installationId: string; installationId: string;
systemUser: EventSystemUser; systemUser: EventSystemUser;
domainName: string; domainName: string;
secretId: string;
serviceAccountId: string;
constructor(response: any) { constructor(response: any) {
super(response); super(response);
@ -44,5 +46,7 @@ export class EventResponse extends BaseResponse {
this.installationId = this.getResponseProperty("InstallationId"); this.installationId = this.getResponseProperty("InstallationId");
this.systemUser = this.getResponseProperty("SystemUser"); this.systemUser = this.getResponseProperty("SystemUser");
this.domainName = this.getResponseProperty("DomainName"); this.domainName = this.getResponseProperty("DomainName");
this.secretId = this.getResponseProperty("SecretId");
this.serviceAccountId = this.getResponseProperty("ServiceAccountId");
} }
} }

View File

@ -14,6 +14,7 @@ export class EventView {
type: EventType; type: EventType;
installationId: string; installationId: string;
systemUser: EventSystemUser; systemUser: EventSystemUser;
serviceAccountId: string;
constructor(data: Required<EventView>) { constructor(data: Required<EventView>) {
this.message = data.message; this.message = data.message;
@ -28,5 +29,6 @@ export class EventView {
this.type = data.type; this.type = data.type;
this.installationId = data.installationId; this.installationId = data.installationId;
this.systemUser = data.systemUser; this.systemUser = data.systemUser;
this.serviceAccountId = data.serviceAccountId;
} }
} }