From 1aa35fee0e18482e09888694ae0177bd41b70058 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Tue, 20 May 2025 18:18:14 -0400 Subject: [PATCH 1/3] new components --- .../get-policy-details/get-policy-details.mjs | 31 +++ .../get-scan-task-status.mjs | 31 +++ .../move-endpoint-to-group.mjs | 40 ++++ .../actions/scan-endpoint/scan-endpoint.mjs | 112 ++++++++++ .../bitdefender_gravityzone.app.mjs | 191 +++++++++++++++++- .../bitdefender_gravityzone/package.json | 5 +- .../sources/common/base.mjs | 68 +++++++ .../new-endpoint-added-instant.mjs | 28 +++ .../new-endpoint-added-instant/test-event.mjs | 11 + .../new-incident-instant.mjs | 28 +++ .../new-incident-instant/test-event.mjs | 34 ++++ .../new-threat-detected-instant.mjs | 28 +++ .../test-event.mjs | 14 ++ 13 files changed, 616 insertions(+), 5 deletions(-) create mode 100644 components/bitdefender_gravityzone/actions/get-policy-details/get-policy-details.mjs create mode 100644 components/bitdefender_gravityzone/actions/get-scan-task-status/get-scan-task-status.mjs create mode 100644 components/bitdefender_gravityzone/actions/move-endpoint-to-group/move-endpoint-to-group.mjs create mode 100644 components/bitdefender_gravityzone/actions/scan-endpoint/scan-endpoint.mjs create mode 100644 components/bitdefender_gravityzone/sources/common/base.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-endpoint-added-instant/test-event.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-incident-instant/new-incident-instant.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-incident-instant/test-event.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-threat-detected-instant/new-threat-detected-instant.mjs create mode 100644 components/bitdefender_gravityzone/sources/new-threat-detected-instant/test-event.mjs diff --git a/components/bitdefender_gravityzone/actions/get-policy-details/get-policy-details.mjs b/components/bitdefender_gravityzone/actions/get-policy-details/get-policy-details.mjs new file mode 100644 index 0000000000000..503c95b51712a --- /dev/null +++ b/components/bitdefender_gravityzone/actions/get-policy-details/get-policy-details.mjs @@ -0,0 +1,31 @@ +import bitdefender from "../../bitdefender_gravityzone.app.mjs"; + +export default { + key: "bitdefender_gravityzone-get-policy-details", + name: "Get Policy Details", + description: "Retrieve details about a specific policy. [See the documentation](https://www.bitdefender.com/business/support/en/77209-135304-getpolicydetails.html)", + version: "0.0.1", + type: "action", + props: { + bitdefender, + policyId: { + propDefinition: [ + bitdefender, + "policyId", + ], + }, + }, + async run({ $ }) { + const response = await this.bitdefender.getPolicyDetails({ + $, + data: { + params: { + policyId: this.policyId, + }, + }, + }); + + $.export("$summary", `Successfully retrieved details for policy ${this.policyId}`); + return response; + }, +}; diff --git a/components/bitdefender_gravityzone/actions/get-scan-task-status/get-scan-task-status.mjs b/components/bitdefender_gravityzone/actions/get-scan-task-status/get-scan-task-status.mjs new file mode 100644 index 0000000000000..d7eea042e422c --- /dev/null +++ b/components/bitdefender_gravityzone/actions/get-scan-task-status/get-scan-task-status.mjs @@ -0,0 +1,31 @@ +import bitdefender from "../../bitdefender_gravityzone.app.mjs"; + +export default { + key: "bitdefender_gravityzone-get-scan-task-status", + name: "Get Scan Task Status", + description: "Get the status of a scan task. [See the documentation(https://www.bitdefender.com/business/support/en/77209-440638-gettaskstatus.html)", + version: "0.0.1", + type: "action", + props: { + bitdefender, + taskId: { + propDefinition: [ + bitdefender, + "taskId", + ], + }, + }, + async run({ $ }) { + const response = await this.bitdefender.getTaskStatus({ + $, + data: { + params: { + taskId: this.taskId, + }, + }, + }); + + $.export("$summary", `Successfully retrieved status for task ${this.taskId}`); + return response; + }, +}; diff --git a/components/bitdefender_gravityzone/actions/move-endpoint-to-group/move-endpoint-to-group.mjs b/components/bitdefender_gravityzone/actions/move-endpoint-to-group/move-endpoint-to-group.mjs new file mode 100644 index 0000000000000..bef8cd71debc3 --- /dev/null +++ b/components/bitdefender_gravityzone/actions/move-endpoint-to-group/move-endpoint-to-group.mjs @@ -0,0 +1,40 @@ +import bitdefender from "../../bitdefender_gravityzone.app.mjs"; + +export default { + key: "bitdefender_gravityzone-move-endpoint-to-group", + name: "Move Endpoint to Group", + description: "Move an endpoint to a different group. [See the documentation](https://www.bitdefender.com/business/support/en/77209-128489-moveendpoints.html)", + version: "0.0.1", + type: "action", + props: { + bitdefender, + endpointId: { + propDefinition: [ + bitdefender, + "endpointId", + ], + }, + groupId: { + propDefinition: [ + bitdefender, + "groupId", + ], + }, + }, + async run({ $ }) { + const response = await this.bitdefender.moveEndpointToGroup({ + $, + data: { + params: { + endpointIds: [ + this.endpointId, + ], + groupId: this.groupId, + }, + }, + }); + + $.export("$summary", `Successfully moved endpoint ${this.endpointId} to group ${this.groupId}`); + return response; + }, +}; diff --git a/components/bitdefender_gravityzone/actions/scan-endpoint/scan-endpoint.mjs b/components/bitdefender_gravityzone/actions/scan-endpoint/scan-endpoint.mjs new file mode 100644 index 0000000000000..5f4e90aec0c89 --- /dev/null +++ b/components/bitdefender_gravityzone/actions/scan-endpoint/scan-endpoint.mjs @@ -0,0 +1,112 @@ +import bitdefender from "../../bitdefender_gravityzone.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "bitdefender_gravityzone-scan-endpoint", + name: "Scan Endpoint", + description: "Trigger a scan on a specific endpoint. [See the documentation](https://www.bitdefender.com/business/support/en/77209-128495-createscantask.html)", + version: "0.0.1", + type: "action", + props: { + bitdefender, + endpointId: { + propDefinition: [ + bitdefender, + "endpointId", + ], + }, + scanType: { + type: "integer", + label: "Scan Type", + description: "Type of scan to perform", + options: [ + { + label: "Quick Scan", + value: 1, + }, + { + label: "Full Scan", + value: 2, + }, + { + label: "Memory Scan", + value: 3, + }, + { + label: "Custom Scan", + value: 4, + }, + ], + }, + name: { + type: "string", + label: "Name", + description: "The name of the task. If the parameter is not passed, the name will be automatically generated.", + optional: true, + }, + returnAllTaskIds: { + type: "boolean", + label: "Return All Task IDs", + description: "Indicates if the response will contain the IDs for all the tasks created as a result of the request", + optional: true, + }, + scanDepth: { + type: "integer", + label: "Scan Depth", + description: "The scan profile", + options: [ + { + label: "Aggressive", + value: 1, + }, + { + label: "Normal", + value: 2, + }, + { + label: "Permissivearray", + value: 3, + }, + ], + optional: true, + }, + scanPath: { + type: "string[]", + label: "Scan Path", + description: "The list of target paths to be scanned", + optional: true, + }, + }, + async run({ $ }) { + if ((this.scanDepth || this.scanPath) && this.scanType !== 4) { + throw new ConfigurationError("Scan depth and path can only be used for custom scans"); + } + + if ((this.scanDepth && !this.scanPath) || (this.scanPath && !this.scanDepth)) { + throw new ConfigurationError("Scan depth and path must be used together"); + } + + const response = await this.bitdefender.scanEndpoint({ + $, + data: { + params: { + targetIds: [ + this.endpointId, + ], + type: this.scanType, + name: this.name, + returnAllTaskIds: this.returnAllTaskIds, + customScanSettings: this.scanDepth + ? { + scanDepth: this.scanDepth, + scanPath: this.scanPath, + } + : undefined, + }, + }, + }); + + $.export("$summary", `Successfully initiated ${this.scanType} scan on endpoint ${this.endpointId}`); + return response; + }, +}; diff --git a/components/bitdefender_gravityzone/bitdefender_gravityzone.app.mjs b/components/bitdefender_gravityzone/bitdefender_gravityzone.app.mjs index 711b49f8a7886..b82e1ef81c2f0 100644 --- a/components/bitdefender_gravityzone/bitdefender_gravityzone.app.mjs +++ b/components/bitdefender_gravityzone/bitdefender_gravityzone.app.mjs @@ -1,11 +1,194 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "bitdefender_gravityzone", - propDefinitions: {}, + propDefinitions: { + endpointId: { + type: "string", + label: "Endpoint ID", + description: "The ID of the endpoint", + async options({ page }) { + const { result } = await this.listEndpoints({ + data: { + params: { + page: page + 1, + }, + }, + }); + return result?.items?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + groupId: { + type: "string", + label: "Group ID", + description: "The ID of the group", + async options() { + const { result } = await this.listGroups(); + return result?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + policyId: { + type: "string", + label: "Policy ID", + description: "The ID of the policy", + async options({ page }) { + const { result } = await this.listPolicies({ + data: { + params: { + page: page + 1, + }, + }, + }); + return result?.items?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + taskId: { + type: "string", + label: "Task ID", + description: "The ID of the task", + async options({ page }) { + const { result } = await this.listScanTasks({ + data: { + params: { + page: page + 1, + }, + }, + }); + return result?.items?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return `${this.$auth.api_url}/v1.0/jsonrpc`; + }, + _auth() { + return { + username: this.$auth.api_key, + password: "", + }; + }, + _makeRequest({ + $ = this, + path, + method, + data = {}, + ...otherOpts + }) { + return axios($, { + method: "POST", + url: `${this._baseUrl()}${path}`, + auth: this._auth(), + data: { + ...data, + id: "120000", + jsonrpc: "2.0", + method, + }, + ...otherOpts, + }); + }, + policiesApi({ + method, ...opts + }) { + return this._makeRequest({ + path: "/policies", + method, + ...opts, + }); + }, + networkApi({ + method, ...opts + }) { + return this._makeRequest({ + path: "/network", + method, + ...opts, + }); + }, + pushApi({ + method, ...opts + }) { + return this._makeRequest({ + path: "/push", + method, + ...opts, + }); + }, + listPolicies(opts = {}) { + return this.policiesApi({ + method: "getPoliciesList", + ...opts, + }); + }, + listEndpoints(opts = {}) { + return this.networkApi({ + method: "getEndpointsList", + ...opts, + }); + }, + listGroups(opts = {}) { + return this.networkApi({ + method: "getCustomGroupsList", + ...opts, + }); + }, + listScanTasks(opts = {}) { + return this.networkApi({ + method: "getScanTasksList", + ...opts, + }); + }, + getTaskStatus(opts = {}) { + return this.networkApi({ + method: "getTaskStatus", + ...opts, + }); + }, + scanEndpoint(opts = {}) { + return this.networkApi({ + method: "createScanTask", + ...opts, + }); + }, + getPolicyDetails(opts = {}) { + return this.policiesApi({ + method: "getPolicyDetails", + ...opts, + }); + }, + moveEndpointToGroup(opts = {}) { + return this.networkApi({ + method: "moveEndpoints", + ...opts, + }); + }, + setPushEventSettings(opts = {}) { + return this.pushApi({ + method: "setPushEventSettings", + ...opts, + }); }, }, }; diff --git a/components/bitdefender_gravityzone/package.json b/components/bitdefender_gravityzone/package.json index 1fc42aaeb4516..31aab44a486b8 100644 --- a/components/bitdefender_gravityzone/package.json +++ b/components/bitdefender_gravityzone/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/bitdefender_gravityzone", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Bitdefender GravityZone Components", "main": "bitdefender_gravityzone.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } } diff --git a/components/bitdefender_gravityzone/sources/common/base.mjs b/components/bitdefender_gravityzone/sources/common/base.mjs new file mode 100644 index 0000000000000..4e2b52fe7fbcc --- /dev/null +++ b/components/bitdefender_gravityzone/sources/common/base.mjs @@ -0,0 +1,68 @@ +import bitdefender from "../../bitdefender_gravityzone.app.mjs"; + +export default { + props: { + bitdefender, + http: { + type: "$.interface.http", + customResponse: true, + }, + }, + hooks: { + async activate() { + await this.bitdefender.setPushEventSettings({ + data: { + params: { + status: 1, // enable push events + ...this.getWebhookParams(), + }, + }, + }); + }, + async deactivate() { + await this.bitdefender.setPushEventSettings({ + data: { + params: { + status: 0, // disable push events + ...this.getWebhookParams(), + }, + }, + }); + }, + }, + methods: { + getWebhookParams() { + return { + serviceType: "jsonRPC", + serviceSettings: { + url: this.http.endpoint, + authorization: `Bearer ${this.bitdefender.$auth.api_key}`, + requireValidSslCertificate: true, + }, + subscribeToEventTypes: this.getEventTypes(), + }; + }, + getEventTypes() { + throw new Error("getEventTypes is not implemented"); + }, + generateMeta() { + throw new Error("generateMeta is not implemented"); + }, + }, + async run(event) { + this.http.respond({ + status: 200, + }); + + const { body } = event; + if (!body) { + return; + } + + const events = body?.params?.events || []; + for (const event of events) { + const meta = this.generateMeta(event); + this.$emit(event, meta); + } + }, +}; diff --git a/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs new file mode 100644 index 0000000000000..fed4e4cf4567e --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "bitdefender_gravityzone-new-endpoint-added-instant", + name: "New Endpoint Added (Instant)", + description: "Emit new event when a new endpoint is registered in Bitdefender GravityZone.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEventTypes() { + return { + "endpoint-moved-in": true, + }; + }, + generateMeta(item) { + return { + id: item.endpointId, + summary: `New Endpoint Added: ${item.endpointId}`, + ts: Date.now(), + }; + }, + }, + sampleEmit, +}; diff --git a/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/test-event.mjs b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/test-event.mjs new file mode 100644 index 0000000000000..8a50b97ed753d --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/test-event.mjs @@ -0,0 +1,11 @@ +export default { + "product_installed": "BEST", + "computer_name": "TEST_ENDPOINT", + "computer_fqdn": "test-endpoint.dsd.ro", + "computer_ip": "10.10.18.226", + "computer_id": "59b7d9bfa849af3a1465b7e3", + "endpointId": "5e2085febf255a545e52276a", + "hwid": "5e284ff-5b7e43d387ba-54a95", + "companyId": "6776d4015c0c96e36a07798a", + "module": "endpoint-moved-in", + } \ No newline at end of file diff --git a/components/bitdefender_gravityzone/sources/new-incident-instant/new-incident-instant.mjs b/components/bitdefender_gravityzone/sources/new-incident-instant/new-incident-instant.mjs new file mode 100644 index 0000000000000..46a4a384f2bc2 --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-incident-instant/new-incident-instant.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "bitdefender_gravityzone-new-incident-instant", + name: "New Incident (Instant)", + description: "Emit new event when a new Root Cause Analysis (RCA) is displayed under the Incidents section of Control Center.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEventTypes() { + return { + "new-incident": true, + }; + }, + generateMeta(item) { + return { + id: item.incident_id, + summary: `New Incident with ID: ${item.incident_id}`, + ts: Date.now(), + }; + }, + }, + sampleEmit, +}; diff --git a/components/bitdefender_gravityzone/sources/new-incident-instant/test-event.mjs b/components/bitdefender_gravityzone/sources/new-incident-instant/test-event.mjs new file mode 100644 index 0000000000000..54e4d6e580f76 --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-incident-instant/test-event.mjs @@ -0,0 +1,34 @@ +export default { + "module": "new-incident", + "created": "2020-07-20T09:36:23.485Z", + "endpointId": "5efb3a520075db7384dfa285", + "companyId": "6776d4015c0c96e36a07798a", + "computer_id": "5efb3a520075db7384dfa286", + "computer_fqdn": "desktop-jac14gs", + "computer_name": "DESKTOP-JAC14GS", + "detection_name": "ATC.Malicious", + "attack_types": [ + "Other" + ], + "computer_ip": "10.17.23.30", + "severityScore": 90, + "incident_id": "5f1557cbe7b2584f3959ee19", + "attack_entry": 1688239188, + "parent_process_path": "c:\\windows\\system32\\cmd.exe", + "parent_process_pid": 9636, + "process_path": "c:\\users\\bdadmin\\desktop\\atcsim\\atcsim32.exe", + "process_pid": 10324, + "username": "DESKTOP-JAC14GS\\bdadmin", + "user_sid": "S-1-5-21-3349207704-443292085-2237656896-1003", + "process_command_line": "detect", + "file_hash_md5": "ccb1b07bdf330627f02b3c832663a489", + "file_hash_sha256": "d5adc6a65a57d30d3ae70d195983d155e7cd24f26eb1ebebde9b92655251ec55", + "att_ck_id": [ + "T1036", + "T1059", + "T1002", + "T1012" + ], + "severity": "high", + "main_action": "no action", + } \ No newline at end of file diff --git a/components/bitdefender_gravityzone/sources/new-threat-detected-instant/new-threat-detected-instant.mjs b/components/bitdefender_gravityzone/sources/new-threat-detected-instant/new-threat-detected-instant.mjs new file mode 100644 index 0000000000000..d742224f27f8b --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-threat-detected-instant/new-threat-detected-instant.mjs @@ -0,0 +1,28 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "bitdefender_gravityzone-new-threat-detected-instant", + name: "New Threat Detected (Instant)", + description: "Emit new event when a potentially dangerous application is detected and blocked on an endpoint", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getEventTypes() { + return { + "avc": true, // advanced threat control + }; + }, + generateMeta() { + return { + id: Date.now(), + summary: "New Threat Detected", + ts: Date.now(), + }; + }, + }, + sampleEmit, +}; diff --git a/components/bitdefender_gravityzone/sources/new-threat-detected-instant/test-event.mjs b/components/bitdefender_gravityzone/sources/new-threat-detected-instant/test-event.mjs new file mode 100644 index 0000000000000..39fab25995d1e --- /dev/null +++ b/components/bitdefender_gravityzone/sources/new-threat-detected-instant/test-event.mjs @@ -0,0 +1,14 @@ +export default { + "computer_name": "FC-WIN7-X64-01", + "computer_fqdn": "fc-win7-x64-01", + "computer_ip": "192.168.0.1", + "computer_id": "59a1604e60369e06733f8abb", + "product_installed": "BEST", + "exploit_type": "AVC Blocked Exploit", + "exploit_path": "C:\\Users\\admin\\Desktop\\Tools\\avcsim\\win32\\avcsim32.exe", + "status": "avc_blocked", + "last_blocked": "2017-09-14T07:56:33.000Z", + "count": 1, + "companyId": "6776d4015c0c96e36a07798a", + "module": "avc", + } \ No newline at end of file From ebb793d5d0f3344044fc27a68e33d6727d990892 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Tue, 20 May 2025 18:19:04 -0400 Subject: [PATCH 2/3] pnpm-lock.yaml --- pnpm-lock.yaml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c1a50a7626a9..45ee0516b8a18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1542,7 +1542,11 @@ importers: components/bitbucket_data_center: {} - components/bitdefender_gravityzone: {} + components/bitdefender_gravityzone: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 components/bitly: dependencies: @@ -15404,14 +15408,6 @@ importers: specifier: ^6.0.0 version: 6.2.0 - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/cjs: {} - - modelcontextprotocol/node_modules2/@modelcontextprotocol/sdk/dist/esm: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/cjs: {} - - modelcontextprotocol/node_modules2/zod-to-json-schema/dist/esm: {} - packages/ai: dependencies: '@pipedream/sdk': From dbda9b682551b4709394ed65ea14a6d3a0fe3875 Mon Sep 17 00:00:00 2001 From: Michelle Bergeron Date: Tue, 20 May 2025 18:28:30 -0400 Subject: [PATCH 3/3] update --- .../new-endpoint-added-instant/new-endpoint-added-instant.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs index fed4e4cf4567e..e972f16d0520c 100644 --- a/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs +++ b/components/bitdefender_gravityzone/sources/new-endpoint-added-instant/new-endpoint-added-instant.mjs @@ -13,7 +13,7 @@ export default { ...common.methods, getEventTypes() { return { - "endpoint-moved-in": true, + "endpoint-moved-in": true, }; }, generateMeta(item) {