mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-19 04:08:21 +00:00
PKI revamp: UI improvements
This commit is contained in:
@@ -68,18 +68,24 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
(tx || db).ref("name").withSchema(TableName.CertificateAuthority).as("caName"),
|
||||
(tx || db).ref("id").withSchema(TableName.CertificateTemplateV2).as("templateId"),
|
||||
(tx || db).ref("projectId").withSchema(TableName.CertificateTemplateV2).as("templateProjectId"),
|
||||
(tx || db).ref("name").withSchema(TableName.CertificateTemplateV2).as("templateName"),
|
||||
(tx || db).ref("slug").withSchema(TableName.CertificateTemplateV2).as("templateName"),
|
||||
(tx || db).ref("description").withSchema(TableName.CertificateTemplateV2).as("templateDescription"),
|
||||
(tx || db).ref("id").withSchema(TableName.EstEnrollmentConfig).as("estConfigId"),
|
||||
(tx || db).ref("id").withSchema(TableName.PkiEstEnrollmentConfig).as("estConfigId"),
|
||||
(tx || db)
|
||||
.ref("disableBootstrapCaValidation")
|
||||
.withSchema(TableName.EstEnrollmentConfig)
|
||||
.withSchema(TableName.PkiEstEnrollmentConfig)
|
||||
.as("estConfigDisableBootstrapCaValidation"),
|
||||
(tx || db).ref("hashedPassphrase").withSchema(TableName.EstEnrollmentConfig).as("estConfigHashedPassphrase"),
|
||||
(tx || db).ref("encryptedCaChain").withSchema(TableName.EstEnrollmentConfig).as("estConfigEncryptedCaChain"),
|
||||
(tx || db).ref("id").withSchema(TableName.ApiEnrollmentConfig).as("apiConfigId"),
|
||||
(tx || db).ref("autoRenew").withSchema(TableName.ApiEnrollmentConfig).as("apiConfigAutoRenew"),
|
||||
(tx || db).ref("autoRenewDays").withSchema(TableName.ApiEnrollmentConfig).as("apiConfigAutoRenewDays")
|
||||
(tx || db)
|
||||
.ref("hashedPassphrase")
|
||||
.withSchema(TableName.PkiEstEnrollmentConfig)
|
||||
.as("estConfigHashedPassphrase"),
|
||||
(tx || db)
|
||||
.ref("encryptedCaChain")
|
||||
.withSchema(TableName.PkiEstEnrollmentConfig)
|
||||
.as("estConfigEncryptedCaChain"),
|
||||
(tx || db).ref("id").withSchema(TableName.PkiApiEnrollmentConfig).as("apiConfigId"),
|
||||
(tx || db).ref("autoRenew").withSchema(TableName.PkiApiEnrollmentConfig).as("apiConfigAutoRenew"),
|
||||
(tx || db).ref("autoRenewDays").withSchema(TableName.PkiApiEnrollmentConfig).as("apiConfigAutoRenewDays")
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.CertificateAuthority,
|
||||
@@ -92,14 +98,14 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
`${TableName.CertificateTemplateV2}.id`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.EstEnrollmentConfig,
|
||||
TableName.PkiEstEnrollmentConfig,
|
||||
`${TableName.CertificateProfile}.estConfigId`,
|
||||
`${TableName.EstEnrollmentConfig}.id`
|
||||
`${TableName.PkiEstEnrollmentConfig}.id`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.ApiEnrollmentConfig,
|
||||
TableName.PkiApiEnrollmentConfig,
|
||||
`${TableName.CertificateProfile}.apiConfigId`,
|
||||
`${TableName.ApiEnrollmentConfig}.id`
|
||||
`${TableName.PkiApiEnrollmentConfig}.id`
|
||||
)
|
||||
.where(`${TableName.CertificateProfile}.id`, id)
|
||||
.first();
|
||||
@@ -151,9 +157,8 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
if (search) {
|
||||
query = query.where((builder) => {
|
||||
void builder
|
||||
.whereILike(`${TableName.CertificateProfile}.name`, `%${search}%`)
|
||||
.orWhereILike(`${TableName.CertificateProfile}.description`, `%${search}%`)
|
||||
.orWhereILike(`${TableName.CertificateProfile}.slug`, `%${search}%`);
|
||||
.whereILike(`${TableName.CertificateProfile}.slug`, `%${search}%`)
|
||||
.orWhereILike(`${TableName.CertificateProfile}.description`, `%${search}%`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,10 +230,7 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
|
||||
if (search) {
|
||||
query = query.where((builder) => {
|
||||
void builder
|
||||
.whereILike("name", `%${search}%`)
|
||||
.orWhereILike("description", `%${search}%`)
|
||||
.orWhereILike("slug", `%${search}%`);
|
||||
void builder.orWhereILike("description", `%${search}%`).orWhereILike("slug", `%${search}%`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -249,7 +251,9 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
|
||||
const findByNameAndProjectId = async (name: string, projectId: string, tx?: Knex) => {
|
||||
try {
|
||||
const certificateProfile = await (tx || db)(TableName.CertificateProfile).where({ name, projectId }).first();
|
||||
const certificateProfile = await (tx || db)(TableName.CertificateProfile)
|
||||
.where({ slug: name, projectId })
|
||||
.first();
|
||||
return certificateProfile;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find certificate profile by name and project id" });
|
||||
|
||||
@@ -8,7 +8,6 @@ export const createCertificateProfileSchema = z
|
||||
projectId: z.string().min(1),
|
||||
caId: z.string().uuid(),
|
||||
certificateTemplateId: z.string().uuid(),
|
||||
name: z.string().min(1).max(255),
|
||||
slug: z
|
||||
.string()
|
||||
.min(1)
|
||||
@@ -46,7 +45,6 @@ export const createCertificateProfileSchema = z
|
||||
);
|
||||
|
||||
export const updateCertificateProfileSchema = z.object({
|
||||
name: z.string().min(1).max(255).optional(),
|
||||
slug: z
|
||||
.string()
|
||||
.min(1)
|
||||
|
||||
@@ -80,7 +80,6 @@ describe("CertificateProfileService", () => {
|
||||
const sampleProfile: TCertificateProfile = {
|
||||
id: "profile-123",
|
||||
projectId: "project-123",
|
||||
name: "Test Profile",
|
||||
description: "Test certificate profile",
|
||||
slug: "test-profile",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
@@ -174,9 +173,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
describe("createProfile", () => {
|
||||
const validProfileData = {
|
||||
name: "New Profile",
|
||||
description: "New test profile",
|
||||
slug: "new-profile",
|
||||
description: "New test profile",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -204,9 +202,8 @@ describe("CertificateProfileService", () => {
|
||||
expect(mockCertificateTemplateV2DAL.findById).toHaveBeenCalledWith("template-123");
|
||||
expect(mockCertificateProfileDAL.findBySlugAndProjectId).toHaveBeenCalledWith("new-profile", "project-123");
|
||||
expect(mockCertificateProfileDAL.create).toHaveBeenCalledWith({
|
||||
name: "New Profile",
|
||||
description: "New test profile",
|
||||
slug: "new-profile",
|
||||
description: "New test profile",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -273,9 +270,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should throw ForbiddenRequestError for API enrollment without API config", async () => {
|
||||
const invalidData = {
|
||||
name: "Invalid Profile",
|
||||
description: "Invalid test profile",
|
||||
slug: "invalid-profile",
|
||||
description: "Invalid test profile",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123"
|
||||
@@ -292,9 +288,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should create profile with API enrollment", async () => {
|
||||
const apiProfileData = {
|
||||
name: "API Profile",
|
||||
description: "Profile with API enrollment",
|
||||
slug: "api-profile",
|
||||
description: "Profile with API enrollment",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -317,7 +312,7 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
describe("updateProfile", () => {
|
||||
const updateData = {
|
||||
name: "Updated Profile",
|
||||
slug: "updated-profile",
|
||||
description: "Updated description"
|
||||
};
|
||||
|
||||
@@ -333,7 +328,7 @@ describe("CertificateProfileService", () => {
|
||||
data: updateData
|
||||
});
|
||||
|
||||
expect(result.name).toBe("Updated Profile");
|
||||
expect(result.slug).toBe("updated-profile");
|
||||
expect(mockCertificateProfileDAL.findById).toHaveBeenCalledWith("profile-123");
|
||||
expect(mockCertificateProfileDAL.updateById).toHaveBeenCalledWith("profile-123", updateData);
|
||||
});
|
||||
@@ -697,9 +692,8 @@ describe("CertificateProfileService", () => {
|
||||
describe("profile configuration validation", () => {
|
||||
it("should validate EST enrollment configuration", async () => {
|
||||
const estProfileData = {
|
||||
name: "EST Profile",
|
||||
description: "Profile with EST enrollment",
|
||||
slug: "est-profile",
|
||||
description: "Profile with EST enrollment",
|
||||
enrollmentType: EnrollmentType.EST,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -737,9 +731,8 @@ describe("CertificateProfileService", () => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
const duplicateSlugData = {
|
||||
name: "Different Profile Name",
|
||||
slug: "different-profile-name",
|
||||
description: "Profile with duplicate slug",
|
||||
slug: "test-profile",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -763,9 +756,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should validate auto-renewal configuration", async () => {
|
||||
const autoRenewData = {
|
||||
name: "Auto Renew Profile",
|
||||
slug: "auto-renew-profile",
|
||||
description: "Profile with auto-renewal",
|
||||
slug: "auto-renew",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -987,9 +979,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should handle invalid template reference during profile creation", async () => {
|
||||
const profileData = {
|
||||
name: "Invalid Template Profile",
|
||||
slug: "invalid-template-profile",
|
||||
description: "Profile with invalid template",
|
||||
slug: "invalid-template",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "nonexistent-template",
|
||||
@@ -1013,9 +1004,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should handle concurrent profile creation conflicts", async () => {
|
||||
const conflictingData = {
|
||||
name: "Concurrent Profile",
|
||||
description: "Profile created concurrently",
|
||||
slug: "concurrent-profile",
|
||||
description: "Profile created concurrently",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
@@ -1042,9 +1032,8 @@ describe("CertificateProfileService", () => {
|
||||
describe("permission and security", () => {
|
||||
it("should validate project ownership for cross-project template access", async () => {
|
||||
const crossProjectData = {
|
||||
name: "Cross Project Profile",
|
||||
slug: "cross-project-profile",
|
||||
description: "Profile using template from different project",
|
||||
slug: "cross-project",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-456",
|
||||
@@ -1056,7 +1045,7 @@ describe("CertificateProfileService", () => {
|
||||
const foreignTemplate = {
|
||||
id: "template-456",
|
||||
projectId: "different-project-456",
|
||||
name: "Foreign Template"
|
||||
slug: "foreign-template"
|
||||
};
|
||||
|
||||
(mockCertificateTemplateV2DAL.findById as any).mockResolvedValue(foreignTemplate);
|
||||
@@ -1072,9 +1061,8 @@ describe("CertificateProfileService", () => {
|
||||
|
||||
it("should validate slug format constraints", async () => {
|
||||
const invalidSlugData = {
|
||||
name: "Invalid Slug Profile",
|
||||
slug: "invalid-slug-profile",
|
||||
description: "Profile with invalid slug format",
|
||||
slug: "Invalid_Slug_With_Underscores_And_Caps",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
certificateTemplateId: "template-123",
|
||||
|
||||
@@ -277,7 +277,28 @@ export const certificateProfileServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const updatedProfile = await certificateProfileDAL.updateById(profileId, data);
|
||||
const { estConfig, apiConfig, ...profileUpdateData } = data;
|
||||
|
||||
if (estConfig && existingProfile.estConfigId) {
|
||||
await estEnrollmentConfigDAL.updateById(existingProfile.estConfigId, {
|
||||
disableBootstrapCaValidation: estConfig.disableBootstrapCaValidation,
|
||||
...(estConfig.passphrase && {
|
||||
hashedPassphrase: await crypto.hashing().createHash(estConfig.passphrase, getConfig().SALT_ROUNDS)
|
||||
}),
|
||||
...(estConfig.caChain && {
|
||||
encryptedCaChain: Buffer.from(estConfig.caChain, "base64")
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (apiConfig && existingProfile.apiConfigId) {
|
||||
await apiEnrollmentConfigDAL.updateById(existingProfile.apiConfigId, {
|
||||
autoRenew: apiConfig.autoRenew,
|
||||
autoRenewDays: apiConfig.autoRenewDays
|
||||
});
|
||||
}
|
||||
|
||||
const updatedProfile = await certificateProfileDAL.updateById(profileId, profileUpdateData);
|
||||
return convertDalToService(updatedProfile);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,15 @@ export type TCertificateProfileInsert = Omit<TCertificateProfilesInsert, "enroll
|
||||
|
||||
export type TCertificateProfileUpdate = Omit<TCertificateProfilesUpdate, "enrollmentType"> & {
|
||||
enrollmentType?: EnrollmentType;
|
||||
estConfig?: {
|
||||
disableBootstrapCaValidation?: boolean;
|
||||
passphrase?: string;
|
||||
caChain?: string;
|
||||
};
|
||||
apiConfig?: {
|
||||
autoRenew?: boolean;
|
||||
autoRenewDays?: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type TCertificateProfileWithConfigs = TCertificateProfile & {
|
||||
|
||||
Reference in New Issue
Block a user