diff --git a/backend/src/ee/services/secret-replication/secret-replication-service.ts b/backend/src/ee/services/secret-replication/secret-replication-service.ts index 480e80028..90fdf561e 100644 --- a/backend/src/ee/services/secret-replication/secret-replication-service.ts +++ b/backend/src/ee/services/secret-replication/secret-replication-service.ts @@ -267,7 +267,6 @@ export const secretReplicationServiceFactory = ({ const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared }); const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id }); const sourceImportedSecrets = await fnSecretsV2FromImports({ - projectId, secretImports: sourceSecretImports, secretDAL: secretV2BridgeDAL, folderDAL, diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index c9f2811b5..54c6b96b2 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -1089,7 +1089,8 @@ export const registerRoutes = async ( secretApprovalRequestSecretDAL, kmsService, snapshotService, - resourceMetadataDAL + resourceMetadataDAL, + keyStore }); const secretApprovalRequestService = secretApprovalRequestServiceFactory({ diff --git a/backend/src/server/routes/v2/project-router.ts b/backend/src/server/routes/v2/project-router.ts index 353c7525b..f7540591e 100644 --- a/backend/src/server/routes/v2/project-router.ts +++ b/backend/src/server/routes/v2/project-router.ts @@ -29,7 +29,8 @@ import { SanitizedProjectSchema } from "../sanitizedSchemas"; const projectWithEnv = SanitizedProjectSchema.extend({ _id: z.string(), - environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array() + environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array(), + kmsSecretManagerKeyId: z.string().nullable().optional() }); export const registerProjectRouter = async (server: FastifyZodProvider) => { diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index a5e036d35..9c0e8d2dd 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -435,12 +435,16 @@ export const identityKubernetesAuthServiceFactory = ({ const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); + const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId }); + if (!identityKubernetesAuth) { + throw new NotFoundError({ message: `Failed to find Kubernetes Auth for identity with ID ${identityId}` }); + } + if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) { throw new BadRequestError({ message: "The identity does not have Kubernetes Auth attached" }); } - const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId }); const { permission } = await permissionService.getOrgPermission( actor, diff --git a/backend/src/services/integration-auth/integration-delete-secret.ts b/backend/src/services/integration-auth/integration-delete-secret.ts index 18406f29a..f77becb02 100644 --- a/backend/src/services/integration-auth/integration-delete-secret.ts +++ b/backend/src/services/integration-auth/integration-delete-secret.ts @@ -50,7 +50,7 @@ const getIntegrationSecretsV2 = async ( } // process secrets in current folder - const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId }); + const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId }); secrets.forEach((secret) => { const secretKey = secret.key; @@ -63,7 +63,6 @@ const getIntegrationSecretsV2 = async ( // if no imports then return secrets in the current folder if (!secretImports.length) return content; const importedSecrets = await fnSecretsV2FromImports({ - projectId: dto.projectId, decryptor: dto.decryptor, folderDAL, secretDAL: secretV2BridgeDAL, diff --git a/backend/src/services/secret-import/secret-import-fns.ts b/backend/src/services/secret-import/secret-import-fns.ts index 2056d5a2c..e5a450441 100644 --- a/backend/src/services/secret-import/secret-import-fns.ts +++ b/backend/src/services/secret-import/secret-import-fns.ts @@ -159,8 +159,7 @@ export const fnSecretsV2FromImports = async ({ decryptor, expandSecretReferences, hasSecretAccess, - viewSecretValue, - projectId + viewSecretValue }: { secretImports: (Omit & { importEnv: { id: string; slug: string; name: string }; @@ -177,7 +176,6 @@ export const fnSecretsV2FromImports = async ({ environment: string; }) => Promise; hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean; - projectId: string; }) => { const cyclicDetector = new Set(); const stack: { @@ -218,8 +216,7 @@ export const fnSecretsV2FromImports = async ({ type: SecretType.Shared }, { - sort: [["id", "asc"]], - useCache: { projectId } + sort: [["id", "asc"]] } ); const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId); diff --git a/backend/src/services/secret-import/secret-import-service.ts b/backend/src/services/secret-import/secret-import-service.ts index d21003b10..2015516f5 100644 --- a/backend/src/services/secret-import/secret-import-service.ts +++ b/backend/src/services/secret-import/secret-import-service.ts @@ -698,7 +698,6 @@ export const secretImportServiceFactory = ({ projectId }); const importedSecrets = await fnSecretsV2FromImports({ - projectId, secretImports, folderDAL, viewSecretValue: true, diff --git a/backend/src/services/secret-sync/secret-sync-queue.ts b/backend/src/services/secret-sync/secret-sync-queue.ts index 9f4e283a9..3177b68b1 100644 --- a/backend/src/services/secret-sync/secret-sync-queue.ts +++ b/backend/src/services/secret-sync/secret-sync-queue.ts @@ -214,7 +214,7 @@ export const secretSyncQueueFactory = ({ canExpandValue: () => true }); - const secrets = await secretV2BridgeDAL.findByFolderId({ folderId, projectId }); + const secrets = await secretV2BridgeDAL.findByFolderId({ folderId }); await Promise.allSettled( secrets.map(async (secret) => { @@ -244,7 +244,6 @@ export const secretSyncQueueFactory = ({ if (secretImports.length) { const importedSecrets = await fnSecretsV2FromImports({ - projectId, decryptor: decryptSecretValue, folderDAL, secretDAL: secretV2BridgeDAL, diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-dal.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-dal.ts index a9c909899..05fc7cd35 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-dal.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-dal.ts @@ -1,3 +1,4 @@ +import { MongoAbility } from "@casl/ability"; import { Knex } from "knex"; import { validate as uuidValidate } from "uuid"; @@ -15,46 +16,29 @@ import { TFindFilter, TFindOpt } from "@app/lib/knex"; -import { BufferKeysToString, OrderByDirection } from "@app/lib/types"; +import { OrderByDirection } from "@app/lib/types"; import { SecretsOrderBy } from "@app/services/secret/secret-types"; -import type { TFindSecretsByFolderIdsFilter } from "@app/services/secret-v2-bridge/secret-v2-bridge-types"; +import type { + TFindSecretsByFolderIdsFilter, + TGetSecretsDTO +} from "@app/services/secret-v2-bridge/secret-v2-bridge-types"; -export const SecretDalCacheKeys = { +export const SecretServiceCacheKeys = { get productKey() { const { INFISICAL_PLATFORM_VERSION } = getConfig(); return `${ProjectType.SecretManager}:${INFISICAL_PLATFORM_VERSION || 0}`; }, getSecretDalVersion: (projectId: string) => { - return `${SecretDalCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`; + return `${SecretServiceCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`; }, - findByFolderIds: ( + getSecretsOfServiceLayer: ( projectId: string, version: number, - { useCache, tx, ...cacheKey }: Parameters[0] + dto: TGetSecretsDTO & { permissionRules: MongoAbility["rules"] } ) => { - return `${SecretDalCacheKeys.productKey}:${projectId}:${ + return `${SecretServiceCacheKeys.productKey}:${projectId}:${ TableName.SecretV2 - }-dal:v${version}:find-by-folder-ids:${generateCacheKeyFromData(cacheKey)}`; - }, - findByFolderId: ( - projectId: string, - version: number, - { useCache, tx, ...cacheKey }: Parameters[0] - ) => { - return `${SecretDalCacheKeys.productKey}:${projectId}:${ - TableName.SecretV2 - }-dal:v${version}:find-by-folder-id:${generateCacheKeyFromData(cacheKey)}`; - }, - find: (projectId: string, version: number, ...args: Parameters) => { - const [filter, opts] = args; - delete opts?.tx; - delete opts?.useCache; - return `${SecretDalCacheKeys.productKey}:${projectId}:${ - TableName.SecretV2 - }-dal:v${version}:find:${generateCacheKeyFromData({ - filter, - opts - })}`; + }-dal:v${version}:get-secrets-service-layer:${dto.actorId}-${generateCacheKeyFromData(dto)}`; } }; @@ -64,14 +48,14 @@ interface TSecretV2DalArg { keyStore: TKeyStoreFactory; } -const SECRET_DAL_TTL = 5 * 60; -const SECRET_DAL_VERSION_TTL = 15 * 60; -const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024; +export const SECRET_DAL_TTL = 5 * 60; +export const SECRET_DAL_VERSION_TTL = 15 * 60; +export const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024; export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { const secretOrm = ormify(db, TableName.SecretV2); const invalidateSecretCacheByProjectId = async (projectId: string) => { - const secretDalVersionKey = SecretDalCacheKeys.getSecretDalVersion(projectId); + const secretDalVersionKey = SecretServiceCacheKeys.getSecretDalVersion(projectId); await keyStore.incrementBy(secretDalVersionKey, 1); await keyStore.setExpiry(secretDalVersionKey, SECRET_DAL_VERSION_TTL); }; @@ -128,35 +112,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { } }; - const find = async ( - filter: TFindFilter, - opts: TFindOpt & { useCache?: { projectId: string } } = {} - ) => { - const { offset, limit, sort, tx, useCache } = opts; + const find = async (filter: TFindFilter, opts: TFindOpt = {}) => { + const { offset, limit, sort, tx } = opts; try { - let secretDalVersion = 0; - if (useCache) { - const cachedSecretDalVersion = await keyStore.getItem( - SecretDalCacheKeys.getSecretDalVersion(useCache.projectId) - ); - secretDalVersion = Number(cachedSecretDalVersion || 0); - const cacheKey = SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts); - const cachedSecrets = await keyStore.getItem(cacheKey); - if (cachedSecrets) { - await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL); - - const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[]; - const sanitizedSecrets = unsanitizedSecrets.map((el) => { - const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null; - const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null; - const createdAt = new Date(el.createdAt); - const updatedAt = new Date(el.updatedAt); - return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt }; - }); - return sanitizedSecrets; - } - } - const query = (tx || db)(TableName.SecretV2) // eslint-disable-next-line @typescript-eslint/no-misused-promises .where(buildFindFilter(filter)) @@ -225,22 +183,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { ] }); - if (useCache) { - const cachedSecrets = data.map((el) => { - const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null; - const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null; - return { ...el, encryptedValue, encryptedComment }; - }); - const cache = JSON.stringify(cachedSecrets); - if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) { - await keyStore.setItemWithExpiry( - SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts), - SECRET_DAL_TTL, - cache - ); - } - } - return data; } catch (error) { throw new DatabaseError({ error, name: `${TableName.SecretV2}: Find` }); @@ -345,15 +287,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { } }; - const findByFolderId = async (dto: { - folderId: string; - userId?: string; - tx?: Knex; - projectId: string; - useCache?: boolean; - }) => { + const findByFolderId = async (dto: { folderId: string; userId?: string; tx?: Knex }) => { try { - const { folderId, tx, projectId } = dto; + const { folderId, tx } = dto; let { userId } = dto; // check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo if (userId && !uuidValidate(userId)) { @@ -361,27 +297,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { userId = undefined; } - const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId)); - const secretDalVersion = Number(cachedSecretDalVersion || 0); - - if (dto.useCache) { - const cacheKey = SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto); - const cachedSecrets = await keyStore.getItem(cacheKey); - if (cachedSecrets) { - await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL); - - const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[]; - const sanitizedSecrets = unsanitizedSecrets.map((el) => { - const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null; - const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null; - const createdAt = new Date(el.createdAt); - const updatedAt = new Date(el.updatedAt); - return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt }; - }); - return sanitizedSecrets; - } - } - const secs = await (tx || db.replicaNode())(TableName.SecretV2) .where({ folderId }) .where((bd) => { @@ -437,22 +352,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { } ] }); - if (dto.useCache) { - const newCachedSecrets = data.map((el) => { - const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null; - const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null; - return { ...el, encryptedValue, encryptedComment }; - }); - const cache = JSON.stringify(newCachedSecrets); - - if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) { - await keyStore.setItemWithExpiry( - SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto), - SECRET_DAL_TTL, - cache - ); - } - } return data; } catch (error) { throw new DatabaseError({ error, name: "get all secret" }); @@ -542,11 +441,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { folderIds: string[]; userId?: string; tx?: Knex; - projectId: string; filters?: TFindSecretsByFolderIdsFilter; - useCache?: boolean; }) => { - const { folderIds, tx, filters, useCache, projectId } = dto; + const { folderIds, tx, filters } = dto; let { userId } = dto; try { // check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo) @@ -555,26 +452,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { userId = undefined; } - const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId)); - const secretDalVersion = Number(cachedSecretDalVersion || 0); - if (useCache) { - const cacheKey = SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto); - const cachedSecrets = await keyStore.getItem(cacheKey); - if (cachedSecrets) { - await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL); - - const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[]; - const sanitizedSecrets = unsanitizedSecrets.map((el) => { - const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null; - const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null; - const createdAt = new Date(el.createdAt); - const updatedAt = new Date(el.updatedAt); - return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt }; - }); - return sanitizedSecrets; - } - } - const query = (tx || db.replicaNode())(TableName.SecretV2) .whereIn(`${TableName.SecretV2}.folderId`, folderIds) .where((bd) => { @@ -700,22 +577,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { } ] }); - if (useCache) { - const cachedSecrets = data.map((el) => { - const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null; - const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null; - return { ...el, encryptedValue, encryptedComment }; - }); - const cache = JSON.stringify(cachedSecrets); - - if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) { - await keyStore.setItemWithExpiry( - SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto), - SECRET_DAL_TTL, - cache - ); - } - } return data; } catch (error) { diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index 4e7a5bca7..f42deb8ff 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -509,7 +509,7 @@ export const expandSecretReferencesFactory = ({ const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); if (!folder) return { value: "", tags: [] }; - const secrets = await secretDAL.findByFolderId({ folderId: folder.id, projectId, useCache: true }); + const secrets = await secretDAL.findByFolderId({ folderId: folder.id }); const decryptedSecret = secrets.reduce>((prev, secret) => { // eslint-disable-next-line no-param-reassign diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index 596ebb5a1..ca815c6e1 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -25,6 +25,7 @@ import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-app import { TSecretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal"; import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-secret-dal"; import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service"; +import { TKeyStoreFactory } from "@app/keystore/keystore"; import { DatabaseErrorCode } from "@app/lib/error-codes"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { diff, groupBy } from "@app/lib/fn"; @@ -43,7 +44,12 @@ import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; import { TSecretImportDALFactory } from "../secret-import/secret-import-dal"; import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns"; import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal"; -import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal"; +import { + MAX_SECRET_CACHE_BYTES, + SECRET_DAL_TTL, + SecretServiceCacheKeys, + TSecretV2BridgeDALFactory +} from "./secret-v2-bridge-dal"; import { buildHierarchy, expandSecretReferencesFactory, @@ -105,6 +111,7 @@ type TSecretV2BridgeServiceFactoryDep = { >; snapshotService: Pick; resourceMetadataDAL: Pick; + keyStore: Pick; }; export type TSecretV2BridgeServiceFactory = ReturnType; @@ -127,7 +134,8 @@ export const secretV2BridgeServiceFactory = ({ secretApprovalRequestDAL, secretApprovalRequestSecretDAL, kmsService, - resourceMetadataDAL + resourceMetadataDAL, + keyStore }: TSecretV2BridgeServiceFactoryDep) => { const $validateSecretReferences = async ( projectId: string, @@ -800,12 +808,10 @@ export const secretV2BridgeServiceFactory = ({ const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId); const secrets = await secretDAL.findByFolderIds({ - projectId, folderIds: folderMappings.map((folderMapping) => folderMapping.folderId), userId, tx: undefined, - filters, - useCache: true + filters }); const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ @@ -909,21 +915,22 @@ export const secretV2BridgeServiceFactory = ({ return decryptedSecrets; }; - const getSecrets = async ({ - actorId, - path, - environment, - projectId, - actor, - actorOrgId, - viewSecretValue, - actorAuthMethod, - includeImports, - recursive, - expandSecretReferences: shouldExpandSecretReferences, - throwOnMissingReadValuePermission = true, - ...params - }: TGetSecretsDTO) => { + const getSecrets = async (dto: TGetSecretsDTO) => { + const { + actorId, + path, + environment, + projectId, + actor, + actorOrgId, + viewSecretValue, + actorAuthMethod, + includeImports, + recursive, + expandSecretReferences: shouldExpandSecretReferences, + throwOnMissingReadValuePermission = true, + ...params + } = dto; const { permission } = await permissionService.getProjectPermission({ actor, actorId, @@ -934,6 +941,42 @@ export const secretV2BridgeServiceFactory = ({ }); throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret); + const cachedSecretDalVersion = await keyStore.getItem(SecretServiceCacheKeys.getSecretDalVersion(projectId)); + const secretDalVersion = Number(cachedSecretDalVersion || 0); + const cacheKey = SecretServiceCacheKeys.getSecretsOfServiceLayer(projectId, secretDalVersion, { + ...dto, + permissionRules: permission.rules + }); + + const { decryptor: secretManagerDecryptor, encryptor: secretManagerEncryptor } = + await kmsService.createCipherPairWithDataKey({ + type: KmsDataKey.SecretManager, + projectId + }); + + const encryptedCachedSecrets = await keyStore.getItem(cacheKey); + if (encryptedCachedSecrets) { + try { + await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL); + const cachedSecrets = secretManagerDecryptor({ cipherTextBlob: Buffer.from(encryptedCachedSecrets, "base64") }); + const { secrets, imports = [] } = JSON.parse(cachedSecrets.toString("utf8")) as { + secrets: typeof decryptedSecrets; + imports: typeof importedSecrets; + }; + return { + secrets: secrets.map((el) => ({ + ...el, + createdAt: new Date(el.createdAt), + updatedAt: new Date(el.updatedAt) + })), + imports + }; + } catch (err) { + logger.error(err, "Secret service layer cache miss"); + await keyStore.deleteItem(cacheKey); + } + } + let paths: { folderId: string; path: string }[] = []; if (recursive) { @@ -958,17 +1001,10 @@ export const secretV2BridgeServiceFactory = ({ const groupedPaths = groupBy(paths, (p) => p.folderId); const secrets = await secretDAL.findByFolderIds({ - projectId, folderIds: paths.map((p) => p.folderId), userId: actorId, tx: undefined, - filters: params, - useCache: true - }); - - const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ - type: KmsDataKey.SecretManager, - projectId + filters: params }); // scott: if any of this changes it also needs to be mirrored in secret rotation for getting dashboard secrets @@ -1086,15 +1122,19 @@ export const secretV2BridgeServiceFactory = ({ } if (!includeImports) { - return { - secrets: decryptedSecrets - }; + const payload = { secrets: decryptedSecrets, imports: [] }; + const encryptedUpdatedCachedSecrets = secretManagerEncryptor({ + plainText: Buffer.from(JSON.stringify(payload)) + }).cipherTextBlob; + if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) { + await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64")); + } + return payload; } const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId)); const allowedImports = secretImports.filter(({ isReplication }) => !isReplication); const importedSecrets = await fnSecretsV2FromImports({ - projectId, viewSecretValue, secretImports: allowedImports, secretDAL, @@ -1129,10 +1169,14 @@ export const secretV2BridgeServiceFactory = ({ } }); - return { - secrets: decryptedSecrets, - imports: importedSecrets - }; + const payload = { secrets: decryptedSecrets, imports: importedSecrets }; + const encryptedUpdatedCachedSecrets = secretManagerEncryptor({ + plainText: Buffer.from(JSON.stringify(payload)) + }).cipherTextBlob; + if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) { + await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64")); + } + return payload; }; const getSecretById = async ({ actorId, actor, actorOrgId, actorAuthMethod, secretId }: TGetASecretByIdDTO) => { @@ -1312,7 +1356,6 @@ export const secretV2BridgeServiceFactory = ({ if (!secret && includeImports) { const secretImports = await secretImportDAL.find({ folderId, isReplication: false }); const importedSecrets = await fnSecretsV2FromImports({ - projectId, secretImports, viewSecretValue, secretDAL, @@ -2729,7 +2772,7 @@ export const secretV2BridgeServiceFactory = ({ generatePaths(folderMap).map(({ folderId, path }) => [folderId, path === "/" ? path : path.substring(1)]) ); - const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id), projectId, useCache: true }); + const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id) }); const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, diff --git a/backend/src/services/secret/secret-queue.ts b/backend/src/services/secret/secret-queue.ts index 0d36250fb..5791c415d 100644 --- a/backend/src/services/secret/secret-queue.ts +++ b/backend/src/services/secret/secret-queue.ts @@ -367,7 +367,7 @@ export const secretQueueFactory = ({ canExpandValue: () => true }); // process secrets in current folder - const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId }); + const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId }); await Promise.allSettled( secrets.map(async (secret) => { @@ -397,7 +397,6 @@ export const secretQueueFactory = ({ // if no imports then return secrets in the current folder if (!secretImports.length) return content; const importedSecrets = await fnSecretsV2FromImports({ - projectId: dto.projectId, decryptor: dto.decryptor, folderDAL, secretDAL: secretV2BridgeDAL, diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx index 89824e9f7..e0cbbe387 100644 --- a/docs/cli/overview.mdx +++ b/docs/cli/overview.mdx @@ -28,21 +28,32 @@ You can use it across various environments, whether it's local development, CI/C ``` - Use [Scoop](https://scoop.sh/) package manager - ```bash - scoop bucket add org https://github.com/Infisical/scoop-infisical.git - ``` + + Use [Scoop](https://scoop.sh/) package manager - ```bash - scoop install infisical - ``` + ```bash + scoop bucket add org https://github.com/Infisical/scoop-infisical.git + ``` - ### Updates + ```bash + scoop install infisical + ``` - ```bash - scoop update infisical - ``` + ### Updates + + ```bash + scoop update infisical + ``` + + + + Use [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) package manager + + ```bash + winget install infisical + ``` + diff --git a/frontend/public/lotties/notification-bell.json b/frontend/public/lotties/notification-bell.json new file mode 100644 index 000000000..56d4c9950 --- /dev/null +++ b/frontend/public/lotties/notification-bell.json @@ -0,0 +1 @@ +{"v":"5.12.1","fr":60,"ip":0,"op":90,"w":500,"h":500,"nm":"system-regular-46-notification-bell","ddd":0,"assets":[{"id":"comp_1","nm":"hover-bell","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.231],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.313],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7.041,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":19,"s":[-53]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":29,"s":[-20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":39,"s":[-62]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":49,"s":[-20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":58,"s":[-62]},{"i":{"x":[0.283],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":69.713,"s":[14]},{"t":79,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.231,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[249.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.313,"y":1},"o":{"x":0.333,"y":0},"t":7.041,"s":[269.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":19,"s":[111.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.313,"y":1},"o":{"x":0.333,"y":0},"t":29,"s":[121.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[111.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":49,"s":[121.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":58,"s":[111.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.283,"y":1},"o":{"x":0.333,"y":0},"t":69.713,"s":[261.998,67.334,0],"to":[0,0,0],"ti":[0,0,0]},{"t":79,"s":[249.998,67.334,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.998,67.334,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,6.468],[0,0],[60.406,0],[0,0],[0,-60.406],[0,0],[2.893,-5.786],[0,0],[0,0]],"o":[[-2.893,-5.786],[0,0],[0,-60.406],[0,0],[-60.406,0],[0,0],[0,6.468],[0,0],[0,0],[0,0]],"v":[[113.773,55.671],[109.375,37.038],[109.375,-20.834],[0.001,-130.21],[-0.001,-130.21],[-109.375,-20.834],[-109.375,37.038],[-113.773,55.671],[-151.042,130.21],[151.042,130.21]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Stroke","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[249.998,229.166],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-20.832],[0,20.832]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Stroke","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[249.998,78.125],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":90,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary.design","cl":"primary design","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[27]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[-26]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32,"s":[29]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[-28]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":52,"s":[29]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[-28]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[29]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":83,"s":[-6]},{"t":90,"s":[0]}],"ix":10},"p":{"a":0,"k":[249.998,182.041,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-219,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-25.889,0],[0,25.889],[0,0]],"o":[[0,0],[0,25.889],[25.888,0],[0,0],[0,0]],"v":[[-46.751,-119.666],[-46.875,-5.21],[0.001,41.666],[46.875,-5.21],[46.998,-119.666]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Stroke","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[23]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[33]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[21]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32,"s":[33]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[21]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":47,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":52,"s":[33]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[21]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[33]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":78,"s":[22.538]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":83,"s":[21]},{"t":90,"s":[22.538]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[79]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":24,"s":[68]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32,"s":[79]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[68]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":47,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":52,"s":[79]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":57,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":61,"s":[68]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[79]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":78,"s":[77.077]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":83,"s":[75]},{"t":90,"s":[77.077]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":1,"op":90,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.038,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[2083,2083,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0.43],[0,0],[-2.48,0],[0,-2.48],[0,0],[-0.19,-0.38],[0,0]],"o":[[0,0],[0.19,-0.38],[0,0],[0,-2.48],[2.48,0],[0,0],[0,0.42],[0,0],[0,0]],"v":[[-6.042,4.5],[-4.792,2.01],[-4.502,0.78],[-4.502,-2],[-0.002,-6.5],[4.498,-2],[4.498,0.78],[4.788,2.01],[6.038,4.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0.19],[0,0],[2.96,0.37],[0,0],[0.41,0],[0,-0.41],[0,0],[0,-3.05],[0,0],[0.08,-0.17],[0,0],[-0.13,-0.22],[-0.26,0],[0,0],[-0.14,0.23],[0.12,0.23]],"o":[[-0.08,-0.18],[0,0],[0,-3.05],[0,0],[0,-0.41],[-0.41,0],[0,0],[-2.96,0.37],[0,0],[0,0.19],[0,0],[-0.12,0.23],[0.14,0.22],[0,0],[0.26,0],[0.14,-0.22],[0,0]],"v":[[6.128,1.34],[5.998,0.78],[5.998,-2],[0.748,-7.95],[0.748,-9.25],[-0.002,-10],[-0.752,-9.25],[-0.752,-7.95],[-6.002,-2],[-6.002,0.78],[-6.132,1.34],[-7.922,4.92],[-7.892,5.65],[-7.252,6],[7.248,6],[7.888,5.64],[7.918,4.91]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Fill","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.038,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[2083,2083,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.83,0],[0,0.83],[0,0],[0,0]],"o":[[0,0.83],[-0.83,0],[0,0],[0,0],[0,0]],"v":[[1.498,7],[-0.002,8.5],[-1.502,7],[-1.501,5.544],[1.499,5.544]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.65,0],[0,1.65],[0,0]],"o":[[0,0],[0,1.65],[1.65,0],[0,0],[0,0]],"v":[[-3.001,5.088],[-3.002,7],[-0.002,10],[2.998,7],[2.999,5.088]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Fill","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.038,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[2083,2083,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0.43],[0,0],[-2.48,0],[0,-2.48],[0,0],[-0.19,-0.38],[0,0]],"o":[[0,0],[0.19,-0.38],[0,0],[0,-2.48],[2.48,0],[0,0],[0,0.42],[0,0],[0,0]],"v":[[-6.042,4.5],[-4.792,2.01],[-4.502,0.78],[-4.502,-2],[-0.002,-6.5],[4.498,-2],[4.498,0.78],[4.788,2.01],[6.038,4.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0.19],[0,0],[2.96,0.37],[0,0],[0.41,0],[0,-0.41],[0,0],[0,-3.05],[0,0],[0.08,-0.17],[0,0],[-0.13,-0.22],[-0.26,0],[0,0],[-0.14,0.23],[0.12,0.23]],"o":[[-0.08,-0.18],[0,0],[0,-3.05],[0,0],[0,-0.41],[-0.41,0],[0,0],[-2.96,0.37],[0,0],[0,0.19],[0,0],[-0.12,0.23],[0.14,0.22],[0,0],[0.26,0],[0.14,-0.22],[0,0]],"v":[[6.128,1.34],[5.998,0.78],[5.998,-2],[0.748,-7.95],[0.748,-9.25],[-0.002,-10],[-0.752,-9.25],[-0.752,-7.95],[-6.002,-2],[-6.002,0.78],[-6.132,1.34],[-7.922,4.92],[-7.892,5.65],[-7.252,6],[7.248,6],[7.888,5.64],[7.918,4.91]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Fill","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":90,"op":300,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.038,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[2083,2083,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.83,0],[0,0.83],[0,0],[0,0]],"o":[[0,0.83],[-0.83,0],[0,0],[0,0],[0,0]],"v":[[1.498,7],[-0.002,8.5],[-1.502,7],[-1.501,5.544],[1.499,5.544]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.65,0],[0,1.65],[0,0]],"o":[[0,0],[0,1.65],[1.65,0],[0,0],[0,0]],"v":[[-3.001,5.088],[-3.002,7],[-0.002,10],[2.998,7],[2.999,5.088]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('system-regular-46-notification-bell').layer('control').effect('primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":".primary","mn":"ADBE Vector Graphic - Fill","hd":false,"cl":"primary"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":90,"op":300,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"control","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"primary","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1],"ix":1}}]}],"ip":0,"op":291,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"hover-bell","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2,"l":2},"a":{"a":0,"k":[250,250,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":500,"h":500,"ip":0,"op":100,"st":0,"bm":0}],"markers":[{"tm":0,"cm":"default:hover-bell","dr":90}],"props":{}} \ No newline at end of file diff --git a/frontend/src/const/routes.ts b/frontend/src/const/routes.ts index 2be3f3dbc..cd3c6675f 100644 --- a/frontend/src/const/routes.ts +++ b/frontend/src/const/routes.ts @@ -281,6 +281,14 @@ export const ROUTE_PATHS = Object.freeze({ "/cert-manager/$projectId/overview", "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview" ), + CertificateAuthoritiesPage: setRoute( + "/cert-manager/$projectId/certificate-authorities", + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities" + ), + AlertingPage: setRoute( + "/cert-manager/$projectId/alerting", + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting" + ), PkiCollectionDetailsByIDPage: setRoute( "/cert-manager/$projectId/pki-collections/$collectionId", "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId" diff --git a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx index e1fd2e4bf..7aed0a6e8 100644 --- a/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx +++ b/frontend/src/layouts/ProjectLayout/ProjectLayout.tsx @@ -92,18 +92,46 @@ export const ProjectLayout = () => { )} {isCertManager && ( - - {({ isActive }) => ( - - Overview - - )} - + <> + + {({ isActive }) => ( + + Certificates + + )} + + + {({ isActive }) => ( + + Certificate Authorities + + )} + + + {({ isActive }) => ( + + Alerting + + )} + + )} {isCmek && ( { + const { t } = useTranslation(); + return ( +
+ + {t("common.head-title", { title: "Alerting" })} + +
+ + + + +
+
+ ); +}; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertModal.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertModal.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertRow.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertRow.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertRow.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertRow.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertsSection.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertsSection.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertsTable.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsTable.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiAlertsTable.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsTable.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionModal.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionModal.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionSection.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionSection.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionTable.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/PkiCollectionTable.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionTable.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/index.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/index.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/components/index.tsx rename to frontend/src/pages/cert-manager/AlertingPage/components/index.tsx diff --git a/frontend/src/pages/cert-manager/AlertingPage/route.tsx b/frontend/src/pages/cert-manager/AlertingPage/route.tsx new file mode 100644 index 000000000..d14e64d94 --- /dev/null +++ b/frontend/src/pages/cert-manager/AlertingPage/route.tsx @@ -0,0 +1,19 @@ +import { createFileRoute } from "@tanstack/react-router"; + +import { AlertingPage } from "./AlertingPage"; + +export const Route = createFileRoute( + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting" +)({ + component: AlertingPage, + beforeLoad: ({ context }) => { + return { + breadcrumbs: [ + ...context.breadcrumbs, + { + label: "Alerting" + } + ] + }; + } +}); diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx index 75d0ca139..9bb6c9096 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx @@ -20,9 +20,9 @@ import { useDeleteCa, useGetCaById } from "@app/hooks/api"; import { ProjectType } from "@app/hooks/api/workspace/types"; import { usePopUp } from "@app/hooks/usePopUp"; -import { CaInstallCertModal } from "../CertificatesPage/components/CaTab/components/CaInstallCertModal"; -import { CaModal } from "../CertificatesPage/components/CaTab/components/CaModal"; -import { CertificateTemplatesSection } from "../CertificatesPage/components/CertificatesTab/components/CertificateTemplatesSection"; +import { CaInstallCertModal } from "../CertificateAuthoritiesPage/components/CaInstallCertModal"; +import { CaModal } from "../CertificateAuthoritiesPage/components/CaModal"; +import { CertificateTemplatesSection } from "../CertificatesPage/components/CertificateTemplatesSection"; import { CaCertificatesSection, CaCrlsSection, diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx index 00244eb98..aa7540a7f 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx @@ -13,7 +13,7 @@ export const Route = createFileRoute( { label: "Certificate Authorities", link: linkOptions({ - to: "/cert-manager/$projectId/overview", + to: "/cert-manager/$projectId/certificate-authorities", params: { projectId: params.projectId } diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx new file mode 100644 index 000000000..f74ececaf --- /dev/null +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/CertificateAuthoritiesPage.tsx @@ -0,0 +1,29 @@ +import { Helmet } from "react-helmet"; +import { useTranslation } from "react-i18next"; + +import { ProjectPermissionCan } from "@app/components/permissions"; +import { PageHeader } from "@app/components/v2"; +import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; + +import { CaSection } from "./components"; + +export const CertificateAuthoritiesPage = () => { + const { t } = useTranslation(); + return ( +
+ + {t("common.head-title", { title: "Certificate Authorities" })} + +
+ + + + +
+
+ ); +}; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaCertModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaCertModal.tsx similarity index 91% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaCertModal.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaCertModal.tsx index 97970d94f..113a88c48 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaCertModal.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaCertModal.tsx @@ -2,7 +2,7 @@ import { Modal, ModalContent } from "@app/components/v2"; import { useGetCaCert } from "@app/hooks/api"; import { UsePopUpState } from "@app/hooks/usePopUp"; -import { CertificateContent } from "../../CertificatesTab/components/CertificateContent"; +import { CertificateContent } from "../../CertificatesPage/components/CertificateContent"; type Props = { popUp: UsePopUpState<["caCert"]>; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/CaInstallCertModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/CaInstallCertModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/CaInstallCertModal.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/CaInstallCertModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/ExternalCaInstallForm.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/InternalCaInstallForm.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/index.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/index.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaInstallCertModal/index.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/index.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaModal.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaSection.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaSection.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/CaTable.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/index.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/index.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/components/index.tsx rename to frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/index.tsx diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/route.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/route.tsx new file mode 100644 index 000000000..e11496710 --- /dev/null +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/route.tsx @@ -0,0 +1,19 @@ +import { createFileRoute } from "@tanstack/react-router"; + +import { CertificateAuthoritiesPage } from "./CertificateAuthoritiesPage"; + +export const Route = createFileRoute( + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities" +)({ + component: CertificateAuthoritiesPage, + beforeLoad: ({ context }) => { + return { + breadcrumbs: [ + ...context.breadcrumbs, + { + label: "Certificate Authorities" + } + ] + }; + } +}); diff --git a/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx b/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx index 0d212e797..c985f313f 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/CertificatesPage.tsx @@ -2,63 +2,49 @@ import { Helmet } from "react-helmet"; import { useTranslation } from "react-i18next"; import { ProjectPermissionCan } from "@app/components/permissions"; -import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; -import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; +import { PageHeader } from "@app/components/v2"; +import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context"; -import { CaTab, CertificatesTab, PkiAlertsTab } from "./components"; - -enum TabSections { - Ca = "certificate-authorities", - Certificates = "certificates", - Alerting = "alerting" -} +import { PkiCollectionSection } from "../AlertingPage/components"; +import { CertificatesSection } from "./components"; export const CertificatesPage = () => { const { t } = useTranslation(); + const { permission } = useProjectPermission(); + + const canAccessPkiColl = permission.can( + ProjectPermissionActions.Read, + ProjectPermissionSub.PkiCollections + ); + const canAccessCerts = permission.can( + ProjectPermissionActions.Read, + ProjectPermissionSub.Certificates + ); + return (
{t("common.head-title", { title: "Certificates" })}
- - - - Certificates - Certificate Authorities - Alerting - - - - - - - - - - - - - - - - - + + {/* If both are false, the section does not render. This is to prevent duplicate banners. */} + {(canAccessCerts || canAccessPkiColl) && ( + + + + )} + + +
); diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/CaTab.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/CaTab.tsx deleted file mode 100644 index aadca4dfe..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/CaTab.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { motion } from "framer-motion"; - -import { CaSection } from "./components"; - -export const CaTab = () => { - return ( - - - - ); -}; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/index.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/index.tsx deleted file mode 100644 index 9e52be028..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CaTab/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { CaTab } from "./CaTab"; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateCertModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateCertModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateCertModal.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateCertModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateContent.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateContent.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateContent.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateContent.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateRevocationModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateRevocationModal.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateEnrollmentModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateEnrollmentModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateEnrollmentModal.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateEnrollmentModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplatesSection.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplatesSection.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplatesSection.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplatesSection.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplatesTable.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplatesTable.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateTemplatesTable.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplatesTable.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesSection.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesSection.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/CertificatesTab.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/CertificatesTab.tsx deleted file mode 100644 index 0f74920ec..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/CertificatesTab.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { motion } from "framer-motion"; - -import { PkiCollectionSection } from "../PkiAlertsTab/components"; -// import { CertificateTemplatesSection } from "./components/CertificateTemplatesSection"; -import { CertificatesSection } from "./components"; - -export const CertificatesTab = () => { - return ( - - - {/* */} - - - ); -}; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/index.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/index.tsx deleted file mode 100644 index 7854a6f8b..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { CertificatesSection } from "./CertificatesSection"; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/index.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/index.tsx deleted file mode 100644 index 277134d56..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { CertificatesTab } from "./CertificatesTab"; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesTable.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesTable.tsx rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesTable.utils.ts b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.utils.ts similarity index 100% rename from frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificatesTable.utils.ts rename to frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.utils.ts diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/PkiAlertsTab.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/PkiAlertsTab.tsx deleted file mode 100644 index 3a5a04345..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/PkiAlertsTab.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { motion } from "framer-motion"; - -import { PkiAlertsSection } from "./components"; - -export const PkiAlertsTab = () => { - return ( - - - - ); -}; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/index.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/index.tsx deleted file mode 100644 index 0acaf13d6..000000000 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/PkiAlertsTab/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { PkiAlertsTab } from "./PkiAlertsTab"; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/index.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/index.tsx index 851d403a0..7854a6f8b 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/index.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/index.tsx @@ -1,3 +1 @@ -export { CaTab } from "./CaTab"; -export { CertificatesTab } from "./CertificatesTab"; -export { PkiAlertsTab } from "./PkiAlertsTab"; +export { CertificatesSection } from "./CertificatesSection"; diff --git a/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx index 5cd8bf7c6..073cac6e8 100644 --- a/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/PkiCollectionDetailsByIDPage/PkiCollectionDetailsByIDPage.tsx @@ -22,7 +22,7 @@ import { PkiItemType } from "@app/hooks/api/pkiCollections/constants"; import { ProjectType } from "@app/hooks/api/workspace/types"; import { usePopUp } from "@app/hooks/usePopUp"; -import { PkiCollectionModal } from "../CertificatesPage/components/PkiAlertsTab/components/PkiCollectionModal"; +import { PkiCollectionModal } from "../AlertingPage/components/PkiCollectionModal"; import { PkiCollectionDetailsSection, PkiCollectionItemsSection } from "./components"; export const PkiCollectionPage = () => { diff --git a/frontend/src/pages/kms/KmipPage/components/KmipClientCertificateModal.tsx b/frontend/src/pages/kms/KmipPage/components/KmipClientCertificateModal.tsx index 4f8744682..81694e025 100644 --- a/frontend/src/pages/kms/KmipPage/components/KmipClientCertificateModal.tsx +++ b/frontend/src/pages/kms/KmipPage/components/KmipClientCertificateModal.tsx @@ -1,6 +1,6 @@ import { Modal, ModalContent } from "@app/components/v2"; import { KmipClientCertificate } from "@app/hooks/api/kmip/types"; -import { CertificateContent } from "@app/pages/cert-manager/CertificatesPage/components/CertificatesTab/components/CertificateContent"; +import { CertificateContent } from "@app/pages/cert-manager/CertificatesPage/components/CertificateContent"; type Props = { isOpen: boolean; diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/ExternalKmsItem.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/ExternalKmsItem.tsx new file mode 100644 index 000000000..d080b57c6 --- /dev/null +++ b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/ExternalKmsItem.tsx @@ -0,0 +1,152 @@ +import { faAws, faGoogle } from "@fortawesome/free-brands-svg-icons"; +import { faCheck, faCopy, faEllipsis } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; + +import { createNotification } from "@app/components/notifications"; +import { OrgPermissionCan } from "@app/components/permissions/OrgPermissionCan"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger +} from "@app/components/v2/Dropdown"; +import { IconButton } from "@app/components/v2/IconButton"; +import { Td, Tr } from "@app/components/v2/Table"; +import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context/OrgPermissionContext"; +import { useToggle } from "@app/hooks"; +import { ExternalKmsProvider, KmsListEntry } from "@app/hooks/api/kms/types"; +import { SubscriptionPlan } from "@app/hooks/api/types"; +import { UsePopUpState } from "@app/hooks/usePopUp"; + +type Props = { + kms: KmsListEntry; + handlePopUpOpen: ( + popUpName: keyof UsePopUpState<["editExternalKms", "removeExternalKms", "upgradePlan"]>, + data?: { + kmsId?: string; + name?: string; + provider?: string; + } + ) => void; + subscription: SubscriptionPlan; +}; + +export const ExternalKmsItem = ({ kms, handlePopUpOpen, subscription }: Props) => { + const [isKmsIdCopied, { timedToggle: toggleKmsIdCopied }] = useToggle(false); + const [isKmsAliasCopied, { timedToggle: toggleKmsAliasCopied }] = useToggle(false); + + return ( + + + {kms.externalKms.provider === ExternalKmsProvider.Aws && } + {kms.externalKms.provider === ExternalKmsProvider.Gcp && ( + + )} +
{kms.externalKms.provider.toUpperCase()}
+ + +
+ {kms.name} + { + if (isKmsAliasCopied) { + return; + } + navigator.clipboard.writeText(kms.name); + createNotification({ + text: "KMS alias copied to clipboard", + type: "success" + }); + toggleKmsAliasCopied(2000); + }} + > + + +
+ + +
+ {kms.id} + { + if (isKmsIdCopied) { + return; + } + navigator.clipboard.writeText(kms.id); + createNotification({ + text: "KMS ID copied to clipboard", + type: "success" + }); + toggleKmsIdCopied(2000); + }} + > + + +
+ + + + +
+ +
+
+ + + {(isAllowed) => ( + { + e.stopPropagation(); + if (subscription && !subscription?.externalKms) { + handlePopUpOpen("upgradePlan"); + return; + } + + handlePopUpOpen("editExternalKms", { + kmsId: kms.id + }); + }} + > + Edit + + )} + + + {(isAllowed) => ( + { + e.stopPropagation(); + handlePopUpOpen("removeExternalKms", { + name: kms.name, + kmsId: kms.id, + provider: kms.externalKms.provider + }); + }} + > + Delete + + )} + + +
+ + + ); +}; diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx index dc25b40af..8f1bd8e79 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx @@ -1,7 +1,5 @@ -import { faAws, faGoogle } from "@fortawesome/free-brands-svg-icons"; -import { faEllipsis, faLock, faPlus } from "@fortawesome/free-solid-svg-icons"; +import { faLock, faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { twMerge } from "tailwind-merge"; import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; import { createNotification } from "@app/components/notifications"; @@ -9,10 +7,6 @@ import { OrgPermissionCan } from "@app/components/permissions"; import { Button, DeleteActionModal, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, EmptyState, Table, TableContainer, @@ -31,9 +25,9 @@ import { import { withPermission } from "@app/hoc"; import { usePopUp } from "@app/hooks"; import { useGetExternalKmsList, useRemoveExternalKms } from "@app/hooks/api"; -import { ExternalKmsProvider } from "@app/hooks/api/kms/types"; import { AddExternalKmsForm } from "./AddExternalKmsForm"; +import { ExternalKmsItem } from "./ExternalKmsItem"; import { UpdateExternalKmsForm } from "./UpdateExternalKmsForm"; export const OrgEncryptionTab = withPermission( @@ -102,6 +96,7 @@ export const OrgEncryptionTab = withPermission( Provider Alias + ID @@ -115,78 +110,12 @@ export const OrgEncryptionTab = withPermission( )} {!isExternalKmsListLoading && externalKmsList?.map((kms) => ( - - - {kms.externalKms.provider === ExternalKmsProvider.Aws && ( - - )} - {kms.externalKms.provider === ExternalKmsProvider.Gcp && ( - - )} -
{kms.externalKms.provider.toUpperCase()}
- - {kms.name} - - - -
- -
-
- - - {(isAllowed) => ( - { - e.stopPropagation(); - if (subscription && !subscription?.externalKms) { - handlePopUpOpen("upgradePlan"); - return; - } - - handlePopUpOpen("editExternalKms", { - kmsId: kms.id - }); - }} - > - Edit - - )} - - - {(isAllowed) => ( - { - e.stopPropagation(); - handlePopUpOpen("removeExternalKms", { - name: kms.name, - kmsId: kms.id, - provider: kms.externalKms.provider - }); - }} - > - Delete - - )} - - -
- - + ))} diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index e3ab6df7d..69186b45d 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -92,6 +92,8 @@ import { Route as kmsOverviewPageRouteImport } from './pages/kms/OverviewPage/ro import { Route as kmsKmipPageRouteImport } from './pages/kms/KmipPage/route' import { Route as certManagerSettingsPageRouteImport } from './pages/cert-manager/SettingsPage/route' import { Route as certManagerCertificatesPageRouteImport } from './pages/cert-manager/CertificatesPage/route' +import { Route as certManagerCertificateAuthoritiesPageRouteImport } from './pages/cert-manager/CertificateAuthoritiesPage/route' +import { Route as certManagerAlertingPageRouteImport } from './pages/cert-manager/AlertingPage/route' import { Route as projectRoleDetailsBySlugPageRouteSshImport } from './pages/project/RoleDetailsBySlugPage/route-ssh' import { Route as projectMemberDetailsByIDPageRouteSshImport } from './pages/project/MemberDetailsByIDPage/route-ssh' import { Route as projectIdentityDetailsByIDPageRouteSshImport } from './pages/project/IdentityDetailsByIDPage/route-ssh' @@ -894,6 +896,20 @@ const certManagerCertificatesPageRouteRoute = getParentRoute: () => certManagerLayoutRoute, } as any) +const certManagerCertificateAuthoritiesPageRouteRoute = + certManagerCertificateAuthoritiesPageRouteImport.update({ + id: '/certificate-authorities', + path: '/certificate-authorities', + getParentRoute: () => certManagerLayoutRoute, + } as any) + +const certManagerAlertingPageRouteRoute = + certManagerAlertingPageRouteImport.update({ + id: '/alerting', + path: '/alerting', + getParentRoute: () => certManagerLayoutRoute, + } as any) + const projectRoleDetailsBySlugPageRouteSshRoute = projectRoleDetailsBySlugPageRouteSshImport.update({ id: '/roles/$roleSlug', @@ -2104,6 +2120,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof sshLayoutImport parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutSshProjectIdImport } + '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting': { + id: '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting' + path: '/alerting' + fullPath: '/cert-manager/$projectId/alerting' + preLoaderRoute: typeof certManagerAlertingPageRouteImport + parentRoute: typeof certManagerLayoutImport + } + '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities': { + id: '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities' + path: '/certificate-authorities' + fullPath: '/cert-manager/$projectId/certificate-authorities' + preLoaderRoute: typeof certManagerCertificateAuthoritiesPageRouteImport + parentRoute: typeof certManagerLayoutImport + } '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview': { id: '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview' path: '/overview' @@ -3119,6 +3149,8 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteWithChildren = ) interface certManagerLayoutRouteChildren { + certManagerAlertingPageRouteRoute: typeof certManagerAlertingPageRouteRoute + certManagerCertificateAuthoritiesPageRouteRoute: typeof certManagerCertificateAuthoritiesPageRouteRoute certManagerCertificatesPageRouteRoute: typeof certManagerCertificatesPageRouteRoute certManagerSettingsPageRouteRoute: typeof certManagerSettingsPageRouteRoute projectAccessControlPageRouteCertManagerRoute: typeof projectAccessControlPageRouteCertManagerRoute @@ -3130,6 +3162,9 @@ interface certManagerLayoutRouteChildren { } const certManagerLayoutRouteChildren: certManagerLayoutRouteChildren = { + certManagerAlertingPageRouteRoute: certManagerAlertingPageRouteRoute, + certManagerCertificateAuthoritiesPageRouteRoute: + certManagerCertificateAuthoritiesPageRouteRoute, certManagerCertificatesPageRouteRoute: certManagerCertificatesPageRouteRoute, certManagerSettingsPageRouteRoute: certManagerSettingsPageRouteRoute, projectAccessControlPageRouteCertManagerRoute: @@ -3794,6 +3829,8 @@ export interface FileRoutesByFullPath { '/organization/secret-manager/overview': typeof organizationSecretManagerOverviewPageRouteRoute '/organization/secret-sharing/settings': typeof organizationSecretSharingSettingsPageRouteRoute '/organization/ssh/overview': typeof organizationSshOverviewPageRouteRoute + '/cert-manager/$projectId/alerting': typeof certManagerAlertingPageRouteRoute + '/cert-manager/$projectId/certificate-authorities': typeof certManagerCertificateAuthoritiesPageRouteRoute '/cert-manager/$projectId/overview': typeof certManagerCertificatesPageRouteRoute '/cert-manager/$projectId/settings': typeof certManagerSettingsPageRouteRoute '/kms/$projectId/kmip': typeof kmsKmipPageRouteRoute @@ -3969,6 +4006,8 @@ export interface FileRoutesByTo { '/organization/secret-manager/overview': typeof organizationSecretManagerOverviewPageRouteRoute '/organization/secret-sharing/settings': typeof organizationSecretSharingSettingsPageRouteRoute '/organization/ssh/overview': typeof organizationSshOverviewPageRouteRoute + '/cert-manager/$projectId/alerting': typeof certManagerAlertingPageRouteRoute + '/cert-manager/$projectId/certificate-authorities': typeof certManagerCertificateAuthoritiesPageRouteRoute '/cert-manager/$projectId/overview': typeof certManagerCertificatesPageRouteRoute '/cert-manager/$projectId/settings': typeof certManagerSettingsPageRouteRoute '/kms/$projectId/kmip': typeof kmsKmipPageRouteRoute @@ -4160,6 +4199,8 @@ export interface FileRoutesById { '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout': typeof kmsLayoutRouteWithChildren '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout': typeof secretManagerLayoutRouteWithChildren '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout': typeof sshLayoutRouteWithChildren + '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting': typeof certManagerAlertingPageRouteRoute + '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities': typeof certManagerCertificateAuthoritiesPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview': typeof certManagerCertificatesPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/settings': typeof certManagerSettingsPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/kmip': typeof kmsKmipPageRouteRoute @@ -4344,6 +4385,8 @@ export interface FileRouteTypes { | '/organization/secret-manager/overview' | '/organization/secret-sharing/settings' | '/organization/ssh/overview' + | '/cert-manager/$projectId/alerting' + | '/cert-manager/$projectId/certificate-authorities' | '/cert-manager/$projectId/overview' | '/cert-manager/$projectId/settings' | '/kms/$projectId/kmip' @@ -4518,6 +4561,8 @@ export interface FileRouteTypes { | '/organization/secret-manager/overview' | '/organization/secret-sharing/settings' | '/organization/ssh/overview' + | '/cert-manager/$projectId/alerting' + | '/cert-manager/$projectId/certificate-authorities' | '/cert-manager/$projectId/overview' | '/cert-manager/$projectId/settings' | '/kms/$projectId/kmip' @@ -4707,6 +4752,8 @@ export interface FileRouteTypes { | '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout' | '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId/_secret-manager-layout' | '/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout' + | '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting' + | '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities' | '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview' | '/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/settings' | '/_authenticate/_inject-org-details/_org-layout/kms/$projectId/_kms-layout/kmip' @@ -5222,6 +5269,8 @@ export const routeTree = rootRoute "filePath": "cert-manager/layout.tsx", "parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId", "children": [ + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting", + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities", "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview", "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/settings", "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/access-management", @@ -5277,6 +5326,14 @@ export const routeTree = rootRoute "/_authenticate/_inject-org-details/_org-layout/ssh/$projectId/_ssh-layout/roles/$roleSlug" ] }, + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting": { + "filePath": "cert-manager/AlertingPage/route.tsx", + "parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout" + }, + "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities": { + "filePath": "cert-manager/CertificateAuthoritiesPage/route.tsx", + "parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout" + }, "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview": { "filePath": "cert-manager/CertificatesPage/route.tsx", "parent": "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout" diff --git a/frontend/src/routes.ts b/frontend/src/routes.ts index d6793ea1a..6c5c2832e 100644 --- a/frontend/src/routes.ts +++ b/frontend/src/routes.ts @@ -282,6 +282,8 @@ const secretManagerIntegrationsRedirect = route("/integrations", [ const certManagerRoutes = route("/cert-manager/$projectId", [ layout("cert-manager-layout", "cert-manager/layout.tsx", [ route("/overview", "cert-manager/CertificatesPage/route.tsx"), + route("/certificate-authorities", "cert-manager/CertificateAuthoritiesPage/route.tsx"), + route("/alerting", "cert-manager/AlertingPage/route.tsx"), route("/ca/$caId", "cert-manager/CertAuthDetailsByIDPage/route.tsx"), route("/pki-collections/$collectionId", "cert-manager/PkiCollectionDetailsByIDPage/routes.tsx"), route("/settings", "cert-manager/SettingsPage/route.tsx"),