mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Minor improvements on self signed certificates
This commit is contained in:
@@ -739,11 +739,7 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
throw new AcmeBadCSRError({ message: "Invalid CSR: Common name + SANs mismatch with order identifiers" });
|
throw new AcmeBadCSRError({ message: "Invalid CSR: Common name + SANs mismatch with order identifiers" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.caId) {
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(profile.caId!);
|
||||||
throw new NotFoundError({ message: "Self-signed certificates are not supported for ACME enrollment" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(profile.caId);
|
|
||||||
if (!ca) {
|
if (!ca) {
|
||||||
throw new NotFoundError({ message: "Certificate Authority not found" });
|
throw new NotFoundError({ message: "Certificate Authority not found" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,58 +51,100 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
|||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data.enrollmentType === EnrollmentType.EST) {
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
if (!data.estConfig) {
|
return !!data.estConfig;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === EnrollmentType.API) {
|
|
||||||
if (!data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.estConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === EnrollmentType.ACME) {
|
|
||||||
if (!data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.estConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.issuerType === IssuerType.CA) {
|
|
||||||
if (!data.caId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
|
||||||
if (data.caId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.enrollmentType !== EnrollmentType.API) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message:
|
message: "EST enrollment type requires EST configuration"
|
||||||
"EST enrollment type requires EST configuration and cannot have API or ACME configuration. API enrollment type requires API configuration and cannot have EST or ACME configuration. ACME enrollment type requires ACME configuration and cannot have EST or API configuration. CA issuer type requires a CA ID. Self-signed issuer type cannot have a CA ID and only supports API enrollment."
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !!data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type requires API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !!data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type requires ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
|
return !data.apiConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "EST enrollment type cannot have API or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !data.estConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type cannot have EST or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !data.estConfig && !data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type cannot have EST or API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.CA) {
|
||||||
|
return !!data.caId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "CA issuer type requires a CA ID"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return !data.caId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type cannot have a CA ID"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return data.enrollmentType === EnrollmentType.API;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type only supports API enrollment"
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
response: {
|
response: {
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ import { EnrollmentType, IssuerType } from "./certificate-profile-types";
|
|||||||
export const createCertificateProfileSchema = z
|
export const createCertificateProfileSchema = z
|
||||||
.object({
|
.object({
|
||||||
projectId: z.string().uuid("Project ID must be valid"),
|
projectId: z.string().uuid("Project ID must be valid"),
|
||||||
caId: z
|
caId: z.string().uuid().nullable().optional(),
|
||||||
.union([z.string().uuid(), z.literal("")])
|
|
||||||
.optional()
|
|
||||||
.nullable()
|
|
||||||
.transform((val) => (val === "" ? null : val)),
|
|
||||||
certificateTemplateId: z.string().uuid(),
|
certificateTemplateId: z.string().uuid(),
|
||||||
slug: z
|
slug: z
|
||||||
.string()
|
.string()
|
||||||
@@ -38,60 +34,101 @@ export const createCertificateProfileSchema = z
|
|||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
// Validate enrollment type configurations
|
|
||||||
if (data.enrollmentType === EnrollmentType.EST) {
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
if (!data.estConfig) {
|
return !!data.estConfig;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === EnrollmentType.API) {
|
|
||||||
if (!data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.estConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === EnrollmentType.ACME) {
|
|
||||||
if (!data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.estConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.issuerType === IssuerType.CA) {
|
|
||||||
if (!data.caId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
|
||||||
if (data.caId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.enrollmentType !== EnrollmentType.API) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message:
|
message: "EST enrollment type requires EST configuration"
|
||||||
"EST enrollment type requires EST configuration and cannot have API configuration. API enrollment type requires API configuration and cannot have EST configuration. CA issuer type requires a CA ID. Self-signed issuer type cannot have a CA ID and only supports API enrollment."
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !!data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type requires API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !!data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type requires ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
|
return !data.apiConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "EST enrollment type cannot have API or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !data.estConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type cannot have EST or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !data.estConfig && !data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type cannot have EST or API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.CA) {
|
||||||
|
return !!data.caId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "CA issuer type requires a CA ID"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return !data.caId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type cannot have a CA ID"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return data.enrollmentType === EnrollmentType.API;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type only supports API enrollment"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -123,27 +160,34 @@ export const updateCertificateProfileSchema = z
|
|||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data.enrollmentType === EnrollmentType.EST) {
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
if (data.apiConfig) {
|
return !data.apiConfig;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (data.enrollmentType === EnrollmentType.API) {
|
|
||||||
if (data.estConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
|
||||||
if (data.enrollmentType && data.enrollmentType !== EnrollmentType.API) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message:
|
message: "EST enrollment type cannot have API configuration"
|
||||||
"Cannot have EST config with API enrollment type or API config with EST enrollment type. Self-signed issuer type only supports API enrollment."
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !data.estConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type cannot have EST configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return !data.enrollmentType || data.enrollmentType === EnrollmentType.API;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type only supports API enrollment"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -407,11 +407,16 @@ const generateSelfSignedCertificate = async ({
|
|||||||
const signatureAlgorithmConfig = signatureAlgorithmToAlgCfg(effectiveSignatureAlgorithm, effectiveKeyAlgorithm);
|
const signatureAlgorithmConfig = signatureAlgorithmToAlgCfg(effectiveSignatureAlgorithm, effectiveKeyAlgorithm);
|
||||||
|
|
||||||
const notBeforeDate = certificateRequest.notBefore ? new Date(certificateRequest.notBefore) : new Date();
|
const notBeforeDate = certificateRequest.notBefore ? new Date(certificateRequest.notBefore) : new Date();
|
||||||
let notAfterDate = new Date(new Date().setFullYear(new Date().getFullYear() + 1));
|
|
||||||
|
let notAfterDate: Date;
|
||||||
if (certificateRequest.notAfter) {
|
if (certificateRequest.notAfter) {
|
||||||
notAfterDate = new Date(certificateRequest.notAfter);
|
notAfterDate = new Date(certificateRequest.notAfter);
|
||||||
} else if (certificateRequest.validity.ttl) {
|
} else if (certificateRequest.validity.ttl) {
|
||||||
notAfterDate = new Date(new Date().getTime() + ms(certificateRequest.validity.ttl));
|
notAfterDate = new Date(new Date().getTime() + ms(certificateRequest.validity.ttl));
|
||||||
|
} else {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Either notAfter date or TTL must be provided for certificate validity"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const serialNumber = createSerialNumber();
|
const serialNumber = createSerialNumber();
|
||||||
@@ -458,10 +463,22 @@ const generateSelfSignedCertificate = async ({
|
|||||||
...(subjectAlternativeNames
|
...(subjectAlternativeNames
|
||||||
? [
|
? [
|
||||||
new x509.SubjectAlternativeNameExtension(
|
new x509.SubjectAlternativeNameExtension(
|
||||||
certificateRequest.altNames?.map((san) => ({
|
certificateRequest.altNames?.map((san) => {
|
||||||
type: san.type === CertSubjectAlternativeNameType.DNS_NAME ? "dns" : "ip",
|
switch (san.type) {
|
||||||
value: san.value
|
case CertSubjectAlternativeNameType.DNS_NAME:
|
||||||
})) || [],
|
return { type: "dns" as const, value: san.value };
|
||||||
|
case CertSubjectAlternativeNameType.IP_ADDRESS:
|
||||||
|
return { type: "ip" as const, value: san.value };
|
||||||
|
case CertSubjectAlternativeNameType.EMAIL:
|
||||||
|
return { type: "email" as const, value: san.value };
|
||||||
|
case CertSubjectAlternativeNameType.URI:
|
||||||
|
return { type: "url" as const, value: san.value };
|
||||||
|
default:
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Unsupported Subject Alternative Name type: ${san.type as string}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}) || [],
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@@ -545,7 +562,7 @@ const createSelfSignedCertificateRecord = async ({
|
|||||||
(selfSignedResult.certificateSubject.common_name as string) ||
|
(selfSignedResult.certificateSubject.common_name as string) ||
|
||||||
certificateRequest.commonName ||
|
certificateRequest.commonName ||
|
||||||
originalCert?.commonName ||
|
originalCert?.commonName ||
|
||||||
(isRenewal ? "Renewed Self-signed Certificate" : "Self-signed Certificate");
|
"";
|
||||||
|
|
||||||
const altNamesList = selfSignedResult.subjectAlternativeNames.map((san) => san.value).join(",");
|
const altNamesList = selfSignedResult.subjectAlternativeNames.map((san) => san.value).join(",");
|
||||||
|
|
||||||
@@ -726,8 +743,8 @@ const processSelfSignedCertificate = async ({
|
|||||||
|
|
||||||
await createEncryptedCertificateData({
|
await createEncryptedCertificateData({
|
||||||
certificateId: certificateData.id,
|
certificateId: certificateData.id,
|
||||||
certificate: Buffer.from(selfSignedResult.certificate),
|
certificate: selfSignedResult.certificate,
|
||||||
privateKey: Buffer.from(selfSignedResult.privateKey),
|
privateKey: selfSignedResult.privateKey,
|
||||||
projectId,
|
projectId,
|
||||||
certificateBodyDAL,
|
certificateBodyDAL,
|
||||||
certificateSecretDAL,
|
certificateSecretDAL,
|
||||||
@@ -1100,10 +1117,25 @@ export const certificateV3ServiceFactory = ({
|
|||||||
commonName: certificateOrder.commonName,
|
commonName: certificateOrder.commonName,
|
||||||
keyUsages: certificateOrder.keyUsages,
|
keyUsages: certificateOrder.keyUsages,
|
||||||
extendedKeyUsages: certificateOrder.extendedKeyUsages,
|
extendedKeyUsages: certificateOrder.extendedKeyUsages,
|
||||||
subjectAlternativeNames: certificateOrder.altNames.map((san) => ({
|
subjectAlternativeNames: certificateOrder.altNames.map((san) => {
|
||||||
type: san.type === "dns" ? CertSubjectAlternativeNameType.DNS_NAME : CertSubjectAlternativeNameType.IP_ADDRESS,
|
let certType: CertSubjectAlternativeNameType;
|
||||||
|
switch (san.type) {
|
||||||
|
case "dns":
|
||||||
|
certType = CertSubjectAlternativeNameType.DNS_NAME;
|
||||||
|
break;
|
||||||
|
case "ip":
|
||||||
|
certType = CertSubjectAlternativeNameType.IP_ADDRESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Unsupported Subject Alternative Name type: ${san.type as string}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: certType,
|
||||||
value: san.value
|
value: san.value
|
||||||
})),
|
};
|
||||||
|
}),
|
||||||
validity: certificateOrder.validity,
|
validity: certificateOrder.validity,
|
||||||
notBefore: certificateOrder.notBefore,
|
notBefore: certificateOrder.notBefore,
|
||||||
notAfter: certificateOrder.notAfter,
|
notAfter: certificateOrder.notAfter,
|
||||||
@@ -1216,7 +1248,8 @@ export const certificateV3ServiceFactory = ({
|
|||||||
|
|
||||||
if (profile.enrollmentType !== EnrollmentType.API) {
|
if (profile.enrollmentType !== EnrollmentType.API) {
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Certificate is not eligible for renewal: EST certificates cannot be renewed through this endpoint"
|
message:
|
||||||
|
"Certificate is not eligible for renewal: Only certificates issued from an API enrollment profile can be renewed through this endpoint"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ export {
|
|||||||
useGetProfileCertificates,
|
useGetProfileCertificates,
|
||||||
useListCertificateProfiles
|
useListCertificateProfiles
|
||||||
} from "./queries";
|
} from "./queries";
|
||||||
export type * from "./types";
|
export * from "./types";
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
export enum EnrollmentType {
|
||||||
|
API = "api",
|
||||||
|
EST = "est",
|
||||||
|
ACME = "acme"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IssuerType {
|
||||||
|
CA = "ca",
|
||||||
|
SELF_SIGNED = "self-signed"
|
||||||
|
}
|
||||||
|
|
||||||
export type TCertificateProfile = {
|
export type TCertificateProfile = {
|
||||||
id: string;
|
id: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@@ -5,8 +16,8 @@ export type TCertificateProfile = {
|
|||||||
certificateTemplateId: string;
|
certificateTemplateId: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
enrollmentType: "api" | "est" | "acme";
|
enrollmentType: EnrollmentType;
|
||||||
issuerType: "ca" | "self-signed";
|
issuerType: IssuerType;
|
||||||
estConfigId?: string;
|
estConfigId?: string;
|
||||||
apiConfigId?: string;
|
apiConfigId?: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -49,8 +60,8 @@ export type TCreateCertificateProfileDTO = {
|
|||||||
certificateTemplateId: string;
|
certificateTemplateId: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
enrollmentType: "api" | "est" | "acme";
|
enrollmentType: EnrollmentType;
|
||||||
issuerType: "ca" | "self-signed";
|
issuerType: IssuerType;
|
||||||
estConfig?: {
|
estConfig?: {
|
||||||
disableBootstrapCaValidation?: boolean;
|
disableBootstrapCaValidation?: boolean;
|
||||||
passphrase: string;
|
passphrase: string;
|
||||||
@@ -67,8 +78,8 @@ export type TUpdateCertificateProfileDTO = {
|
|||||||
profileId: string;
|
profileId: string;
|
||||||
slug?: string;
|
slug?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
enrollmentType?: "api" | "est" | "acme";
|
enrollmentType?: EnrollmentType;
|
||||||
issuerType?: "ca" | "self-signed";
|
issuerType?: IssuerType;
|
||||||
estConfig?: {
|
estConfig?: {
|
||||||
disableBootstrapCaValidation?: boolean;
|
disableBootstrapCaValidation?: boolean;
|
||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
@@ -91,8 +102,8 @@ export type TListCertificateProfilesDTO = {
|
|||||||
offset?: number;
|
offset?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
includeConfigs?: boolean;
|
includeConfigs?: boolean;
|
||||||
enrollmentType?: "api" | "est" | "acme";
|
enrollmentType?: EnrollmentType;
|
||||||
issuerType?: "ca" | "self-signed";
|
issuerType?: IssuerType;
|
||||||
caId?: string;
|
caId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
import { useProject } from "@app/context";
|
import { useProject } from "@app/context";
|
||||||
import { useGetCert } from "@app/hooks/api";
|
import { useGetCert } from "@app/hooks/api";
|
||||||
import { useCreateCertificateV3 } from "@app/hooks/api/ca";
|
import { useCreateCertificateV3 } from "@app/hooks/api/ca";
|
||||||
import { useListCertificateProfiles } from "@app/hooks/api/certificateProfiles";
|
import { EnrollmentType, useListCertificateProfiles } from "@app/hooks/api/certificateProfiles";
|
||||||
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/hooks/api/certificates/enums";
|
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/hooks/api/certificates/enums";
|
||||||
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -122,7 +122,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
|||||||
|
|
||||||
const { data: profilesData } = useListCertificateProfiles({
|
const { data: profilesData } = useListCertificateProfiles({
|
||||||
projectId: currentProject?.id || "",
|
projectId: currentProject?.id || "",
|
||||||
enrollmentType: "api"
|
enrollmentType: EnrollmentType.API
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mutateAsync: createCertificate } = useCreateCertificateV3({
|
const { mutateAsync: createCertificate } = useCreateCertificateV3({
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import {
|
|||||||
import { useProject, useSubscription } from "@app/context";
|
import { useProject, useSubscription } from "@app/context";
|
||||||
import { useListCasByProjectId } from "@app/hooks/api/ca/queries";
|
import { useListCasByProjectId } from "@app/hooks/api/ca/queries";
|
||||||
import {
|
import {
|
||||||
|
EnrollmentType,
|
||||||
|
IssuerType,
|
||||||
TCertificateProfileWithDetails,
|
TCertificateProfileWithDetails,
|
||||||
TCreateCertificateProfileDTO,
|
TCreateCertificateProfileDTO,
|
||||||
TUpdateCertificateProfileDTO,
|
TUpdateCertificateProfileDTO,
|
||||||
@@ -46,8 +48,8 @@ const createSchema = z
|
|||||||
.trim()
|
.trim()
|
||||||
.max(1000, "Description must be less than 1000 characters")
|
.max(1000, "Description must be less than 1000 characters")
|
||||||
.optional(),
|
.optional(),
|
||||||
enrollmentType: z.enum(["api", "est", "acme"]),
|
enrollmentType: z.nativeEnum(EnrollmentType),
|
||||||
issuerType: z.enum(["ca", "self-signed"]),
|
issuerType: z.nativeEnum(IssuerType),
|
||||||
certificateAuthorityId: z.string().nullable().optional(),
|
certificateAuthorityId: z.string().nullable().optional(),
|
||||||
certificateTemplateId: z.string().min(1, "Certificate Template is required"),
|
certificateTemplateId: z.string().min(1, "Certificate Template is required"),
|
||||||
estConfig: z
|
estConfig: z
|
||||||
@@ -79,30 +81,101 @@ const createSchema = z
|
|||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data.enrollmentType === "est" && !data.estConfig) {
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
return false;
|
return !!data.estConfig;
|
||||||
}
|
}
|
||||||
if (data.enrollmentType === "api" && !data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === "acme" && !data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.issuerType === "ca" && !data.certificateAuthorityId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.issuerType === "self-signed" && data.certificateAuthorityId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.issuerType === "self-signed" && data.enrollmentType !== "api") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: "Configuration is required for selected enrollment type and issuer type"
|
message: "EST enrollment type requires EST configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !!data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type requires API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !!data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type requires ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
|
return !data.apiConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "EST enrollment type cannot have API or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !data.estConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type cannot have EST or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !data.estConfig && !data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type cannot have EST or API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.CA) {
|
||||||
|
return !!data.certificateAuthorityId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "CA issuer type requires a certificate authority"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return !data.certificateAuthorityId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type cannot have a certificate authority"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return data.enrollmentType === EnrollmentType.API;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type only supports API enrollment"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -122,8 +195,8 @@ const editSchema = z
|
|||||||
.trim()
|
.trim()
|
||||||
.max(1000, "Description must be less than 1000 characters")
|
.max(1000, "Description must be less than 1000 characters")
|
||||||
.optional(),
|
.optional(),
|
||||||
enrollmentType: z.enum(["api", "est", "acme"]),
|
enrollmentType: z.nativeEnum(EnrollmentType),
|
||||||
issuerType: z.enum(["ca", "self-signed"]),
|
issuerType: z.nativeEnum(IssuerType),
|
||||||
certificateAuthorityId: z.string().nullable().optional(),
|
certificateAuthorityId: z.string().nullable().optional(),
|
||||||
certificateTemplateId: z.string().optional(),
|
certificateTemplateId: z.string().optional(),
|
||||||
estConfig: z
|
estConfig: z
|
||||||
@@ -143,31 +216,101 @@ const editSchema = z
|
|||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(data) => {
|
(data) => {
|
||||||
if (data.enrollmentType === "est" && !data.estConfig) {
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
return false;
|
return !!data.estConfig;
|
||||||
}
|
}
|
||||||
if (data.enrollmentType === "api" && !data.apiConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.enrollmentType === "acme" && !data.acmeConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.issuerType === "ca" && !data.certificateAuthorityId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.issuerType === "self-signed" && data.certificateAuthorityId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.issuerType === "self-signed" && data.enrollmentType !== "api") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message:
|
message: "EST enrollment type requires EST configuration"
|
||||||
"Configuration is required for selected enrollment type and issuer type. CA issuer requires a certificate authority. Self-signed issuer cannot have a certificate authority and only supports API enrollment."
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !!data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type requires API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !!data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type requires ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.EST) {
|
||||||
|
return !data.apiConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "EST enrollment type cannot have API or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.API) {
|
||||||
|
return !data.estConfig && !data.acmeConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "API enrollment type cannot have EST or ACME configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.enrollmentType === EnrollmentType.ACME) {
|
||||||
|
return !data.estConfig && !data.apiConfig;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "ACME enrollment type cannot have EST or API configuration"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.CA) {
|
||||||
|
return !!data.certificateAuthorityId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "CA issuer type requires a certificate authority"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return !data.certificateAuthorityId;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type cannot have a certificate authority"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (data.issuerType === IssuerType.SELF_SIGNED) {
|
||||||
|
return data.enrollmentType === EnrollmentType.API;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: "Self-signed issuer type only supports API enrollment"
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -222,7 +365,7 @@ export const CreateProfileModal = ({
|
|||||||
certificateAuthorityId: profile.caId || undefined,
|
certificateAuthorityId: profile.caId || undefined,
|
||||||
certificateTemplateId: profile.certificateTemplateId,
|
certificateTemplateId: profile.certificateTemplateId,
|
||||||
estConfig:
|
estConfig:
|
||||||
profile.enrollmentType === "est"
|
profile.enrollmentType === EnrollmentType.EST
|
||||||
? {
|
? {
|
||||||
disableBootstrapCaValidation:
|
disableBootstrapCaValidation:
|
||||||
profile.estConfig?.disableBootstrapCaValidation || false,
|
profile.estConfig?.disableBootstrapCaValidation || false,
|
||||||
@@ -231,19 +374,19 @@ export const CreateProfileModal = ({
|
|||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
apiConfig:
|
apiConfig:
|
||||||
profile.enrollmentType === "api"
|
profile.enrollmentType === EnrollmentType.API
|
||||||
? {
|
? {
|
||||||
autoRenew: profile.apiConfig?.autoRenew || false,
|
autoRenew: profile.apiConfig?.autoRenew || false,
|
||||||
renewBeforeDays: profile.apiConfig?.renewBeforeDays || 30
|
renewBeforeDays: profile.apiConfig?.renewBeforeDays || 30
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
acmeConfig: profile.enrollmentType === "acme" ? {} : undefined
|
acmeConfig: profile.enrollmentType === EnrollmentType.ACME ? {} : undefined
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
slug: "",
|
slug: "",
|
||||||
description: "",
|
description: "",
|
||||||
enrollmentType: "api",
|
enrollmentType: EnrollmentType.API,
|
||||||
issuerType: "ca",
|
issuerType: IssuerType.CA,
|
||||||
certificateAuthorityId: "",
|
certificateAuthorityId: "",
|
||||||
certificateTemplateId: "",
|
certificateTemplateId: "",
|
||||||
apiConfig: {
|
apiConfig: {
|
||||||
@@ -284,13 +427,13 @@ export const CreateProfileModal = ({
|
|||||||
renewBeforeDays: profile.apiConfig?.renewBeforeDays || 30
|
renewBeforeDays: profile.apiConfig?.renewBeforeDays || 30
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
acmeConfig: profile.enrollmentType === "acme" ? {} : undefined
|
acmeConfig: profile.enrollmentType === EnrollmentType.ACME ? {} : undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [isEdit, profile, reset]);
|
}, [isEdit, profile, reset]);
|
||||||
|
|
||||||
const onFormSubmit = async (data: FormData) => {
|
const onFormSubmit = async (data: FormData) => {
|
||||||
if (!isEdit && !subscription?.pkiAcme && data.enrollmentType === "acme") {
|
if (!isEdit && !subscription?.pkiAcme && data.enrollmentType === EnrollmentType.ACME) {
|
||||||
reset();
|
reset();
|
||||||
onClose();
|
onClose();
|
||||||
handlePopUpOpen("upgradePlan", {
|
handlePopUpOpen("upgradePlan", {
|
||||||
@@ -309,11 +452,11 @@ export const CreateProfileModal = ({
|
|||||||
issuerType: data.issuerType
|
issuerType: data.issuerType
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.enrollmentType === "est" && data.estConfig) {
|
if (data.enrollmentType === EnrollmentType.EST && data.estConfig) {
|
||||||
updateData.estConfig = data.estConfig;
|
updateData.estConfig = data.estConfig;
|
||||||
} else if (data.enrollmentType === "api" && data.apiConfig) {
|
} else if (data.enrollmentType === EnrollmentType.API && data.apiConfig) {
|
||||||
updateData.apiConfig = data.apiConfig;
|
updateData.apiConfig = data.apiConfig;
|
||||||
} else if (data.enrollmentType === "acme" && data.acmeConfig) {
|
} else if (data.enrollmentType === EnrollmentType.ACME && data.acmeConfig) {
|
||||||
updateData.acmeConfig = data.acmeConfig;
|
updateData.acmeConfig = data.acmeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,19 +473,21 @@ export const CreateProfileModal = ({
|
|||||||
enrollmentType: data.enrollmentType,
|
enrollmentType: data.enrollmentType,
|
||||||
issuerType: data.issuerType,
|
issuerType: data.issuerType,
|
||||||
caId:
|
caId:
|
||||||
data.issuerType === "self-signed" ? undefined : data.certificateAuthorityId || undefined,
|
data.issuerType === IssuerType.SELF_SIGNED
|
||||||
|
? undefined
|
||||||
|
: data.certificateAuthorityId || undefined,
|
||||||
certificateTemplateId: data.certificateTemplateId
|
certificateTemplateId: data.certificateTemplateId
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.enrollmentType === "est" && data.estConfig) {
|
if (data.enrollmentType === EnrollmentType.EST && data.estConfig) {
|
||||||
createData.estConfig = {
|
createData.estConfig = {
|
||||||
passphrase: data.estConfig.passphrase,
|
passphrase: data.estConfig.passphrase,
|
||||||
caChain: data.estConfig.caChain || undefined,
|
caChain: data.estConfig.caChain || undefined,
|
||||||
disableBootstrapCaValidation: data.estConfig.disableBootstrapCaValidation
|
disableBootstrapCaValidation: data.estConfig.disableBootstrapCaValidation
|
||||||
};
|
};
|
||||||
} else if (data.enrollmentType === "api" && data.apiConfig) {
|
} else if (data.enrollmentType === EnrollmentType.API && data.apiConfig) {
|
||||||
createData.apiConfig = data.apiConfig;
|
createData.apiConfig = data.apiConfig;
|
||||||
} else if (data.enrollmentType === "acme" && data.acmeConfig) {
|
} else if (data.enrollmentType === EnrollmentType.ACME && data.acmeConfig) {
|
||||||
createData.acmeConfig = data.acmeConfig;
|
createData.acmeConfig = data.acmeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +562,7 @@ export const CreateProfileModal = ({
|
|||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
if (value === "self-signed") {
|
if (value === "self-signed") {
|
||||||
setValue("certificateAuthorityId", "");
|
setValue("certificateAuthorityId", "");
|
||||||
setValue("enrollmentType", "api");
|
setValue("enrollmentType", EnrollmentType.API);
|
||||||
setValue("apiConfig", {
|
setValue("apiConfig", {
|
||||||
autoRenew: false,
|
autoRenew: false,
|
||||||
renewBeforeDays: 30
|
renewBeforeDays: 30
|
||||||
@@ -559,12 +704,12 @@ export const CreateProfileModal = ({
|
|||||||
isDisabled={Boolean(isEdit)}
|
isDisabled={Boolean(isEdit)}
|
||||||
>
|
>
|
||||||
<SelectItem value="api">API</SelectItem>
|
<SelectItem value="api">API</SelectItem>
|
||||||
<SelectItem value="est" isDisabled={watchedIssuerType === "self-signed"}>
|
{watchedIssuerType !== IssuerType.SELF_SIGNED && (
|
||||||
EST
|
<SelectItem value="est">EST</SelectItem>
|
||||||
</SelectItem>
|
)}
|
||||||
<SelectItem value="acme" isDisabled={watchedIssuerType === "self-signed"}>
|
{watchedIssuerType !== IssuerType.SELF_SIGNED && (
|
||||||
ACME
|
<SelectItem value="acme">ACME</SelectItem>
|
||||||
</SelectItem>
|
)}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ export const ProfileList = ({
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Th>Name</Th>
|
<Th>Name</Th>
|
||||||
<Th>Enrollment Method</Th>
|
<Th>Enrollment Method</Th>
|
||||||
<Th>Issuer Type</Th>
|
|
||||||
<Th>Issuing CA</Th>
|
<Th>Issuing CA</Th>
|
||||||
<Th>Certificate Template</Th>
|
<Th>Certificate Template</Th>
|
||||||
<Th className="w-5" />
|
<Th className="w-5" />
|
||||||
@@ -55,7 +54,7 @@ export const ProfileList = ({
|
|||||||
</THead>
|
</THead>
|
||||||
<TBody>
|
<TBody>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td colSpan={7}>
|
<Td colSpan={5}>
|
||||||
<EmptyState title="No Project Selected" />
|
<EmptyState title="No Project Selected" />
|
||||||
</Td>
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
@@ -72,17 +71,16 @@ export const ProfileList = ({
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Th>Name</Th>
|
<Th>Name</Th>
|
||||||
<Th>Enrollment Method</Th>
|
<Th>Enrollment Method</Th>
|
||||||
<Th>Issuer Type</Th>
|
|
||||||
<Th>Issuing CA</Th>
|
<Th>Issuing CA</Th>
|
||||||
<Th>Certificate Template</Th>
|
<Th>Certificate Template</Th>
|
||||||
<Th className="w-5" />
|
<Th className="w-5" />
|
||||||
</Tr>
|
</Tr>
|
||||||
</THead>
|
</THead>
|
||||||
<TBody>
|
<TBody>
|
||||||
{isLoading && <TableSkeleton columns={6} innerKey="certificate-profiles" />}
|
{isLoading && <TableSkeleton columns={5} innerKey="certificate-profiles" />}
|
||||||
{!isLoading && (!profiles || profiles.length === 0) && (
|
{!isLoading && (!profiles || profiles.length === 0) && (
|
||||||
<Tr>
|
<Tr>
|
||||||
<Td colSpan={6}>
|
<Td colSpan={5}>
|
||||||
<EmptyState title="No Certificate Profiles" />
|
<EmptyState title="No Certificate Profiles" />
|
||||||
</Td>
|
</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
} from "@app/context/ProjectPermissionContext/types";
|
} from "@app/context/ProjectPermissionContext/types";
|
||||||
import { usePopUp, useToggle } from "@app/hooks";
|
import { usePopUp, useToggle } from "@app/hooks";
|
||||||
import { useGetCaById } from "@app/hooks/api/ca/queries";
|
import { useGetCaById } from "@app/hooks/api/ca/queries";
|
||||||
import { TCertificateProfile } from "@app/hooks/api/certificateProfiles";
|
import { IssuerType, TCertificateProfile } from "@app/hooks/api/certificateProfiles";
|
||||||
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
||||||
import { CertificateIssuanceModal } from "@app/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal";
|
import { CertificateIssuanceModal } from "@app/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal";
|
||||||
|
|
||||||
@@ -106,20 +106,6 @@ export const ProfileRow = ({
|
|||||||
return <Badge variant={variant}>{label}</Badge>;
|
return <Badge variant={variant}>{label}</Badge>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getIssuerTypeBadge = (issuerType: string) => {
|
|
||||||
const config = {
|
|
||||||
ca: { variant: "success" as const, label: "CA" },
|
|
||||||
"self-signed": { variant: "info" as const, label: "Self-Signed" }
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const configKey = Object.keys(config).includes(issuerType)
|
|
||||||
? (issuerType as keyof typeof config)
|
|
||||||
: "ca";
|
|
||||||
const { variant, label } = config[configKey];
|
|
||||||
|
|
||||||
return <Badge variant={variant}>{label}</Badge>;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tr key={profile.id} className="h-10 transition-colors duration-100 hover:bg-mineshaft-700">
|
<Tr key={profile.id} className="h-10 transition-colors duration-100 hover:bg-mineshaft-700">
|
||||||
<Td>
|
<Td>
|
||||||
@@ -133,11 +119,10 @@ export const ProfileRow = ({
|
|||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
<Td className="text-start">{getEnrollmentTypeBadge(profile.enrollmentType)}</Td>
|
<Td className="text-start">{getEnrollmentTypeBadge(profile.enrollmentType)}</Td>
|
||||||
<Td className="text-start">{getIssuerTypeBadge(profile.issuerType)}</Td>
|
|
||||||
<Td className="text-start">
|
<Td className="text-start">
|
||||||
<span className="text-sm text-mineshaft-300">
|
<span className="text-sm text-mineshaft-300">
|
||||||
{profile.issuerType === "self-signed"
|
{profile.issuerType === IssuerType.SELF_SIGNED
|
||||||
? "—"
|
? "Self-signed"
|
||||||
: caData?.friendlyName || caData?.commonName || profile.caId}
|
: caData?.friendlyName || caData?.commonName || profile.caId}
|
||||||
</span>
|
</span>
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
Reference in New Issue
Block a user