diff --git a/packages/nodes-base/credentials/DatadogApi.credentials.ts b/packages/nodes-base/credentials/DatadogApi.credentials.ts new file mode 100644 index 0000000000..2c962a92a0 --- /dev/null +++ b/packages/nodes-base/credentials/DatadogApi.credentials.ts @@ -0,0 +1,73 @@ +import type { + ICredentialDataDecryptedObject, + ICredentialTestRequest, + ICredentialType, + IHttpRequestOptions, + INodeProperties, +} from 'n8n-workflow'; + +export class DatadogApi implements ICredentialType { + name = 'datadogApi'; + + displayName = 'Datadog API'; + + documentationUrl = 'datadog'; + + icon = { light: 'file:icons/Datadog.svg', dark: 'file:icons/Datadog.svg' } as const; + + httpRequestNode = { + name: 'Datadog', + docsUrl: 'https://docs.datadoghq.com/api/latest/', + apiBaseUrlPlaceholder: 'https://api.datadoghq.com/api/v1/metrics', + }; + + properties: INodeProperties[] = [ + { + displayName: 'URL', + name: 'url', + required: true, + type: 'string', + default: 'https://api.datadoghq.com', + }, + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + { + displayName: 'APP Key', + name: 'appKey', + required: false, + type: 'string', + default: '', + typeOptions: { password: true }, + description: 'For some endpoints, you also need an Application key.', + }, + ]; + + async authenticate( + credentials: ICredentialDataDecryptedObject, + requestOptions: IHttpRequestOptions, + ): Promise { + requestOptions.headers = { + 'DD-API-KEY': credentials.apiKey, + 'DD-APPLICATION-KEY': credentials.appKey, + }; + if (!requestOptions.headers['DD-APPLICATION-KEY']) { + delete requestOptions.headers['DD-APPLICATION-KEY']; + } + + return requestOptions; + } + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.url}}', + url: '/api/v1/validate', + method: 'GET', + }, + }; +} diff --git a/packages/nodes-base/credentials/DfirIrisApi.credentials.ts b/packages/nodes-base/credentials/DfirIrisApi.credentials.ts new file mode 100644 index 0000000000..cf631fba06 --- /dev/null +++ b/packages/nodes-base/credentials/DfirIrisApi.credentials.ts @@ -0,0 +1,67 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class DfirIrisApi implements ICredentialType { + name = 'dfirIrisApi'; + + displayName = 'DFIR-IRIS API'; + + documentationUrl = 'dfiriris'; + + icon = { light: 'file:icons/DfirIris.svg', dark: 'file:icons/DfirIris.svg' } as const; + + httpRequestNode = { + name: 'DFIR-IRIS', + docsUrl: 'https://docs.dfir-iris.org/operations/api/', + apiBaseUrlPlaceholder: 'http:///manage/cases/list', + }; + + properties: INodeProperties[] = [ + { + displayName: 'Base URL', + name: 'baseUrl', + type: 'string', + default: '', + placeholder: 'e.g. https://localhost', + description: + 'The API endpoints are reachable on the same Address and port as the web interface.', + required: true, + }, + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + { + displayName: 'Ignore SSL Issues', + name: 'skipSslCertificateValidation', + type: 'boolean', + default: false, + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + Authorization: '=Bearer {{$credentials.apiKey}}', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.baseUrl}}', + url: '/api/ping', + method: 'GET', + skipSslCertificateValidation: '={{$credentials.skipSslCertificateValidation}}', + }, + }; +} diff --git a/packages/nodes-base/credentials/DynatraceApi.credentials.ts b/packages/nodes-base/credentials/DynatraceApi.credentials.ts new file mode 100644 index 0000000000..9934bd1b96 --- /dev/null +++ b/packages/nodes-base/credentials/DynatraceApi.credentials.ts @@ -0,0 +1,37 @@ +import type { IAuthenticateGeneric, ICredentialType, INodeProperties } from 'n8n-workflow'; + +export class DynatraceApi implements ICredentialType { + name = 'dynatraceApi'; + + displayName = 'DynatraceAPI'; + + documentationUrl = 'dynatrace'; + + icon = { light: 'file:icons/Dynatrace.svg', dark: 'file:icons/Dynatrace.svg' } as const; + + httpRequestNode = { + name: 'Dynatrace', + docsUrl: 'https://docs.dynatrace.com/docs/dynatrace-api', + apiBaseUrlPlaceholder: 'https://{your-environment-id}.live.dynatrace.com/api/v2/events', + }; + + properties: INodeProperties[] = [ + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + Authorization: '=Api-Token {{$credentials.apiKey}}', + }, + }, + }; +} diff --git a/packages/nodes-base/credentials/ElasticSecurityApi.credentials.ts b/packages/nodes-base/credentials/ElasticSecurityApi.credentials.ts index 11759991fe..6571428f97 100644 --- a/packages/nodes-base/credentials/ElasticSecurityApi.credentials.ts +++ b/packages/nodes-base/credentials/ElasticSecurityApi.credentials.ts @@ -1,4 +1,10 @@ -import type { ICredentialType, INodeProperties } from 'n8n-workflow'; +import type { + ICredentialDataDecryptedObject, + ICredentialTestRequest, + ICredentialType, + IHttpRequestOptions, + INodeProperties, +} from 'n8n-workflow'; export class ElasticSecurityApi implements ICredentialType { name = 'elasticSecurityApi'; @@ -8,12 +14,42 @@ export class ElasticSecurityApi implements ICredentialType { documentationUrl = 'elasticSecurity'; properties: INodeProperties[] = [ + { + displayName: 'Base URL', + name: 'baseUrl', + type: 'string', + default: '', + placeholder: 'e.g. https://mydeployment.kb.us-central1.gcp.cloud.es.io:9243', + description: "Referred to as Kibana 'endpoint' in the Elastic deployment dashboard", + required: true, + }, + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'API Key', + value: 'apiKey', + }, + { + name: 'Basic Auth', + value: 'basicAuth', + }, + ], + default: 'basicAuth', + }, { displayName: 'Username', name: 'username', type: 'string', default: '', required: true, + displayOptions: { + show: { + type: ['basicAuth'], + }, + }, }, { displayName: 'Password', @@ -24,15 +60,52 @@ export class ElasticSecurityApi implements ICredentialType { }, default: '', required: true, + displayOptions: { + show: { + type: ['basicAuth'], + }, + }, }, { - displayName: 'Base URL', - name: 'baseUrl', - type: 'string', - default: '', - placeholder: 'e.g. https://mydeployment.kb.us-central1.gcp.cloud.es.io:9243', - description: "Referred to as Kibana 'endpoint' in the Elastic deployment dashboard", + displayName: 'API Key', + name: 'apiKey', required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + displayOptions: { + show: { + type: ['apiKey'], + }, + }, }, ]; + + async authenticate( + credentials: ICredentialDataDecryptedObject, + requestOptions: IHttpRequestOptions, + ): Promise { + if (credentials.type === 'apiKey') { + requestOptions.headers = { + Authorization: `ApiKey ${credentials.apiKey}`, + }; + } else { + requestOptions.auth = { + username: credentials.username as string, + password: credentials.password as string, + }; + requestOptions.headers = { + 'kbn-xsrf': true, + }; + } + return requestOptions; + } + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.baseUrl}}', + url: '/api/endpoint/metadata', + method: 'GET', + }, + }; } diff --git a/packages/nodes-base/credentials/FilescanApi.credentials.ts b/packages/nodes-base/credentials/FilescanApi.credentials.ts new file mode 100644 index 0000000000..ebc4562b0f --- /dev/null +++ b/packages/nodes-base/credentials/FilescanApi.credentials.ts @@ -0,0 +1,50 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class FilescanApi implements ICredentialType { + name = 'filescanApi'; + + displayName = 'Filescan API'; + + documentationUrl = 'filescan'; + + icon = { light: 'file:icons/Filescan.svg', dark: 'file:icons/Filescan.svg' } as const; + + httpRequestNode = { + name: 'Filescan', + docsUrl: 'https://www.filescan.io/api/docs', + apiBaseUrlPlaceholder: 'https://www.filescan.io/api/system/do-healthcheck', + }; + + properties: INodeProperties[] = [ + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + 'X-Api-Key': '={{$credentials.apiKey}}', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + baseURL: 'https://www.filescan.io/api', + url: '/system/do-healthcheck', + method: 'GET', + }, + }; +} diff --git a/packages/nodes-base/credentials/MalcoreApi.credentials.ts b/packages/nodes-base/credentials/MalcoreApi.credentials.ts new file mode 100644 index 0000000000..fc299f35ea --- /dev/null +++ b/packages/nodes-base/credentials/MalcoreApi.credentials.ts @@ -0,0 +1,51 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class MalcoreApi implements ICredentialType { + name = 'malcoreApi'; + + displayName = 'MalcoreAPI'; + + documentationUrl = 'malcore'; + + icon = { light: 'file:icons/Malcore.png', dark: 'file:icons/Malcore.png' } as const; + + httpRequestNode = { + name: 'Malcore', + docsUrl: 'https://malcore.readme.io/reference/upload', + apiBaseUrlPlaceholder: 'https://api.malcore.io/api/urlcheck', + }; + + properties: INodeProperties[] = [ + { + displayName: 'API Key', + name: 'apiKey', + required: true, + type: 'string', + typeOptions: { password: true }, + default: '', + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + apiKey: '={{$credentials.apiKey}}', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + baseURL: 'https://api.malcore.io/api', + url: '/urlcheck', + method: 'POST', + body: { url: 'google.com' }, + }, + }; +} diff --git a/packages/nodes-base/credentials/icons/Datadog.svg b/packages/nodes-base/credentials/icons/Datadog.svg new file mode 100644 index 0000000000..49e6f8473f --- /dev/null +++ b/packages/nodes-base/credentials/icons/Datadog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/nodes-base/credentials/icons/DfirIris.svg b/packages/nodes-base/credentials/icons/DfirIris.svg new file mode 100644 index 0000000000..83c41d6544 --- /dev/null +++ b/packages/nodes-base/credentials/icons/DfirIris.svg @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/nodes-base/credentials/icons/Dynatrace.svg b/packages/nodes-base/credentials/icons/Dynatrace.svg new file mode 100644 index 0000000000..863f93c123 --- /dev/null +++ b/packages/nodes-base/credentials/icons/Dynatrace.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/nodes-base/credentials/icons/Elastic.svg b/packages/nodes-base/credentials/icons/Elastic.svg new file mode 100644 index 0000000000..d240ad568c --- /dev/null +++ b/packages/nodes-base/credentials/icons/Elastic.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/packages/nodes-base/credentials/icons/Filescan.svg b/packages/nodes-base/credentials/icons/Filescan.svg new file mode 100644 index 0000000000..16f2bdba0a --- /dev/null +++ b/packages/nodes-base/credentials/icons/Filescan.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/nodes-base/credentials/icons/Malcore.png b/packages/nodes-base/credentials/icons/Malcore.png new file mode 100644 index 0000000000..b7f3ef35ca Binary files /dev/null and b/packages/nodes-base/credentials/icons/Malcore.png differ diff --git a/packages/nodes-base/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.ts b/packages/nodes-base/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.ts index 5d53ce9647..36df215476 100644 --- a/packages/nodes-base/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.ts +++ b/packages/nodes-base/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.ts @@ -1,15 +1,11 @@ import type { IExecuteFunctions, - ICredentialsDecrypted, - ICredentialTestFunctions, IDataObject, ILoadOptionsFunctions, - INodeCredentialTestResult, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription, - IRequestOptions, } from 'n8n-workflow'; import { NodeOperationError } from 'n8n-workflow'; @@ -19,7 +15,6 @@ import { getVersion, handleListing, throwOnEmptyUpdate, - tolerateTrailingSlash, } from './GenericFunctions'; import { @@ -33,12 +28,7 @@ import { connectorOperations, } from './descriptions'; -import type { - Connector, - ConnectorCreatePayload, - ConnectorType, - ElasticSecurityApiCredentials, -} from './types'; +import type { Connector, ConnectorCreatePayload, ConnectorType } from './types'; export class ElasticSecurity implements INodeType { description: INodeTypeDescription = { @@ -58,7 +48,6 @@ export class ElasticSecurity implements INodeType { { name: 'elasticSecurityApi', required: true, - testedBy: 'elasticSecurityApiTest', }, ], properties: [ @@ -115,49 +104,6 @@ export class ElasticSecurity implements INodeType { return connectors.map(({ name, id }) => ({ name, value: id })); }, }, - credentialTest: { - async elasticSecurityApiTest( - this: ICredentialTestFunctions, - credential: ICredentialsDecrypted, - ): Promise { - const { - username, - password, - baseUrl: rawBaseUrl, - } = credential.data as ElasticSecurityApiCredentials; - - const baseUrl = tolerateTrailingSlash(rawBaseUrl); - - const token = Buffer.from(`${username}:${password}`).toString('base64'); - - const endpoint = '/cases/status'; - - const options: IRequestOptions = { - headers: { - Authorization: `Basic ${token}`, - 'kbn-xsrf': true, - }, - method: 'GET', - body: {}, - qs: {}, - uri: `${baseUrl}/api${endpoint}`, - json: true, - }; - - try { - await this.helpers.request(options); - return { - status: 'OK', - message: 'Authentication successful', - }; - } catch (error) { - return { - status: 'Error', - message: error.message, - }; - } - }, - }, }; async execute(this: IExecuteFunctions): Promise { diff --git a/packages/nodes-base/nodes/Elastic/ElasticSecurity/GenericFunctions.ts b/packages/nodes-base/nodes/Elastic/ElasticSecurity/GenericFunctions.ts index 696170cff1..7a055eb1e1 100644 --- a/packages/nodes-base/nodes/Elastic/ElasticSecurity/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Elastic/ElasticSecurity/GenericFunctions.ts @@ -21,21 +21,13 @@ export async function elasticSecurityApiRequest( body: IDataObject = {}, qs: IDataObject = {}, ) { - const { - username, - password, - baseUrl: rawBaseUrl, - } = (await this.getCredentials('elasticSecurityApi')) as ElasticSecurityApiCredentials; + const { baseUrl: rawBaseUrl } = (await this.getCredentials( + 'elasticSecurityApi', + )) as ElasticSecurityApiCredentials; const baseUrl = tolerateTrailingSlash(rawBaseUrl); - const token = Buffer.from(`${username}:${password}`).toString('base64'); - const options: IRequestOptions = { - headers: { - Authorization: `Basic ${token}`, - 'kbn-xsrf': true, - }, method, body, qs, @@ -52,7 +44,7 @@ export async function elasticSecurityApiRequest( } try { - return await this.helpers.request(options); + return await this.helpers.requestWithAuthentication.call(this, 'elasticSecurityApi', options); } catch (error) { if (error?.error?.error === 'Not Acceptable' && error?.error?.message) { error.error.error = `${error.error.error}: ${error.error.message}`; diff --git a/packages/nodes-base/nodes/Elastic/ElasticSecurity/types.ts b/packages/nodes-base/nodes/Elastic/ElasticSecurity/types.ts index 268762ec62..dd426714e7 100644 --- a/packages/nodes-base/nodes/Elastic/ElasticSecurity/types.ts +++ b/packages/nodes-base/nodes/Elastic/ElasticSecurity/types.ts @@ -1,6 +1,7 @@ export type ElasticSecurityApiCredentials = { - username: string; - password: string; + username?: string; + password?: string; + apiKey?: string; baseUrl: string; }; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index db05bf38c1..4239424b67 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -75,8 +75,10 @@ "dist/credentials/CrowdStrikeOAuth2Api.credentials.js", "dist/credentials/CrowdDevApi.credentials.js", "dist/credentials/CustomerIoApi.credentials.js", + "dist/credentials/DatadogApi.credentials.js", "dist/credentials/DeepLApi.credentials.js", "dist/credentials/DemioApi.credentials.js", + "dist/credentials/DfirIrisApi.credentials.js", "dist/credentials/DhlApi.credentials.js", "dist/credentials/DiscordBotApi.credentials.js", "dist/credentials/DiscordOAuth2Api.credentials.js", @@ -88,6 +90,7 @@ "dist/credentials/DropboxApi.credentials.js", "dist/credentials/DropboxOAuth2Api.credentials.js", "dist/credentials/DropcontactApi.credentials.js", + "dist/credentials/DynatraceApi.credentials.js", "dist/credentials/EgoiApi.credentials.js", "dist/credentials/ElasticsearchApi.credentials.js", "dist/credentials/ElasticSecurityApi.credentials.js", @@ -101,6 +104,7 @@ "dist/credentials/FacebookLeadAdsOAuth2Api.credentials.js", "dist/credentials/FigmaApi.credentials.js", "dist/credentials/FileMaker.credentials.js", + "dist/credentials/FilescanApi.credentials.js", "dist/credentials/FlowApi.credentials.js", "dist/credentials/FormIoApi.credentials.js", "dist/credentials/FormstackApi.credentials.js", @@ -198,6 +202,7 @@ "dist/credentials/MailgunApi.credentials.js", "dist/credentials/MailjetEmailApi.credentials.js", "dist/credentials/MailjetSmsApi.credentials.js", + "dist/credentials/MalcoreApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", "dist/credentials/MarketstackApi.credentials.js", "dist/credentials/MatrixApi.credentials.js",