import type { OptionsWithUri } from 'request'; import type { IExecuteFunctions, ILoadOptionsFunctions, IDataObject, IHookFunctions, JsonObject, } from 'n8n-workflow'; import { NodeApiError } from 'n8n-workflow'; import get from 'lodash/get'; import * as nacl_factory from 'js-nacl'; export async function venafiApiRequest( this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions, method: string, resource: string, body = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}, ): Promise { const operation = this.getNodeParameter('operation', 0); const credentials = await this.getCredentials('venafiTlsProtectCloudApi'); const region = credentials.region ?? 'cloud'; const options: OptionsWithUri = { headers: { Accept: 'application/json', 'content-type': 'application/json', }, method, body, qs, uri: `https://api.venafi.${region}${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, body: IDataObject = {}, query: IDataObject = {}, ) { 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] as IDataObject[]); } while (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 = async () => { return new Promise((resolve, reject) => { 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 as Buffer).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 as Buffer).toString('base64'); return resolve([encryptedKeyPass, encryptedKeyStorePass]); } catch (error) { return reject(error); } }); }); }; return promise(); }