From b3baaac5c8c73b1d9b49cee2bffb310a4e93beec Mon Sep 17 00:00:00 2001 From: Sunil Kumar Date: Thu, 20 Jul 2023 12:57:16 +0530 Subject: [PATCH] map secret comments to windmill api description --- backend/src/helpers/bot.ts | 68 ++++++++++++++++++++++++++++++ backend/src/helpers/integration.ts | 9 ++++ backend/src/integrations/sync.ts | 23 ++++++---- backend/src/services/BotService.ts | 25 +++++++++++ 4 files changed, 116 insertions(+), 9 deletions(-) diff --git a/backend/src/helpers/bot.ts b/backend/src/helpers/bot.ts index c7c5904c7..d3db7febf 100644 --- a/backend/src/helpers/bot.ts +++ b/backend/src/helpers/bot.ts @@ -16,6 +16,7 @@ import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; import { InternalServerError } from "../utils/errors"; import Folder from "../models/folder"; import { getFolderByPath } from "../services/FolderService"; +import { environment } from "../routes/v2"; /** * Create an inactive bot with name [name] for workspace with id [workspaceId] @@ -275,3 +276,70 @@ export const decryptSymmetricHelper = async ({ return plaintext; }; + +/** + * Return decrypted comments for workspace secrets with id [workspaceId] + * and [envionment] using bot + * @param {Object} obj + * @param {String} obj.workspaceId - id of workspace + * @param {String} obj.environment - environment + */ +export const getSecretsCommentBotHelper = async ({ + workspaceId, + environment, + secretPath +} : { + workspaceId: Types.ObjectId; + environment: string; + secretPath: string; +}) => { + const content = {} as any; + const key = await getKey({ workspaceId: workspaceId }); + + let folderId = "root"; + const folders = await Folder.findOne({ + workspace: workspaceId, + environment, + }); + + if (!folders && secretPath !== "/") { + throw InternalServerError({ message: "Folder not found" }); + } + + if (folders) { + const folder = getFolderByPath(folders.nodes, secretPath); + if (!folder) { + throw InternalServerError({ message: "Folder not found" }); + } + folderId = folder.id; + } + + const secrets = await Secret.find({ + workspace: workspaceId, + environment, + type: SECRET_SHARED, + folder: folderId, + }); + + secrets.forEach((secret: ISecret) => { + if(secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { + const secretKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretKeyCiphertext, + iv: secret.secretKeyIV, + tag: secret.secretKeyTag, + key, + }); + + const commentValue = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretCommentCiphertext, + iv: secret.secretCommentIV, + tag: secret.secretCommentTag, + key, + }); + + content[secretKey] = commentValue; + } + }); + + return content; +} \ No newline at end of file diff --git a/backend/src/helpers/integration.ts b/backend/src/helpers/integration.ts index f2dd1ba66..aaa8c9610 100644 --- a/backend/src/helpers/integration.ts +++ b/backend/src/helpers/integration.ts @@ -137,6 +137,14 @@ export const syncIntegrationsHelper = async ({ secretPath: integration.secretPath, }); + // get workspace, environment (shared) secrets comments + const secretComments = await BotService.getSecretComments({ + workspaceId: integration.workspace, + environment: integration.environment, + secretPath: integration.secretPath, + }) + + const integrationAuth = await IntegrationAuth.findById( integration.integrationAuth ); @@ -154,6 +162,7 @@ export const syncIntegrationsHelper = async ({ secrets, accessId: access.accessId === undefined ? null : access.accessId, accessToken: access.accessToken, + secretComments }); } }; diff --git a/backend/src/integrations/sync.ts b/backend/src/integrations/sync.ts index 14ab37ea5..59445ce4f 100644 --- a/backend/src/integrations/sync.ts +++ b/backend/src/integrations/sync.ts @@ -55,6 +55,7 @@ import { standardRequest} from "../config/request"; * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) * @param {String} obj.accessId - access id for integration * @param {String} obj.accessToken - access token for integration + * @param {Object} obj.secretComments - secret comments to push to integration (object where keys are secret keys and values are comment values) */ const syncSecrets = async ({ integration, @@ -62,12 +63,14 @@ const syncSecrets = async ({ secrets, accessId, accessToken, + secretComments }: { integration: IIntegration; integrationAuth: IIntegrationAuth; secrets: any; accessId: string | null; accessToken: string; + secretComments: any; }) => { switch (integration.integration) { case INTEGRATION_AZURE_KEY_VAULT: @@ -209,6 +212,7 @@ const syncSecrets = async ({ integration, secrets, accessToken, + secretComments }); break; } @@ -1953,24 +1957,24 @@ const syncSecretsCloudflarePages = async ({ * @param {IIntegrationAuth} obj.integrationAuth - integration auth details * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) * @param {String} obj.accessToken - access token for windmill integration + * @param {Object} obj.secretComments - secret comments to push to integration (object where keys are secret keys and values are comment values) */ const syncSecretsWindmill = async ({ integration, secrets, accessToken, + secretComments }: { integration: IIntegration; secrets: any; accessToken: string; + secretComments: any; }) => { - interface WindmilSecretUpdate { + interface WindmillSecret { path: string; value: string; is_secret: boolean; - } - - interface WindmillSecretCreate extends WindmilSecretUpdate { - description: string; + description?: string; } // get secrets stored in windmill workspace @@ -1988,8 +1992,8 @@ const syncSecretsWindmill = async ({ const secretsResList = getSecretsRes.map((secretObj: any) => (secretObj.path)); // convert the secrets to [{}] format - const modifiedFormatForCreateSecretInjection: WindmillSecretCreate[] = []; - const modifiedFormatForUpdateSecretInjection: WindmilSecretUpdate[] = []; + const modifiedFormatForCreateSecretInjection: WindmillSecret[] = []; + const modifiedFormatForUpdateSecretInjection: WindmillSecret[] = []; Object.keys(secrets).forEach( (key) => { @@ -1999,14 +2003,15 @@ const syncSecretsWindmill = async ({ modifiedFormatForUpdateSecretInjection.push({ path: key, value: secrets[key], - is_secret: true + is_secret: true, + description: secretComments[key] || "" }); } else { modifiedFormatForCreateSecretInjection.push({ path: key, value: secrets[key], is_secret: true, - description: "" + description: secretComments[key] || "" }); } }; diff --git a/backend/src/services/BotService.ts b/backend/src/services/BotService.ts index ca31bf103..7ebf53ae8 100644 --- a/backend/src/services/BotService.ts +++ b/backend/src/services/BotService.ts @@ -5,6 +5,7 @@ import { getIsWorkspaceE2EEHelper, getKey, getSecretsBotHelper, + getSecretsCommentBotHelper, } from "../helpers/bot"; /** @@ -107,6 +108,30 @@ class BotService { tag, }); } + + /** + * Return decreypted secrets comment for workspace with id [worskpaceId] and + * environment [environment] shared to bot. + * @param {Object} obj + * @param {String} obj.workspaceId - id of workspace of secrets + * @param {String} obj.environment - environment for secrets + * @returns {Object} secretObj - object where keys are secret keys and values are comment values + */ + static async getSecretComments({ + workspaceId, + environment, + secretPath + }: { + workspaceId: Types.ObjectId; + environment: string; + secretPath: string; + }) { + return await getSecretsCommentBotHelper({ + workspaceId, + environment, + secretPath + }); + } } export default BotService;