diff --git a/package-lock.json b/package-lock.json
index 0193f52c32..daf3fb0ee6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8498,6 +8498,11 @@
"integrity": "sha512-uaht4XcYSq5ZrPriQW8C+g5DhptewRd1E84ph7L167sCyzLObz+U3JTpmYq/CNkvjNsz2mtyQoHPNEYQYTzWmg==",
"dev": true
},
+ "node_modules/@types/js-nacl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@types/js-nacl/-/js-nacl-1.3.0.tgz",
+ "integrity": "sha512-juUvxo444ZfwDSwWyhssMxSN+snqTdiUoOVXZF+/ffVrGHq3rAf1fmczWn3z9TCEAuRbaTmgAcYlZ9MutyyOkQ=="
+ },
"node_modules/@types/json-diff": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@types/json-diff/-/json-diff-0.5.2.tgz",
@@ -46250,12 +46255,25 @@
"@types/vorpal": "^1.11.0"
}
},
+ "packages/node-dev/node_modules/typescript": {
+ "version": "4.6.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
+ "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
"packages/nodes-base": {
"name": "n8n-nodes-base",
"version": "0.194.0",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"@kafkajs/confluent-schema-registry": "1.0.6",
+ "@types/js-nacl": "^1.3.0",
"amqplib": "^0.8.0",
"aws4": "^1.8.0",
"basic-auth": "^2.0.1",
@@ -46275,6 +46293,7 @@
"imap-simple": "^4.3.0",
"isbot": "^3.3.4",
"iso-639-1": "^2.1.3",
+ "js-nacl": "^1.4.0",
"jsonwebtoken": "^8.5.1",
"kafkajs": "^1.14.0",
"lodash.get": "^4.4.2",
@@ -54844,6 +54863,11 @@
"integrity": "sha512-uaht4XcYSq5ZrPriQW8C+g5DhptewRd1E84ph7L167sCyzLObz+U3JTpmYq/CNkvjNsz2mtyQoHPNEYQYTzWmg==",
"dev": true
},
+ "@types/js-nacl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@types/js-nacl/-/js-nacl-1.3.0.tgz",
+ "integrity": "sha512-juUvxo444ZfwDSwWyhssMxSN+snqTdiUoOVXZF+/ffVrGHq3rAf1fmczWn3z9TCEAuRbaTmgAcYlZ9MutyyOkQ=="
+ },
"@types/json-diff": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@types/json-diff/-/json-diff-0.5.2.tgz",
@@ -74246,6 +74270,7 @@
"@types/gm": "^1.18.2",
"@types/imap-simple": "^4.2.0",
"@types/jest": "^27.4.0",
+ "@types/js-nacl": "^1.3.0",
"@types/jsonwebtoken": "^8.5.2",
"@types/lodash.set": "^4.3.6",
"@types/lossless-json": "^1.0.0",
@@ -74285,6 +74310,7 @@
"isbot": "^3.3.4",
"iso-639-1": "^2.1.3",
"jest": "^27.4.7",
+ "js-nacl": "^1.4.0",
"jsonwebtoken": "^8.5.1",
"kafkajs": "^1.14.0",
"lodash.get": "^4.4.2",
diff --git a/packages/nodes-base/credentials/VenafiTlsProtectCloudApi.credentials.ts b/packages/nodes-base/credentials/VenafiTlsProtectCloudApi.credentials.ts
new file mode 100644
index 0000000000..91488a6e9c
--- /dev/null
+++ b/packages/nodes-base/credentials/VenafiTlsProtectCloudApi.credentials.ts
@@ -0,0 +1,35 @@
+import {
+ IAuthenticateGeneric,
+ ICredentialDataDecryptedObject,
+ ICredentialTestRequest,
+ ICredentialType,
+ IHttpRequestOptions,
+ NodePropertyTypes,
+} from 'n8n-workflow';
+
+export class VenafiTlsProtectCloudApi implements ICredentialType {
+ name = 'venafiTlsProtectCloudApi';
+ displayName = 'Venafi TLS Protect Cloud';
+ properties = [
+ {
+ displayName: 'API Key',
+ name: 'apiKey',
+ type: 'string' as NodePropertyTypes,
+ default: '',
+ },
+ ];
+ authenticate: IAuthenticateGeneric = {
+ type: 'generic',
+ properties: {
+ headers: {
+ 'tppl-api-key': '={{$credentials.apiKey}}',
+ },
+ },
+ };
+ test: ICredentialTestRequest = {
+ request: {
+ baseURL: 'https://api.venafi.cloud',
+ url: '/v1/preferences',
+ },
+ };
+}
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateDescription.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateDescription.ts
new file mode 100644
index 0000000000..d813c71718
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateDescription.ts
@@ -0,0 +1,398 @@
+import { INodeProperties } from 'n8n-workflow';
+
+export const certificateOperations: INodeProperties[] = [
+ {
+ displayName: 'Operation',
+ name: 'operation',
+ noDataExpression: true,
+ type: 'options',
+ displayOptions: {
+ show: {
+ resource: ['certificate'],
+ },
+ },
+ options: [
+ {
+ name: 'Delete',
+ value: 'delete',
+ description: 'Delete a certificate',
+ action: 'Delete a certificate',
+ },
+ {
+ name: 'Download',
+ value: 'download',
+ description: 'Download a certificate',
+ action: 'Download a certificate',
+ },
+ {
+ name: 'Get',
+ value: 'get',
+ description: 'Retrieve a certificate',
+ action: 'Get a certificate',
+ },
+ {
+ name: 'Get Many',
+ value: 'getMany',
+ description: 'Retrieve many certificates',
+ action: 'Get many certificates',
+ },
+ {
+ name: 'Renew',
+ value: 'renew',
+ description: 'Renew a certificate',
+ action: 'Renew a certificate',
+ },
+ ],
+ default: 'delete',
+ },
+];
+
+export const certificateFields: INodeProperties[] = [
+ /* -------------------------------------------------------------------------- */
+ /* certificate:download */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Certificate ID',
+ name: 'certificateId',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Download Item',
+ name: 'downloadItem',
+ type: 'options',
+ options: [
+ {
+ name: 'Certificate',
+ value: 'certificate',
+ },
+ {
+ name: 'Keystore',
+ value: 'keystore',
+ },
+ ],
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ },
+ },
+ default: 'certificate',
+ },
+ {
+ displayName: 'Keystore Type',
+ name: 'keystoreType',
+ type: 'options',
+ options: [
+ {
+ name: 'JKS',
+ value: 'JKS',
+ },
+ {
+ name: 'PKCS12',
+ value: 'PKCS12',
+ },
+ {
+ name: 'PEM',
+ value: 'PEM',
+ },
+ ],
+ default: 'PEM',
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ downloadItem: ['keystore'],
+ },
+ },
+ },
+ {
+ displayName: 'Certificate Label',
+ name: 'certificateLabel',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ downloadItem: ['keystore'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Private Key Passphrase',
+ name: 'privateKeyPassphrase',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ downloadItem: ['keystore'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Keystore Passphrase',
+ name: 'keystorePassphrase',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ downloadItem: ['keystore'],
+ keystoreType: ['JKS'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Input Data Field Name',
+ name: 'binaryProperty',
+ type: 'string',
+ default: 'data',
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ },
+ },
+ required: true,
+ description:
+ 'The name of the input field containing the binary file data to be uploaded',
+ },
+ {
+ displayName: 'Options',
+ name: 'options',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ displayOptions: {
+ show: {
+ operation: ['download'],
+ resource: ['certificate'],
+ },
+ },
+ options: [
+ {
+ displayName: 'Chain Order',
+ name: 'chainOrder',
+ type: 'options',
+ options: [
+ {
+ name: 'EE_FIRST',
+ value: 'EE_FIRST',
+ description: 'Download the certificate with the end-entity portion of the chain first',
+ },
+ {
+ name: 'EE_ONLY',
+ value: 'EE_ONLY',
+ description: 'Download only the end-entity certificate',
+ },
+ {
+ name: 'ROOT_FIRST',
+ value: 'ROOT_FIRST',
+ description: 'Download the certificate with root portion of the chain first',
+ },
+ ],
+ default: 'ROOT_FIRST',
+ },
+ {
+ displayName: 'Format',
+ name: 'format',
+ type: 'options',
+ options: [
+ {
+ name: 'PEM',
+ value: 'PEM',
+ },
+ {
+ name: 'DER',
+ value: 'DER',
+ },
+ ],
+ default: 'PEM',
+ },
+ ],
+ },
+ /* -------------------------------------------------------------------------- */
+ /* certificate:get */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Certificate ID',
+ name: 'certificateId',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['get', 'delete'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ /* -------------------------------------------------------------------------- */
+ /* certificate:getMany */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Return All',
+ name: 'returnAll',
+ type: 'boolean',
+ displayOptions: {
+ show: {
+ operation: ['getMany'],
+ resource: ['certificate'],
+ },
+ },
+ default: false,
+ description: 'Whether to return all results or only up to a given limit',
+ },
+ {
+ displayName: 'Limit',
+ name: 'limit',
+ type: 'number',
+ displayOptions: {
+ show: {
+ operation: ['getMany'],
+ resource: ['certificate'],
+ returnAll: [false],
+ },
+ },
+ typeOptions: {
+ minValue: 1,
+ maxValue: 500,
+ },
+ default: 50,
+ description: 'Max number of results to return',
+ },
+ {
+ displayName: 'Filters',
+ name: 'filters',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ displayOptions: {
+ show: {
+ operation: ['getMany'],
+ resource: ['certificate'],
+ },
+ },
+ options: [
+ {
+ displayName: 'Subject',
+ name: 'subject',
+ type: 'string',
+ default: '',
+ },
+ ],
+ },
+ /* -------------------------------------------------------------------------- */
+ /* certificate:renew */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Application Name or ID',
+ name: 'applicationId',
+ type: 'options',
+ description:
+ 'Choose from the list, or specify an ID using an expression',
+ typeOptions: {
+ loadOptionsMethod: 'getApplications',
+ },
+ displayOptions: {
+ show: {
+ operation: ['renew'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Existing Certificate ID',
+ name: 'existingCertificateId',
+ type: 'string',
+ displayOptions: {
+ show: {
+ operation: ['renew'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Certificate Issuing Template Name or ID',
+ name: 'certificateIssuingTemplateId',
+ type: 'options',
+ description:
+ 'Choose from the list, or specify an ID using an expression',
+ typeOptions: {
+ loadOptionsMethod: 'getCertificateIssuingTemplates',
+ },
+ displayOptions: {
+ show: {
+ operation: ['renew'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Certificate Signing Request',
+ name: 'certificateSigningRequest',
+ type: 'string',
+ typeOptions: {
+ alwaysOpenEditWindow: true,
+ },
+ displayOptions: {
+ show: {
+ operation: ['renew'],
+ resource: ['certificate'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Options',
+ name: 'options',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ displayOptions: {
+ show: {
+ operation: ['renew'],
+ resource: ['certificate'],
+ },
+ },
+ options: [
+ {
+ displayName: 'Validity Period',
+ name: 'validityPeriod',
+ type: 'options',
+ options: [
+ {
+ name: '1 Year',
+ value: 'P1Y',
+ },
+ {
+ name: '10 Days',
+ value: 'P10D',
+ },
+ {
+ name: '12 Hours',
+ value: 'PT12H',
+ },
+ ],
+ default: 'P1Y',
+ },
+ ],
+ },
+];
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateInterface.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateInterface.ts
new file mode 100644
index 0000000000..53d41cc404
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateInterface.ts
@@ -0,0 +1,41 @@
+export interface ICertficateRequest {
+ isVaaSGenerated?: boolean;
+ csrAttributes?: ICsrAttributes;
+ applicationServerTypeId?: string;
+ certificateSigningRequest?: string;
+ applicationId?: string;
+ certificateIssuingTemplateId?: string;
+ certficateOwnerUserId?: string;
+ validityPeriod?: string;
+}
+
+export interface ICsrAttributes {
+ commonName?: string;
+ organization?: string;
+ organizationalUnits?: string[];
+ locality?: string;
+ state?: string;
+ country?: string;
+ keyTypeParameters?: IKeyTypeParameters;
+ subjectAlternativeNamesByType?: ISubjectAltNamesByType;
+}
+
+export interface IKeyTypeParameters {
+ keyType?: string;
+ keyCurve?: string;
+ keyLength?: number;
+}
+
+export interface ISubjectAltNamesByType {
+ dnsNames?: string[];
+ rfc822Names?: string[];
+ ipAddresses?: string[];
+ uniformResourceIdentifiers?: string[];
+}
+
+export interface ICertficateKeystoreRequest {
+ exportFormat?: string;
+ encryptedPrivateKeyPassphrase?: string;
+ encryptedKeystorePassphrase?: string;
+ certificateLabel?: string;
+}
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateRequestDescription.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateRequestDescription.ts
new file mode 100644
index 0000000000..f2d3e9d73e
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/CertificateRequestDescription.ts
@@ -0,0 +1,388 @@
+import { INodeProperties } from 'n8n-workflow';
+
+export const certificateRequestOperations: INodeProperties[] = [
+ {
+ displayName: 'Operation',
+ name: 'operation',
+ noDataExpression: true,
+ type: 'options',
+ displayOptions: {
+ show: {
+ resource: ['certificateRequest'],
+ },
+ },
+ options: [
+ {
+ name: 'Create',
+ value: 'create',
+ description: 'Create a new certificate request',
+ action: 'Create a certificate request',
+ },
+ {
+ name: 'Get',
+ value: 'get',
+ description: 'Retrieve a certificate request',
+ action: 'Get a certificate request',
+ },
+ {
+ name: 'Get Many',
+ value: 'getMany',
+ description: 'Retrieve many certificate requests',
+ action: 'Get many certificate requests',
+ },
+ ],
+ default: 'create',
+ },
+];
+
+export const certificateRequestFields: INodeProperties[] = [
+ /* -------------------------------------------------------------------------- */
+ /* certificateRequest:create */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Application Name or ID',
+ name: 'applicationId',
+ type: 'options',
+ description:
+ 'Choose from the list, or specify an ID using an expression',
+ typeOptions: {
+ loadOptionsMethod: 'getApplications',
+ },
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Certificate Issuing Template Name or ID',
+ name: 'certificateIssuingTemplateId',
+ type: 'options',
+ description:
+ 'Choose from the list, or specify an ID using an expression',
+ typeOptions: {
+ loadOptionsMethod: 'getCertificateIssuingTemplates',
+ },
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Generate CSR',
+ name: 'generateCsr',
+ type: 'boolean',
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ },
+ },
+ default: false,
+ },
+ {
+ displayName: 'Application Server Type Name or ID',
+ name: 'applicationServerTypeId',
+ type: 'options',
+ description:
+ 'Choose from the list, or specify an ID using an expression',
+ typeOptions: {
+ loadOptionsMethod: 'getApplicationServerTypes',
+ },
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ generateCsr: [true],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Common Name',
+ name: 'commonName',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ generateCsr: [true],
+ },
+ },
+ type: 'string',
+ default: 'n8n.io',
+ description: 'The Common Name field for the certificate Subject (CN)',
+ },
+ // Optional...
+ {
+ displayName: 'Additional Fields',
+ name: 'additionalFields',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ generateCsr: [true],
+ },
+ },
+ options: [
+ {
+ displayName: 'Country',
+ name: 'country',
+ type: 'string',
+ default: '',
+ description: 'A 2 letter country code',
+ },
+ {
+ displayName: 'Key Curve',
+ name: 'keyCurve',
+ type: 'options',
+ options: [
+ {
+ name: 'ED25519',
+ value: 'ED25519',
+ description: 'Use Edwards-curve Digital Signature Algorithm (EdDSA)',
+ },
+ {
+ name: 'P256',
+ value: 'P256',
+ description: 'Use Elliptic Prime Curve 256 bit encryption',
+ },
+ {
+ name: 'P384',
+ value: 'P384',
+ description: 'Use Elliptic Prime Curve 384 bit encryption',
+ },
+ {
+ name: 'P521',
+ value: 'P521',
+ description: 'Use Elliptic Prime Curve 521 bit encryption',
+ },
+ {
+ name: 'UNKNOWN',
+ value: 'UNKNOWN',
+ },
+ ],
+ default: 'ED25519',
+ },
+ {
+ displayName: 'Key Length',
+ name: 'keyLength',
+ type: 'number',
+ default: 2048,
+ description: 'The number of bits to allow for key generation',
+ },
+ {
+ displayName: 'Key Type',
+ name: 'keyType',
+ type: 'options',
+ options: [
+ {
+ name: 'EC',
+ value: 'EC',
+ description: 'Elliptic Curve (EC)',
+ },
+ {
+ name: 'RSA',
+ value: 'RSA',
+ description: 'Rivest, Shamir, Adleman key (RSA)',
+ },
+ ],
+ default: 'RSA',
+ description: 'The encryption algorithm for the public key',
+ },
+ {
+ displayName: 'Locality',
+ name: 'locality',
+ type: 'string',
+ default: '',
+ description: 'The name of a city or town',
+ },
+ {
+ displayName: 'Organization',
+ name: 'organization',
+ type: 'string',
+ default: '',
+ description: 'The name of a company or organization',
+ },
+ {
+ displayName: 'Organizational Units',
+ name: 'organizationalUnits',
+ type: 'string',
+ typeOptions: {
+ multipleValues: true,
+ },
+ default: '',
+ description: 'The name of a department or section',
+ },
+ {
+ displayName: 'State',
+ name: 'state',
+ type: 'string',
+ default: '',
+ description: 'The name of a state or province',
+ },
+ {
+ displayName: 'Subject Alt Names',
+ name: 'SubjectAltNamesUi',
+ placeholder: 'Add Subject',
+ type: 'fixedCollection',
+ default: {},
+ typeOptions: {
+ multipleValues: true,
+ },
+ options: [
+ {
+ name: 'SubjectAltNamesValues',
+ displayName: 'Subject Alt Name',
+ values: [
+ {
+ displayName: 'Typename',
+ name: 'Typename',
+ type: 'options',
+ options: [
+ {
+ name: 'DNS',
+ value: 'dnsNames',
+ },
+ /*{
+ name: 'IP Address',
+ value: 'ipAddresses',
+ },
+ {
+ name: 'RFC822 Names',
+ value: 'rfc822Names',
+ },
+
+ {
+ name: 'URI',
+ value: 'uniformResourceIdentifiers',
+ },*/
+ ],
+ description: 'What type of SAN is being used',
+ default: 'dnsNames',
+ },
+ {
+ displayName: 'Name',
+ name: 'name',
+ type: 'string',
+ default: 'community.n8n.io',
+ description:
+ 'The SAN friendly name that corresponds to the Type or TypeName parameter. For example, if a TypeName is IPAddress, the Name value is a valid IP address.',
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ // End CSR Builder
+ {
+ displayName: 'Certificate Signing Request',
+ name: 'certificateSigningRequest',
+ type: 'string',
+ typeOptions: {
+ alwaysOpenEditWindow: true,
+ },
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ generateCsr: [false],
+ },
+ },
+ default: '',
+ },
+ {
+ displayName: 'Options',
+ name: 'options',
+ type: 'collection',
+ placeholder: 'Add Field',
+ default: {},
+ displayOptions: {
+ show: {
+ operation: ['create'],
+ resource: ['certificateRequest'],
+ },
+ },
+ options: [
+ {
+ displayName: 'Validity Period',
+ name: 'validityPeriod',
+ type: 'options',
+ options: [
+ {
+ name: '1 Year',
+ value: 'P1Y',
+ },
+ {
+ name: '10 Days',
+ value: 'P10D',
+ },
+ {
+ name: '12 Hours',
+ value: 'PT12H',
+ },
+ ],
+ default: 'P1Y',
+ },
+ ],
+ },
+ /* -------------------------------------------------------------------------- */
+ /* certificateRequest:get */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Certificate Request ID',
+ name: 'certificateRequestId',
+ type: 'string',
+ required: true,
+ displayOptions: {
+ show: {
+ operation: ['get'],
+ resource: ['certificateRequest'],
+ },
+ },
+ default: '',
+ },
+ /* -------------------------------------------------------------------------- */
+ /* certificateRequest:getMany */
+ /* -------------------------------------------------------------------------- */
+ {
+ displayName: 'Return All',
+ name: 'returnAll',
+ type: 'boolean',
+ displayOptions: {
+ show: {
+ operation: ['getMany'],
+ resource: ['certificateRequest'],
+ },
+ },
+ default: false,
+ description: 'Whether to return all results or only up to a given limit',
+ },
+ {
+ displayName: 'Limit',
+ name: 'limit',
+ type: 'number',
+ displayOptions: {
+ show: {
+ operation: ['getMany'],
+ resource: ['certificateRequest'],
+ returnAll: [false],
+ },
+ },
+ typeOptions: {
+ minValue: 1,
+ maxValue: 500,
+ },
+ default: 50,
+ description: 'Max number of results to return',
+ },
+];
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/GenericFunctions.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/GenericFunctions.ts
new file mode 100644
index 0000000000..678dd9d0a9
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/GenericFunctions.ts
@@ -0,0 +1,146 @@
+import { OptionsWithUri } from 'request';
+
+import {
+ IExecuteFunctions,
+ IExecuteSingleFunctions,
+ ILoadOptionsFunctions,
+ IPollFunctions,
+} from 'n8n-core';
+
+import { IDataObject, JsonObject, NodeApiError } from 'n8n-workflow';
+
+import { get } from 'lodash';
+
+import * as nacl_factory from 'js-nacl';
+
+export async function venafiApiRequest(
+ this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions | IPollFunctions,
+ method: string,
+ resource: string,
+ body = {},
+ qs: IDataObject = {},
+ uri?: string,
+ option: IDataObject = {},
+ // tslint:disable-next-line:no-any
+): Promise {
+ const operation = this.getNodeParameter('operation', 0) as string;
+
+ const options: OptionsWithUri = {
+ headers: {
+ Accept: 'application/json',
+ 'content-type': 'application/json',
+ },
+ method,
+ body,
+ qs,
+ uri: `https://api.venafi.cloud${resource}`,
+ json: true,
+ };
+
+ if (Object.keys(option).length) {
+ Object.assign(options, option);
+ }
+
+ // For cert download we don't need any headers
+ // If we remove for everything the key fetch fails
+ if (operation === 'download') {
+ // We need content-type for keystore
+ if (!resource.endsWith('keystore')) {
+ delete options!.headers!['Accept'];
+ delete options!.headers!['content-type'];
+ }
+ }
+
+ try {
+ if (Object.keys(body).length === 0) {
+ delete options.body;
+ }
+ return await this.helpers.requestWithAuthentication.call(
+ this,
+ 'venafiTlsProtectCloudApi',
+ options,
+ );
+ } catch (error) {
+ throw new NodeApiError(this.getNode(), error as JsonObject);
+ }
+}
+
+export async function venafiApiRequestAllItems(
+ this: IExecuteFunctions | ILoadOptionsFunctions,
+ propertyName: string,
+ method: string,
+ endpoint: string,
+ // tslint:disable-next-line:no-any
+ body: any = {},
+ query: IDataObject = {},
+ // tslint:disable-next-line:no-any
+): Promise {
+ const returnData: IDataObject[] = [];
+
+ let responseData;
+
+ do {
+ responseData = await venafiApiRequest.call(this, method, endpoint, body, query);
+ endpoint = get(responseData, '_links[0].Next');
+ returnData.push.apply(returnData, responseData[propertyName]);
+ } while (responseData._links && responseData._links[0].Next);
+
+ return returnData;
+}
+
+export async function encryptPassphrase(
+ this: IExecuteFunctions | ILoadOptionsFunctions,
+ certificateId: string,
+ passphrase: string,
+ storePassphrase: string,
+) {
+ let dekHash = '';
+ const dekResponse = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificates/${certificateId}`,
+ );
+
+ if (dekResponse.dekHash) {
+ dekHash = dekResponse.dekHash;
+ }
+
+ let pubKey = '';
+ const pubKeyResponse = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/v1/edgeencryptionkeys/${dekHash}`,
+ );
+
+ if (pubKeyResponse.key) {
+ pubKey = pubKeyResponse.key;
+ }
+
+ let encryptedKeyPass = '';
+ let encryptedKeyStorePass = '';
+
+ const promise = () => {
+ return new Promise((resolve, reject) => {
+ // tslint:disable-next-line:no-any
+ nacl_factory.instantiate((nacl: any) => {
+ try {
+ const passphraseUTF8 = nacl.encode_utf8(passphrase) as string;
+ const keyPassBuffer = nacl.crypto_box_seal(passphraseUTF8, Buffer.from(pubKey, 'base64'));
+ encryptedKeyPass = Buffer.from(keyPassBuffer).toString('base64');
+
+ const storePassphraseUTF8 = nacl.encode_utf8(storePassphrase) as string;
+ const keyStorePassBuffer = nacl.crypto_box_seal(
+ storePassphraseUTF8,
+ Buffer.from(pubKey, 'base64'),
+ );
+ encryptedKeyStorePass = Buffer.from(keyStorePassBuffer).toString('base64');
+
+ return resolve([encryptedKeyPass, encryptedKeyStorePass]);
+ } catch (error) {
+ return reject(error);
+ }
+ });
+ });
+ };
+ return await promise();
+}
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.json b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.json
new file mode 100644
index 0000000000..8aaa7e1d1f
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.json
@@ -0,0 +1,18 @@
+{
+ "node": "n8n-nodes-base.venafiTlsProtectCloud",
+ "nodeVersion": "1.0",
+ "codexVersion": "1.0",
+ "categories": ["Development"],
+ "resources": {
+ "credentialDocumentation": [
+ {
+ "url": "https://docs.n8n.io/credentials/venafiTlsProtectCloud"
+ }
+ ],
+ "primaryDocumentation": [
+ {
+ "url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.venafiTlsProtectCloud/"
+ }
+ ]
+ }
+}
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.ts
new file mode 100644
index 0000000000..ef125f44ce
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.ts
@@ -0,0 +1,488 @@
+import { IExecuteFunctions } from 'n8n-core';
+
+import {
+ IDataObject,
+ ILoadOptionsFunctions,
+ INodeExecutionData,
+ INodePropertyOptions,
+ INodeType,
+ INodeTypeDescription,
+} from 'n8n-workflow';
+
+import { encryptPassphrase, venafiApiRequest, venafiApiRequestAllItems } from './GenericFunctions';
+
+import { certificateFields, certificateOperations } from './CertificateDescription';
+
+import {
+ certificateRequestFields,
+ certificateRequestOperations,
+} from './CertificateRequestDescription';
+
+import {
+ ICertficateKeystoreRequest,
+ ICertficateRequest,
+ ICsrAttributes,
+ IKeyTypeParameters,
+ ISubjectAltNamesByType,
+} from './CertificateInterface';
+
+export class VenafiTlsProtectCloud implements INodeType {
+ description: INodeTypeDescription = {
+ displayName: 'Venafi TLS Protect Cloud',
+ name: 'venafiTlsProtectCloud',
+ icon: 'file:../venafi.svg',
+ group: ['input'],
+ version: 1,
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
+ description: 'Consume Venafi TLS Protect Cloud API',
+ defaults: {
+ name: 'Venafi TLS Protect Cloud',
+ color: '#000000',
+ },
+ inputs: ['main'],
+ outputs: ['main'],
+ credentials: [
+ {
+ name: 'venafiTlsProtectCloudApi',
+ required: true,
+ },
+ ],
+ properties: [
+ {
+ displayName: 'Resource',
+ name: 'resource',
+ noDataExpression: true,
+ type: 'options',
+ options: [
+ {
+ name: 'Certificate',
+ value: 'certificate',
+ },
+ {
+ name: 'Certificate Request',
+ value: 'certificateRequest',
+ },
+ ],
+ default: 'certificateRequest',
+ },
+ ...certificateOperations,
+ ...certificateFields,
+ ...certificateRequestOperations,
+ ...certificateRequestFields,
+ ],
+ };
+
+ methods = {
+ loadOptions: {
+ async getApplications(this: ILoadOptionsFunctions): Promise {
+ const returnData: INodePropertyOptions[] = [];
+ const { applications } = await venafiApiRequest.call(
+ this,
+ 'GET',
+ '/outagedetection/v1/applications',
+ );
+ for (const application of applications) {
+ returnData.push({
+ name: application.name,
+ value: application.id,
+ });
+ }
+ return returnData;
+ },
+ async getApplicationServerTypes(
+ this: ILoadOptionsFunctions,
+ ): Promise {
+ const returnData: INodePropertyOptions[] = [];
+ const { applicationServerTypes } = await venafiApiRequest.call(
+ this,
+ 'GET',
+ '/outagedetection/v1/applicationservertypes',
+ );
+ for (const applicationServerType of applicationServerTypes) {
+ returnData.push({
+ name: applicationServerType.platformName,
+ value: applicationServerType.id,
+ });
+ }
+ return returnData;
+ },
+ async getCertificateIssuingTemplates(
+ this: ILoadOptionsFunctions,
+ ): Promise {
+ const returnData: INodePropertyOptions[] = [];
+ const { certificateIssuingTemplates } = await venafiApiRequest.call(
+ this,
+ 'GET',
+ '/v1/certificateissuingtemplates',
+ );
+ for (const issueTemplate of certificateIssuingTemplates) {
+ returnData.push({
+ name: issueTemplate.name,
+ value: issueTemplate.id,
+ });
+ }
+ return returnData;
+ },
+ },
+ };
+
+ async execute(this: IExecuteFunctions): Promise {
+ const items = this.getInputData();
+ const returnData: IDataObject[] = [];
+ const length = items.length;
+ const qs: IDataObject = {};
+ let responseData;
+ const resource = this.getNodeParameter('resource', 0) as string;
+ const operation = this.getNodeParameter('operation', 0) as string;
+ for (let i = 0; i < length; i++) {
+ try {
+ if (resource === 'certificateRequest') {
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config&urls.primaryName=outagedetection-service#//v1/certificaterequests_create
+ if (operation === 'create') {
+ const applicationId = this.getNodeParameter('applicationId', i) as string;
+ const certificateIssuingTemplateId = this.getNodeParameter(
+ 'certificateIssuingTemplateId',
+ i,
+ ) as string;
+ const options = this.getNodeParameter('options', i) as IDataObject;
+ const generateCsr = this.getNodeParameter('generateCsr', i) as boolean;
+
+ const body: ICertficateRequest = {
+ applicationId,
+ certificateIssuingTemplateId,
+ };
+
+ if (generateCsr) {
+ const applicationServerTypeId = this.getNodeParameter(
+ 'applicationServerTypeId',
+ i,
+ ) as string;
+ const commonName = this.getNodeParameter('commonName', i) as string;
+ const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
+
+ const keyTypeDetails: IKeyTypeParameters = {};
+ const csrAttributes: ICsrAttributes = {};
+ const subjectAltNamesByType: ISubjectAltNamesByType = {};
+
+ body.isVaaSGenerated = true;
+ body.applicationServerTypeId = applicationServerTypeId as string;
+
+ csrAttributes.commonName = commonName as string;
+
+ // Csr Generation
+ if (additionalFields.organization) {
+ csrAttributes.organization = additionalFields.organization as string;
+ }
+ if (additionalFields.organizationalUnits) {
+ csrAttributes.organizationalUnits =
+ additionalFields.organizationalUnits as string[];
+ }
+ if (additionalFields.locality) {
+ csrAttributes.locality = additionalFields.locality as string;
+ }
+ if (additionalFields.state) {
+ csrAttributes.state = additionalFields.state as string;
+ }
+ if (additionalFields.country) {
+ csrAttributes.country = additionalFields.country as string;
+ }
+ body.csrAttributes = csrAttributes;
+
+ // Key type
+ if (additionalFields.keyType) {
+ keyTypeDetails.keyType = additionalFields.keyType as string;
+ }
+ if (additionalFields.keyCurve) {
+ keyTypeDetails.keyCurve = additionalFields.keyCurve as string;
+ }
+ if (additionalFields.keyLength) {
+ keyTypeDetails.keyLength = additionalFields.keyLength as number;
+ }
+ if (Object.keys(keyTypeDetails).length !== 0) {
+ body.csrAttributes.keyTypeParameters = keyTypeDetails;
+ }
+
+ // SAN
+ if (additionalFields.SubjectAltNamesUi) {
+ for (const key of (additionalFields.SubjectAltNamesUi as IDataObject)
+ .SubjectAltNamesValues as IDataObject[]) {
+ if (key.Typename === 'dnsNames') {
+ subjectAltNamesByType.dnsNames
+ ? subjectAltNamesByType.dnsNames.push(key.name as string)
+ : (subjectAltNamesByType.dnsNames = [key.name as string]);
+ }
+ /*if (key.Typename === 'ipAddresses') {
+ subjectAltNamesByType.ipAddresses ? subjectAltNamesByType.ipAddresses.push(key.name as string) : subjectAltNamesByType.ipAddresses = [key.name as string];
+ }
+ if (key.Typename === 'rfc822Names') {
+ subjectAltNamesByType.rfc822Names ? subjectAltNamesByType.rfc822Names.push(key.name as string) : subjectAltNamesByType.rfc822Names = [key.name as string];
+ }
+ if (key.Typename === 'uniformResourceIdentifiers') {
+ subjectAltNamesByType.uniformResourceIdentifiers ? subjectAltNamesByType.uniformResourceIdentifiers.push(key.name as string) : subjectAltNamesByType.uniformResourceIdentifiers = [key.name as string];
+ }*/
+ }
+ }
+ if (Object.keys(subjectAltNamesByType).length !== 0) {
+ body.csrAttributes.subjectAlternativeNamesByType = subjectAltNamesByType;
+ }
+ } else {
+ const certificateSigningRequest = this.getNodeParameter(
+ 'certificateSigningRequest',
+ i,
+ ) as string;
+ body.isVaaSGenerated = false;
+ body.certificateSigningRequest = certificateSigningRequest;
+ }
+
+ Object.assign(body, options);
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'POST',
+ `/outagedetection/v1/certificaterequests`,
+ body,
+ qs,
+ );
+
+ responseData = responseData.certificateRequests;
+ }
+
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config&urls.primaryName=outagedetection-service#//v1/certificaterequests_getById
+ if (operation === 'get') {
+ const certificateId = this.getNodeParameter('certificateRequestId', i) as string;
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificaterequests/${certificateId}`,
+ {},
+ qs,
+ );
+ }
+
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config&urls.primaryName=outagedetection-service#//v1/certificaterequests_getAll
+ if (operation === 'getMany') {
+ const returnAll = this.getNodeParameter('returnAll', i) as boolean;
+
+ if (returnAll) {
+ responseData = await venafiApiRequestAllItems.call(
+ this,
+ 'certificateRequests',
+ 'GET',
+ `/outagedetection/v1/certificaterequests`,
+ {},
+ qs,
+ );
+ } else {
+ const limit = this.getNodeParameter('limit', i) as number;
+ responseData = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificaterequests`,
+ {},
+ qs,
+ );
+
+ responseData = responseData.certificateRequests.splice(0, limit);
+ }
+ }
+ }
+
+ if (resource === 'certificate') {
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=%2Fv3%2Fapi-docs%2Fswagger-config&urls.primaryName=outagedetection-service#/%2Fv1/certificateretirement_deleteCertificates
+ if (operation === 'delete') {
+ const certificateId = this.getNodeParameter('certificateId', i) as string;
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'POST',
+ `/outagedetection/v1/certificates/deletion`,
+ { certificateIds: [certificateId] },
+ );
+
+ responseData = responseData.certificates;
+ }
+
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=%2Fv3%2Fapi-docs%2Fswagger-config&urls.primaryName=outagedetection-service#/
+ if (operation === 'download') {
+ const certificateId = this.getNodeParameter('certificateId', i) as string;
+ const binaryProperty = this.getNodeParameter('binaryProperty', i) as string;
+ const downloadItem = this.getNodeParameter('downloadItem', i) as string;
+ const options = this.getNodeParameter('options', i) as IDataObject;
+
+ // Cert Download
+ if (downloadItem === 'certificate') {
+ Object.assign(qs, options);
+ responseData = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificates/${certificateId}/contents`,
+ {},
+ qs,
+ undefined,
+ { encoding: null, json: false, resolveWithFullResponse: true, cert: true },
+ );
+ } else {
+ const exportFormat = this.getNodeParameter('keystoreType', i) as string;
+
+ const body: ICertficateKeystoreRequest = {
+ exportFormat,
+ };
+
+ const privateKeyPassphrase = this.getNodeParameter(
+ 'privateKeyPassphrase',
+ i,
+ ) as string;
+ const certificateLabel = this.getNodeParameter('certificateLabel', i) as string;
+
+ body.certificateLabel = certificateLabel;
+
+ let keystorePassphrase = '';
+
+ if (exportFormat === 'JKS') {
+ keystorePassphrase = this.getNodeParameter('keystorePassphrase', i) as string;
+ }
+
+ const encryptedValues = (await encryptPassphrase.call(
+ this,
+ certificateId,
+ privateKeyPassphrase,
+ keystorePassphrase,
+ )) as string;
+ body.encryptedPrivateKeyPassphrase = encryptedValues[0];
+ if (exportFormat === 'JKS') {
+ body.encryptedKeystorePassphrase = encryptedValues[1];
+ }
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'POST',
+ `/outagedetection/v1/certificates/${certificateId}/keystore`,
+ body,
+ {},
+ undefined,
+ { encoding: null, json: false, resolveWithFullResponse: true },
+ );
+ }
+
+ const contentDisposition = responseData.headers['content-disposition'];
+ const fileNameRegex = /(?<=filename=").*\b/;
+ const match = fileNameRegex.exec(contentDisposition);
+ let fileName = '';
+
+ if (match !== null) {
+ fileName = match[0];
+ }
+
+ const binaryData = await this.helpers.prepareBinaryData(
+ Buffer.from(responseData.body),
+ fileName,
+ );
+
+ responseData = {
+ json: {},
+ binary: {
+ [binaryProperty]: binaryData,
+ },
+ };
+ }
+
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=%2Fv3%2Fapi-docs%2Fswagger-config&urls.primaryName=outagedetection-service#/%2Fv1/certificates_getById
+ if (operation === 'get') {
+ const certificateId = this.getNodeParameter('certificateId', i) as string;
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificates/${certificateId}`,
+ {},
+ qs,
+ );
+ }
+
+ //https://api.venafi.cloud/webjars/swagger-ui/index.html?configUrl=%2Fv3%2Fapi-docs%2Fswagger-config&urls.primaryName=outagedetection-service#/%2Fv1/certificates_getAllAsCsv
+ if (operation === 'getMany') {
+ const returnAll = this.getNodeParameter('returnAll', i) as boolean;
+ const filters = this.getNodeParameter('filters', i) as IDataObject;
+
+ Object.assign(qs, filters);
+
+ if (returnAll) {
+ responseData = await venafiApiRequestAllItems.call(
+ this,
+ 'certificates',
+ 'GET',
+ `/outagedetection/v1/certificates`,
+ {},
+ qs,
+ );
+ } else {
+ qs.limit = this.getNodeParameter('limit', i) as number;
+ responseData = await venafiApiRequest.call(
+ this,
+ 'GET',
+ `/outagedetection/v1/certificates`,
+ {},
+ qs,
+ );
+
+ responseData = responseData.certificates;
+ }
+ }
+
+ //https://docs.venafi.cloud/api/t-cloud-api-renew-cert/
+ if (operation === 'renew') {
+ const applicationId = this.getNodeParameter('applicationId', i) as string;
+ const certificateIssuingTemplateId = this.getNodeParameter(
+ 'certificateIssuingTemplateId',
+ i,
+ ) as string;
+ const certificateSigningRequest = this.getNodeParameter(
+ 'certificateSigningRequest',
+ i,
+ ) as string;
+ const existingCertificateId = this.getNodeParameter(
+ 'existingCertificateId',
+ i,
+ ) as string;
+ const options = this.getNodeParameter('options', i) as IDataObject;
+
+ const body: IDataObject = {
+ certificateSigningRequest,
+ certificateIssuingTemplateId,
+ applicationId,
+ existingCertificateId,
+ };
+
+ Object.assign(body, options);
+
+ responseData = await venafiApiRequest.call(
+ this,
+ 'POST',
+ `/outagedetection/v1/certificaterequests`,
+ body,
+ qs,
+ );
+
+ responseData = responseData.certificateRequests;
+ }
+ }
+
+ returnData.push(
+ ...this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), {
+ itemData: { item: i },
+ }),
+ );
+
+ } catch (error) {
+ if (this.continueOnFail()) {
+ returnData.push({ json: { error: error.message } });
+ continue;
+ }
+ throw error;
+ }
+ }
+
+ return [returnData as INodeExecutionData[]];
+ }
+}
diff --git a/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloudTrigger.node.ts b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloudTrigger.node.ts
new file mode 100644
index 0000000000..8db5ba08ca
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloudTrigger.node.ts
@@ -0,0 +1,101 @@
+import { IPollFunctions } from 'n8n-core';
+
+import { INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
+
+import moment from 'moment';
+
+import { venafiApiRequest } from './GenericFunctions';
+
+export class VenafiTlsProtectCloudTrigger implements INodeType {
+ description: INodeTypeDescription = {
+ displayName: 'Venafi TLS Protect Cloud Trigger',
+ name: 'venafiTlsProtectCloudTrigger',
+ icon: 'file:../venafi.svg',
+ group: ['trigger'],
+ version: 1,
+ subtitle: '={{$parameter["triggerOn"]}}',
+ description: 'Starts the workflow when Venafi events occure',
+ defaults: {
+ name: 'Venafi TLS Protect Cloud',
+ color: '#000000',
+ },
+ credentials: [
+ {
+ name: 'venafiTlsProtectCloudApi',
+ required: true,
+ },
+ ],
+ polling: true,
+ inputs: [],
+ outputs: ['main'],
+ properties: [
+ {
+ displayName: 'Trigger On',
+ name: 'trigger On',
+ type: 'options',
+ options: [
+ {
+ name: 'Certificate Expired',
+ value: 'certificateExpired',
+ },
+ ],
+ required: true,
+ default: 'certificateExpired',
+ },
+ ],
+ };
+
+ async poll(this: IPollFunctions): Promise {
+ const webhookData = this.getWorkflowStaticData('node');
+ const event = this.getNodeParameter('event') as string;
+
+ const now = moment().format();
+
+ const startDate = webhookData.lastTimeChecked || now;
+ const endDate = now;
+
+ const { certificates: certificates } = await venafiApiRequest.call(
+ this,
+ 'POST',
+ `/outagedetection/v1/certificatesearch`,
+ {
+ expression: {
+ operands: [
+ {
+ operator: 'AND',
+ operands: [
+ {
+ field: 'validityEnd',
+ operator: 'LTE',
+ values: [endDate],
+ },
+ {
+ field: 'validityEnd',
+ operator: 'GTE',
+ values: [startDate],
+ },
+ ],
+ },
+ ],
+ },
+ ordering: {
+ orders: [
+ {
+ field: 'certificatInstanceModificationDate',
+ direction: 'DESC',
+ },
+ ],
+ },
+ },
+ {},
+ );
+
+ webhookData.lastTimeChecked = endDate;
+
+ if (Array.isArray(certificates) && certificates.length) {
+ return [this.helpers.returnJsonArray(certificates)];
+ }
+
+ return null;
+ }
+}
diff --git a/packages/nodes-base/nodes/Venafi/venafi.svg b/packages/nodes-base/nodes/Venafi/venafi.svg
new file mode 100644
index 0000000000..70ed4594fa
--- /dev/null
+++ b/packages/nodes-base/nodes/Venafi/venafi.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json
index 232658f50c..d31e340462 100644
--- a/packages/nodes-base/package.json
+++ b/packages/nodes-base/package.json
@@ -317,6 +317,7 @@
"dist/credentials/UrlScanIoApi.credentials.js",
"dist/credentials/VeroApi.credentials.js",
"dist/credentials/VonageApi.credentials.js",
+ "dist/credentials/VenafiTlsProtectCloudApi.credentials.js",
"dist/credentials/VenafiTlsProtectDatacenterApi.credentials.js",
"dist/credentials/WebflowApi.credentials.js",
"dist/credentials/WebflowOAuth2Api.credentials.js",
@@ -686,6 +687,7 @@
"dist/nodes/UptimeRobot/UptimeRobot.node.js",
"dist/nodes/UrlScanIo/UrlScanIo.node.js",
"dist/nodes/Vero/Vero.node.js",
+ "dist/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.js",
"dist/nodes/Venafi/Datacenter/VenafiTlsProtectDatacenter.node.js",
"dist/nodes/Vonage/Vonage.node.js",
"dist/nodes/Wait/Wait.node.js",
@@ -754,6 +756,7 @@
},
"dependencies": {
"@kafkajs/confluent-schema-registry": "1.0.6",
+ "@types/js-nacl": "^1.3.0",
"amqplib": "^0.8.0",
"aws4": "^1.8.0",
"basic-auth": "^2.0.1",
@@ -773,6 +776,7 @@
"imap-simple": "^4.3.0",
"isbot": "^3.3.4",
"iso-639-1": "^2.1.3",
+ "js-nacl": "^1.4.0",
"jsonwebtoken": "^8.5.1",
"kafkajs": "^1.14.0",
"lodash.get": "^4.4.2",