PKI syncs: fixes and add includeRootCa to PKI cert issuance endpoints

This commit is contained in:
Carlos Monastyrski
2025-11-20 15:23:38 -03:00
parent b46313ed5a
commit e0c6f48808
20 changed files with 124 additions and 31 deletions
@@ -23,6 +23,8 @@ import { mapEnumsForValidation } from "@app/services/certificate-common/certific
import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types"; import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types";
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
import { booleanSchema } from "../sanitizedSchemas";
interface CertificateRequestForService { interface CertificateRequestForService {
commonName?: string; commonName?: string;
keyUsages?: CertKeyUsageType[]; keyUsages?: CertKeyUsageType[];
@@ -87,7 +89,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
) )
.optional(), .optional(),
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm), signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm),
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm) keyAlgorithm: z.nativeEnum(CertKeyAlgorithm),
removeRootsFromChain: booleanSchema.default(false).optional()
}) })
.refine(validateTtlAndDateFields, { .refine(validateTtlAndDateFields, {
message: message:
@@ -131,7 +134,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
profileId: req.body.profileId, profileId: req.body.profileId,
certificateRequest: mappedCertificateRequest certificateRequest: mappedCertificateRequest,
removeRootsFromChain: req.body.removeRootsFromChain
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@@ -171,7 +175,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
.min(1, "TTL cannot be empty") .min(1, "TTL cannot be empty")
.refine((val) => ms(val) > 0, "TTL must be a positive number"), .refine((val) => ms(val) > 0, "TTL must be a positive number"),
notBefore: validateCaDateField.optional(), notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional() notAfter: validateCaDateField.optional(),
removeRootsFromChain: booleanSchema.default(false).optional()
}) })
.refine(validateTtlAndDateFields, { .refine(validateTtlAndDateFields, {
message: message:
@@ -206,7 +211,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
}, },
notBefore: req.body.notBefore ? new Date(req.body.notBefore) : undefined, notBefore: req.body.notBefore ? new Date(req.body.notBefore) : undefined,
notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined, notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined,
enrollmentType: EnrollmentType.API enrollmentType: EnrollmentType.API,
removeRootsFromChain: req.body.removeRootsFromChain
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@@ -262,7 +268,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
notAfter: validateCaDateField.optional(), notAfter: validateCaDateField.optional(),
commonName: validateTemplateRegexField.optional(), commonName: validateTemplateRegexField.optional(),
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm), signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm),
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm) keyAlgorithm: z.nativeEnum(CertKeyAlgorithm),
removeRootsFromChain: booleanSchema.default(false).optional()
}) })
.refine(validateTtlAndDateFields, { .refine(validateTtlAndDateFields, {
message: message:
@@ -325,7 +332,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined, notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined,
signatureAlgorithm: req.body.signatureAlgorithm, signatureAlgorithm: req.body.signatureAlgorithm,
keyAlgorithm: req.body.keyAlgorithm keyAlgorithm: req.body.keyAlgorithm
} },
removeRootsFromChain: req.body.removeRootsFromChain
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@@ -357,6 +365,11 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
params: z.object({ params: z.object({
certificateId: z.string().uuid() certificateId: z.string().uuid()
}), }),
body: z
.object({
removeRootsFromChain: booleanSchema.default(false).optional()
})
.optional(),
response: { response: {
200: z.object({ 200: z.object({
certificate: z.string().trim(), certificate: z.string().trim(),
@@ -375,7 +388,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
certificateId: req.params.certificateId certificateId: req.params.certificateId,
removeRootsFromChain: req.body?.removeRootsFromChain
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
@@ -47,7 +47,8 @@ import {
convertKeyUsageArrayFromLegacy, convertKeyUsageArrayFromLegacy,
convertKeyUsageArrayToLegacy, convertKeyUsageArrayToLegacy,
mapEnumsForValidation, mapEnumsForValidation,
normalizeDateForApi normalizeDateForApi,
removeRootCaFromChain
} from "../certificate-common/certificate-utils"; } from "../certificate-common/certificate-utils";
import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal"; import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal";
import { TPkiSyncDALFactory } from "../pki-sync/pki-sync-dal"; import { TPkiSyncDALFactory } from "../pki-sync/pki-sync-dal";
@@ -366,7 +367,8 @@ export const certificateV3ServiceFactory = ({
actor, actor,
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId,
removeRootsFromChain
}: TIssueCertificateFromProfileDTO): Promise<TCertificateFromProfileResponse> => { }: TIssueCertificateFromProfileDTO): Promise<TCertificateFromProfileResponse> => {
const profile = await validateProfileAndPermissions( const profile = await validateProfileAndPermissions(
profileId, profileId,
@@ -480,10 +482,15 @@ export const certificateV3ServiceFactory = ({
renewBeforeDays: finalRenewBeforeDays renewBeforeDays: finalRenewBeforeDays
}); });
let finalCertificateChain = bufferToString(certificateChain);
if (removeRootsFromChain) {
finalCertificateChain = removeRootCaFromChain(finalCertificateChain);
}
return { return {
certificate: bufferToString(certificate), certificate: bufferToString(certificate),
issuingCaCertificate: bufferToString(issuingCaCertificate), issuingCaCertificate: bufferToString(issuingCaCertificate),
certificateChain: bufferToString(certificateChain), certificateChain: finalCertificateChain,
privateKey: bufferToString(privateKey), privateKey: bufferToString(privateKey),
serialNumber, serialNumber,
certificateId: cert.id, certificateId: cert.id,
@@ -503,7 +510,8 @@ export const certificateV3ServiceFactory = ({
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
enrollmentType enrollmentType,
removeRootsFromChain
}: TSignCertificateFromProfileDTO): Promise<Omit<TCertificateFromProfileResponse, "privateKey">> => { }: TSignCertificateFromProfileDTO): Promise<Omit<TCertificateFromProfileResponse, "privateKey">> => {
const profile = await validateProfileAndPermissions( const profile = await validateProfileAndPermissions(
profileId, profileId,
@@ -590,7 +598,10 @@ export const certificateV3ServiceFactory = ({
}); });
const certificateString = extractCertificateFromBuffer(certificate as unknown as Buffer); const certificateString = extractCertificateFromBuffer(certificate as unknown as Buffer);
const certificateChainString = extractCertificateFromBuffer(certificateChain as unknown as Buffer); let certificateChainString = extractCertificateFromBuffer(certificateChain as unknown as Buffer);
if (removeRootsFromChain) {
certificateChainString = removeRootCaFromChain(certificateChainString);
}
return { return {
certificate: certificateString, certificate: certificateString,
@@ -610,7 +621,8 @@ export const certificateV3ServiceFactory = ({
actor, actor,
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId,
removeRootsFromChain
}: TOrderCertificateFromProfileDTO): Promise<TCertificateOrderResponse> => { }: TOrderCertificateFromProfileDTO): Promise<TCertificateOrderResponse> => {
const profile = await validateProfileAndPermissions( const profile = await validateProfileAndPermissions(
profileId, profileId,
@@ -665,7 +677,8 @@ export const certificateV3ServiceFactory = ({
actor, actor,
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId,
removeRootsFromChain
}); });
const orderId = randomUUID(); const orderId = randomUUID();
@@ -703,7 +716,8 @@ export const certificateV3ServiceFactory = ({
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
internal = false internal = false,
removeRootsFromChain
}: TRenewCertificateDTO & { internal?: boolean }): Promise<TCertificateFromProfileResponse> => { }: TRenewCertificateDTO & { internal?: boolean }): Promise<TCertificateFromProfileResponse> => {
const renewalResult = await certificateDAL.transaction(async (tx) => { const renewalResult = await certificateDAL.transaction(async (tx) => {
const originalCert = await certificateDAL.findById(certificateId, tx); const originalCert = await certificateDAL.findById(certificateId, tx);
@@ -929,10 +943,14 @@ export const certificateV3ServiceFactory = ({
pkiSyncQueue pkiSyncQueue
}); });
let finalCertificateChain = renewalResult.certificateChain;
if (removeRootsFromChain) {
finalCertificateChain = removeRootCaFromChain(finalCertificateChain);
}
return { return {
certificate: renewalResult.certificate, certificate: renewalResult.certificate,
issuingCaCertificate: renewalResult.issuingCaCertificate, issuingCaCertificate: renewalResult.issuingCaCertificate,
certificateChain: renewalResult.certificateChain, certificateChain: finalCertificateChain,
serialNumber: renewalResult.serialNumber, serialNumber: renewalResult.serialNumber,
certificateId: renewalResult.newCert.id, certificateId: renewalResult.newCert.id,
projectId: renewalResult.profile.projectId, projectId: renewalResult.profile.projectId,
@@ -26,6 +26,7 @@ export type TIssueCertificateFromProfileDTO = {
signatureAlgorithm?: string; signatureAlgorithm?: string;
keyAlgorithm?: string; keyAlgorithm?: string;
}; };
removeRootsFromChain?: boolean;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TSignCertificateFromProfileDTO = { export type TSignCertificateFromProfileDTO = {
@@ -37,6 +38,7 @@ export type TSignCertificateFromProfileDTO = {
notBefore?: Date; notBefore?: Date;
notAfter?: Date; notAfter?: Date;
enrollmentType: EnrollmentType; enrollmentType: EnrollmentType;
removeRootsFromChain?: boolean;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TOrderCertificateFromProfileDTO = { export type TOrderCertificateFromProfileDTO = {
@@ -57,6 +59,7 @@ export type TOrderCertificateFromProfileDTO = {
signatureAlgorithm?: string; signatureAlgorithm?: string;
keyAlgorithm?: string; keyAlgorithm?: string;
}; };
removeRootsFromChain?: boolean;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TCertificateFromProfileResponse = { export type TCertificateFromProfileResponse = {
@@ -101,6 +104,7 @@ export type TCertificateOrderResponse = {
export type TRenewCertificateDTO = { export type TRenewCertificateDTO = {
certificateId: string; certificateId: string;
removeRootsFromChain?: boolean;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TUpdateRenewalConfigDTO = { export type TUpdateRenewalConfigDTO = {
@@ -14,6 +14,7 @@ export const AwsCertificateManagerPkiSyncConfigSchema = z.object({
const AwsCertificateManagerPkiSyncOptionsSchema = z.object({ const AwsCertificateManagerPkiSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
preserveArn: z.boolean().default(true), preserveArn: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
@@ -17,7 +17,6 @@ import { AWSRegion } from "@app/services/app-connection/app-connection-enums";
import { getAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-fns"; import { getAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-fns";
import { TAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-types"; import { TAwsConnectionConfig } from "@app/services/app-connection/aws/aws-connection-types";
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
import { removeRootCaFromChain } from "@app/services/certificate-common/certificate-utils";
import { TCertificateSyncDALFactory } from "@app/services/certificate-sync/certificate-sync-dal"; import { TCertificateSyncDALFactory } from "@app/services/certificate-sync/certificate-sync-dal";
import { CertificateSyncStatus } from "@app/services/certificate-sync/certificate-sync-enums"; import { CertificateSyncStatus } from "@app/services/certificate-sync/certificate-sync-enums";
import { createConnectionQueue, RateLimitConfig } from "@app/services/connection-queue"; import { createConnectionQueue, RateLimitConfig } from "@app/services/connection-queue";
@@ -263,10 +262,7 @@ export const awsSecretsManagerPkiSyncFactory = ({
}; };
if (certificateChain && certificateChain.trim().length > 0) { if (certificateChain && certificateChain.trim().length > 0) {
const processedCertificateChain = removeRootCaFromChain(certificateChain); certificateData[fieldMappings.certificateChain] = certificateChain;
if (processedCertificateChain.trim().length > 0) {
certificateData[fieldMappings.certificateChain] = processedCertificateChain;
}
} }
if (caCertificate && typeof caCertificate === "string" && caCertificate.trim().length > 0) { if (caCertificate && typeof caCertificate === "string" && caCertificate.trim().length > 0) {
@@ -307,6 +303,7 @@ export const awsSecretsManagerPkiSyncFactory = ({
} else if (certificate?.renewedFromCertificateId && !preserveSecretOnRenewal) { } else if (certificate?.renewedFromCertificateId && !preserveSecretOnRenewal) {
activeExternalIdentifiers.add(existingRecord.externalIdentifier); activeExternalIdentifiers.add(existingRecord.externalIdentifier);
} else if (!certificate?.renewedFromCertificateId) { } else if (!certificate?.renewedFromCertificateId) {
activeExternalIdentifiers.add(existingRecord.externalIdentifier);
shouldProcess = false; shouldProcess = false;
} }
} }
@@ -22,6 +22,7 @@ export const AwsSecretsManagerFieldMappingsSchema = z.object({
const AwsSecretsManagerPkiSyncOptionsSchema = z.object({ const AwsSecretsManagerPkiSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
preserveSecretOnRenewal: z.boolean().default(true), preserveSecretOnRenewal: z.boolean().default(true),
updateExistingCertificates: z.boolean().default(true), updateExistingCertificates: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
@@ -14,6 +14,7 @@ export const AzureKeyVaultPkiSyncConfigSchema = z.object({
const AzureKeyVaultPkiSyncOptionsSchema = z.object({ const AzureKeyVaultPkiSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
enableVersioning: z.boolean().default(true), enableVersioning: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
@@ -10,7 +10,6 @@ import {
import { TChefDataBagItemContent } from "@app/ee/services/secret-sync/chef"; import { TChefDataBagItemContent } from "@app/ee/services/secret-sync/chef";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
import { removeRootCaFromChain } from "@app/services/certificate-common/certificate-utils";
import { TCertificateSyncDALFactory } from "@app/services/certificate-sync/certificate-sync-dal"; import { TCertificateSyncDALFactory } from "@app/services/certificate-sync/certificate-sync-dal";
import { CertificateSyncStatus } from "@app/services/certificate-sync/certificate-sync-enums"; import { CertificateSyncStatus } from "@app/services/certificate-sync/certificate-sync-enums";
import { createConnectionQueue, RateLimitConfig } from "@app/services/connection-queue"; import { createConnectionQueue, RateLimitConfig } from "@app/services/connection-queue";
@@ -265,13 +264,11 @@ export const chefPkiSyncFactory = ({ certificateDAL, certificateSyncDAL }: TChef
} = certificateData; } = certificateData;
try { try {
const processedCertificateChain = certificateChain ? removeRootCaFromChain(certificateChain) : undefined;
const chefDataBagItem: ChefCertificateDataBagItem = { const chefDataBagItem: ChefCertificateDataBagItem = {
id: targetItemName, id: targetItemName,
[fieldMappings.certificate]: cert, [fieldMappings.certificate]: cert,
[fieldMappings.privateKey]: certPrivateKey, [fieldMappings.privateKey]: certPrivateKey,
...(processedCertificateChain && { [fieldMappings.certificateChain]: processedCertificateChain }), ...(certificateChain && { [fieldMappings.certificateChain]: certificateChain }),
...(caCertificate && { [fieldMappings.caCertificate]: caCertificate }) ...(caCertificate && { [fieldMappings.caCertificate]: caCertificate })
}; };
@@ -29,6 +29,7 @@ const ChefFieldMappingsSchema = z.object({
const ChefPkiSyncOptionsSchema = z.object({ const ChefPkiSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
preserveItemOnRenewal: z.boolean().default(true), preserveItemOnRenewal: z.boolean().default(true),
updateExistingCertificates: z.boolean().default(true), updateExistingCertificates: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
@@ -26,7 +26,7 @@ import { TCertificateSecretDALFactory } from "../certificate/certificate-secret-
import { TCertificateAuthorityCertDALFactory } from "../certificate-authority/certificate-authority-cert-dal"; import { TCertificateAuthorityCertDALFactory } from "../certificate-authority/certificate-authority-cert-dal";
import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal"; import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal";
import { getCaCertChain } from "../certificate-authority/certificate-authority-fns"; import { getCaCertChain } from "../certificate-authority/certificate-authority-fns";
import { extractRootCaFromChain } from "../certificate-common/certificate-utils"; import { extractRootCaFromChain, removeRootCaFromChain } from "../certificate-common/certificate-utils";
import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal"; import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal";
import { CertificateSyncStatus } from "../certificate-sync/certificate-sync-enums"; import { CertificateSyncStatus } from "../certificate-sync/certificate-sync-enums";
import { TPkiSyncDALFactory } from "./pki-sync-dal"; import { TPkiSyncDALFactory } from "./pki-sync-dal";
@@ -269,7 +269,12 @@ export const pkiSyncQueueFactory = ({
} }
let certificateName: string; let certificateName: string;
const syncOptions = pkiSync.syncOptions as { certificateNameSchema?: string } | undefined; const syncOptions = pkiSync.syncOptions as
| {
certificateNameSchema?: string;
includeRootCa?: boolean;
}
| undefined;
const certificateNameSchema = syncOptions?.certificateNameSchema; const certificateNameSchema = syncOptions?.certificateNameSchema;
if (certificateNameSchema) { if (certificateNameSchema) {
@@ -301,10 +306,15 @@ export const pkiSyncQueueFactory = ({
alternativeNames.push(originalLegacyName); alternativeNames.push(originalLegacyName);
} }
let processedCertificateChain = certificateChain;
if (certificateChain && syncOptions?.includeRootCa === false) {
processedCertificateChain = removeRootCaFromChain(certificateChain);
}
certificateMap[certificateName] = { certificateMap[certificateName] = {
cert: certificatePem, cert: certificatePem,
privateKey: certPrivateKey || "", privateKey: certPrivateKey || "",
certificateChain, certificateChain: processedCertificateChain,
caCertificate, caCertificate,
alternativeNames, alternativeNames,
certificateId: certificate.id certificateId: certificate.id
@@ -7,6 +7,7 @@ import { PkiSync } from "./pki-sync-enums";
export const PkiSyncOptionsSchema = z.object({ export const PkiSyncOptionsSchema = z.object({
canImportCertificates: z.boolean(), canImportCertificates: z.boolean(),
canRemoveCertificates: z.boolean().optional(), canRemoveCertificates: z.boolean().optional(),
includeRootCa: z.boolean().optional().default(false),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
.optional() .optional()
@@ -95,6 +95,48 @@ export const PkiSyncOptionsFields = ({ destination }: Props) => {
)} )}
/> />
<Controller
control={control}
name="syncOptions.includeRootCa"
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl isError={Boolean(error)} errorText={error?.message}>
<Switch
className="bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80"
id="include-root-ca"
thumbClassName="bg-mineshaft-800"
onCheckedChange={onChange}
isChecked={value}
>
<p>
Include Root CA in Certificate Chain{" "}
<Tooltip
className="max-w-md"
content={
<>
<p>
When enabled, the full certificate chain including the root CA will be
synced to the destination.
</p>
<p className="mt-4">
When disabled, the root CA will be excluded from the certificate chain
during sync operations, reducing the size of the synced certificate chain.
</p>
<p className="mt-4">
Most applications and services work correctly with intermediate certificates
only, as they can validate the trust chain up to a root CA they already
trust.
</p>
</>
}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" className="ml-1" />
</Tooltip>
</p>
</Switch>
</FormControl>
)}
/>
{currentDestination === PkiSync.AwsCertificateManager && ( {currentDestination === PkiSync.AwsCertificateManager && (
<Controller <Controller
control={control} control={control}
@@ -7,6 +7,7 @@ import { BasePkiSyncSchema } from "./base-pki-sync-schema";
const AwsCertificateManagerSyncOptionsSchema = z.object({ const AwsCertificateManagerSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(false), canRemoveCertificates: z.boolean().default(false),
includeRootCa: z.boolean().default(false),
preserveArn: z.boolean().default(true), preserveArn: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
@@ -20,6 +20,7 @@ const AwsSecretsManagerFieldMappingsSchema = z.object({
const AwsSecretsManagerSyncOptionsSchema = z.object({ const AwsSecretsManagerSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
preserveSecretOnRenewal: z.boolean().default(true), preserveSecretOnRenewal: z.boolean().default(true),
updateExistingCertificates: z.boolean().default(true), updateExistingCertificates: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
@@ -7,6 +7,7 @@ import { BasePkiSyncSchema } from "./base-pki-sync-schema";
const AzureKeyVaultSyncOptionsSchema = z.object({ const AzureKeyVaultSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
enableVersioning: z.boolean().default(true), enableVersioning: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
@@ -6,6 +6,7 @@ export const BasePkiSyncSchema = <T extends AnyZodObject | undefined = undefined
const baseSyncOptionsSchema = z.object({ const baseSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(false), canRemoveCertificates: z.boolean().default(false),
includeRootCa: z.boolean().default(false),
certificateNameSchema: z certificateNameSchema: z
.string() .string()
.optional() .optional()
@@ -20,6 +20,7 @@ const ChefFieldMappingsSchema = z.object({
const ChefSyncOptionsSchema = z.object({ const ChefSyncOptionsSchema = z.object({
canImportCertificates: z.boolean().default(false), canImportCertificates: z.boolean().default(false),
canRemoveCertificates: z.boolean().default(true), canRemoveCertificates: z.boolean().default(true),
includeRootCa: z.boolean().default(false),
preserveItemOnRenewal: z.boolean().default(true), preserveItemOnRenewal: z.boolean().default(true),
updateExistingCertificates: z.boolean().default(true), updateExistingCertificates: z.boolean().default(true),
certificateNameSchema: z certificateNameSchema: z
+1 -1
View File
@@ -14,7 +14,7 @@ export enum PkiSyncStatus {
export enum CertificateSyncStatus { export enum CertificateSyncStatus {
Pending = "pending", Pending = "pending",
Syncing = "syncing", Running = "running",
Succeeded = "succeeded", Succeeded = "succeeded",
Failed = "failed" Failed = "failed"
} }
@@ -354,6 +354,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
<div> <div>
<h4 className="text-sm font-medium text-mineshaft-300">Certificate Details</h4> <h4 className="text-sm font-medium text-mineshaft-300">Certificate Details</h4>
<p className="text-sm text-mineshaft-400">Serial Number: {cert.serialNumber}</p> <p className="text-sm text-mineshaft-400">Serial Number: {cert.serialNumber}</p>
<p className="text-sm text-mineshaft-400">Certificate Id: {cert.id}</p>
<p className="text-sm text-mineshaft-400">Common Name: {cert.commonName}</p> <p className="text-sm text-mineshaft-400">Common Name: {cert.commonName}</p>
<p className="text-sm text-mineshaft-400">Status: {cert.status}</p> <p className="text-sm text-mineshaft-400">Status: {cert.status}</p>
</div> </div>
@@ -42,14 +42,14 @@ type Props = {
const getSyncStatusVariant = (status?: CertificateSyncStatus | null) => { const getSyncStatusVariant = (status?: CertificateSyncStatus | null) => {
if (status === CertificateSyncStatus.Succeeded) return "success"; if (status === CertificateSyncStatus.Succeeded) return "success";
if (status === CertificateSyncStatus.Failed) return "danger"; if (status === CertificateSyncStatus.Failed) return "danger";
if (status === CertificateSyncStatus.Syncing) return "neutral"; if (status === CertificateSyncStatus.Running) return "neutral";
return "project"; return "project";
}; };
const getSyncStatusText = (status?: CertificateSyncStatus | null) => { const getSyncStatusText = (status?: CertificateSyncStatus | null) => {
if (status === CertificateSyncStatus.Succeeded) return "Synced"; if (status === CertificateSyncStatus.Succeeded) return "Synced";
if (status === CertificateSyncStatus.Failed) return "Failed"; if (status === CertificateSyncStatus.Failed) return "Failed";
if (status === CertificateSyncStatus.Syncing) return "Syncing"; if (status === CertificateSyncStatus.Running) return "Syncing";
if (status === CertificateSyncStatus.Pending) return "Pending"; if (status === CertificateSyncStatus.Pending) return "Pending";
return "Unknown"; return "Unknown";
}; };