@grc-claw/integration-marketplace 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IntegrationMarketplace.d.ts +32 -0
- package/dist/IntegrationMarketplace.js +165 -0
- package/dist/connectors/AWSCloudTrailConnector.d.ts +12 -0
- package/dist/connectors/AWSCloudTrailConnector.js +77 -0
- package/dist/connectors/AWSIAMConnector.d.ts +12 -0
- package/dist/connectors/AWSIAMConnector.js +90 -0
- package/dist/connectors/AWSS3Connector.d.ts +12 -0
- package/dist/connectors/AWSS3Connector.js +112 -0
- package/dist/connectors/AzureADConnector.d.ts +12 -0
- package/dist/connectors/AzureADConnector.js +115 -0
- package/dist/connectors/AzureSentinelConnector.d.ts +12 -0
- package/dist/connectors/AzureSentinelConnector.js +88 -0
- package/dist/connectors/BambooHRConnector.d.ts +12 -0
- package/dist/connectors/BambooHRConnector.js +84 -0
- package/dist/connectors/CrowdStrikeConnector.d.ts +12 -0
- package/dist/connectors/CrowdStrikeConnector.js +86 -0
- package/dist/connectors/DatadogConnector.d.ts +12 -0
- package/dist/connectors/DatadogConnector.js +110 -0
- package/dist/connectors/DockerHubConnector.d.ts +12 -0
- package/dist/connectors/DockerHubConnector.js +80 -0
- package/dist/connectors/GCPIAMConnector.d.ts +12 -0
- package/dist/connectors/GCPIAMConnector.js +98 -0
- package/dist/connectors/GCPSCCConnector.d.ts +12 -0
- package/dist/connectors/GCPSCCConnector.js +94 -0
- package/dist/connectors/GitHubActionsConnector.d.ts +12 -0
- package/dist/connectors/GitHubActionsConnector.js +104 -0
- package/dist/connectors/GitHubConnector.d.ts +12 -0
- package/dist/connectors/GitHubConnector.js +135 -0
- package/dist/connectors/GitLabConnector.d.ts +12 -0
- package/dist/connectors/GitLabConnector.js +101 -0
- package/dist/connectors/HubSpotConnector.d.ts +12 -0
- package/dist/connectors/HubSpotConnector.js +77 -0
- package/dist/connectors/JiraConnector.d.ts +12 -0
- package/dist/connectors/JiraConnector.js +103 -0
- package/dist/connectors/KubernetesConnector.d.ts +12 -0
- package/dist/connectors/KubernetesConnector.js +109 -0
- package/dist/connectors/OktaConnector.d.ts +12 -0
- package/dist/connectors/OktaConnector.js +123 -0
- package/dist/connectors/PagerDutyConnector.d.ts +12 -0
- package/dist/connectors/PagerDutyConnector.js +106 -0
- package/dist/connectors/QualysConnector.d.ts +12 -0
- package/dist/connectors/QualysConnector.js +96 -0
- package/dist/connectors/SalesforceConnector.d.ts +12 -0
- package/dist/connectors/SalesforceConnector.js +91 -0
- package/dist/connectors/SlackConnector.d.ts +12 -0
- package/dist/connectors/SlackConnector.js +109 -0
- package/dist/connectors/SnowflakeConnector.d.ts +12 -0
- package/dist/connectors/SnowflakeConnector.js +105 -0
- package/dist/connectors/SnykConnector.d.ts +12 -0
- package/dist/connectors/SnykConnector.js +84 -0
- package/dist/connectors/TerraformCloudConnector.d.ts +12 -0
- package/dist/connectors/TerraformCloudConnector.js +106 -0
- package/dist/connectors/index.d.ts +25 -0
- package/dist/connectors/index.js +25 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/index.test.d.ts +1 -0
- package/dist/index.test.js +138 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +8 -0
- package/package.json +26 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "sentinel-incidents",
|
|
5
|
+
name: "Sentinel Incidents",
|
|
6
|
+
description: "Fetch Microsoft Sentinel security incidents",
|
|
7
|
+
evidenceCategories: ["incident_management", "siem"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "sentinel-alerts",
|
|
11
|
+
name: "Sentinel Alerts",
|
|
12
|
+
description: "Fetch Sentinel alert rules and recent alerts",
|
|
13
|
+
evidenceCategories: ["monitoring", "detection"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export class AzureSentinelConnector {
|
|
17
|
+
id = "azure-sentinel";
|
|
18
|
+
name = "Microsoft Sentinel";
|
|
19
|
+
category = "siem";
|
|
20
|
+
authType = "oauth2";
|
|
21
|
+
capabilities = capabilities;
|
|
22
|
+
frameworks = ["SOC2", "ISO27001", "NIST_CSF"];
|
|
23
|
+
async getAccessToken(config) {
|
|
24
|
+
const resp = await fetch(`https://login.microsoftonline.com/${config.tenantId}/oauth2/v2.0/token`, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
27
|
+
body: new URLSearchParams({
|
|
28
|
+
grant_type: "client_credentials",
|
|
29
|
+
client_id: config.clientId || "",
|
|
30
|
+
client_secret: config.clientSecret || "",
|
|
31
|
+
scope: "https://management.azure.com/.default",
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
if (!resp.ok)
|
|
35
|
+
throw new Error(`Azure token ${resp.status}`);
|
|
36
|
+
const data = (await resp.json());
|
|
37
|
+
return data.access_token;
|
|
38
|
+
}
|
|
39
|
+
async testConnection(config) {
|
|
40
|
+
try {
|
|
41
|
+
const token = await this.getAccessToken(config);
|
|
42
|
+
const workspace = config.extra?.workspace || "default";
|
|
43
|
+
const resp = await fetch(`https://management.azure.com/subscriptions/${config.accountId}/resourceGroups/${config.extra?.resourceGroup || "default"}/providers/Microsoft.OperationalInsights/workspaces/${workspace}?api-version=2023-09-01`, { headers: { Authorization: `Bearer ${token}` } });
|
|
44
|
+
return resp.ok;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async collectEvidence(config) {
|
|
51
|
+
const artifacts = [];
|
|
52
|
+
const now = new Date().toISOString();
|
|
53
|
+
const token = await this.getAccessToken(config);
|
|
54
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
55
|
+
const workspace = config.extra?.workspace || "default";
|
|
56
|
+
const rg = config.extra?.resourceGroup || "default";
|
|
57
|
+
const base = `https://management.azure.com/subscriptions/${config.accountId}/resourceGroups/${rg}/providers/Microsoft.OperationalInsights/workspaces/${workspace}`;
|
|
58
|
+
const incidents = await fetch(`${base}/providers/Microsoft.SecurityInsights/incidents?api-version=2024-01-01&$top=100`, { headers }).then((r) => r.json());
|
|
59
|
+
artifacts.push({
|
|
60
|
+
id: generateEvidenceId(),
|
|
61
|
+
connectorId: this.id,
|
|
62
|
+
capabilityId: "sentinel-incidents",
|
|
63
|
+
timestamp: now,
|
|
64
|
+
hash: hashEvidence(incidents),
|
|
65
|
+
framework: "SOC2",
|
|
66
|
+
controlId: "CC7.3",
|
|
67
|
+
source: "azure-sentinel/incidents",
|
|
68
|
+
status: "unknown",
|
|
69
|
+
data: { incidentCount: (incidents.value || []).length, incidents: incidents.value },
|
|
70
|
+
metadata: { workspace },
|
|
71
|
+
});
|
|
72
|
+
const alerts = await fetch(`${base}/providers/Microsoft.SecurityInsights/alertRules?api-version=2024-01-01`, { headers }).then((r) => r.json());
|
|
73
|
+
artifacts.push({
|
|
74
|
+
id: generateEvidenceId(),
|
|
75
|
+
connectorId: this.id,
|
|
76
|
+
capabilityId: "sentinel-alerts",
|
|
77
|
+
timestamp: now,
|
|
78
|
+
hash: hashEvidence(alerts),
|
|
79
|
+
framework: "SOC2",
|
|
80
|
+
controlId: "CC7.2",
|
|
81
|
+
source: "azure-sentinel/alertRules",
|
|
82
|
+
status: (alerts.value || []).length > 0 ? "compliant" : "non_compliant",
|
|
83
|
+
data: { alertRuleCount: (alerts.value || []).length },
|
|
84
|
+
metadata: { workspace },
|
|
85
|
+
});
|
|
86
|
+
return artifacts;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class BambooHRConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "bamboohr";
|
|
4
|
+
readonly name = "BambooHR";
|
|
5
|
+
readonly category: "hr";
|
|
6
|
+
readonly authType: "api_key";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private fetchApi;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "bhr-onboarding",
|
|
5
|
+
name: "Employee Onboarding",
|
|
6
|
+
description: "Fetch recent employee onboarding records and access provisioning",
|
|
7
|
+
evidenceCategories: ["hr", "access_provisioning"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "bhr-offboarding",
|
|
11
|
+
name: "Employee Offboarding",
|
|
12
|
+
description: "Fetch employee offboarding records and access revocations",
|
|
13
|
+
evidenceCategories: ["hr", "access_revocation"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export class BambooHRConnector {
|
|
17
|
+
id = "bamboohr";
|
|
18
|
+
name = "BambooHR";
|
|
19
|
+
category = "hr";
|
|
20
|
+
authType = "api_key";
|
|
21
|
+
capabilities = capabilities;
|
|
22
|
+
frameworks = ["SOC2", "ISO27001"];
|
|
23
|
+
async fetchApi(config, endpoint) {
|
|
24
|
+
const domain = config.extra?.domain || "yourcompany";
|
|
25
|
+
const base = config.baseUrl || `https://api.bamboohr.com/api/gate.php/${domain}`;
|
|
26
|
+
const resp = await fetch(`${base}${endpoint}`, {
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `Basic ${Buffer.from(`${config.apiToken}:x`).toString("base64")}`,
|
|
29
|
+
Accept: "application/json",
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
if (!resp.ok)
|
|
33
|
+
throw new Error(`BambooHR API ${resp.status}: ${resp.statusText}`);
|
|
34
|
+
return (await resp.json());
|
|
35
|
+
}
|
|
36
|
+
async testConnection(config) {
|
|
37
|
+
try {
|
|
38
|
+
await this.fetchApi(config, "/v1/meta/fields");
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async collectEvidence(config) {
|
|
46
|
+
const artifacts = [];
|
|
47
|
+
const now = new Date().toISOString();
|
|
48
|
+
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
|
|
49
|
+
.toISOString()
|
|
50
|
+
.split("T")[0];
|
|
51
|
+
const employees = await this.fetchApi(config, `/v1/employees/directory?fields=id,employmentEndDate,employmentStatus,hireDate`).catch(() => ({ employees: [] }));
|
|
52
|
+
const empList = (employees.employees || []);
|
|
53
|
+
const terminated = empList.filter((e) => e.employmentStatus === "Terminated" &&
|
|
54
|
+
e.employmentEndDate >= thirtyDaysAgo);
|
|
55
|
+
artifacts.push({
|
|
56
|
+
id: generateEvidenceId(),
|
|
57
|
+
connectorId: this.id,
|
|
58
|
+
capabilityId: "bhr-offboarding",
|
|
59
|
+
timestamp: now,
|
|
60
|
+
hash: hashEvidence({ totalEmployees: empList.length, recentTerminations: terminated.length }),
|
|
61
|
+
framework: "SOC2",
|
|
62
|
+
controlId: "CC6.2",
|
|
63
|
+
source: "bamboohr/directory",
|
|
64
|
+
status: "unknown",
|
|
65
|
+
data: { totalEmployees: empList.length, recentTerminations: terminated.length },
|
|
66
|
+
metadata: { domain: config.extra?.domain || "" },
|
|
67
|
+
});
|
|
68
|
+
const newHires = empList.filter((e) => e.hireDate >= thirtyDaysAgo);
|
|
69
|
+
artifacts.push({
|
|
70
|
+
id: generateEvidenceId(),
|
|
71
|
+
connectorId: this.id,
|
|
72
|
+
capabilityId: "bhr-onboarding",
|
|
73
|
+
timestamp: now,
|
|
74
|
+
hash: hashEvidence({ newHires: newHires.length }),
|
|
75
|
+
framework: "SOC2",
|
|
76
|
+
controlId: "CC6.1",
|
|
77
|
+
source: "bamboohr/directory",
|
|
78
|
+
status: "unknown",
|
|
79
|
+
data: { newHiresLast30Days: newHires.length },
|
|
80
|
+
metadata: { domain: config.extra?.domain || "" },
|
|
81
|
+
});
|
|
82
|
+
return artifacts;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class CrowdStrikeConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "crowdstrike";
|
|
4
|
+
readonly name = "CrowdStrike Falcon";
|
|
5
|
+
readonly category: "endpoint";
|
|
6
|
+
readonly authType: "oauth2";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private getAccessToken;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "cs-device-posture",
|
|
5
|
+
name: "Device Posture",
|
|
6
|
+
description: "Fetch CrowdStrike device posture assessments and compliance",
|
|
7
|
+
evidenceCategories: ["endpoint_security", "device_management"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "cs-threat-detections",
|
|
11
|
+
name: "Threat Detections",
|
|
12
|
+
description: "Fetch CrowdStrike Falcon threat detections",
|
|
13
|
+
evidenceCategories: ["threat_detection", "incident_management"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export class CrowdStrikeConnector {
|
|
17
|
+
id = "crowdstrike";
|
|
18
|
+
name = "CrowdStrike Falcon";
|
|
19
|
+
category = "endpoint";
|
|
20
|
+
authType = "oauth2";
|
|
21
|
+
capabilities = capabilities;
|
|
22
|
+
frameworks = ["SOC2", "ISO27001", "NIST_CSF"];
|
|
23
|
+
async getAccessToken(config) {
|
|
24
|
+
const resp = await fetch("https://api.crowdstrike.com/oauth2/token", {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
27
|
+
body: new URLSearchParams({
|
|
28
|
+
client_id: config.clientId || "",
|
|
29
|
+
client_secret: config.clientSecret || "",
|
|
30
|
+
}),
|
|
31
|
+
});
|
|
32
|
+
if (!resp.ok)
|
|
33
|
+
throw new Error(`CrowdStrike token ${resp.status}`);
|
|
34
|
+
const data = (await resp.json());
|
|
35
|
+
return data.access_token;
|
|
36
|
+
}
|
|
37
|
+
async testConnection(config) {
|
|
38
|
+
try {
|
|
39
|
+
const token = await this.getAccessToken(config);
|
|
40
|
+
const resp = await fetch("https://api.crowdstrike.com/devices/queries/devices/v1?limit=1", {
|
|
41
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
42
|
+
});
|
|
43
|
+
return resp.ok;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async collectEvidence(config) {
|
|
50
|
+
const artifacts = [];
|
|
51
|
+
const now = new Date().toISOString();
|
|
52
|
+
const token = await this.getAccessToken(config);
|
|
53
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
54
|
+
const devices = await fetch("https://api.crowdstrike.com/devices/queries/devices/v1?limit=100", { headers }).then((r) => r.json());
|
|
55
|
+
const deviceIds = (devices.resources || []);
|
|
56
|
+
artifacts.push({
|
|
57
|
+
id: generateEvidenceId(),
|
|
58
|
+
connectorId: this.id,
|
|
59
|
+
capabilityId: "cs-device-posture",
|
|
60
|
+
timestamp: now,
|
|
61
|
+
hash: hashEvidence({ deviceCount: deviceIds.length }),
|
|
62
|
+
framework: "SOC2",
|
|
63
|
+
controlId: "CC6.8",
|
|
64
|
+
source: "crowdstrike/devices",
|
|
65
|
+
status: deviceIds.length > 0 ? "compliant" : "non_compliant",
|
|
66
|
+
data: { deviceCount: deviceIds.length },
|
|
67
|
+
metadata: {},
|
|
68
|
+
});
|
|
69
|
+
const detections = await fetch("https://api.crowdstrike.com/detects/queries/detects/v1?limit=100&sort=created_timestamp|desc", { headers }).then((r) => r.json());
|
|
70
|
+
const detectionIds = (detections.resources || []);
|
|
71
|
+
artifacts.push({
|
|
72
|
+
id: generateEvidenceId(),
|
|
73
|
+
connectorId: this.id,
|
|
74
|
+
capabilityId: "cs-threat-detections",
|
|
75
|
+
timestamp: now,
|
|
76
|
+
hash: hashEvidence({ detectionCount: detectionIds.length }),
|
|
77
|
+
framework: "SOC2",
|
|
78
|
+
controlId: "CC7.2",
|
|
79
|
+
source: "crowdstrike/detects",
|
|
80
|
+
status: "unknown",
|
|
81
|
+
data: { detectionCount: detectionIds.length },
|
|
82
|
+
metadata: {},
|
|
83
|
+
});
|
|
84
|
+
return artifacts;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class DatadogConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "datadog";
|
|
4
|
+
readonly name = "Datadog";
|
|
5
|
+
readonly category: "monitoring";
|
|
6
|
+
readonly authType: "api_key";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private fetchApi;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "dd-monitors",
|
|
5
|
+
name: "Monitors",
|
|
6
|
+
description: "Fetch Datadog monitor configurations and alert states",
|
|
7
|
+
evidenceCategories: ["monitoring", "configuration"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "dd-alerts",
|
|
11
|
+
name: "Alerts",
|
|
12
|
+
description: "Fetch triggered alerts and alert rule configurations",
|
|
13
|
+
evidenceCategories: ["monitoring", "incident_detection"],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "dd-apm",
|
|
17
|
+
name: "APM Configurations",
|
|
18
|
+
description: "Fetch APM service configurations and security tracking",
|
|
19
|
+
evidenceCategories: ["application_security", "monitoring"],
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
export class DatadogConnector {
|
|
23
|
+
id = "datadog";
|
|
24
|
+
name = "Datadog";
|
|
25
|
+
category = "monitoring";
|
|
26
|
+
authType = "api_key";
|
|
27
|
+
capabilities = capabilities;
|
|
28
|
+
frameworks = ["SOC2", "ISO27001"];
|
|
29
|
+
async fetchApi(config, endpoint, method = "GET") {
|
|
30
|
+
const site = config.extra?.site || "datadoghq.com";
|
|
31
|
+
const base = `https://api.${site}`;
|
|
32
|
+
const resp = await fetch(`${base}${endpoint}`, {
|
|
33
|
+
method,
|
|
34
|
+
headers: {
|
|
35
|
+
"DD-API-KEY": config.apiToken || "",
|
|
36
|
+
"DD-APPLICATION-KEY": config.extra?.appKey || "",
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
if (!resp.ok)
|
|
41
|
+
throw new Error(`Datadog API ${resp.status}: ${resp.statusText}`);
|
|
42
|
+
return (await resp.json());
|
|
43
|
+
}
|
|
44
|
+
async testConnection(config) {
|
|
45
|
+
try {
|
|
46
|
+
await this.fetchApi(config, "/api/v1/validate");
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async collectEvidence(config) {
|
|
54
|
+
const artifacts = [];
|
|
55
|
+
const now = new Date().toISOString();
|
|
56
|
+
const monitors = await this.fetchApi(config, "/api/v1/monitor");
|
|
57
|
+
const monitorList = Array.isArray(monitors) ? monitors : [];
|
|
58
|
+
const activeMonitors = monitorList.filter((m) => m.overall_state === "OK");
|
|
59
|
+
artifacts.push({
|
|
60
|
+
id: generateEvidenceId(),
|
|
61
|
+
connectorId: this.id,
|
|
62
|
+
capabilityId: "dd-monitors",
|
|
63
|
+
timestamp: now,
|
|
64
|
+
hash: hashEvidence({ monitorCount: monitorList.length }),
|
|
65
|
+
framework: "SOC2",
|
|
66
|
+
controlId: "CC7.1",
|
|
67
|
+
source: "datadog/monitors",
|
|
68
|
+
status: monitorList.length > 0 ? "compliant" : "non_compliant",
|
|
69
|
+
data: {
|
|
70
|
+
totalMonitors: monitorList.length,
|
|
71
|
+
activeMonitors: activeMonitors.length,
|
|
72
|
+
alertMonitors: monitorList.length - activeMonitors.length,
|
|
73
|
+
},
|
|
74
|
+
metadata: { site: config.extra?.site || "datadoghq.com" },
|
|
75
|
+
});
|
|
76
|
+
const alerts = await this.fetchApi(config, "/api/v1/alerts").catch(() => []);
|
|
77
|
+
const alertList = Array.isArray(alerts) ? alerts : [];
|
|
78
|
+
artifacts.push({
|
|
79
|
+
id: generateEvidenceId(),
|
|
80
|
+
connectorId: this.id,
|
|
81
|
+
capabilityId: "dd-alerts",
|
|
82
|
+
timestamp: now,
|
|
83
|
+
hash: hashEvidence({ alertCount: alertList.length }),
|
|
84
|
+
framework: "SOC2",
|
|
85
|
+
controlId: "CC7.2",
|
|
86
|
+
source: "datadog/alerts",
|
|
87
|
+
status: "unknown",
|
|
88
|
+
data: { alertRuleCount: alertList.length },
|
|
89
|
+
metadata: { site: config.extra?.site || "datadoghq.com" },
|
|
90
|
+
});
|
|
91
|
+
const services = await this.fetchApi(config, "/api/v1/services").catch(() => ({
|
|
92
|
+
services: [],
|
|
93
|
+
}));
|
|
94
|
+
const serviceList = (services.services || []);
|
|
95
|
+
artifacts.push({
|
|
96
|
+
id: generateEvidenceId(),
|
|
97
|
+
connectorId: this.id,
|
|
98
|
+
capabilityId: "dd-apm",
|
|
99
|
+
timestamp: now,
|
|
100
|
+
hash: hashEvidence({ serviceCount: serviceList.length }),
|
|
101
|
+
framework: "ISO27001",
|
|
102
|
+
controlId: "A.12.4.1",
|
|
103
|
+
source: "datadog/services",
|
|
104
|
+
status: "unknown",
|
|
105
|
+
data: { serviceCount: serviceList.length },
|
|
106
|
+
metadata: { site: config.extra?.site || "datadoghq.com" },
|
|
107
|
+
});
|
|
108
|
+
return artifacts;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class DockerHubConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "docker-hub";
|
|
4
|
+
readonly name = "Docker Hub";
|
|
5
|
+
readonly category: "container";
|
|
6
|
+
readonly authType: "bearer_token";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private fetchApi;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "docker-image-scans",
|
|
5
|
+
name: "Image Scans",
|
|
6
|
+
description: "Fetch Docker Hub image vulnerability scan results",
|
|
7
|
+
evidenceCategories: ["container_security", "vulnerability_management"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "docker-vuln-reports",
|
|
11
|
+
name: "Vulnerability Reports",
|
|
12
|
+
description: "Fetch detailed vulnerability reports per image tag",
|
|
13
|
+
evidenceCategories: ["vulnerability_management", "supply_chain"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export class DockerHubConnector {
|
|
17
|
+
id = "docker-hub";
|
|
18
|
+
name = "Docker Hub";
|
|
19
|
+
category = "container";
|
|
20
|
+
authType = "bearer_token";
|
|
21
|
+
capabilities = capabilities;
|
|
22
|
+
frameworks = ["SOC2", "ISO27001", "NIST_CSF"];
|
|
23
|
+
async fetchApi(config, endpoint) {
|
|
24
|
+
const base = config.baseUrl || "https://hub.docker.com/v2";
|
|
25
|
+
const resp = await fetch(`${base}${endpoint}`, {
|
|
26
|
+
headers: { Authorization: `Bearer ${config.apiToken}` },
|
|
27
|
+
});
|
|
28
|
+
if (!resp.ok)
|
|
29
|
+
throw new Error(`Docker Hub API ${resp.status}: ${resp.statusText}`);
|
|
30
|
+
return (await resp.json());
|
|
31
|
+
}
|
|
32
|
+
async testConnection(config) {
|
|
33
|
+
try {
|
|
34
|
+
await this.fetchApi(config, "/user/");
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async collectEvidence(config) {
|
|
42
|
+
const artifacts = [];
|
|
43
|
+
const now = new Date().toISOString();
|
|
44
|
+
const namespace = config.extra?.namespace || "library";
|
|
45
|
+
const repo = config.extra?.repo || "nginx";
|
|
46
|
+
const images = await this.fetchApi(config, `/repositories/${namespace}/${repo}/tags?page_size=50`).catch(() => ({ results: [] }));
|
|
47
|
+
const tagList = (images.results || []);
|
|
48
|
+
artifacts.push({
|
|
49
|
+
id: generateEvidenceId(),
|
|
50
|
+
connectorId: this.id,
|
|
51
|
+
capabilityId: "docker-image-scans",
|
|
52
|
+
timestamp: now,
|
|
53
|
+
hash: hashEvidence({ tagCount: tagList.length }),
|
|
54
|
+
framework: "SOC2",
|
|
55
|
+
controlId: "CC6.8",
|
|
56
|
+
source: `dockerhub/${namespace}/${repo}/tags`,
|
|
57
|
+
status: tagList.length > 0 ? "compliant" : "non_compliant",
|
|
58
|
+
data: { tagCount: tagList.length, tags: tagList.map((t) => t.name) },
|
|
59
|
+
metadata: { namespace, repo },
|
|
60
|
+
});
|
|
61
|
+
const vulnReport = tagList.length > 0
|
|
62
|
+
? await this.fetchApi(config, `/repositories/${namespace}/${repo}/tags/${tagList[0].name}/vulnerabilities`).catch(() => ({ vulnerabilities: [] }))
|
|
63
|
+
: { vulnerabilities: [] };
|
|
64
|
+
const vulns = (vulnReport.vulnerabilities || []);
|
|
65
|
+
artifacts.push({
|
|
66
|
+
id: generateEvidenceId(),
|
|
67
|
+
connectorId: this.id,
|
|
68
|
+
capabilityId: "docker-vuln-reports",
|
|
69
|
+
timestamp: now,
|
|
70
|
+
hash: hashEvidence({ vulnCount: vulns.length }),
|
|
71
|
+
framework: "ISO27001",
|
|
72
|
+
controlId: "A.12.6.1",
|
|
73
|
+
source: `dockerhub/${namespace}/${repo}/vulnerabilities`,
|
|
74
|
+
status: vulns.length === 0 ? "compliant" : "non_compliant",
|
|
75
|
+
data: { totalVulnerabilities: vulns.length },
|
|
76
|
+
metadata: { namespace, repo },
|
|
77
|
+
});
|
|
78
|
+
return artifacts;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class GCPIAMConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "gcp-iam";
|
|
4
|
+
readonly name = "GCP IAM";
|
|
5
|
+
readonly category: "cloud_provider";
|
|
6
|
+
readonly authType: "service_account";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private getAccessToken;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { hashEvidence, generateEvidenceId } from "../types.js";
|
|
2
|
+
const capabilities = [
|
|
3
|
+
{
|
|
4
|
+
id: "gcp-iam-bindings",
|
|
5
|
+
name: "IAM Bindings",
|
|
6
|
+
description: "Fetch GCP project IAM policy bindings",
|
|
7
|
+
evidenceCategories: ["access_control"],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
id: "gcp-iam-audit",
|
|
11
|
+
name: "IAM Audit Logs",
|
|
12
|
+
description: "Fetch admin activity and data access audit logs",
|
|
13
|
+
evidenceCategories: ["logging", "audit"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export class GCPIAMConnector {
|
|
17
|
+
id = "gcp-iam";
|
|
18
|
+
name = "GCP IAM";
|
|
19
|
+
category = "cloud_provider";
|
|
20
|
+
authType = "service_account";
|
|
21
|
+
capabilities = capabilities;
|
|
22
|
+
frameworks = [
|
|
23
|
+
"SOC2",
|
|
24
|
+
"ISO27001",
|
|
25
|
+
"NIST_CSF",
|
|
26
|
+
"HIPAA",
|
|
27
|
+
];
|
|
28
|
+
async getAccessToken(config) {
|
|
29
|
+
const now = Math.floor(Date.now() / 1000);
|
|
30
|
+
const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
|
|
31
|
+
const payload = Buffer.from(JSON.stringify({
|
|
32
|
+
iss: config.clientId,
|
|
33
|
+
scope: "https://www.googleapis.com/auth/cloud-platform",
|
|
34
|
+
aud: "https://oauth2.googleapis.com/token",
|
|
35
|
+
exp: now + 3600,
|
|
36
|
+
iat: now,
|
|
37
|
+
})).toString("base64url");
|
|
38
|
+
const jwt = `${header}.${payload}.signature`;
|
|
39
|
+
const resp = await fetch("https://oauth2.googleapis.com/token", {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
42
|
+
body: new URLSearchParams({
|
|
43
|
+
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
44
|
+
assertion: jwt,
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
if (!resp.ok)
|
|
48
|
+
throw new Error(`GCP token ${resp.status}`);
|
|
49
|
+
const data = (await resp.json());
|
|
50
|
+
return data.access_token;
|
|
51
|
+
}
|
|
52
|
+
async testConnection(config) {
|
|
53
|
+
try {
|
|
54
|
+
const token = await this.getAccessToken(config);
|
|
55
|
+
const resp = await fetch(`https://cloudresourcemanager.googleapis.com/v1/projects/${config.accountId}`, { headers: { Authorization: `Bearer ${token}` } });
|
|
56
|
+
return resp.ok;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async collectEvidence(config) {
|
|
63
|
+
const artifacts = [];
|
|
64
|
+
const now = new Date().toISOString();
|
|
65
|
+
const token = await this.getAccessToken(config);
|
|
66
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
67
|
+
const iam = await fetch(`https://cloudresourcemanager.googleapis.com/v1/projects/${config.accountId}:getIamPolicy`, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: "{}" }).then((r) => r.json());
|
|
68
|
+
const bindings = (iam.bindings || []);
|
|
69
|
+
artifacts.push({
|
|
70
|
+
id: generateEvidenceId(),
|
|
71
|
+
connectorId: this.id,
|
|
72
|
+
capabilityId: "gcp-iam-bindings",
|
|
73
|
+
timestamp: now,
|
|
74
|
+
hash: hashEvidence(iam),
|
|
75
|
+
framework: "SOC2",
|
|
76
|
+
controlId: "CC6.1",
|
|
77
|
+
source: `gcp/${config.accountId}/getIamPolicy`,
|
|
78
|
+
status: bindings.length > 0 ? "compliant" : "non_compliant",
|
|
79
|
+
data: { bindingCount: bindings.length, bindings },
|
|
80
|
+
metadata: { projectId: config.accountId || "" },
|
|
81
|
+
});
|
|
82
|
+
const auditLogs = await fetch(`https://logging.googleapis.com/v2/entries:list?filter=logName%3D%22projects%2F${config.accountId}%2Flogs%2Fcloudaudit.googleapis.com%252Factivity%22&pageSize=50`, { headers }).then((r) => r.json());
|
|
83
|
+
artifacts.push({
|
|
84
|
+
id: generateEvidenceId(),
|
|
85
|
+
connectorId: this.id,
|
|
86
|
+
capabilityId: "gcp-iam-audit",
|
|
87
|
+
timestamp: now,
|
|
88
|
+
hash: hashEvidence(auditLogs),
|
|
89
|
+
framework: "SOC2",
|
|
90
|
+
controlId: "CC7.1",
|
|
91
|
+
source: `gcp/${config.accountId}/auditLogs`,
|
|
92
|
+
status: (auditLogs.entries || []).length > 0 ? "compliant" : "non_compliant",
|
|
93
|
+
data: { logCount: (auditLogs.entries || []).length },
|
|
94
|
+
metadata: { projectId: config.accountId || "" },
|
|
95
|
+
});
|
|
96
|
+
return artifacts;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
|
|
2
|
+
export declare class GCPSCCConnector implements IntegrationConnector {
|
|
3
|
+
readonly id = "gcp-scc";
|
|
4
|
+
readonly name = "GCP Security Command Center";
|
|
5
|
+
readonly category: "cloud_provider";
|
|
6
|
+
readonly authType: "service_account";
|
|
7
|
+
readonly capabilities: IntegrationCapability[];
|
|
8
|
+
readonly frameworks: ComplianceFramework[];
|
|
9
|
+
private getAccessToken;
|
|
10
|
+
testConnection(config: ConnectorConfig): Promise<boolean>;
|
|
11
|
+
collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
|
|
12
|
+
}
|