mirror of
https://github.com/bitwarden/clients.git
synced 2025-12-22 05:07:16 +00:00
[PM-26971] Fix DataDog and Crowdstrike Integration (#18024)
This commit is contained in:
@@ -4,15 +4,19 @@ import { OrganizationIntegrationServiceName } from "../organization-integration-
|
||||
export class DatadogConfiguration implements OrgIntegrationConfiguration {
|
||||
uri: string;
|
||||
apiKey: string;
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
|
||||
constructor(uri: string, apiKey: string, service: OrganizationIntegrationServiceName) {
|
||||
constructor(uri: string, apiKey: string, bw_serviceName: OrganizationIntegrationServiceName) {
|
||||
this.uri = uri;
|
||||
this.apiKey = apiKey;
|
||||
this.service = service;
|
||||
this.bw_serviceName = bw_serviceName;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify(this);
|
||||
toString() {
|
||||
return JSON.stringify({
|
||||
Uri: this.uri,
|
||||
ApiKey: this.apiKey,
|
||||
bw_serviceName: this.bw_serviceName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,21 @@ export class HecConfiguration implements OrgIntegrationConfiguration {
|
||||
uri: string;
|
||||
scheme = "Bearer";
|
||||
token: string;
|
||||
service: OrganizationIntegrationServiceName;
|
||||
service?: string;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
|
||||
constructor(uri: string, token: string, service: OrganizationIntegrationServiceName) {
|
||||
constructor(uri: string, token: string, bw_serviceName: OrganizationIntegrationServiceName) {
|
||||
this.uri = uri;
|
||||
this.token = token;
|
||||
this.service = service;
|
||||
this.bw_serviceName = bw_serviceName;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify(this);
|
||||
return JSON.stringify({
|
||||
Uri: this.uri,
|
||||
Scheme: this.scheme,
|
||||
Token: this.token,
|
||||
bw_serviceName: this.bw_serviceName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import { OrganizationIntegrationServiceName } from "../organization-integration-
|
||||
export class WebhookConfiguration implements OrgIntegrationConfiguration {
|
||||
propA: string;
|
||||
propB: string;
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
|
||||
constructor(propA: string, propB: string, service: OrganizationIntegrationServiceName) {
|
||||
constructor(propA: string, propB: string, bw_serviceName: OrganizationIntegrationServiceName) {
|
||||
this.propA = propA;
|
||||
this.propB = propB;
|
||||
this.service = service;
|
||||
this.bw_serviceName = bw_serviceName;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { OrganizationIntegrationType } from "./organization-integration-type";
|
||||
* Defines the structure for organization integration configuration
|
||||
*/
|
||||
export interface OrgIntegrationConfiguration {
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface OrgIntegrationConfiguration {
|
||||
* Defines the structure for organization integration template
|
||||
*/
|
||||
export interface OrgIntegrationTemplate {
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
@@ -28,24 +28,26 @@ export class OrgIntegrationBuilder {
|
||||
static buildHecConfiguration(
|
||||
uri: string,
|
||||
token: string,
|
||||
service: OrganizationIntegrationServiceName,
|
||||
bw_serviceName: OrganizationIntegrationServiceName,
|
||||
): OrgIntegrationConfiguration {
|
||||
return new HecConfiguration(uri, token, service);
|
||||
return new HecConfiguration(uri, token, bw_serviceName);
|
||||
}
|
||||
|
||||
static buildHecTemplate(
|
||||
index: string,
|
||||
service: OrganizationIntegrationServiceName,
|
||||
bw_serviceName: OrganizationIntegrationServiceName,
|
||||
): OrgIntegrationTemplate {
|
||||
return new HecTemplate(index, service);
|
||||
return new HecTemplate(index, bw_serviceName);
|
||||
}
|
||||
|
||||
static buildDataDogConfiguration(uri: string, apiKey: string): OrgIntegrationConfiguration {
|
||||
return new DatadogConfiguration(uri, apiKey, OrganizationIntegrationServiceName.Datadog);
|
||||
}
|
||||
|
||||
static buildDataDogTemplate(service: OrganizationIntegrationServiceName): OrgIntegrationTemplate {
|
||||
return new DatadogTemplate(service);
|
||||
static buildDataDogTemplate(
|
||||
bw_serviceName: OrganizationIntegrationServiceName,
|
||||
): OrgIntegrationTemplate {
|
||||
return new DatadogTemplate(bw_serviceName);
|
||||
}
|
||||
|
||||
static buildConfiguration(
|
||||
@@ -55,7 +57,7 @@ export class OrgIntegrationBuilder {
|
||||
switch (type) {
|
||||
case OrganizationIntegrationType.Hec: {
|
||||
const hecConfig = this.convertToJson<HecConfiguration>(configuration);
|
||||
return this.buildHecConfiguration(hecConfig.uri, hecConfig.token, hecConfig.service);
|
||||
return this.buildHecConfiguration(hecConfig.uri, hecConfig.token, hecConfig.bw_serviceName);
|
||||
}
|
||||
case OrganizationIntegrationType.Datadog: {
|
||||
const datadogConfig = this.convertToJson<DatadogConfiguration>(configuration);
|
||||
@@ -73,11 +75,11 @@ export class OrgIntegrationBuilder {
|
||||
switch (type) {
|
||||
case OrganizationIntegrationType.Hec: {
|
||||
const hecTemplate = this.convertToJson<HecTemplate>(template);
|
||||
return this.buildHecTemplate(hecTemplate.index, hecTemplate.service);
|
||||
return this.buildHecTemplate(hecTemplate.index, hecTemplate.bw_serviceName);
|
||||
}
|
||||
case OrganizationIntegrationType.Datadog: {
|
||||
const datadogTemplate = this.convertToJson<DatadogTemplate>(template);
|
||||
return this.buildDataDogTemplate(datadogTemplate.service);
|
||||
return this.buildDataDogTemplate(datadogTemplate.bw_serviceName);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unsupported integration type: ${type}`);
|
||||
@@ -86,9 +88,33 @@ export class OrgIntegrationBuilder {
|
||||
|
||||
private static convertToJson<T>(jsonString?: string): T {
|
||||
try {
|
||||
return JSON.parse(jsonString || "{}") as T;
|
||||
const parsed = JSON.parse(jsonString || "{}");
|
||||
return this.normalizePropertyCase(parsed) as T;
|
||||
} catch {
|
||||
throw new Error("Invalid integration configuration: JSON parse error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively normalizes object property names to camelCase
|
||||
* Converts the first character of each property to lowercase
|
||||
*/
|
||||
private static normalizePropertyCase(obj: any): any {
|
||||
if (obj === null || typeof obj !== "object") {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((item) => this.normalizePropertyCase(item));
|
||||
}
|
||||
|
||||
const normalized: any = {};
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
const normalizedKey = key.charAt(0).toLowerCase() + key.slice(1);
|
||||
normalized[normalizedKey] = this.normalizePropertyCase(obj[key]);
|
||||
}
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,54 @@ import { OrgIntegrationTemplate } from "../../integration-builder";
|
||||
import { OrganizationIntegrationServiceName } from "../../organization-integration-service-type";
|
||||
|
||||
export class DatadogTemplate implements OrgIntegrationTemplate {
|
||||
source_type_name = "Bitwarden";
|
||||
title: string = "#Title#";
|
||||
text: string =
|
||||
"ActingUser: #ActingUserId#\nUser: #UserId#\nEvent: #Type#\nOrganization: #OrganizationId#\nPolicyId: #PolicyId#\nIpAddress: #IpAddress#\nDomainName: #DomainName#\nCipherId: #CipherId#\n";
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
|
||||
constructor(service: OrganizationIntegrationServiceName) {
|
||||
this.service = service;
|
||||
this.bw_serviceName = service;
|
||||
}
|
||||
|
||||
private toJSON() {
|
||||
return {
|
||||
bw_serviceName: this.bw_serviceName,
|
||||
ddsource: "bitwarden",
|
||||
service: "event-logs",
|
||||
event: {
|
||||
service: "payments",
|
||||
object: "event",
|
||||
type: "#Type#",
|
||||
itemId: "#CipherId#",
|
||||
collectionId: "#CollectionId#",
|
||||
groupId: "#GroupId#",
|
||||
policyId: "#PolicyId#",
|
||||
memberId: "#UserId#",
|
||||
actingUserId: "#ActingUserId#",
|
||||
installationId: "#InstallationId#",
|
||||
date: "#DateIso8601#",
|
||||
device: "#DeviceType#",
|
||||
ipAddress: "#IpAddress#",
|
||||
secretId: "#SecretId#",
|
||||
projectId: "#ProjectId#",
|
||||
serviceAccountId: "#ServiceAccountId#",
|
||||
},
|
||||
enrichment_details: {
|
||||
actingUser: {
|
||||
name: "#ActingUserName#",
|
||||
email: "#ActingUserEmail#",
|
||||
type: "#ActingUserType#",
|
||||
},
|
||||
member: {
|
||||
name: "#UserName#",
|
||||
email: "#UserEmail#",
|
||||
type: "#UserType#",
|
||||
},
|
||||
group: {
|
||||
name: "#GroupName#",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify(this);
|
||||
return JSON.stringify(this.toJSON());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,19 @@ export class HecTemplate implements OrgIntegrationTemplate {
|
||||
event = "#EventMessage#";
|
||||
source = "Bitwarden";
|
||||
index: string;
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
|
||||
constructor(index: string, service: OrganizationIntegrationServiceName) {
|
||||
this.index = index;
|
||||
this.service = service;
|
||||
this.bw_serviceName = service;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify(this);
|
||||
return JSON.stringify({
|
||||
Event: this.event,
|
||||
Source: this.source,
|
||||
Index: this.index,
|
||||
bw_serviceName: this.bw_serviceName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import { OrganizationIntegrationServiceName } from "../../organization-integrati
|
||||
|
||||
// Added to reflect how future webhook integrations could be structured within the OrganizationIntegration
|
||||
export class WebhookTemplate implements OrgIntegrationTemplate {
|
||||
service: OrganizationIntegrationServiceName;
|
||||
bw_serviceName: OrganizationIntegrationServiceName;
|
||||
propA: string;
|
||||
propB: string;
|
||||
|
||||
constructor(service: OrganizationIntegrationServiceName, propA: string, propB: string) {
|
||||
this.service = service;
|
||||
constructor(bw_serviceName: OrganizationIntegrationServiceName, propA: string, propB: string) {
|
||||
this.bw_serviceName = bw_serviceName;
|
||||
this.propA = propA;
|
||||
this.propB = propB;
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ export class OrganizationIntegrationService {
|
||||
return new OrganizationIntegration(
|
||||
integrationResponse.id,
|
||||
integrationResponse.type,
|
||||
config.service,
|
||||
config.bw_serviceName,
|
||||
config,
|
||||
[integrationConfig],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user