mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 20:27:12 +00:00
PKI syncs: fixes and add includeRootCa to PKI cert issuance endpoints
This commit is contained in:
@@ -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 = {
|
||||||
|
|||||||
+1
@@ -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()
|
||||||
|
|||||||
+2
-5
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -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}
|
||||||
|
|||||||
+1
@@ -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()
|
||||||
|
|||||||
+1
@@ -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
|
||||||
|
|||||||
+1
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -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>
|
||||||
|
|||||||
+2
-2
@@ -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";
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user