@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.
Files changed (61) hide show
  1. package/dist/IntegrationMarketplace.d.ts +32 -0
  2. package/dist/IntegrationMarketplace.js +165 -0
  3. package/dist/connectors/AWSCloudTrailConnector.d.ts +12 -0
  4. package/dist/connectors/AWSCloudTrailConnector.js +77 -0
  5. package/dist/connectors/AWSIAMConnector.d.ts +12 -0
  6. package/dist/connectors/AWSIAMConnector.js +90 -0
  7. package/dist/connectors/AWSS3Connector.d.ts +12 -0
  8. package/dist/connectors/AWSS3Connector.js +112 -0
  9. package/dist/connectors/AzureADConnector.d.ts +12 -0
  10. package/dist/connectors/AzureADConnector.js +115 -0
  11. package/dist/connectors/AzureSentinelConnector.d.ts +12 -0
  12. package/dist/connectors/AzureSentinelConnector.js +88 -0
  13. package/dist/connectors/BambooHRConnector.d.ts +12 -0
  14. package/dist/connectors/BambooHRConnector.js +84 -0
  15. package/dist/connectors/CrowdStrikeConnector.d.ts +12 -0
  16. package/dist/connectors/CrowdStrikeConnector.js +86 -0
  17. package/dist/connectors/DatadogConnector.d.ts +12 -0
  18. package/dist/connectors/DatadogConnector.js +110 -0
  19. package/dist/connectors/DockerHubConnector.d.ts +12 -0
  20. package/dist/connectors/DockerHubConnector.js +80 -0
  21. package/dist/connectors/GCPIAMConnector.d.ts +12 -0
  22. package/dist/connectors/GCPIAMConnector.js +98 -0
  23. package/dist/connectors/GCPSCCConnector.d.ts +12 -0
  24. package/dist/connectors/GCPSCCConnector.js +94 -0
  25. package/dist/connectors/GitHubActionsConnector.d.ts +12 -0
  26. package/dist/connectors/GitHubActionsConnector.js +104 -0
  27. package/dist/connectors/GitHubConnector.d.ts +12 -0
  28. package/dist/connectors/GitHubConnector.js +135 -0
  29. package/dist/connectors/GitLabConnector.d.ts +12 -0
  30. package/dist/connectors/GitLabConnector.js +101 -0
  31. package/dist/connectors/HubSpotConnector.d.ts +12 -0
  32. package/dist/connectors/HubSpotConnector.js +77 -0
  33. package/dist/connectors/JiraConnector.d.ts +12 -0
  34. package/dist/connectors/JiraConnector.js +103 -0
  35. package/dist/connectors/KubernetesConnector.d.ts +12 -0
  36. package/dist/connectors/KubernetesConnector.js +109 -0
  37. package/dist/connectors/OktaConnector.d.ts +12 -0
  38. package/dist/connectors/OktaConnector.js +123 -0
  39. package/dist/connectors/PagerDutyConnector.d.ts +12 -0
  40. package/dist/connectors/PagerDutyConnector.js +106 -0
  41. package/dist/connectors/QualysConnector.d.ts +12 -0
  42. package/dist/connectors/QualysConnector.js +96 -0
  43. package/dist/connectors/SalesforceConnector.d.ts +12 -0
  44. package/dist/connectors/SalesforceConnector.js +91 -0
  45. package/dist/connectors/SlackConnector.d.ts +12 -0
  46. package/dist/connectors/SlackConnector.js +109 -0
  47. package/dist/connectors/SnowflakeConnector.d.ts +12 -0
  48. package/dist/connectors/SnowflakeConnector.js +105 -0
  49. package/dist/connectors/SnykConnector.d.ts +12 -0
  50. package/dist/connectors/SnykConnector.js +84 -0
  51. package/dist/connectors/TerraformCloudConnector.d.ts +12 -0
  52. package/dist/connectors/TerraformCloudConnector.js +106 -0
  53. package/dist/connectors/index.d.ts +25 -0
  54. package/dist/connectors/index.js +25 -0
  55. package/dist/index.d.ts +5 -0
  56. package/dist/index.js +3 -0
  57. package/dist/index.test.d.ts +1 -0
  58. package/dist/index.test.js +138 -0
  59. package/dist/types.d.ts +57 -0
  60. package/dist/types.js +8 -0
  61. package/package.json +26 -0
@@ -0,0 +1,103 @@
1
+ import { hashEvidence, generateEvidenceId } from "../types.js";
2
+ const capabilities = [
3
+ {
4
+ id: "jira-projects",
5
+ name: "Jira Projects",
6
+ description: "Fetch Jira project configurations and permissions",
7
+ evidenceCategories: ["project_management", "access_control"],
8
+ },
9
+ {
10
+ id: "jira-workflows",
11
+ name: "Workflows",
12
+ description: "Fetch workflow configurations and approval gates",
13
+ evidenceCategories: ["change_management"],
14
+ },
15
+ {
16
+ id: "jira-sla",
17
+ name: "SLA Compliance",
18
+ description: "Fetch SLA compliance metrics and breach history",
19
+ evidenceCategories: ["service_management"],
20
+ },
21
+ ];
22
+ export class JiraConnector {
23
+ id = "jira";
24
+ name = "Jira";
25
+ category = "project_management";
26
+ authType = "basic_auth";
27
+ capabilities = capabilities;
28
+ frameworks = ["SOC2", "ISO27001"];
29
+ async fetchApi(config, endpoint) {
30
+ const base = config.baseUrl || "https://your-domain.atlassian.net";
31
+ const resp = await fetch(`${base}/rest/api/3${endpoint}`, {
32
+ headers: {
33
+ Authorization: `Basic ${Buffer.from(`${config.clientId}:${config.apiToken}`).toString("base64")}`,
34
+ Accept: "application/json",
35
+ },
36
+ });
37
+ if (!resp.ok)
38
+ throw new Error(`Jira API ${resp.status}: ${resp.statusText}`);
39
+ return (await resp.json());
40
+ }
41
+ async testConnection(config) {
42
+ try {
43
+ await this.fetchApi(config, "/myself");
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ async collectEvidence(config) {
51
+ const artifacts = [];
52
+ const now = new Date().toISOString();
53
+ const projects = await this.fetchApi(config, "/project");
54
+ const projectList = Array.isArray(projects) ? projects : [];
55
+ artifacts.push({
56
+ id: generateEvidenceId(),
57
+ connectorId: this.id,
58
+ capabilityId: "jira-projects",
59
+ timestamp: now,
60
+ hash: hashEvidence({ projects: projectList.map((p) => ({ id: p.id, key: p.key })) }),
61
+ framework: "SOC2",
62
+ controlId: "CC8.1",
63
+ source: "jira/projects",
64
+ status: "unknown",
65
+ data: { projectCount: projectList.length },
66
+ metadata: { domain: config.baseUrl || "" },
67
+ });
68
+ const workflows = await fetch(`${config.baseUrl || "https://your-domain.atlassian.net"}/rest/api/3/workflow`, {
69
+ headers: {
70
+ Authorization: `Basic ${Buffer.from(`${config.clientId}:${config.apiToken}`).toString("base64")}`,
71
+ Accept: "application/json",
72
+ },
73
+ }).then((r) => r.json());
74
+ artifacts.push({
75
+ id: generateEvidenceId(),
76
+ connectorId: this.id,
77
+ capabilityId: "jira-workflows",
78
+ timestamp: now,
79
+ hash: hashEvidence(workflows),
80
+ framework: "SOC2",
81
+ controlId: "CC8.1",
82
+ source: "jira/workflows",
83
+ status: "unknown",
84
+ data: { workflows },
85
+ metadata: { domain: config.baseUrl || "" },
86
+ });
87
+ const issues = await this.fetchApi(config, "/search?jql=issuetype=Story&maxResults=0&expand=names").catch(() => ({ total: 0 }));
88
+ artifacts.push({
89
+ id: generateEvidenceId(),
90
+ connectorId: this.id,
91
+ capabilityId: "jira-sla",
92
+ timestamp: now,
93
+ hash: hashEvidence(issues),
94
+ framework: "ISO27001",
95
+ controlId: "A.12.1.4",
96
+ source: "jira/search",
97
+ status: "unknown",
98
+ data: { totalIssues: issues.total || 0 },
99
+ metadata: { domain: config.baseUrl || "" },
100
+ });
101
+ return artifacts;
102
+ }
103
+ }
@@ -0,0 +1,12 @@
1
+ import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
2
+ export declare class KubernetesConnector implements IntegrationConnector {
3
+ readonly id = "kubernetes";
4
+ readonly name = "Kubernetes";
5
+ readonly category: "infrastructure";
6
+ readonly authType: "bearer_token";
7
+ readonly capabilities: IntegrationCapability[];
8
+ readonly frameworks: ComplianceFramework[];
9
+ private fetchK8s;
10
+ testConnection(config: ConnectorConfig): Promise<boolean>;
11
+ collectEvidence(config: ConnectorConfig): Promise<EvidenceArtifact[]>;
12
+ }
@@ -0,0 +1,109 @@
1
+ import { hashEvidence, generateEvidenceId } from "../types.js";
2
+ const capabilities = [
3
+ {
4
+ id: "k8s-rbac",
5
+ name: "RBAC Policies",
6
+ description: "Fetch Kubernetes ClusterRole, ClusterRoleBinding, and Role data",
7
+ evidenceCategories: ["access_control", "authorization"],
8
+ },
9
+ {
10
+ id: "k8s-network-policies",
11
+ name: "Network Policies",
12
+ description: "Fetch Kubernetes NetworkPolicy resources",
13
+ evidenceCategories: ["network_security"],
14
+ },
15
+ {
16
+ id: "k8s-pod-security",
17
+ name: "Pod Security",
18
+ description: "Fetch Pod Security Standards and PSP/PSA configurations",
19
+ evidenceCategories: ["container_security", "configuration"],
20
+ },
21
+ ];
22
+ export class KubernetesConnector {
23
+ id = "kubernetes";
24
+ name = "Kubernetes";
25
+ category = "infrastructure";
26
+ authType = "bearer_token";
27
+ capabilities = capabilities;
28
+ frameworks = ["SOC2", "ISO27001", "NIST_CSF"];
29
+ async fetchK8s(config, apiPath) {
30
+ const base = config.baseUrl || "https://kubernetes.default.svc";
31
+ const resp = await fetch(`${base}${apiPath}`, {
32
+ headers: { Authorization: `Bearer ${config.apiToken}` },
33
+ });
34
+ if (!resp.ok)
35
+ throw new Error(`K8s API ${resp.status}: ${resp.statusText}`);
36
+ return (await resp.json());
37
+ }
38
+ async testConnection(config) {
39
+ try {
40
+ await this.fetchK8s(config, "/version");
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ async collectEvidence(config) {
48
+ const artifacts = [];
49
+ const now = new Date().toISOString();
50
+ const rbac = await this.fetchK8s(config, "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings").catch(() => ({
51
+ items: [],
52
+ }));
53
+ const roleBindings = (rbac.items || []);
54
+ const clusterAdminBindings = roleBindings.filter((r) => r.roleRef?.name === "cluster-admin");
55
+ artifacts.push({
56
+ id: generateEvidenceId(),
57
+ connectorId: this.id,
58
+ capabilityId: "k8s-rbac",
59
+ timestamp: now,
60
+ hash: hashEvidence({ totalBindings: roleBindings.length, clusterAdminBindings: clusterAdminBindings.length }),
61
+ framework: "SOC2",
62
+ controlId: "CC6.1",
63
+ source: "k8s/rbac/clusterrolebindings",
64
+ status: clusterAdminBindings.length <= 2 ? "compliant" : "partial",
65
+ data: { totalBindings: roleBindings.length, clusterAdminBindings: clusterAdminBindings.length },
66
+ metadata: {},
67
+ });
68
+ const netPol = await this.fetchK8s(config, "/apis/networking.k8s.io/v1/networkpolicies").catch(() => ({
69
+ items: [],
70
+ }));
71
+ const netPolicies = (netPol.items || []);
72
+ artifacts.push({
73
+ id: generateEvidenceId(),
74
+ connectorId: this.id,
75
+ capabilityId: "k8s-network-policies",
76
+ timestamp: now,
77
+ hash: hashEvidence({ policyCount: netPolicies.length }),
78
+ framework: "ISO27001",
79
+ controlId: "A.13.1.1",
80
+ source: "k8s/networking/networkpolicies",
81
+ status: netPolicies.length > 0 ? "compliant" : "non_compliant",
82
+ data: { networkPolicyCount: netPolicies.length },
83
+ metadata: {},
84
+ });
85
+ const pods = await this.fetchK8s(config, "/api/v1/pods").catch(() => ({ items: [] }));
86
+ const podList = (pods.items || []);
87
+ const privilegedPods = podList.filter((p) => {
88
+ const containers = [
89
+ ...(p.spec?.containers || []),
90
+ ...(p.spec?.initContainers || []),
91
+ ];
92
+ return containers.some((c) => c.securityContext?.privileged === true);
93
+ });
94
+ artifacts.push({
95
+ id: generateEvidenceId(),
96
+ connectorId: this.id,
97
+ capabilityId: "k8s-pod-security",
98
+ timestamp: now,
99
+ hash: hashEvidence({ totalPods: podList.length, privilegedPods: privilegedPods.length }),
100
+ framework: "SOC2",
101
+ controlId: "CC6.8",
102
+ source: "k8s/pods",
103
+ status: privilegedPods.length === 0 ? "compliant" : "non_compliant",
104
+ data: { totalPods: podList.length, privilegedPods: privilegedPods.length },
105
+ metadata: {},
106
+ });
107
+ return artifacts;
108
+ }
109
+ }
@@ -0,0 +1,12 @@
1
+ import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
2
+ export declare class OktaConnector implements IntegrationConnector {
3
+ readonly id = "okta";
4
+ readonly name = "Okta";
5
+ readonly category: "identity";
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,123 @@
1
+ import { hashEvidence, generateEvidenceId } from "../types.js";
2
+ const capabilities = [
3
+ {
4
+ id: "okta-users",
5
+ name: "User Accounts",
6
+ description: "Fetch Okta user accounts and status",
7
+ evidenceCategories: ["identity_management"],
8
+ },
9
+ {
10
+ id: "okta-mfa-factors",
11
+ name: "MFA Factors",
12
+ description: "Fetch enrolled MFA factors across users",
13
+ evidenceCategories: ["authentication"],
14
+ },
15
+ {
16
+ id: "okta-app-assignments",
17
+ name: "App Assignments",
18
+ description: "Fetch application assignments and SSO configurations",
19
+ evidenceCategories: ["access_control"],
20
+ },
21
+ {
22
+ id: "okta-group-memberships",
23
+ name: "Group Memberships",
24
+ description: "Fetch group memberships and role assignments",
25
+ evidenceCategories: ["access_control", "authorization"],
26
+ },
27
+ ];
28
+ export class OktaConnector {
29
+ id = "okta";
30
+ name = "Okta";
31
+ category = "identity";
32
+ authType = "bearer_token";
33
+ capabilities = capabilities;
34
+ frameworks = [
35
+ "SOC2",
36
+ "ISO27001",
37
+ "NIST_CSF",
38
+ "HIPAA",
39
+ ];
40
+ async fetchApi(config, endpoint) {
41
+ const base = config.baseUrl || `https://${config.extra?.domain || "example"}.okta.com/api/v1`;
42
+ const resp = await fetch(`${base}${endpoint}`, {
43
+ headers: { Authorization: `SSWS ${config.apiToken}` },
44
+ });
45
+ if (!resp.ok)
46
+ throw new Error(`Okta API ${resp.status}: ${resp.statusText}`);
47
+ return (await resp.json());
48
+ }
49
+ async testConnection(config) {
50
+ try {
51
+ await this.fetchApi(config, "/users/me");
52
+ return true;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ async collectEvidence(config) {
59
+ const artifacts = [];
60
+ const now = new Date().toISOString();
61
+ const users = await this.fetchApi(config, "/users?filter=status%20eq%20%22ACTIVE%22&limit=200");
62
+ const userList = Array.isArray(users) ? users : [];
63
+ artifacts.push({
64
+ id: generateEvidenceId(),
65
+ connectorId: this.id,
66
+ capabilityId: "okta-users",
67
+ timestamp: now,
68
+ hash: hashEvidence({ users: userList.map((u) => ({ id: u.id, status: u.status })) }),
69
+ framework: "SOC2",
70
+ controlId: "CC6.1",
71
+ source: "okta/users",
72
+ status: "compliant",
73
+ data: { activeUserCount: userList.length },
74
+ metadata: { domain: config.extra?.domain || "" },
75
+ });
76
+ const factors = await this.fetchApi(config, "/users/me/factors").catch(() => []);
77
+ const factorList = Array.isArray(factors) ? factors : [];
78
+ artifacts.push({
79
+ id: generateEvidenceId(),
80
+ connectorId: this.id,
81
+ capabilityId: "okta-mfa-factors",
82
+ timestamp: now,
83
+ hash: hashEvidence({ factors: factorList }),
84
+ framework: "SOC2",
85
+ controlId: "CC6.1",
86
+ source: "okta/factors",
87
+ status: factorList.length > 0 ? "compliant" : "non_compliant",
88
+ data: { factorTypes: factorList.map((f) => f.factorType) },
89
+ metadata: { domain: config.extra?.domain || "" },
90
+ });
91
+ const apps = await this.fetchApi(config, "/apps?limit=100").catch(() => []);
92
+ const appList = Array.isArray(apps) ? apps : [];
93
+ artifacts.push({
94
+ id: generateEvidenceId(),
95
+ connectorId: this.id,
96
+ capabilityId: "okta-app-assignments",
97
+ timestamp: now,
98
+ hash: hashEvidence({ apps: appList.map((a) => ({ id: a.id, name: a.name })) }),
99
+ framework: "ISO27001",
100
+ controlId: "A.9.2.5",
101
+ source: "okta/apps",
102
+ status: "unknown",
103
+ data: { appCount: appList.length },
104
+ metadata: { domain: config.extra?.domain || "" },
105
+ });
106
+ const groups = await this.fetchApi(config, "/groups?limit=100").catch(() => []);
107
+ const groupList = Array.isArray(groups) ? groups : [];
108
+ artifacts.push({
109
+ id: generateEvidenceId(),
110
+ connectorId: this.id,
111
+ capabilityId: "okta-group-memberships",
112
+ timestamp: now,
113
+ hash: hashEvidence({ groups: groupList.map((g) => ({ id: g.id, name: (g.profile || {}).name })) }),
114
+ framework: "SOC2",
115
+ controlId: "CC6.3",
116
+ source: "okta/groups",
117
+ status: groupList.length > 0 ? "compliant" : "non_compliant",
118
+ data: { groupCount: groupList.length },
119
+ metadata: { domain: config.extra?.domain || "" },
120
+ });
121
+ return artifacts;
122
+ }
123
+ }
@@ -0,0 +1,12 @@
1
+ import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
2
+ export declare class PagerDutyConnector implements IntegrationConnector {
3
+ readonly id = "pagerduty";
4
+ readonly name = "PagerDuty";
5
+ readonly category: "incident_management";
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,106 @@
1
+ import { hashEvidence, generateEvidenceId } from "../types.js";
2
+ const capabilities = [
3
+ {
4
+ id: "pd-services",
5
+ name: "Services",
6
+ description: "Fetch PagerDuty service configurations and escalation policies",
7
+ evidenceCategories: ["incident_management", "configuration"],
8
+ },
9
+ {
10
+ id: "pd-oncall",
11
+ name: "On-Call Schedules",
12
+ description: "Fetch on-call schedules and rotation policies",
13
+ evidenceCategories: ["incident_management", "availability"],
14
+ },
15
+ {
16
+ id: "pd-incidents",
17
+ name: "Incident History",
18
+ description: "Fetch recent incidents and resolution metrics",
19
+ evidenceCategories: ["incident_management"],
20
+ },
21
+ ];
22
+ export class PagerDutyConnector {
23
+ id = "pagerduty";
24
+ name = "PagerDuty";
25
+ category = "incident_management";
26
+ authType = "bearer_token";
27
+ capabilities = capabilities;
28
+ frameworks = ["SOC2", "ISO27001"];
29
+ async fetchApi(config, endpoint) {
30
+ const base = config.baseUrl || "https://api.pagerduty.com";
31
+ const resp = await fetch(`${base}${endpoint}`, {
32
+ headers: {
33
+ Authorization: `Token token=${config.apiToken}`,
34
+ Accept: "application/vnd.pagerduty+json;version=2",
35
+ },
36
+ });
37
+ if (!resp.ok)
38
+ throw new Error(`PagerDuty API ${resp.status}: ${resp.statusText}`);
39
+ return (await resp.json());
40
+ }
41
+ async testConnection(config) {
42
+ try {
43
+ await this.fetchApi(config, "/users/me");
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ async collectEvidence(config) {
51
+ const artifacts = [];
52
+ const now = new Date().toISOString();
53
+ const services = await this.fetchApi(config, "/services?limit=100");
54
+ const serviceList = (services.services || []);
55
+ artifacts.push({
56
+ id: generateEvidenceId(),
57
+ connectorId: this.id,
58
+ capabilityId: "pd-services",
59
+ timestamp: now,
60
+ hash: hashEvidence({ services: serviceList.map((s) => ({ id: s.id, name: s.name })) }),
61
+ framework: "SOC2",
62
+ controlId: "CC7.3",
63
+ source: "pagerduty/services",
64
+ status: serviceList.length > 0 ? "compliant" : "non_compliant",
65
+ data: { serviceCount: serviceList.length },
66
+ metadata: {},
67
+ });
68
+ const schedules = await this.fetchApi(config, "/schedules?limit=100").catch(() => ({
69
+ schedules: [],
70
+ }));
71
+ const scheduleList = (schedules.schedules || []);
72
+ artifacts.push({
73
+ id: generateEvidenceId(),
74
+ connectorId: this.id,
75
+ capabilityId: "pd-oncall",
76
+ timestamp: now,
77
+ hash: hashEvidence({ schedules: scheduleList.map((s) => ({ id: s.id, name: s.name })) }),
78
+ framework: "SOC2",
79
+ controlId: "CC7.2",
80
+ source: "pagerduty/schedules",
81
+ status: scheduleList.length > 0 ? "compliant" : "non_compliant",
82
+ data: { scheduleCount: scheduleList.length },
83
+ metadata: {},
84
+ });
85
+ const since = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
86
+ const incidents = await this.fetchApi(config, `/incidents?since=${since}&limit=100&statuses[]=triggered&statuses[]=resolved`).catch(() => ({ incidents: [] }));
87
+ const incidentList = (incidents.incidents || []);
88
+ artifacts.push({
89
+ id: generateEvidenceId(),
90
+ connectorId: this.id,
91
+ capabilityId: "pd-incidents",
92
+ timestamp: now,
93
+ hash: hashEvidence({ incidents: incidentList.map((i) => ({ id: i.id, status: i.status })) }),
94
+ framework: "ISO27001",
95
+ controlId: "A.16.1.4",
96
+ source: "pagerduty/incidents",
97
+ status: "unknown",
98
+ data: {
99
+ incidentCount: incidentList.length,
100
+ resolved: incidentList.filter((i) => i.status === "resolved").length,
101
+ },
102
+ metadata: {},
103
+ });
104
+ return artifacts;
105
+ }
106
+ }
@@ -0,0 +1,12 @@
1
+ import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
2
+ export declare class QualysConnector implements IntegrationConnector {
3
+ readonly id = "qualys";
4
+ readonly name = "Qualys";
5
+ readonly category: "vulnerability";
6
+ readonly authType: "basic_auth";
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,96 @@
1
+ import { hashEvidence, generateEvidenceId } from "../types.js";
2
+ const capabilities = [
3
+ {
4
+ id: "qualys-vuln-scans",
5
+ name: "Vulnerability Scans",
6
+ description: "Fetch Qualys vulnerability scan results and host detections",
7
+ evidenceCategories: ["vulnerability_management"],
8
+ },
9
+ {
10
+ id: "qualys-compliance-scans",
11
+ name: "Compliance Scans",
12
+ description: "Fetch Qualys policy compliance scan results",
13
+ evidenceCategories: ["compliance", "configuration"],
14
+ },
15
+ ];
16
+ export class QualysConnector {
17
+ id = "qualys";
18
+ name = "Qualys";
19
+ category = "vulnerability";
20
+ authType = "basic_auth";
21
+ capabilities = capabilities;
22
+ frameworks = ["SOC2", "ISO27001", "PCI_DSS", "NIST_CSF"];
23
+ async fetchApi(config, endpoint, body) {
24
+ const base = config.baseUrl || "https://qualysapi.qualys.com";
25
+ const resp = await fetch(`${base}${endpoint}`, {
26
+ method: body ? "POST" : "GET",
27
+ headers: {
28
+ Authorization: `Basic ${Buffer.from(`${config.clientId}:${config.apiToken}`).toString("base64")}`,
29
+ "Content-Type": body ? "application/x-www-form-urlencoded" : "text/xml",
30
+ Accept: "application/json",
31
+ },
32
+ body,
33
+ });
34
+ if (!resp.ok)
35
+ throw new Error(`Qualys API ${resp.status}: ${resp.statusText}`);
36
+ return resp.text();
37
+ }
38
+ async testConnection(config) {
39
+ try {
40
+ await this.fetchApi(config, "/api/2.0/fo/user/?action=list");
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ async collectEvidence(config) {
48
+ const artifacts = [];
49
+ const now = new Date().toISOString();
50
+ const vulnScan = await this.fetchApi(config, "/api/2.0/fo/scan/?action=list&output_format=JSON&truncate_limit=100").catch(() => '{"response":{"scan_list":[]}}');
51
+ let vulnData = {};
52
+ try {
53
+ vulnData = JSON.parse(vulnScan);
54
+ }
55
+ catch {
56
+ vulnData = { raw: vulnScan.substring(0, 500) };
57
+ }
58
+ const scanList = vulnData.response?.scan_list || [];
59
+ artifacts.push({
60
+ id: generateEvidenceId(),
61
+ connectorId: this.id,
62
+ capabilityId: "qualys-vuln-scans",
63
+ timestamp: now,
64
+ hash: hashEvidence({ scanCount: Array.isArray(scanList) ? scanList.length : 0 }),
65
+ framework: "SOC2",
66
+ controlId: "CC7.1",
67
+ source: "qualys/scans",
68
+ status: "unknown",
69
+ data: { scanCount: Array.isArray(scanList) ? scanList.length : 0 },
70
+ metadata: {},
71
+ });
72
+ const compScan = await this.fetchApi(config, "/api/2.0/compliance_policy/?action=list&output_format=JSON").catch(() => '{"response":{"policy_list":[]}}');
73
+ let compData = {};
74
+ try {
75
+ compData = JSON.parse(compScan);
76
+ }
77
+ catch {
78
+ compData = { raw: compScan.substring(0, 500) };
79
+ }
80
+ const policyList = compData.response?.policy_list || [];
81
+ artifacts.push({
82
+ id: generateEvidenceId(),
83
+ connectorId: this.id,
84
+ capabilityId: "qualys-compliance-scans",
85
+ timestamp: now,
86
+ hash: hashEvidence({ policyCount: Array.isArray(policyList) ? policyList.length : 0 }),
87
+ framework: "ISO27001",
88
+ controlId: "A.12.6.1",
89
+ source: "qualys/compliance",
90
+ status: "unknown",
91
+ data: { policyCount: Array.isArray(policyList) ? policyList.length : 0 },
92
+ metadata: {},
93
+ });
94
+ return artifacts;
95
+ }
96
+ }
@@ -0,0 +1,12 @@
1
+ import type { IntegrationConnector, ConnectorConfig, EvidenceArtifact, IntegrationCapability, ComplianceFramework } from "../types.js";
2
+ export declare class SalesforceConnector implements IntegrationConnector {
3
+ readonly id = "salesforce";
4
+ readonly name = "Salesforce";
5
+ readonly category: "hr";
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
+ }