feat: resolved all ts issues on router schema and other functions

This commit is contained in:
=
2024-07-30 23:19:05 +05:30
parent 36ac1f47ca
commit 641860cdb8
10 changed files with 316 additions and 133 deletions
@@ -3,16 +3,14 @@ import { z } from "zod";
import { import {
SecretApprovalRequestsReviewersSchema, SecretApprovalRequestsReviewersSchema,
SecretApprovalRequestsSchema, SecretApprovalRequestsSchema,
SecretApprovalRequestsSecretsSchema,
SecretsSchema,
SecretTagsSchema, SecretTagsSchema,
SecretVersionsSchema,
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApprovalStatus, RequestState } from "@app/ee/services/secret-approval-request/secret-approval-request-types"; import { ApprovalStatus, RequestState } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { secretRawSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
const approvalRequestUser = z.object({ userId: z.string() }).merge( const approvalRequestUser = z.object({ userId: z.string() }).merge(
@@ -261,43 +259,30 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
committerUser: approvalRequestUser, committerUser: approvalRequestUser,
reviewers: approvalRequestUser.extend({ status: z.string() }).array(), reviewers: approvalRequestUser.extend({ status: z.string() }).array(),
secretPath: z.string(), secretPath: z.string(),
commits: SecretApprovalRequestsSecretsSchema.omit({ secretBlindIndex: true }) commits: secretRawSchema
.omit({ _id: true, environment: true, workspace: true, type: true, version: true })
.merge( .merge(
z.object({ z.object({
tags: tagSchema, tags: tagSchema,
secret: SecretsSchema.pick({ secret: z
id: true, .object({
version: true, id: z.string(),
secretKeyIV: true, version: z.number(),
secretKeyTag: true, secretKey: z.string(),
secretKeyCiphertext: true, secretValue: z.string().optional(),
secretValueIV: true, secretComment: z.string().optional()
secretValueTag: true,
secretValueCiphertext: true,
secretCommentIV: true,
secretCommentTag: true,
secretCommentCiphertext: true
}) })
.optional() .optional()
.nullable(), .nullable(),
secretVersion: SecretVersionsSchema.pick({ secretVersion: z
id: true, .object({
version: true, id: z.string(),
secretKeyIV: true, version: z.number(),
secretKeyTag: true, secretKey: z.string(),
secretKeyCiphertext: true, secretValue: z.string().optional(),
secretValueIV: true, secretComment: z.string().optional(),
secretValueTag: true,
secretValueCiphertext: true,
secretCommentIV: true,
secretCommentTag: true,
secretCommentCiphertext: true
})
.merge(
z.object({
tags: tagSchema tags: tagSchema
}) })
)
.optional() .optional()
}) })
) )
@@ -1,8 +1,8 @@
import { z } from "zod"; import { z } from "zod";
import { SecretVersionsSchema } from "@app/db/schemas";
import { readLimit } from "@app/server/config/rateLimiter"; import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { secretRawSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretVersionRouter = async (server: FastifyZodProvider) => { export const registerSecretVersionRouter = async (server: FastifyZodProvider) => {
@@ -22,7 +22,7 @@ export const registerSecretVersionRouter = async (server: FastifyZodProvider) =>
}), }),
response: { response: {
200: z.object({ 200: z.object({
secretVersions: SecretVersionsSchema.omit({ secretBlindIndex: true }).array() secretVersions: secretRawSchema.array()
}) })
} }
}, },
+4 -2
View File
@@ -1,9 +1,10 @@
import { z } from "zod"; import { z } from "zod";
import { SecretSnapshotsSchema, SecretTagsSchema, SecretVersionsSchema } from "@app/db/schemas"; import { SecretSnapshotsSchema, SecretTagsSchema } from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs"; import { PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { secretRawSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
export const registerSnapshotRouter = async (server: FastifyZodProvider) => { export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
@@ -27,7 +28,8 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
slug: z.string(), slug: z.string(),
name: z.string() name: z.string()
}), }),
secretVersions: SecretVersionsSchema.omit({ secretBlindIndex: true }) secretVersions: secretRawSchema
.omit({ _id: true, environment: true, workspace: true, type: true, version: true })
.merge( .merge(
z.object({ z.object({
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
@@ -221,6 +221,15 @@ export const secretApprovalRequestServiceFactory = ({
); );
secrets = encrypedSecrets.map((el) => ({ secrets = encrypedSecrets.map((el) => ({
...el, ...el,
secretKey: el.key,
id: el.id,
version: el.version,
secretValue: el.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString()
: undefined,
secretComment: el.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString()
: undefined,
secret: { secret: {
secretKey: el.secret.key, secretKey: el.secret.key,
id: el.secret.id, id: el.secret.id,
@@ -249,6 +258,7 @@ export const secretApprovalRequestServiceFactory = ({
const encrypedSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id); const encrypedSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id);
secrets = encrypedSecrets.map((el) => ({ secrets = encrypedSecrets.map((el) => ({
...el, ...el,
...decryptSecretWithBot(el, botKey),
secret: { secret: {
id: el.secret.id, id: el.secret.id,
version: el.secret.version, version: el.secret.version,
@@ -1,9 +1,13 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas"; import { TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas";
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
import { BadRequestError, InternalServerError } from "@app/lib/errors"; import { BadRequestError, InternalServerError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn"; import { groupBy } from "@app/lib/fn";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { KmsDataKey } from "@app/services/kms/kms-types";
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
import { TSecretDALFactory } from "@app/services/secret/secret-dal"; import { TSecretDALFactory } from "@app/services/secret/secret-dal";
import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal"; import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal";
import { TSecretVersionTagDALFactory } from "@app/services/secret/secret-version-tag-dal"; import { TSecretVersionTagDALFactory } from "@app/services/secret/secret-version-tag-dal";
@@ -45,6 +49,8 @@ type TSecretSnapshotServiceFactoryDep = {
folderDAL: Pick<TSecretFolderDALFactory, "findById" | "findBySecretPath" | "delete" | "insertMany" | "find">; folderDAL: Pick<TSecretFolderDALFactory, "findById" | "findBySecretPath" | "delete" | "insertMany" | "find">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
licenseService: Pick<TLicenseServiceFactory, "isValidLicense">; licenseService: Pick<TLicenseServiceFactory, "isValidLicense">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
}; };
export type TSecretSnapshotServiceFactory = ReturnType<typeof secretSnapshotServiceFactory>; export type TSecretSnapshotServiceFactory = ReturnType<typeof secretSnapshotServiceFactory>;
@@ -64,7 +70,9 @@ export const secretSnapshotServiceFactory = ({
secretVersionV2BridgeDAL, secretVersionV2BridgeDAL,
secretV2BridgeDAL, secretV2BridgeDAL,
snapshotSecretV2BridgeDAL, snapshotSecretV2BridgeDAL,
secretVersionV2TagBridgeDAL secretVersionV2TagBridgeDAL,
kmsService,
projectBotService
}: TSecretSnapshotServiceFactoryDep) => { }: TSecretSnapshotServiceFactoryDep) => {
const projectSecretSnapshotCount = async ({ const projectSecretSnapshotCount = async ({
environment, environment,
@@ -144,9 +152,55 @@ export const secretSnapshotServiceFactory = ({
const shouldUseBridge = snapshot.projectVersion === 3; const shouldUseBridge = snapshot.projectVersion === 3;
let snapshotDetails; let snapshotDetails;
if (shouldUseBridge) { if (shouldUseBridge) {
snapshotDetails = await snapshotDAL.findSecretSnapshotV2DataById(id); const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId: snapshot.projectId
});
const encryptedSnapshotDetails = await snapshotDAL.findSecretSnapshotV2DataById(id);
snapshotDetails = {
...encryptedSnapshotDetails,
secretVersions: encryptedSnapshotDetails.secretVersions.map((el) => ({
...el,
secretKey: el.key,
secretValue: el.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString()
: undefined,
secretComment: el.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString()
: undefined
}))
};
} else { } else {
snapshotDetails = await snapshotDAL.findSecretSnapshotDataById(id); const encryptedSnapshotDetails = await snapshotDAL.findSecretSnapshotDataById(id);
const { botKey } = await projectBotService.getBotKey(snapshot.projectId);
if (!botKey) throw new BadRequestError({ message: "bot not found" });
snapshotDetails = {
...encryptedSnapshotDetails,
secretVersions: encryptedSnapshotDetails.secretVersions.map((el) => ({
...el,
secretKey: decryptSymmetric128BitHexKeyUTF8({
ciphertext: el.secretKeyCiphertext,
iv: el.secretKeyIV,
tag: el.secretKeyTag,
key: botKey
}),
secretValue: decryptSymmetric128BitHexKeyUTF8({
ciphertext: el.secretValueCiphertext,
iv: el.secretValueIV,
tag: el.secretValueTag,
key: botKey
}),
secretComment:
el.secretCommentTag && el.secretCommentIV && el.secretCommentCiphertext
? decryptSymmetric128BitHexKeyUTF8({
ciphertext: el.secretCommentCiphertext,
iv: el.secretCommentIV,
tag: el.secretCommentTag,
key: botKey
})
: ""
}))
};
} }
const fullFolderPath = await getFullFolderPath({ const fullFolderPath = await getFullFolderPath({
+59 -31
View File
@@ -66,6 +66,7 @@ import { secretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/s
import { snapshotDALFactory } from "@app/ee/services/secret-snapshot/snapshot-dal"; import { snapshotDALFactory } from "@app/ee/services/secret-snapshot/snapshot-dal";
import { snapshotFolderDALFactory } from "@app/ee/services/secret-snapshot/snapshot-folder-dal"; import { snapshotFolderDALFactory } from "@app/ee/services/secret-snapshot/snapshot-folder-dal";
import { snapshotSecretDALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-dal"; import { snapshotSecretDALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-dal";
import { snapshotSecretV2DALFactory } from "@app/ee/services/secret-snapshot/snapshot-secret-v2-dal";
import { trustedIpDALFactory } from "@app/ee/services/trusted-ip/trusted-ip-dal"; import { trustedIpDALFactory } from "@app/ee/services/trusted-ip/trusted-ip-dal";
import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service"; import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
import { TKeyStoreFactory } from "@app/keystore/keystore"; import { TKeyStoreFactory } from "@app/keystore/keystore";
@@ -235,7 +236,7 @@ export const registerRoutes = async (
const secretV2BridgeDAL = secretV2BridgeDALFactory(db); const secretV2BridgeDAL = secretV2BridgeDALFactory(db);
const secretVersionV2BridgeDAL = secretVersionV2BridgeDALFactory(db); const secretVersionV2BridgeDAL = secretVersionV2BridgeDALFactory(db);
const secretVersionV2TagBridgeDAL = secretVersionV2TagBridgeDALFactory(db); const secretVersionTagV2BridgeDAL = secretVersionV2TagBridgeDALFactory(db);
const integrationDAL = integrationDALFactory(db); const integrationDAL = integrationDALFactory(db);
const integrationAuthDAL = integrationAuthDALFactory(db); const integrationAuthDAL = integrationAuthDALFactory(db);
@@ -285,6 +286,7 @@ export const registerRoutes = async (
const secretRotationDAL = secretRotationDALFactory(db); const secretRotationDAL = secretRotationDALFactory(db);
const snapshotDAL = snapshotDALFactory(db); const snapshotDAL = snapshotDALFactory(db);
const snapshotSecretDAL = snapshotSecretDALFactory(db); const snapshotSecretDAL = snapshotSecretDALFactory(db);
const snapshotSecretV2BridgeDAL = snapshotSecretV2DALFactory(db);
const snapshotFolderDAL = snapshotFolderDALFactory(db); const snapshotFolderDAL = snapshotFolderDALFactory(db);
const gitAppInstallSessionDAL = gitAppInstallSessionDALFactory(db); const gitAppInstallSessionDAL = gitAppInstallSessionDALFactory(db);
@@ -665,7 +667,13 @@ export const registerRoutes = async (
secretVersionDAL, secretVersionDAL,
folderVersionDAL, folderVersionDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL secretVersionTagDAL,
projectBotService,
kmsService,
secretV2BridgeDAL,
secretVersionV2BridgeDAL,
snapshotSecretV2BridgeDAL,
secretVersionV2TagBridgeDAL: secretVersionTagV2BridgeDAL
}); });
const webhookService = webhookServiceFactory({ const webhookService = webhookServiceFactory({
permissionService, permissionService,
@@ -689,7 +697,8 @@ export const registerRoutes = async (
integrationDAL, integrationDAL,
permissionService, permissionService,
projectBotDAL, projectBotDAL,
projectBotService projectBotService,
kmsService
}); });
const secretQueueService = secretQueueFactory({ const secretQueueService = secretQueueFactory({
queueService, queueService,
@@ -709,7 +718,11 @@ export const registerRoutes = async (
secretVersionDAL, secretVersionDAL,
secretBlindIndexDAL, secretBlindIndexDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL secretVersionTagDAL,
kmsService,
secretVersionV2BridgeDAL,
secretV2BridgeDAL,
secretVersionTagV2BridgeDAL
}); });
const secretImportService = secretImportServiceFactory({ const secretImportService = secretImportServiceFactory({
licenseService, licenseService,
@@ -720,7 +733,9 @@ export const registerRoutes = async (
secretImportDAL, secretImportDAL,
projectDAL, projectDAL,
secretDAL, secretDAL,
secretQueueService secretQueueService,
secretV2BridgeDAL,
kmsService
}); });
const secretBlindIndexService = secretBlindIndexServiceFactory({ const secretBlindIndexService = secretBlindIndexServiceFactory({
permissionService, permissionService,
@@ -734,13 +749,39 @@ export const registerRoutes = async (
secretQueueService, secretQueueService,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
permissionService, permissionService,
secretVersionTagDAL: secretVersionV2TagBridgeDAL, secretVersionTagDAL: secretVersionTagV2BridgeDAL,
secretTagDAL, secretTagDAL,
projectEnvDAL, projectEnvDAL,
secretImportDAL, secretImportDAL,
secretApprovalRequestDAL, secretApprovalRequestDAL,
secretApprovalPolicyService, secretApprovalPolicyService,
secretApprovalRequestSecretDAL secretApprovalRequestSecretDAL,
kmsService,
snapshotService
});
const secretApprovalRequestService = secretApprovalRequestServiceFactory({
permissionService,
projectBotService,
folderDAL,
secretDAL,
secretTagDAL,
secretApprovalRequestSecretDAL,
secretApprovalRequestReviewerDAL,
projectDAL,
secretVersionDAL,
secretBlindIndexDAL,
secretApprovalRequestDAL,
snapshotService,
secretVersionTagDAL,
secretQueueService,
kmsService,
secretV2BridgeDAL,
secretVersionV2BridgeDAL,
secretVersionTagV2BridgeDAL,
smtpService,
projectEnvDAL,
userDAL
}); });
const secretService = secretServiceFactory({ const secretService = secretServiceFactory({
@@ -760,7 +801,8 @@ export const registerRoutes = async (
secretApprovalPolicyService, secretApprovalPolicyService,
secretApprovalRequestDAL, secretApprovalRequestDAL,
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
secretV2BridgeService secretV2BridgeService,
secretApprovalRequestService
}); });
const secretSharingService = secretSharingServiceFactory({ const secretSharingService = secretSharingServiceFactory({
@@ -769,26 +811,6 @@ export const registerRoutes = async (
orgDAL orgDAL
}); });
const secretApprovalRequestService = secretApprovalRequestServiceFactory({
permissionService,
projectBotService,
folderDAL,
secretDAL,
secretTagDAL,
secretApprovalRequestSecretDAL,
secretApprovalRequestReviewerDAL,
projectDAL,
secretVersionDAL,
secretBlindIndexDAL,
secretApprovalRequestDAL,
snapshotService,
secretVersionTagDAL,
secretQueueService,
smtpService,
userDAL,
projectEnvDAL
});
const accessApprovalPolicyService = accessApprovalPolicyServiceFactory({ const accessApprovalPolicyService = accessApprovalPolicyServiceFactory({
accessApprovalPolicyDAL, accessApprovalPolicyDAL,
accessApprovalPolicyApproverDAL, accessApprovalPolicyApproverDAL,
@@ -822,11 +844,14 @@ export const registerRoutes = async (
queueService, queueService,
folderDAL, folderDAL,
secretApprovalPolicyService, secretApprovalPolicyService,
secretBlindIndexDAL,
secretApprovalRequestDAL, secretApprovalRequestDAL,
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
secretQueueService, secretQueueService,
projectBotService projectBotService,
kmsService,
secretV2BridgeDAL,
secretVersionV2TagBridgeDAL: secretVersionTagV2BridgeDAL,
secretVersionV2BridgeDAL
}); });
const secretRotationQueue = secretRotationQueueFactory({ const secretRotationQueue = secretRotationQueueFactory({
telemetryService, telemetryService,
@@ -834,7 +859,10 @@ export const registerRoutes = async (
queue: queueService, queue: queueService,
secretDAL, secretDAL,
secretVersionDAL, secretVersionDAL,
projectBotService projectBotService,
secretVersionV2BridgeDAL,
secretV2BridgeDAL,
kmsService
}); });
const secretRotationService = secretRotationServiceFactory({ const secretRotationService = secretRotationServiceFactory({
+61 -19
View File
@@ -18,7 +18,7 @@ import { getUserAgentType } from "@app/server/plugins/audit-log";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type"; import { ActorType, AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types"; import { ProjectFilterType } from "@app/services/project/project-types";
import { SecretOperations } from "@app/services/secret/secret-types"; import { SecretOperations, SecretProtectionType } from "@app/services/secret/secret-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
import { secretRawSchema } from "../sanitizedSchemas"; import { secretRawSchema } from "../sanitizedSchemas";
@@ -442,14 +442,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.CREATE.secretReminderNote) secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.CREATE.secretReminderNote)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secret: secretRawSchema secret: secretRawSchema
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const secret = await server.services.secret.createSecretRaw({ const secretOperation = await server.services.secret.createSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -466,7 +469,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretReminderNote: req.body.secretReminderNote, secretReminderNote: req.body.secretReminderNote,
secretReminderRepeatDays: req.body.secretReminderRepeatDays secretReminderRepeatDays: req.body.secretReminderRepeatDays
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secret } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
...req.auditLogInfo, ...req.auditLogInfo,
@@ -542,14 +549,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretComment: z.string().optional().describe(RAW_SECRETS.UPDATE.secretComment) secretComment: z.string().optional().describe(RAW_SECRETS.UPDATE.secretComment)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secret: secretRawSchema secret: secretRawSchema
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const secret = await server.services.secret.updateSecretRaw({ const secretOperation = await server.services.secret.updateSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -568,6 +578,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
newSecretName: req.body.newSecretName, newSecretName: req.body.newSecretName,
secretComment: req.body.secretComment secretComment: req.body.secretComment
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secret } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -628,14 +642,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.DELETE.type) type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.DELETE.type)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secret: secretRawSchema secret: secretRawSchema
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const secret = await server.services.secret.deleteSecretRaw({ const secretOperation = await server.services.secret.deleteSecretRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -646,6 +663,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretName: req.params.secretName, secretName: req.params.secretName,
type: req.body.type type: req.body.type
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secret } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
@@ -1815,16 +1836,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
.min(1) .min(1)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secrets: secretRawSchema.array() secrets: secretRawSchema.array()
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body;
const secrets = await server.services.secret.createManySecretsRaw({ const secretOperation = await server.services.secret.createManySecretsRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -1835,6 +1859,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secrets: inputSecrets secrets: inputSecrets
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secrets } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: secrets[0].workspace, projectId: secrets[0].workspace,
@@ -1914,15 +1942,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
.min(1) .min(1)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secrets: secretRawSchema.array() secrets: secretRawSchema.array()
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body;
const secrets = await server.services.secret.updateManySecretsRaw({ const secretOperation = await server.services.secret.updateManySecretsRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -1933,6 +1964,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secrets: inputSecrets secrets: inputSecrets
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secrets } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: secrets[0].workspace, projectId: secrets[0].workspace,
@@ -1999,15 +2034,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
.min(1) .min(1)
}), }),
response: { response: {
200: z.object({ 200: z.union([
z.object({
secrets: secretRawSchema.array() secrets: secretRawSchema.array()
}) }),
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
} }
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body; const { environment, projectSlug, secretPath, secrets: inputSecrets } = req.body;
const secrets = await server.services.secret.deleteManySecretsRaw({ const secretOperation = await server.services.secret.deleteManySecretsRaw({
actorId: req.permission.id, actorId: req.permission.id,
actor: req.permission.type, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -2018,6 +2056,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId: req.body.workspaceId, projectId: req.body.workspaceId,
secrets: inputSecrets secrets: inputSecrets
}); });
if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval };
}
const { secrets } = secretOperation;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
projectId: secrets[0].workspace, projectId: secrets[0].workspace,
@@ -995,9 +995,20 @@ export const secretV2BridgeServiceFactory = ({
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId: folder.projectId
});
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
return secretVersions; return secretVersions.map((el) =>
reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", {
...el,
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : undefined,
comment: el.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString()
: undefined
})
);
}; };
// this is a backfilling API for secret references // this is a backfilling API for secret references
+76 -30
View File
@@ -51,6 +51,7 @@ import {
import { TSecretQueueFactory } from "./secret-queue"; import { TSecretQueueFactory } from "./secret-queue";
import { import {
SecretOperations, SecretOperations,
SecretProtectionType,
TAttachSecretTagsDTO, TAttachSecretTagsDTO,
TBackFillSecretReferencesDTO, TBackFillSecretReferencesDTO,
TCreateBulkSecretDTO, TCreateBulkSecretDTO,
@@ -1228,7 +1229,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1251,6 +1252,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secret = await secretV2BridgeService.createSecret({ const secret = await secretV2BridgeService.createSecret({
@@ -1270,7 +1272,7 @@ export const secretServiceFactory = ({
skipMultilineEncoding, skipMultilineEncoding,
secretReminderRepeatDays secretReminderRepeatDays
}); });
return secret; return { secret, type: SecretProtectionType.Direct as const };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
@@ -1278,7 +1280,7 @@ export const secretServiceFactory = ({
const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey); const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8(secretValue || "", botKey);
const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey); const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8(secretComment || "", botKey);
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1306,6 +1308,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secret = await createSecret({ const secret = await createSecret({
@@ -1333,7 +1336,7 @@ export const secretServiceFactory = ({
tags: tagIds tags: tagIds
}); });
return decryptSecretRaw(secret, botKey); return { type: SecretProtectionType.Direct as const, secret: decryptSecretRaw(secret, botKey) };
}; };
const updateSecretRaw = async ({ const updateSecretRaw = async ({
@@ -1362,7 +1365,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1386,6 +1389,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secret = await secretV2BridgeService.updateSecret({ const secret = await secretV2BridgeService.updateSecret({
secretReminderRepeatDays, secretReminderRepeatDays,
@@ -1406,7 +1410,7 @@ export const secretServiceFactory = ({
metadata, metadata,
secretValue secretValue
}); });
return secret; return { type: SecretProtectionType.Direct as const, secret };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
@@ -1416,7 +1420,7 @@ export const secretServiceFactory = ({
const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(newSecretName || secretName, botKey); const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8(newSecretName || secretName, botKey);
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1447,6 +1451,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { approval, type: SecretProtectionType.Approval as const };
} }
const secret = await updateSecret({ const secret = await updateSecret({
@@ -1477,7 +1482,7 @@ export const secretServiceFactory = ({
}); });
await snapshotService.performSnapshot(secret.folderId); await snapshotService.performSnapshot(secret.folderId);
return decryptSecretRaw(secret, botKey); return { type: SecretProtectionType.Direct as const, secret: decryptSecretRaw(secret, botKey) };
}; };
const deleteSecretRaw = async ({ const deleteSecretRaw = async ({
@@ -1498,7 +1503,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
@@ -1515,6 +1520,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secret = await secretV2BridgeService.deleteSecret({ const secret = await secretV2BridgeService.deleteSecret({
secretName, secretName,
@@ -1527,11 +1533,11 @@ export const secretServiceFactory = ({
environment, environment,
secretPath secretPath
}); });
return secret; return { type: SecretProtectionType.Direct as const, secret };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
@@ -1548,6 +1554,7 @@ export const secretServiceFactory = ({
] ]
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secret = await deleteSecret({ const secret = await deleteSecret({
secretName, secretName,
@@ -1561,7 +1568,7 @@ export const secretServiceFactory = ({
actorAuthMethod actorAuthMethod
}); });
return decryptSecretRaw(secret, botKey); return { type: SecretProtectionType.Direct as const, secret: decryptSecretRaw(secret, botKey) };
}; };
const createManySecretsRaw = async ({ const createManySecretsRaw = async ({
@@ -1593,7 +1600,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1613,6 +1620,7 @@ export const secretServiceFactory = ({
})) }))
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await secretV2BridgeService.createManySecret({ const secrets = await secretV2BridgeService.createManySecret({
secretPath, secretPath,
@@ -1624,8 +1632,9 @@ export const secretServiceFactory = ({
actorId, actorId,
secrets: inputSecrets secrets: inputSecrets
}); });
return secrets; return { secrets, type: SecretProtectionType.Direct as const };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
const sanitizedSecrets = inputSecrets.map( const sanitizedSecrets = inputSecrets.map(
({ secretComment, secretKey, metadata, tagIds, secretValue, skipMultilineEncoding }) => { ({ secretComment, secretKey, metadata, tagIds, secretValue, skipMultilineEncoding }) => {
@@ -1651,7 +1660,7 @@ export const secretServiceFactory = ({
} }
); );
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1664,6 +1673,7 @@ export const secretServiceFactory = ({
[SecretOperations.Create]: sanitizedSecrets [SecretOperations.Create]: sanitizedSecrets
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await createManySecret({ const secrets = await createManySecret({
projectId, projectId,
@@ -1676,9 +1686,12 @@ export const secretServiceFactory = ({
secrets: sanitizedSecrets secrets: sanitizedSecrets
}); });
return secrets.map((secret) => return {
type: SecretProtectionType.Direct as const,
secrets: secrets.map((secret) =>
decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey) decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey)
); )
};
}; };
const updateManySecretsRaw = async ({ const updateManySecretsRaw = async ({
@@ -1709,7 +1722,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1728,6 +1741,7 @@ export const secretServiceFactory = ({
})) }))
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await secretV2BridgeService.updateManySecret({ const secrets = await secretV2BridgeService.updateManySecret({
secretPath, secretPath,
@@ -1739,7 +1753,7 @@ export const secretServiceFactory = ({
actorId, actorId,
secrets: inputSecrets secrets: inputSecrets
}); });
return secrets; return { type: SecretProtectionType.Direct as const, secrets };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
@@ -1779,7 +1793,7 @@ export const secretServiceFactory = ({
} }
); );
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
secretPath, secretPath,
environment, environment,
@@ -1792,6 +1806,8 @@ export const secretServiceFactory = ({
[SecretOperations.Update]: sanitizedSecrets [SecretOperations.Update]: sanitizedSecrets
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await updateManySecret({ const secrets = await updateManySecret({
projectId, projectId,
@@ -1804,9 +1820,12 @@ export const secretServiceFactory = ({
secrets: sanitizedSecrets secrets: sanitizedSecrets
}); });
return secrets.map((secret) => return {
type: SecretProtectionType.Direct as const,
secrets: secrets.map((secret) =>
decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey) decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey)
); )
};
}; };
const deleteManySecretsRaw = async ({ const deleteManySecretsRaw = async ({
@@ -1837,7 +1856,7 @@ export const secretServiceFactory = ({
: undefined; : undefined;
if (shouldUseSecretV2Bridge) { if (shouldUseSecretV2Bridge) {
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({ const approval = await secretApprovalRequestService.generateSecretApprovalRequestV2Bridge({
policy, policy,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
@@ -1850,6 +1869,7 @@ export const secretServiceFactory = ({
[SecretOperations.Delete]: inputSecrets [SecretOperations.Delete]: inputSecrets
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await secretV2BridgeService.deleteManySecret({ const secrets = await secretV2BridgeService.deleteManySecret({
secretPath, secretPath,
@@ -1861,13 +1881,13 @@ export const secretServiceFactory = ({
actorId, actorId,
secrets: inputSecrets secrets: inputSecrets
}); });
return secrets; return { type: SecretProtectionType.Direct as const, secrets };
} }
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" }); if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
if (policy) { if (policy) {
return secretApprovalRequestService.generateSecretApprovalRequest({ const approval = await secretApprovalRequestService.generateSecretApprovalRequest({
policy, policy,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
@@ -1880,6 +1900,7 @@ export const secretServiceFactory = ({
[SecretOperations.Delete]: inputSecrets.map((el) => ({ secretName: el.secretKey })) [SecretOperations.Delete]: inputSecrets.map((el) => ({ secretName: el.secretKey }))
} }
}); });
return { type: SecretProtectionType.Approval as const, approval };
} }
const secrets = await deleteManySecret({ const secrets = await deleteManySecret({
projectId, projectId,
@@ -1892,9 +1913,12 @@ export const secretServiceFactory = ({
secrets: inputSecrets.map(({ secretKey, type = SecretType.Shared }) => ({ secretName: secretKey, type })) secrets: inputSecrets.map(({ secretKey, type = SecretType.Shared }) => ({ secretName: secretKey, type }))
}); });
return secrets.map((secret) => return {
type: SecretProtectionType.Direct as const,
secrets: secrets.map((secret) =>
decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey) decryptSecretRaw({ ...secret, workspace: projectId, environment, secretPath }, botKey)
); )
};
}; };
const getSecretVersions = async ({ const getSecretVersions = async ({
@@ -1906,12 +1930,25 @@ export const secretServiceFactory = ({
offset = 0, offset = 0,
secretId secretId
}: TGetSecretVersionsDTO) => { }: TGetSecretVersionsDTO) => {
const secretVersionV2 = await secretV2BridgeService.getSecretVersions({
actorId,
actor,
actorOrgId,
actorAuthMethod,
limit,
offset,
secretId
});
if (secretVersionV2) return secretVersionV2;
const secret = await secretDAL.findById(secretId); const secret = await secretDAL.findById(secretId);
if (!secret) throw new BadRequestError({ message: "Failed to find secret" }); if (!secret) throw new BadRequestError({ message: "Failed to find secret" });
const folder = await folderDAL.findById(secret.folderId); const folder = await folderDAL.findById(secret.folderId);
if (!folder) throw new BadRequestError({ message: "Failed to find secret" }); if (!folder) throw new BadRequestError({ message: "Failed to find secret" });
const { botKey } = await projectBotService.getBotKey(folder.projectId);
if (!botKey) throw new BadRequestError({ message: "bot not found" });
const { permission } = await permissionService.getProjectPermission( const { permission } = await permissionService.getProjectPermission(
actor, actor,
actorId, actorId,
@@ -1920,9 +1957,18 @@ export const secretServiceFactory = ({
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
return secretVersions; return secretVersions.map((el) =>
decryptSecretRaw(
{
...el,
workspace: folder.projectId,
environment: folder.environment.envSlug,
secretPath: "/"
},
botKey
)
);
}; };
const attachTags = async ({ const attachTags = async ({
@@ -444,3 +444,8 @@ export type TMoveSecretsDTO = {
secretIds: string[]; secretIds: string[];
shouldOverwrite: boolean; shouldOverwrite: boolean;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export enum SecretProtectionType {
Approval = "approval",
Direct = "direct"
}