mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-02 18:25:45 +00:00
Move crl functionality under ee
This commit is contained in:
Vendored
+2
@@ -6,6 +6,7 @@ import { TAccessApprovalRequestServiceFactory } from "@app/ee/services/access-ap
|
|||||||
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { TAuditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
import { TAuditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
||||||
|
import { TCertificateAuthorityCrlServiceFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-service";
|
||||||
import { TDynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service";
|
import { TDynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service";
|
||||||
import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service";
|
import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service";
|
||||||
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
||||||
@@ -141,6 +142,7 @@ declare module "fastify" {
|
|||||||
auditLogStream: TAuditLogStreamServiceFactory;
|
auditLogStream: TAuditLogStreamServiceFactory;
|
||||||
certificate: TCertificateServiceFactory;
|
certificate: TCertificateServiceFactory;
|
||||||
certificateAuthority: TCertificateAuthorityServiceFactory;
|
certificateAuthority: TCertificateAuthorityServiceFactory;
|
||||||
|
certificateAuthorityCrl: TCertificateAuthorityCrlServiceFactory;
|
||||||
secretScanning: TSecretScanningServiceFactory;
|
secretScanning: TSecretScanningServiceFactory;
|
||||||
license: TLicenseServiceFactory;
|
license: TLicenseServiceFactory;
|
||||||
trustedIp: TTrustedIpServiceFactory;
|
trustedIp: TTrustedIpServiceFactory;
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
|
import { CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||||
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
export const registerCaCrlRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/:caId/crl",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
schema: {
|
||||||
|
description: "Get CRL of the CA",
|
||||||
|
params: z.object({
|
||||||
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRL.caId)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
crl: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CRL.crl)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const { crl, ca } = await server.services.certificateAuthorityCrl.getCaCrl({
|
||||||
|
caId: req.params.caId,
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorOrgId: req.permission.orgId
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.services.auditLog.createAuditLog({
|
||||||
|
...req.auditLogInfo,
|
||||||
|
projectId: ca.projectId,
|
||||||
|
event: {
|
||||||
|
type: EventType.GET_CA_CRL,
|
||||||
|
metadata: {
|
||||||
|
caId: ca.id,
|
||||||
|
dn: ca.dn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
crl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// server.route({
|
||||||
|
// method: "GET",
|
||||||
|
// url: "/:caId/crl/rotate",
|
||||||
|
// config: {
|
||||||
|
// rateLimit: writeLimit
|
||||||
|
// },
|
||||||
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
// schema: {
|
||||||
|
// description: "Rotate CRL of the CA",
|
||||||
|
// params: z.object({
|
||||||
|
// caId: z.string().trim()
|
||||||
|
// }),
|
||||||
|
// response: {
|
||||||
|
// 200: z.object({
|
||||||
|
// message: z.string()
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// handler: async (req) => {
|
||||||
|
// await server.services.certificateAuthority.rotateCaCrl({
|
||||||
|
// caId: req.params.caId,
|
||||||
|
// actor: req.permission.type,
|
||||||
|
// actorId: req.permission.id,
|
||||||
|
// actorAuthMethod: req.permission.authMethod,
|
||||||
|
// actorOrgId: req.permission.orgId
|
||||||
|
// });
|
||||||
|
// return {
|
||||||
|
// message: "Successfully rotated CA CRL"
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
||||||
import { registerAccessApprovalRequestRouter } from "./access-approval-request-router";
|
import { registerAccessApprovalRequestRouter } from "./access-approval-request-router";
|
||||||
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
||||||
|
import { registerCaCrlRouter } from "./certificate-authority-crl-router";
|
||||||
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
||||||
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
||||||
import { registerGroupRouter } from "./group-router";
|
import { registerGroupRouter } from "./group-router";
|
||||||
@@ -54,6 +55,13 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
{ prefix: "/dynamic-secrets" }
|
{ prefix: "/dynamic-secrets" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await server.register(
|
||||||
|
async (pkiRouter) => {
|
||||||
|
await pkiRouter.register(registerCaCrlRouter, { prefix: "/ca" });
|
||||||
|
},
|
||||||
|
{ prefix: "/pki" }
|
||||||
|
);
|
||||||
|
|
||||||
await server.register(registerSamlRouter, { prefix: "/sso" });
|
await server.register(registerSamlRouter, { prefix: "/sso" });
|
||||||
await server.register(registerScimRouter, { prefix: "/scim" });
|
await server.register(registerScimRouter, { prefix: "/scim" });
|
||||||
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
||||||
|
|||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
import * as x509 from "@peculiar/x509";
|
||||||
|
|
||||||
|
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||||
|
|
||||||
|
import { TGetCrl } from "./certificate-authority-crl-types";
|
||||||
|
|
||||||
|
type TCertificateAuthorityCrlServiceFactoryDep = {
|
||||||
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
||||||
|
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "findOne">;
|
||||||
|
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||||
|
kmsService: Pick<TKmsServiceFactory, "decrypt" | "generateKmsKey">;
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TCertificateAuthorityCrlServiceFactory = ReturnType<typeof certificateAuthorityCrlServiceFactory>;
|
||||||
|
|
||||||
|
export const certificateAuthorityCrlServiceFactory = ({
|
||||||
|
certificateAuthorityDAL,
|
||||||
|
certificateAuthorityCrlDAL,
|
||||||
|
projectDAL,
|
||||||
|
kmsService,
|
||||||
|
permissionService,
|
||||||
|
licenseService
|
||||||
|
}: TCertificateAuthorityCrlServiceFactoryDep) => {
|
||||||
|
/**
|
||||||
|
* Return the Certificate Revocation List (CRL) for CA with id [caId]
|
||||||
|
*/
|
||||||
|
const getCaCrl = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCrl) => {
|
||||||
|
const ca = await certificateAuthorityDAL.findById(caId);
|
||||||
|
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||||
|
|
||||||
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
|
actor,
|
||||||
|
actorId,
|
||||||
|
ca.projectId,
|
||||||
|
actorAuthMethod,
|
||||||
|
actorOrgId
|
||||||
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
ProjectPermissionSub.CertificateAuthorities
|
||||||
|
);
|
||||||
|
|
||||||
|
const plan = await licenseService.getPlan(actorOrgId);
|
||||||
|
if (!plan.caCrl)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to get CA certificate revocation list (CRL) due to plan restriction. Upgrade plan to get the CA CRL."
|
||||||
|
});
|
||||||
|
|
||||||
|
const caCrl = await certificateAuthorityCrlDAL.findOne({ caId: ca.id });
|
||||||
|
if (!caCrl) throw new BadRequestError({ message: "CRL not found" });
|
||||||
|
|
||||||
|
const keyId = await getProjectKmsCertificateKeyId({
|
||||||
|
projectId: ca.projectId,
|
||||||
|
projectDAL,
|
||||||
|
kmsService
|
||||||
|
});
|
||||||
|
|
||||||
|
const decryptedCrl = await kmsService.decrypt({
|
||||||
|
kmsId: keyId,
|
||||||
|
cipherTextBlob: caCrl.encryptedCrl
|
||||||
|
});
|
||||||
|
|
||||||
|
const crl = new x509.X509Crl(decryptedCrl);
|
||||||
|
|
||||||
|
const base64crl = crl.toString("base64");
|
||||||
|
const crlPem = `-----BEGIN X509 CRL-----\n${base64crl.match(/.{1,64}/g)?.join("\n")}\n-----END X509 CRL-----`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
crl: crlPem,
|
||||||
|
ca
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// const rotateCaCrl = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TRotateCrlDTO) => {
|
||||||
|
// const ca = await certificateAuthorityDAL.findById(caId);
|
||||||
|
// if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||||
|
|
||||||
|
// const { permission } = await permissionService.getProjectPermission(
|
||||||
|
// actor,
|
||||||
|
// actorId,
|
||||||
|
// ca.projectId,
|
||||||
|
// actorAuthMethod,
|
||||||
|
// actorOrgId
|
||||||
|
// );
|
||||||
|
|
||||||
|
// ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
// ProjectPermissionActions.Read,
|
||||||
|
// ProjectPermissionSub.CertificateAuthorities
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
||||||
|
|
||||||
|
// const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
|
// const keyId = await getProjectKmsCertificateKeyId({
|
||||||
|
// projectId: ca.projectId,
|
||||||
|
// projectDAL,
|
||||||
|
// kmsService
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const privateKey = await kmsService.decrypt({
|
||||||
|
// kmsId: keyId,
|
||||||
|
// cipherTextBlob: caSecret.encryptedPrivateKey
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const skObj = crypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
||||||
|
// const sk = await crypto.subtle.importKey("pkcs8", skObj.export({ format: "der", type: "pkcs8" }), alg, true, [
|
||||||
|
// "sign"
|
||||||
|
// ]);
|
||||||
|
|
||||||
|
// const revokedCerts = await certificateDAL.find({
|
||||||
|
// caId: ca.id,
|
||||||
|
// status: CertStatus.REVOKED
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const crl = await x509.X509CrlGenerator.create({
|
||||||
|
// issuer: ca.dn,
|
||||||
|
// thisUpdate: new Date(),
|
||||||
|
// nextUpdate: new Date("2025/12/12"),
|
||||||
|
// entries: revokedCerts.map((revokedCert) => {
|
||||||
|
// return {
|
||||||
|
// serialNumber: revokedCert.serialNumber,
|
||||||
|
// revocationDate: new Date(revokedCert.revokedAt as Date),
|
||||||
|
// reason: revokedCert.revocationReason as number,
|
||||||
|
// invalidity: new Date("2022/01/01"),
|
||||||
|
// issuer: ca.dn
|
||||||
|
// };
|
||||||
|
// }),
|
||||||
|
// signingAlgorithm: alg,
|
||||||
|
// signingKey: sk
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const { cipherTextBlob: encryptedCrl } = await kmsService.encrypt({
|
||||||
|
// kmsId: keyId,
|
||||||
|
// plainText: Buffer.from(new Uint8Array(crl.rawData))
|
||||||
|
// });
|
||||||
|
|
||||||
|
// await certificateAuthorityCrlDAL.update(
|
||||||
|
// {
|
||||||
|
// caId: ca.id
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// encryptedCrl
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const base64crl = crl.toString("base64");
|
||||||
|
// const crlPem = `-----BEGIN X509 CRL-----\n${base64crl.match(/.{1,64}/g)?.join("\n")}\n-----END X509 CRL-----`;
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// crl: crlPem
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
|
||||||
|
return {
|
||||||
|
getCaCrl
|
||||||
|
// rotateCaCrl
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { TProjectPermission } from "@app/lib/types";
|
||||||
|
|
||||||
|
export type TGetCrl = {
|
||||||
|
caId: string;
|
||||||
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
@@ -25,6 +25,7 @@ export const getDefaultOnPremFeatures = () => {
|
|||||||
trial_end: null,
|
trial_end: null,
|
||||||
has_used_trial: true,
|
has_used_trial: true,
|
||||||
secretApproval: false,
|
secretApproval: false,
|
||||||
secretRotation: true
|
secretRotation: true,
|
||||||
|
caCrl: false
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
trial_end: null,
|
trial_end: null,
|
||||||
has_used_trial: true,
|
has_used_trial: true,
|
||||||
secretApproval: false,
|
secretApproval: false,
|
||||||
secretRotation: true
|
secretRotation: true,
|
||||||
|
caCrl: false
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export type TFeatureSet = {
|
|||||||
has_used_trial: true;
|
has_used_trial: true;
|
||||||
secretApproval: false;
|
secretApproval: false;
|
||||||
secretRotation: true;
|
secretRotation: true;
|
||||||
|
caCrl: false;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOrgPlansTableDTO = {
|
export type TOrgPlansTableDTO = {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { auditLogQueueServiceFactory } from "@app/ee/services/audit-log/audit-lo
|
|||||||
import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
import { auditLogStreamDALFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-dal";
|
import { auditLogStreamDALFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-dal";
|
||||||
import { auditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
import { auditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
||||||
|
import { certificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
|
import { certificateAuthorityCrlServiceFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-service";
|
||||||
import { dynamicSecretDALFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-dal";
|
import { dynamicSecretDALFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-dal";
|
||||||
import { dynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service";
|
import { dynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service";
|
||||||
import { buildDynamicSecretProviders } from "@app/ee/services/dynamic-secret/providers";
|
import { buildDynamicSecretProviders } from "@app/ee/services/dynamic-secret/providers";
|
||||||
@@ -75,7 +77,6 @@ import { certificateBodyDALFactory } from "@app/services/certificate/certificate
|
|||||||
import { certificateDALFactory } from "@app/services/certificate/certificate-dal";
|
import { certificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||||
import { certificateServiceFactory } from "@app/services/certificate/certificate-service";
|
import { certificateServiceFactory } from "@app/services/certificate/certificate-service";
|
||||||
import { certificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
import { certificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
||||||
import { certificateAuthorityCrlDALFactory } from "@app/services/certificate-authority/certificate-authority-crl-dal";
|
|
||||||
import { certificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { certificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
import { certificateAuthorityQueueFactory } from "@app/services/certificate-authority/certificate-authority-queue";
|
import { certificateAuthorityQueueFactory } from "@app/services/certificate-authority/certificate-authority-queue";
|
||||||
import { certificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
|
import { certificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
|
||||||
@@ -558,6 +559,15 @@ export const registerRoutes = async (
|
|||||||
permissionService
|
permissionService
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const certificateAuthorityCrlService = certificateAuthorityCrlServiceFactory({
|
||||||
|
certificateAuthorityDAL,
|
||||||
|
certificateAuthorityCrlDAL,
|
||||||
|
projectDAL,
|
||||||
|
kmsService,
|
||||||
|
permissionService,
|
||||||
|
licenseService
|
||||||
|
});
|
||||||
|
|
||||||
const projectService = projectServiceFactory({
|
const projectService = projectServiceFactory({
|
||||||
permissionService,
|
permissionService,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
@@ -945,6 +955,7 @@ export const registerRoutes = async (
|
|||||||
auditLogStream: auditLogStreamService,
|
auditLogStream: auditLogStreamService,
|
||||||
certificate: certificateService,
|
certificate: certificateService,
|
||||||
certificateAuthority: certificateAuthorityService,
|
certificateAuthority: certificateAuthorityService,
|
||||||
|
certificateAuthorityCrl: certificateAuthorityCrlService,
|
||||||
secretScanning: secretScanningService,
|
secretScanning: secretScanningService,
|
||||||
license: licenseService,
|
license: licenseService,
|
||||||
trustedIp: trustedIpService,
|
trustedIp: trustedIpService,
|
||||||
|
|||||||
@@ -512,81 +512,4 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
|
||||||
method: "GET",
|
|
||||||
url: "/:caId/crl",
|
|
||||||
config: {
|
|
||||||
rateLimit: readLimit
|
|
||||||
},
|
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
||||||
schema: {
|
|
||||||
description: "Get CRL of the CA",
|
|
||||||
params: z.object({
|
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRL.caId)
|
|
||||||
}),
|
|
||||||
response: {
|
|
||||||
200: z.object({
|
|
||||||
crl: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CRL.crl)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handler: async (req) => {
|
|
||||||
const { crl, ca } = await server.services.certificateAuthority.getCaCrl({
|
|
||||||
caId: req.params.caId,
|
|
||||||
actor: req.permission.type,
|
|
||||||
actorId: req.permission.id,
|
|
||||||
actorAuthMethod: req.permission.authMethod,
|
|
||||||
actorOrgId: req.permission.orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
await server.services.auditLog.createAuditLog({
|
|
||||||
...req.auditLogInfo,
|
|
||||||
projectId: ca.projectId,
|
|
||||||
event: {
|
|
||||||
type: EventType.GET_CA_CRL,
|
|
||||||
metadata: {
|
|
||||||
caId: ca.id,
|
|
||||||
dn: ca.dn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
crl
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// server.route({
|
|
||||||
// method: "GET",
|
|
||||||
// url: "/:caId/crl/rotate",
|
|
||||||
// config: {
|
|
||||||
// rateLimit: writeLimit
|
|
||||||
// },
|
|
||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
||||||
// schema: {
|
|
||||||
// description: "Rotate CRL of the CA",
|
|
||||||
// params: z.object({
|
|
||||||
// caId: z.string().trim()
|
|
||||||
// }),
|
|
||||||
// response: {
|
|
||||||
// 200: z.object({
|
|
||||||
// message: z.string()
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// handler: async (req) => {
|
|
||||||
// await server.services.certificateAuthority.rotateCaCrl({
|
|
||||||
// caId: req.params.caId,
|
|
||||||
// actor: req.permission.type,
|
|
||||||
// actorId: req.permission.id,
|
|
||||||
// actorAuthMethod: req.permission.authMethod,
|
|
||||||
// actorOrgId: req.permission.orgId
|
|
||||||
// });
|
|
||||||
// return {
|
|
||||||
// message: "Successfully rotated CA CRL"
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
|||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||||
|
|
||||||
import { TCertificateAuthorityCrlDALFactory } from "./certificate-authority-crl-dal";
|
import { TCertificateAuthorityCrlDALFactory } from "../../ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
||||||
import { keyAlgorithmToAlgCfg } from "./certificate-authority-fns";
|
import { keyAlgorithmToAlgCfg } from "./certificate-authority-fns";
|
||||||
import { TCertificateAuthoritySecretDALFactory } from "./certificate-authority-secret-dal";
|
import { TCertificateAuthoritySecretDALFactory } from "./certificate-authority-secret-dal";
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
|||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||||
|
|
||||||
|
import { TCertificateAuthorityCrlDALFactory } from "../../ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
import { CertKeyAlgorithm, CertStatus } from "../certificate/certificate-types";
|
import { CertKeyAlgorithm, CertStatus } from "../certificate/certificate-types";
|
||||||
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
||||||
import { TCertificateAuthorityCrlDALFactory } from "./certificate-authority-crl-dal";
|
|
||||||
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
||||||
import {
|
import {
|
||||||
createDistinguishedName,
|
createDistinguishedName,
|
||||||
@@ -33,10 +33,8 @@ import {
|
|||||||
TGetCaCertDTO,
|
TGetCaCertDTO,
|
||||||
TGetCaCsrDTO,
|
TGetCaCsrDTO,
|
||||||
TGetCaDTO,
|
TGetCaDTO,
|
||||||
TGetCrl,
|
|
||||||
TImportCertToCaDTO,
|
TImportCertToCaDTO,
|
||||||
TIssueCertFromCaDTO,
|
TIssueCertFromCaDTO,
|
||||||
// TRotateCrlDTO,
|
|
||||||
TSignIntermediateDTO,
|
TSignIntermediateDTO,
|
||||||
TUpdateCaDTO
|
TUpdateCaDTO
|
||||||
} from "./certificate-authority-types";
|
} from "./certificate-authority-types";
|
||||||
@@ -809,132 +807,6 @@ export const certificateAuthorityServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the Certificate Revocation List (CRL) for CA with id [caId]
|
|
||||||
*/
|
|
||||||
const getCaCrl = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCrl) => {
|
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
|
||||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
|
||||||
actor,
|
|
||||||
actorId,
|
|
||||||
ca.projectId,
|
|
||||||
actorAuthMethod,
|
|
||||||
actorOrgId
|
|
||||||
);
|
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
|
||||||
ProjectPermissionActions.Read,
|
|
||||||
ProjectPermissionSub.CertificateAuthorities
|
|
||||||
);
|
|
||||||
|
|
||||||
const caCrl = await certificateAuthorityCrlDAL.findOne({ caId: ca.id });
|
|
||||||
if (!caCrl) throw new BadRequestError({ message: "CRL not found" });
|
|
||||||
|
|
||||||
const keyId = await getProjectKmsCertificateKeyId({
|
|
||||||
projectId: ca.projectId,
|
|
||||||
projectDAL,
|
|
||||||
kmsService
|
|
||||||
});
|
|
||||||
|
|
||||||
const decryptedCrl = await kmsService.decrypt({
|
|
||||||
kmsId: keyId,
|
|
||||||
cipherTextBlob: caCrl.encryptedCrl
|
|
||||||
});
|
|
||||||
|
|
||||||
const crl = new x509.X509Crl(decryptedCrl);
|
|
||||||
|
|
||||||
const base64crl = crl.toString("base64");
|
|
||||||
const crlPem = `-----BEGIN X509 CRL-----\n${base64crl.match(/.{1,64}/g)?.join("\n")}\n-----END X509 CRL-----`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
crl: crlPem,
|
|
||||||
ca
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// const rotateCaCrl = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TRotateCrlDTO) => {
|
|
||||||
// const ca = await certificateAuthorityDAL.findById(caId);
|
|
||||||
// if (!ca) throw new BadRequestError({ message: "CA not found" });
|
|
||||||
|
|
||||||
// const { permission } = await permissionService.getProjectPermission(
|
|
||||||
// actor,
|
|
||||||
// actorId,
|
|
||||||
// ca.projectId,
|
|
||||||
// actorAuthMethod,
|
|
||||||
// actorOrgId
|
|
||||||
// );
|
|
||||||
|
|
||||||
// ForbiddenError.from(permission).throwUnlessCan(
|
|
||||||
// ProjectPermissionActions.Read,
|
|
||||||
// ProjectPermissionSub.CertificateAuthorities
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
|
||||||
|
|
||||||
// const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
|
||||||
|
|
||||||
// const keyId = await getProjectKmsCertificateKeyId({
|
|
||||||
// projectId: ca.projectId,
|
|
||||||
// projectDAL,
|
|
||||||
// kmsService
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const privateKey = await kmsService.decrypt({
|
|
||||||
// kmsId: keyId,
|
|
||||||
// cipherTextBlob: caSecret.encryptedPrivateKey
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const skObj = crypto.createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
||||||
// const sk = await crypto.subtle.importKey("pkcs8", skObj.export({ format: "der", type: "pkcs8" }), alg, true, [
|
|
||||||
// "sign"
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// const revokedCerts = await certificateDAL.find({
|
|
||||||
// caId: ca.id,
|
|
||||||
// status: CertStatus.REVOKED
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const crl = await x509.X509CrlGenerator.create({
|
|
||||||
// issuer: ca.dn,
|
|
||||||
// thisUpdate: new Date(),
|
|
||||||
// nextUpdate: new Date("2025/12/12"),
|
|
||||||
// entries: revokedCerts.map((revokedCert) => {
|
|
||||||
// return {
|
|
||||||
// serialNumber: revokedCert.serialNumber,
|
|
||||||
// revocationDate: new Date(revokedCert.revokedAt as Date),
|
|
||||||
// reason: revokedCert.revocationReason as number,
|
|
||||||
// invalidity: new Date("2022/01/01"),
|
|
||||||
// issuer: ca.dn
|
|
||||||
// };
|
|
||||||
// }),
|
|
||||||
// signingAlgorithm: alg,
|
|
||||||
// signingKey: sk
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const { cipherTextBlob: encryptedCrl } = await kmsService.encrypt({
|
|
||||||
// kmsId: keyId,
|
|
||||||
// plainText: Buffer.from(new Uint8Array(crl.rawData))
|
|
||||||
// });
|
|
||||||
|
|
||||||
// await certificateAuthorityCrlDAL.update(
|
|
||||||
// {
|
|
||||||
// caId: ca.id
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// encryptedCrl
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
// const base64crl = crl.toString("base64");
|
|
||||||
// const crlPem = `-----BEGIN X509 CRL-----\n${base64crl.match(/.{1,64}/g)?.join("\n")}\n-----END X509 CRL-----`;
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// crl: crlPem
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createCa,
|
createCa,
|
||||||
getCaById,
|
getCaById,
|
||||||
@@ -944,8 +816,6 @@ export const certificateAuthorityServiceFactory = ({
|
|||||||
getCaCert,
|
getCaCert,
|
||||||
signIntermediate,
|
signIntermediate,
|
||||||
importCertToCa,
|
importCertToCa,
|
||||||
issueCertFromCa,
|
issueCertFromCa
|
||||||
getCaCrl
|
|
||||||
// rotateCaCrl
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { TCertificateDALFactory } from "@app/services/certificate/certificate-da
|
|||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
|
import { TCertificateAuthorityCrlDALFactory } from "../../ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
import { CertKeyAlgorithm } from "../certificate/certificate-types";
|
import { CertKeyAlgorithm } from "../certificate/certificate-types";
|
||||||
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
||||||
import { TCertificateAuthorityCrlDALFactory } from "./certificate-authority-crl-dal";
|
|
||||||
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
||||||
import { TCertificateAuthoritySecretDALFactory } from "./certificate-authority-secret-dal";
|
import { TCertificateAuthoritySecretDALFactory } from "./certificate-authority-secret-dal";
|
||||||
|
|
||||||
@@ -80,14 +80,6 @@ export type TIssueCertFromCaDTO = {
|
|||||||
notAfter?: string;
|
notAfter?: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TGetCrl = {
|
|
||||||
caId: string;
|
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
|
||||||
|
|
||||||
export type TRotateCrlDTO = {
|
|
||||||
caId: string;
|
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
|
||||||
|
|
||||||
export type TDNParts = {
|
export type TDNParts = {
|
||||||
commonName?: string;
|
commonName?: string;
|
||||||
organization?: string;
|
organization?: string;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
import * as x509 from "@peculiar/x509";
|
import * as x509 from "@peculiar/x509";
|
||||||
|
|
||||||
|
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { TCertificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal";
|
import { TCertificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal";
|
||||||
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||||
import { TCertificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
import { TCertificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
||||||
import { TCertificateAuthorityCrlDALFactory } from "@app/services/certificate-authority/certificate-authority-crl-dal";
|
|
||||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
import { TCertificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
|
import { TCertificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ export type SubscriptionPlan = {
|
|||||||
ldap: boolean;
|
ldap: boolean;
|
||||||
groups: boolean;
|
groups: boolean;
|
||||||
status:
|
status:
|
||||||
| "incomplete"
|
| "incomplete"
|
||||||
| "incomplete_expired"
|
| "incomplete_expired"
|
||||||
| "trialing"
|
| "trialing"
|
||||||
| "active"
|
| "active"
|
||||||
| "past_due"
|
| "past_due"
|
||||||
| "canceled"
|
| "canceled"
|
||||||
| "unpaid"
|
| "unpaid"
|
||||||
| null;
|
| null;
|
||||||
trial_end: number | null;
|
trial_end: number | null;
|
||||||
has_used_trial: boolean;
|
has_used_trial: boolean;
|
||||||
|
caCrl: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
+8
-2
@@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
import { Button, DeleteActionModal, UpgradePlanModal } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
import { CaStatus, useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
import { CaStatus, useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
@@ -25,7 +25,8 @@ export const CaSection = () => {
|
|||||||
"installCaCert",
|
"installCaCert",
|
||||||
"deleteCa",
|
"deleteCa",
|
||||||
"caStatus", // enable / disable
|
"caStatus", // enable / disable
|
||||||
"caCrl" // enable / disable
|
"caCrl", // enable / disable
|
||||||
|
"upgradePlan"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
const onRemoveCaSubmit = async (caId: string) => {
|
const onRemoveCaSubmit = async (caId: string) => {
|
||||||
@@ -124,6 +125,11 @@ export const CaSection = () => {
|
|||||||
onUpdateCaStatus(popUp?.caStatus?.data as { caId: string; status: CaStatus })
|
onUpdateCaStatus(popUp?.caStatus?.data as { caId: string; status: CaStatus })
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text={(popUp.upgradePlan?.data as { description: string })?.description}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-7
@@ -27,7 +27,11 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
import {
|
||||||
|
ProjectPermissionActions,
|
||||||
|
ProjectPermissionSub,
|
||||||
|
useSubscription,
|
||||||
|
useWorkspace} from "@app/context";
|
||||||
import { CaStatus, useListWorkspaceCas } from "@app/hooks/api";
|
import { CaStatus, useListWorkspaceCas } from "@app/hooks/api";
|
||||||
import { caStatusToNameMap, caTypeToNameMap } from "@app/hooks/api/ca/constants";
|
import { caStatusToNameMap, caTypeToNameMap } from "@app/hooks/api/ca/constants";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -35,17 +39,19 @@ import { UsePopUpState } from "@app/hooks/usePopUp";
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (
|
handlePopUpOpen: (
|
||||||
popUpName: keyof UsePopUpState<
|
popUpName: keyof UsePopUpState<
|
||||||
["installCaCert", "caCert", "ca", "deleteCa", "caStatus", "caCrl"]
|
["installCaCert", "caCert", "ca", "deleteCa", "caStatus", "caCrl", "upgradePlan"]
|
||||||
>,
|
>,
|
||||||
data?: {
|
data?: {
|
||||||
caId?: string;
|
caId?: string;
|
||||||
dn?: string;
|
dn?: string;
|
||||||
status?: CaStatus;
|
status?: CaStatus;
|
||||||
|
description?: string;
|
||||||
}
|
}
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CaTable = ({ handlePopUpOpen }: Props) => {
|
export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||||
|
const { subscription } = useSubscription();
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { data, isLoading } = useListWorkspaceCas({
|
const { data, isLoading } = useListWorkspaceCas({
|
||||||
projectSlug: currentWorkspace?.slug ?? ""
|
projectSlug: currentWorkspace?.slug ?? ""
|
||||||
@@ -144,11 +150,18 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
!isAllowed &&
|
!isAllowed &&
|
||||||
"pointer-events-none cursor-not-allowed opacity-50"
|
"pointer-events-none cursor-not-allowed opacity-50"
|
||||||
)}
|
)}
|
||||||
onClick={async () =>
|
onClick={async () => {
|
||||||
handlePopUpOpen("caCrl", {
|
if (!subscription?.caCrl) {
|
||||||
caId: ca.id
|
handlePopUpOpen("upgradePlan", {
|
||||||
})
|
description:
|
||||||
}
|
"You can use the certificate revocation list (CRL) feature if you upgrade your Infisical plan."
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
handlePopUpOpen("caCrl", {
|
||||||
|
caId: ca.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
disabled={!isAllowed}
|
disabled={!isAllowed}
|
||||||
icon={<FontAwesomeIcon icon={faFile} />}
|
icon={<FontAwesomeIcon icon={faFile} />}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user