diff --git a/backend/src/@types/knex.d.ts b/backend/src/@types/knex.d.ts index 6b77af1c5..5b2f1f2c8 100644 --- a/backend/src/@types/knex.d.ts +++ b/backend/src/@types/knex.d.ts @@ -239,6 +239,9 @@ import { TSecretRotationOutputs, TSecretRotationOutputsInsert, TSecretRotationOutputsUpdate, + TSecretRotationOutputV2, + TSecretRotationOutputV2Insert, + TSecretRotationOutputV2Update, TSecretRotations, TSecretRotationsInsert, TSecretRotationsUpdate, @@ -718,6 +721,11 @@ declare module "knex/types/tables" { TSecretApprovalRequestSecretTagsV2Insert, TSecretApprovalRequestSecretTagsV2Update >; + [TableName.SecretRotationOutputV2]: KnexOriginal.CompositeTableType< + TSecretRotationOutputV2, + TSecretRotationOutputV2Insert, + TSecretRotationOutputV2Update + >; // KMS service [TableName.KmsServerRootConfig]: KnexOriginal.CompositeTableType< TKmsRootConfig, diff --git a/backend/src/db/migrations/20240716105646_secret-v2.ts b/backend/src/db/migrations/20240716105646_secret-v2.ts index 97ecb5676..dac414f5b 100644 --- a/backend/src/db/migrations/20240716105646_secret-v2.ts +++ b/backend/src/db/migrations/20240716105646_secret-v2.ts @@ -128,7 +128,18 @@ export async function up(knex: Knex): Promise { if (!hasEncryptedAccess) t.binary("encryptedAccess"); if (!hasEncryptedAccessId) t.binary("encryptedAccessId"); if (!hasEncryptedRefresh) t.binary("encryptedRefresh"); - if (!hasEncryptedAwsIamAssumRole) t.binary("encryptedAwsIamAssumRole"); + if (!hasEncryptedAwsIamAssumRole) t.binary("encryptedAwsAssumeIamRoleArn"); + }); + } + + if (!(await knex.schema.hasTable(TableName.SecretRotationOutputV2))) { + await knex.schema.createTable(TableName.SecretRotationOutputV2, (t) => { + t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); + t.string("key").notNullable(); + t.uuid("secretId").notNullable(); + t.foreign("secretId").references("id").inTable(TableName.SecretV2).onDelete("CASCADE"); + t.uuid("rotationId").notNullable(); + t.foreign("rotationId").references("id").inTable(TableName.SecretRotation).onDelete("CASCADE"); }); } } @@ -141,13 +152,15 @@ export async function down(knex: Knex): Promise { await knex.schema.dropTableIfExists(TableName.SecretV2JnTag); await knex.schema.dropTableIfExists(TableName.SecretReferenceV2); - await dropOnUpdateTrigger(knex, TableName.SecretV2); - await knex.schema.dropTableIfExists(TableName.SecretV2); + await knex.schema.dropTableIfExists(TableName.SecretRotationOutputV2); await dropOnUpdateTrigger(knex, TableName.SecretVersionV2); await knex.schema.dropTableIfExists(TableName.SecretVersionV2Tag); await knex.schema.dropTableIfExists(TableName.SecretVersionV2); + await dropOnUpdateTrigger(knex, TableName.SecretV2); + await knex.schema.dropTableIfExists(TableName.SecretV2); + if (await knex.schema.hasTable(TableName.IntegrationAuth)) { const hasEncryptedAccess = await knex.schema.hasColumn(TableName.IntegrationAuth, "encryptedAccess"); const hasEncryptedAccessId = await knex.schema.hasColumn(TableName.IntegrationAuth, "encryptedAccessId"); @@ -160,7 +173,7 @@ export async function down(knex: Knex): Promise { if (hasEncryptedAccess) t.dropColumn("encryptedAccess"); if (hasEncryptedAccessId) t.dropColumn("encryptedAccessId"); if (hasEncryptedRefresh) t.dropColumn("encryptedRefresh"); - if (hasEncryptedAwsIamAssumRole) t.dropColumn("encryptedAwsIamAssumRole"); + if (hasEncryptedAwsIamAssumRole) t.dropColumn("encryptedAwsAssumeIamRoleArn"); }); } } diff --git a/backend/src/db/schemas/index.ts b/backend/src/db/schemas/index.ts index d0aa56727..9c5754f1e 100644 --- a/backend/src/db/schemas/index.ts +++ b/backend/src/db/schemas/index.ts @@ -103,3 +103,4 @@ export * from "./user-encryption-keys"; export * from "./user-group-membership"; export * from "./users"; export * from "./webhooks"; +export * from "./secret-rotation-output-v2"; diff --git a/backend/src/db/schemas/integration-auths.ts b/backend/src/db/schemas/integration-auths.ts index 1c0600e81..1e38c2139 100644 --- a/backend/src/db/schemas/integration-auths.ts +++ b/backend/src/db/schemas/integration-auths.ts @@ -35,10 +35,11 @@ export const IntegrationAuthsSchema = z.object({ awsAssumeIamRoleArnCipherText: z.string().nullable().optional(), awsAssumeIamRoleArnIV: z.string().nullable().optional(), awsAssumeIamRoleArnTag: z.string().nullable().optional(), + encryptedAwsIamAssumRole: zodBuffer.nullable().optional(), encryptedAccess: zodBuffer.nullable().optional(), encryptedAccessId: zodBuffer.nullable().optional(), encryptedRefresh: zodBuffer.nullable().optional(), - encryptedAwsIamAssumRole: zodBuffer.nullable().optional() + encryptedAwsAssumeIamRoleArn: zodBuffer.nullable().optional() }); export type TIntegrationAuths = z.infer; diff --git a/backend/src/db/schemas/models.ts b/backend/src/db/schemas/models.ts index 37d4fa699..2e91608e3 100644 --- a/backend/src/db/schemas/models.ts +++ b/backend/src/db/schemas/models.ts @@ -101,6 +101,7 @@ export enum TableName { JnSecretTag = "secret_tag_junction", SecretVersionTag = "secret_version_tag_junction", SecretVersionV2Tag = "secret_version_v2_tag_junction", + SecretRotationOutputV2 = "secret_rotation_output_v2", // KMS Service KmsServerRootConfig = "kms_root_config", KmsKey = "kms_keys", diff --git a/backend/src/db/schemas/secret-rotation-output-v2.ts b/backend/src/db/schemas/secret-rotation-output-v2.ts new file mode 100644 index 000000000..28d45413a --- /dev/null +++ b/backend/src/db/schemas/secret-rotation-output-v2.ts @@ -0,0 +1,21 @@ +// Code generated by automation script, DO NOT EDIT. +// Automated by pulling database and generating zod schema +// To update. Just run npm run generate:schema +// Written by akhilmhdh. + +import { z } from "zod"; + +import { TImmutableDBKeys } from "./models"; + +export const SecretRotationOutputV2Schema = z.object({ + id: z.string().uuid(), + key: z.string(), + secretId: z.string().uuid(), + rotationId: z.string().uuid() +}); + +export type TSecretRotationOutputV2 = z.infer; +export type TSecretRotationOutputV2Insert = Omit, TImmutableDBKeys>; +export type TSecretRotationOutputV2Update = Partial< + Omit, TImmutableDBKeys> +>; diff --git a/backend/src/ee/routes/v1/secret-rotation-router.ts b/backend/src/ee/routes/v1/secret-rotation-router.ts index d951eb744..936459fa1 100644 --- a/backend/src/ee/routes/v1/secret-rotation-router.ts +++ b/backend/src/ee/routes/v1/secret-rotation-router.ts @@ -1,6 +1,6 @@ import { z } from "zod"; -import { SecretRotationOutputsSchema, SecretRotationsSchema, SecretsSchema } from "@app/db/schemas"; +import { SecretRotationOutputsSchema, SecretRotationsSchema } from "@app/db/schemas"; import { removeTrailingSlash } from "@app/lib/fn"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; @@ -112,18 +112,10 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) = outputs: z .object({ key: z.string(), - secret: SecretsSchema.pick({ - id: true, - version: true, - secretKeyIV: true, - secretKeyTag: true, - secretKeyCiphertext: true, - secretValueIV: true, - secretValueTag: true, - secretValueCiphertext: true, - secretCommentIV: true, - secretCommentTag: true, - secretCommentCiphertext: true + secret: z.object({ + secretKey: z.string(), + id: z.string(), + version: z.number() }) }) .array() diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-dal.ts b/backend/src/ee/services/secret-rotation/secret-rotation-dal.ts index 57d86ff04..8927928d5 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-dal.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-dal.ts @@ -10,6 +10,7 @@ export type TSecretRotationDALFactory = ReturnType { const secretRotationOrm = ormify(db, TableName.SecretRotation); const secretRotationOutputOrm = ormify(db, TableName.SecretRotationOutput); + const secretRotationOutputV2Orm = ormify(db, TableName.SecretRotationOutputV2); const findQuery = (filter: TFindFilter, tx: Knex) => tx(TableName.SecretRotation) @@ -31,13 +32,7 @@ export const secretRotationDALFactory = (db: TDbClient) => { .select(tx.ref("version").withSchema(TableName.Secret).as("secVersion")) .select(tx.ref("secretKeyIV").withSchema(TableName.Secret)) .select(tx.ref("secretKeyTag").withSchema(TableName.Secret)) - .select(tx.ref("secretKeyCiphertext").withSchema(TableName.Secret)) - .select(tx.ref("secretValueIV").withSchema(TableName.Secret)) - .select(tx.ref("secretValueTag").withSchema(TableName.Secret)) - .select(tx.ref("secretValueCiphertext").withSchema(TableName.Secret)) - .select(tx.ref("secretCommentIV").withSchema(TableName.Secret)) - .select(tx.ref("secretCommentTag").withSchema(TableName.Secret)) - .select(tx.ref("secretCommentCiphertext").withSchema(TableName.Secret)); + .select(tx.ref("secretKeyCiphertext").withSchema(TableName.Secret)); const find = async (filter: TFindFilter, tx?: Knex) => { try { @@ -54,33 +49,65 @@ export const secretRotationDALFactory = (db: TDbClient) => { { key: "secId", label: "outputs" as const, - mapper: ({ - secId, - outputKey, - secVersion, - secretKeyIV, - secretKeyTag, - secretKeyCiphertext, - secretValueTag, - secretValueIV, - secretValueCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext - }) => ({ + mapper: ({ secId, outputKey, secVersion, secretKeyIV, secretKeyTag, secretKeyCiphertext }) => ({ key: outputKey, secret: { id: secId, version: secVersion, secretKeyIV, secretKeyTag, - secretKeyCiphertext, - secretValueTag, - secretValueIV, - secretValueCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentCiphertext + secretKeyCiphertext + } + }) + } + ] + }); + } catch (error) { + throw new DatabaseError({ error, name: "SecretRotationFind" }); + } + }; + + const findQuerySecretV2 = (filter: TFindFilter, tx: Knex) => + tx(TableName.SecretRotation) + .where(filter) + .join(TableName.Environment, `${TableName.SecretRotation}.envId`, `${TableName.Environment}.id`) + .leftJoin( + TableName.SecretRotationOutputV2, + `${TableName.SecretRotation}.id`, + `${TableName.SecretRotationOutputV2}.rotationId` + ) + .join(TableName.SecretV2, `${TableName.SecretRotationOutputV2}.secretId`, `${TableName.SecretV2}.id`) + .select(selectAllTableCols(TableName.SecretRotation)) + .select(tx.ref("name").withSchema(TableName.Environment).as("envName")) + .select(tx.ref("slug").withSchema(TableName.Environment).as("envSlug")) + .select(tx.ref("id").withSchema(TableName.Environment).as("envId")) + .select(tx.ref("projectId").withSchema(TableName.Environment)) + .select(tx.ref("key").withSchema(TableName.SecretRotationOutputV2).as("outputKey")) + .select(tx.ref("id").withSchema(TableName.SecretV2).as("secId")) + .select(tx.ref("version").withSchema(TableName.SecretV2).as("secVersion")) + .select(tx.ref("key").withSchema(TableName.SecretV2).as("secretKey")); + + const findSecretV2 = async (filter: TFindFilter, tx?: Knex) => { + try { + const data = await findQuerySecretV2(filter, tx || db.replicaNode()); + return sqlNestRelationships({ + data, + key: "id", + parentMapper: (el) => ({ + ...SecretRotationsSchema.parse(el), + projectId: el.projectId, + environment: { id: el.envId, name: el.envName, slug: el.envSlug } + }), + childrenMapper: [ + { + key: "secId", + label: "outputs" as const, + mapper: ({ secId, outputKey, secVersion, secretKey }) => ({ + key: outputKey, + secret: { + id: secId, + version: secVersion, + secretKey } }) } @@ -114,12 +141,17 @@ export const secretRotationDALFactory = (db: TDbClient) => { }; const findRotationOutputsByRotationId = async (rotationId: string) => secretRotationOutputOrm.find({ rotationId }); + const findRotationOutputsV2ByRotationId = async (rotationId: string) => + secretRotationOutputV2Orm.find({ rotationId }); return { ...secretRotationOrm, find, + findSecretV2, findById, secretOutputInsertMany: secretRotationOutputOrm.insertMany, - findRotationOutputsByRotationId + secretOutputV2InsertMany: secretRotationOutputV2Orm.insertMany, + findRotationOutputsByRotationId, + findRotationOutputsV2ByRotationId }; }; diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts index 11b6c34af..ab419e4c9 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts @@ -121,7 +121,13 @@ export const secretRotationQueueFactory = ({ try { if (!rotationProvider || !secretRotation) throw new DisableRotationErrors({ message: "Provider not found" }); - const rotationOutputs = await secretRotationDAL.findRotationOutputsByRotationId(rotationId); + const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(secretRotation.projectId); + let rotationOutputs; + if (shouldUseSecretV2Bridge) { + rotationOutputs = await secretRotationDAL.findRotationOutputsV2ByRotationId(rotationId); + } else { + rotationOutputs = await secretRotationDAL.findRotationOutputsByRotationId(rotationId); + } if (!rotationOutputs.length) throw new DisableRotationErrors({ message: "Secrets not found" }); // deep copy @@ -277,7 +283,6 @@ export const secretRotationQueueFactory = ({ internal: newCredential.internal }); const encVarData = infisicalSymmetricEncypt(JSON.stringify(variables)); - const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(secretRotation.projectId); const { encryptor: secretManagerEncryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: secretRotation.projectId diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts index 9b0109a35..d346c5bd3 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-service.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-service.ts @@ -1,12 +1,15 @@ import { ForbiddenError, subject } from "@casl/ability"; import Ajv from "ajv"; -import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; +import { ProjectVersion } from "@app/db/schemas"; +import { decryptSymmetric128BitHexKeyUTF8, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; import { BadRequestError } from "@app/lib/errors"; import { TProjectPermission } from "@app/lib/types"; import { TProjectDALFactory } from "@app/services/project/project-dal"; +import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service"; import { TSecretDALFactory } from "@app/services/secret/secret-dal"; import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal"; +import { TSecretV2BridgeDALFactory } from "@app/services/secret-v2-bridge/secret-v2-bridge-dal"; import { TLicenseServiceFactory } from "../license/license-service"; import { TPermissionServiceFactory } from "../permission/permission-service"; @@ -22,9 +25,11 @@ type TSecretRotationServiceFactoryDep = { projectDAL: Pick; folderDAL: Pick; secretDAL: Pick; + secretV2BridgeDAL: Pick; licenseService: Pick; permissionService: Pick; secretRotationQueue: TSecretRotationQueueFactory; + projectBotService: Pick; }; export type TSecretRotationServiceFactory = ReturnType; @@ -37,7 +42,9 @@ export const secretRotationServiceFactory = ({ licenseService, projectDAL, folderDAL, - secretDAL + secretDAL, + projectBotService, + secretV2BridgeDAL }: TSecretRotationServiceFactoryDep) => { const getProviderTemplates = async ({ actor, @@ -92,15 +99,25 @@ export const secretRotationServiceFactory = ({ ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { environment, secretPath }) ); - - const selectedSecrets = await secretDAL.find({ - folderId: folder.id, - $in: { id: Object.values(outputs) } - }); - if (selectedSecrets.length !== Object.values(outputs).length) - throw new BadRequestError({ message: "Secrets not found" }); - const project = await projectDAL.findById(projectId); + const shouldUseBridge = project.version === ProjectVersion.V3; + + if (shouldUseBridge) { + const selectedSecrets = await secretV2BridgeDAL.find({ + folderId: folder.id, + $in: { id: Object.values(outputs) } + }); + if (selectedSecrets.length !== Object.values(outputs).length) + throw new BadRequestError({ message: "Secrets not found" }); + } else { + const selectedSecrets = await secretDAL.find({ + folderId: folder.id, + $in: { id: Object.values(outputs) } + }); + if (selectedSecrets.length !== Object.values(outputs).length) + throw new BadRequestError({ message: "Secrets not found" }); + } + const plan = await licenseService.getPlan(project.orgId); if (!plan.secretRotation) throw new BadRequestError({ @@ -148,10 +165,18 @@ export const secretRotationServiceFactory = ({ }, tx ); - const outputSecretMapping = await secretRotationDAL.secretOutputInsertMany( - Object.entries(outputs).map(([key, secretId]) => ({ key, secretId, rotationId: doc.id })), - tx - ); + let outputSecretMapping; + if (shouldUseBridge) { + outputSecretMapping = await secretRotationDAL.secretOutputV2InsertMany( + Object.entries(outputs).map(([key, secretId]) => ({ key, secretId, rotationId: doc.id })), + tx + ); + } else { + outputSecretMapping = await secretRotationDAL.secretOutputInsertMany( + Object.entries(outputs).map(([key, secretId]) => ({ key, secretId, rotationId: doc.id })), + tx + ); + } return { ...doc, outputs: outputSecretMapping, environment: folder.environment }; }); await secretRotationQueue.addToQueue(secretRotation.id, secretRotation.interval); @@ -167,8 +192,30 @@ export const secretRotationServiceFactory = ({ actorOrgId ); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation); - const doc = await secretRotationDAL.find({ projectId }); - return doc; + const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); + if (shouldUseSecretV2Bridge) { + const docs = await secretRotationDAL.findSecretV2({ projectId }); + return docs; + } + + if (!botKey) throw new BadRequestError({ message: "bot not found" }); + const docs = await secretRotationDAL.find({ projectId }); + return docs.map((el) => ({ + ...el, + outputs: el.outputs.map((output) => ({ + ...output, + secret: { + id: output.secret.id, + version: output.secret.version, + secretKey: decryptSymmetric128BitHexKeyUTF8({ + ciphertext: output.secret.secretKeyCiphertext, + iv: output.secret.secretKeyIV, + tag: output.secret.secretKeyTag, + key: botKey + }) + } + })) + })); }; const restartById = async ({ actor, actorId, actorOrgId, actorAuthMethod, rotationId }: TRestartDTO) => { diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index daa679dc4..2d096221c 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -869,7 +869,9 @@ export const registerRoutes = async ( projectDAL, licenseService, secretDAL, - folderDAL + folderDAL, + projectBotService, + secretV2BridgeDAL }); const integrationService = integrationServiceFactory({ diff --git a/frontend/src/hooks/api/secretRotation/queries.tsx b/frontend/src/hooks/api/secretRotation/queries.tsx index a3c8e270e..d612189ad 100644 --- a/frontend/src/hooks/api/secretRotation/queries.tsx +++ b/frontend/src/hooks/api/secretRotation/queries.tsx @@ -1,14 +1,9 @@ -import { useCallback } from "react"; import { useQuery, UseQueryOptions } from "@tanstack/react-query"; -import { - decryptAssymmetric, - decryptSymmetric -} from "@app/components/utilities/cryptography/crypto"; import { apiRequest } from "@app/config/request"; import { - TGetSecretRotationList, + TGetSecretRotationListDTO, TGetSecretRotationProviders, TSecretRotation, TSecretRotationProviderList @@ -19,7 +14,7 @@ export const secretRotationKeys = { { workspaceId }, "secret-rotation-providers" ], - list: ({ workspaceId }: Omit) => + list: ({ workspaceId }: Omit) => [{ workspaceId }, "secret-rotations"] as const }; @@ -53,7 +48,7 @@ export const useGetSecretRotationProviders = ({ const fetchSecretRotations = async ({ workspaceId -}: Omit) => { +}: Omit) => { const { data } = await apiRequest.get<{ secretRotations: TSecretRotation[] }>( "/api/v1/secret-rotations", { params: { workspaceId } } @@ -63,14 +58,13 @@ const fetchSecretRotations = async ({ export const useGetSecretRotations = ({ workspaceId, - decryptFileKey, options = {} -}: TGetSecretRotationList & { +}: TGetSecretRotationListDTO & { options?: Omit< UseQueryOptions< TSecretRotation[], unknown, - TSecretRotation<{ key: string }>[], + TSecretRotation[], ReturnType >, "queryKey" | "queryFn" @@ -80,31 +74,5 @@ export const useGetSecretRotations = ({ ...options, queryKey: secretRotationKeys.list({ workspaceId }), enabled: Boolean(workspaceId) && (options?.enabled ?? true), - queryFn: async () => fetchSecretRotations({ workspaceId }), - select: useCallback( - (data: TSecretRotation[]) => { - const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string; - const decryptKey = decryptAssymmetric({ - ciphertext: decryptFileKey.encryptedKey, - nonce: decryptFileKey.nonce, - publicKey: decryptFileKey.sender.publicKey, - privateKey: PRIVATE_KEY - }); - return data.map((el) => ({ - ...el, - outputs: el.outputs.map(({ key, secret }) => ({ - key, - secret: { - key: decryptSymmetric({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key: decryptKey - }) - } - })) - })); - }, - [decryptFileKey] - ) + queryFn: async () => fetchSecretRotations({ workspaceId }) }); diff --git a/frontend/src/hooks/api/secretRotation/types.ts b/frontend/src/hooks/api/secretRotation/types.ts index b8963a95e..07a4c70df 100644 --- a/frontend/src/hooks/api/secretRotation/types.ts +++ b/frontend/src/hooks/api/secretRotation/types.ts @@ -1,5 +1,3 @@ -import { UserWsKeyPair } from "../keys/types"; -import { EncryptedSecret } from "../secrets/types"; import { WorkspaceEnv } from "../workspace/types"; export enum TProviderFunctionTypes { @@ -74,7 +72,7 @@ export type TDbProviderTemplate = { outputs: Record; }; -export type TSecretRotation = { +export type TSecretRotation = { id: string; interval: number; provider: string; @@ -85,7 +83,11 @@ export type TSecretRotation = { secretPath: string; outputs: Array<{ key: string; - secret: T; + secret: { + version: number; + id: string; + secretKey: string; + }; }>; status?: "success" | "failed"; lastRotatedAt?: string; @@ -103,9 +105,8 @@ export type TGetSecretRotationProviders = { workspaceId: string; }; -export type TGetSecretRotationList = { +export type TGetSecretRotationListDTO = { workspaceId: string; - decryptFileKey: UserWsKeyPair; }; export type TCreateSecretRotationDTO = { diff --git a/frontend/src/views/SecretRotationPage/SecretRotationPage.tsx b/frontend/src/views/SecretRotationPage/SecretRotationPage.tsx index 405cf004a..535fe1bf0 100644 --- a/frontend/src/views/SecretRotationPage/SecretRotationPage.tsx +++ b/frontend/src/views/SecretRotationPage/SecretRotationPage.tsx @@ -1,4 +1,3 @@ -import { useTranslation } from "react-i18next"; import Link from "next/link"; import { faArrowsSpin, @@ -16,12 +15,9 @@ import { formatDistance } from "date-fns"; import { createNotification } from "@app/components/notifications"; import { ProjectPermissionCan } from "@app/components/permissions"; import { - Button, DeleteActionModal, EmptyState, IconButton, - Modal, - ModalContent, Skeleton, Spinner, Table, @@ -48,22 +44,17 @@ import { useDeleteSecretRotation, useGetSecretRotationProviders, useGetSecretRotations, - useGetUserWsKey, - useGetWorkspaceBot, - useRestartSecretRotation, - useUpdateBotActiveStatus + useRestartSecretRotation } from "@app/hooks/api"; import { TSecretRotationProviderTemplate } from "@app/hooks/api/types"; import { CreateRotationForm } from "./components/CreateRotationForm"; -import { generateBotKey } from "./SecretRotationPage.utils"; export const SecretRotationPage = withProjectPermission( () => { const { currentWorkspace } = useWorkspace(); - const { t } = useTranslation(); const { permission } = useProjectPermission(); - + const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([ "createRotation", "activeBot", @@ -77,13 +68,10 @@ export const SecretRotationPage = withProjectPermission( ); const { subscription } = useSubscription(); - const { data: userWsKey } = useGetUserWsKey(workspaceId); - const { data: secretRotationProviders, isLoading: isRotationProviderLoading } = useGetSecretRotationProviders({ workspaceId }); const { data: secretRotations, isLoading: isRotationLoading } = useGetSecretRotations({ - workspaceId, - decryptFileKey: userWsKey! + workspaceId }); const { @@ -97,11 +85,6 @@ export const SecretRotationPage = withProjectPermission( isLoading: isRestartingRotation } = useRestartSecretRotation(); - const { data: bot } = useGetWorkspaceBot(workspaceId); - const { mutateAsync: updateBotActiveStatus } = useUpdateBotActiveStatus(); - - const isBotActive = Boolean(bot?.isActive); - const handleDeleteRotation = async () => { const { id } = popUp.deleteRotation.data as { id: string }; try { @@ -142,29 +125,6 @@ export const SecretRotationPage = withProjectPermission( } }; - const handleUserAcceptBotCondition = async () => { - const provider = popUp.activeBot?.data as TSecretRotationProviderTemplate; - try { - if (bot?.id) { - const botKey = generateBotKey(bot.publicKey, userWsKey!); - await updateBotActiveStatus({ - isActive: true, - botId: bot.id, - workspaceId, - botKey - }); - } - handlePopUpOpen("createRotation", provider); - handlePopUpClose("activeBot"); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to create bot" - }); - } - }; - const handleCreateRotation = async (provider: TSecretRotationProviderTemplate) => { if (subscription && !subscription?.secretRotation) { handlePopUpOpen("upgradePlan"); @@ -174,11 +134,7 @@ export const SecretRotationPage = withProjectPermission( createNotification({ type: "error", text: "Access permission denied!!" }); return; } - if (isBotActive) { - handlePopUpOpen("createRotation", provider); - } else { - handlePopUpOpen("activeBot", provider); - } + handlePopUpOpen("createRotation", provider); }; return ( @@ -391,30 +347,6 @@ export const SecretRotationPage = withProjectPermission( onToggle={(isOpen) => handlePopUpToggle("createRotation", isOpen)} provider={(popUp.createRotation.data as TSecretRotationProviderTemplate) || {}} /> - handlePopUpToggle("activeBot", isOpen)} - > - - - - - } - > - {t("integrations.why-infisical-needs-access")} - -