mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-18 02:56:57 +00:00
Add Certificate Syncs
This commit is contained in:
@@ -248,6 +248,9 @@ import { pkiCollectionServiceFactory } from "@app/services/pki-collection/pki-co
|
||||
import { pkiSubscriberDALFactory } from "@app/services/pki-subscriber/pki-subscriber-dal";
|
||||
import { pkiSubscriberQueueServiceFactory } from "@app/services/pki-subscriber/pki-subscriber-queue";
|
||||
import { pkiSubscriberServiceFactory } from "@app/services/pki-subscriber/pki-subscriber-service";
|
||||
import { pkiSyncDALFactory } from "@app/services/pki-sync/pki-sync-dal";
|
||||
import { pkiSyncQueueFactory } from "@app/services/pki-sync/pki-sync-queue";
|
||||
import { pkiSyncServiceFactory } from "@app/services/pki-sync/pki-sync-service";
|
||||
import { pkiTemplatesDALFactory } from "@app/services/pki-templates/pki-templates-dal";
|
||||
import { pkiTemplatesServiceFactory } from "@app/services/pki-templates/pki-templates-service";
|
||||
import { projectDALFactory } from "@app/services/project/project-dal";
|
||||
@@ -975,6 +978,7 @@ export const registerRoutes = async (
|
||||
const pkiCollectionDAL = pkiCollectionDALFactory(db);
|
||||
const pkiCollectionItemDAL = pkiCollectionItemDALFactory(db);
|
||||
const pkiSubscriberDAL = pkiSubscriberDALFactory(db);
|
||||
const pkiSyncDAL = pkiSyncDALFactory(db);
|
||||
const pkiTemplatesDAL = pkiTemplatesDALFactory(db);
|
||||
|
||||
const instanceRelayConfigDAL = instanceRelayConfigDalFactory(db);
|
||||
@@ -984,21 +988,6 @@ export const registerRoutes = async (
|
||||
|
||||
const orgGatewayConfigV2DAL = orgGatewayConfigV2DalFactory(db);
|
||||
|
||||
const certificateService = certificateServiceFactory({
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService,
|
||||
pkiCollectionDAL,
|
||||
pkiCollectionItemDAL
|
||||
});
|
||||
|
||||
const sshCertificateAuthorityService = sshCertificateAuthorityServiceFactory({
|
||||
sshCertificateAuthorityDAL,
|
||||
sshCertificateAuthoritySecretDAL,
|
||||
@@ -1977,6 +1966,38 @@ export const registerRoutes = async (
|
||||
internalCaFns
|
||||
});
|
||||
|
||||
const pkiSyncQueue = pkiSyncQueueFactory({
|
||||
queueService,
|
||||
kmsService,
|
||||
appConnectionDAL,
|
||||
keyStore,
|
||||
pkiSyncDAL,
|
||||
auditLogService,
|
||||
projectMembershipDAL,
|
||||
projectDAL,
|
||||
licenseService,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL
|
||||
});
|
||||
|
||||
const certificateService = certificateServiceFactory({
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService,
|
||||
pkiCollectionDAL,
|
||||
pkiCollectionItemDAL,
|
||||
pkiSyncDAL,
|
||||
pkiSyncQueue
|
||||
});
|
||||
|
||||
const pkiSubscriberService = pkiSubscriberServiceFactory({
|
||||
pkiSubscriberDAL,
|
||||
certificateAuthorityDAL,
|
||||
@@ -1990,7 +2011,18 @@ export const registerRoutes = async (
|
||||
kmsService,
|
||||
permissionService,
|
||||
certificateAuthorityQueue,
|
||||
internalCaFns
|
||||
internalCaFns,
|
||||
pkiSyncDAL,
|
||||
pkiSyncQueue
|
||||
});
|
||||
|
||||
const pkiSyncService = pkiSyncServiceFactory({
|
||||
pkiSyncDAL,
|
||||
pkiSubscriberDAL,
|
||||
appConnectionService,
|
||||
permissionService,
|
||||
licenseService,
|
||||
pkiSyncQueue
|
||||
});
|
||||
|
||||
const pkiTemplateService = pkiTemplatesServiceFactory({
|
||||
@@ -2136,6 +2168,7 @@ export const registerRoutes = async (
|
||||
pkiAlert: pkiAlertService,
|
||||
pkiCollection: pkiCollectionService,
|
||||
pkiSubscriber: pkiSubscriberService,
|
||||
pkiSync: pkiSyncService,
|
||||
pkiTemplate: pkiTemplateService,
|
||||
secretScanning: secretScanningService,
|
||||
license: licenseService,
|
||||
|
||||
@@ -40,6 +40,7 @@ import { registerPasswordRouter } from "./password-router";
|
||||
import { registerPkiAlertRouter } from "./pki-alert-router";
|
||||
import { registerPkiCollectionRouter } from "./pki-collection-router";
|
||||
import { registerPkiSubscriberRouter } from "./pki-subscriber-router";
|
||||
import { registerPkiSyncRouter } from "./pki-sync-router";
|
||||
import { registerProjectEnvRouter } from "./project-env-router";
|
||||
import { registerProjectKeyRouter } from "./project-key-router";
|
||||
import { registerProjectMembershipRouter } from "./project-membership-router";
|
||||
@@ -137,6 +138,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
|
||||
await server.register(registerIntegrationAuthRouter, { prefix: "/integration-auth" });
|
||||
await server.register(registerWebhookRouter, { prefix: "/webhooks" });
|
||||
await server.register(registerIdentityRouter, { prefix: "/identities" });
|
||||
await server.register(registerPkiSyncRouter, { prefix: "/pki-syncs" });
|
||||
|
||||
await server.register(
|
||||
async (secretSharingRouter) => {
|
||||
|
||||
@@ -0,0 +1,540 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { AzureKeyVaultPkiSyncConfigSchema } from "@app/services/pki-sync/azure-key-vault/azure-key-vault-pki-sync-types";
|
||||
import { PkiSync } from "@app/services/pki-sync/pki-sync-enums";
|
||||
import { PkiSyncDetailsSchema, PkiSyncListItemSchema, PkiSyncSchema } from "@app/services/pki-sync/pki-sync-schemas";
|
||||
import { TCreatePkiSyncDTO, TUpdatePkiSyncDTO } from "@app/services/pki-sync/pki-sync-types";
|
||||
|
||||
const CreatePkiSyncRequestBodySchema = z.object({
|
||||
name: z.string().trim().min(1).max(64),
|
||||
description: z.string().optional(),
|
||||
destination: z.nativeEnum(PkiSync),
|
||||
isAutoSyncEnabled: z.boolean().default(true),
|
||||
destinationConfig: z
|
||||
.discriminatedUnion("destination", [
|
||||
z.object({
|
||||
destination: z.literal(PkiSync.AzureKeyVault),
|
||||
config: AzureKeyVaultPkiSyncConfigSchema
|
||||
})
|
||||
])
|
||||
.transform(({ config }) => config),
|
||||
syncOptions: z.record(z.unknown()).default({}),
|
||||
subscriberId: z.string().optional(),
|
||||
connectionId: z.string(),
|
||||
projectId: z.string().trim().min(1)
|
||||
});
|
||||
|
||||
const UpdatePkiSyncRequestBodySchema = z.object({
|
||||
name: z.string().trim().min(1).max(64).optional(),
|
||||
description: z.string().optional(),
|
||||
isAutoSyncEnabled: z.boolean().optional(),
|
||||
destinationConfig: z.record(z.unknown()).optional(),
|
||||
syncOptions: z.record(z.unknown()).optional(),
|
||||
subscriberId: z.string().optional(),
|
||||
connectionId: z.string().optional()
|
||||
});
|
||||
|
||||
export const registerPkiSyncRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/options",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get PKI sync options",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync options retrieved successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSyncOptions: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
destination: z.nativeEnum(PkiSync),
|
||||
canImportCertificates: z.boolean(),
|
||||
canRemoveCertificates: z.boolean(),
|
||||
enterprise: z.boolean().optional()
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async () => {
|
||||
const pkiSyncOptions = [
|
||||
{
|
||||
name: "Azure Key Vault",
|
||||
destination: PkiSync.AzureKeyVault,
|
||||
canImportCertificates: true,
|
||||
canRemoveCertificates: true,
|
||||
enterprise: false
|
||||
}
|
||||
];
|
||||
|
||||
return { pkiSyncOptions };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Create PKI sync",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: CreatePkiSyncRequestBodySchema
|
||||
}
|
||||
}
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync created successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSync: PkiSyncSchema
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const requestBody = CreatePkiSyncRequestBodySchema.parse(req.body);
|
||||
const createData: Omit<TCreatePkiSyncDTO, "auditLogInfo"> = requestBody;
|
||||
|
||||
try {
|
||||
const pkiSync = await server.services.pkiSync.createPkiSync(createData, req.permission);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: createData.projectId,
|
||||
event: {
|
||||
type: EventType.CREATE_PKI_SYNC,
|
||||
metadata: {
|
||||
pkiSyncId: pkiSync.id,
|
||||
name: pkiSync.name,
|
||||
destination: pkiSync.destination
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { pkiSync };
|
||||
} catch (error) {
|
||||
logger.error("Failed to create PKI sync");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "List PKI syncs",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI syncs retrieved successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSyncs: z.array(PkiSyncListItemSchema)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const pkiSyncs = await server.services.pkiSync.listPkiSyncsByProjectId(
|
||||
{
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
return { pkiSyncs };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:pkiSyncId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Get PKI sync by ID",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync retrieved successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSync: PkiSyncDetailsSchema
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const pkiSync = await server.services.pkiSync.findPkiSyncById(
|
||||
{
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
return { pkiSync };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:pkiSyncId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Update PKI sync",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: UpdatePkiSyncRequestBodySchema
|
||||
}
|
||||
}
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync updated successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSync: PkiSyncSchema
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const requestBody = UpdatePkiSyncRequestBodySchema.parse(req.body);
|
||||
const updateData: Omit<TUpdatePkiSyncDTO, "auditLogInfo"> = {
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId,
|
||||
...requestBody
|
||||
};
|
||||
|
||||
try {
|
||||
const pkiSync = await server.services.pkiSync.updatePkiSync(updateData, req.permission);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_PKI_SYNC,
|
||||
metadata: {
|
||||
pkiSyncId: pkiSync.id,
|
||||
name: pkiSync.name
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { pkiSync };
|
||||
} catch (error) {
|
||||
logger.error("Failed to update PKI sync");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:pkiSyncId",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Delete PKI sync",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync deleted successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
pkiSync: z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
destination: z.nativeEnum(PkiSync)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
try {
|
||||
const pkiSync = await server.services.pkiSync.deletePkiSync(
|
||||
{
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_PKI_SYNC,
|
||||
metadata: {
|
||||
pkiSyncId: pkiSync.id,
|
||||
name: pkiSync.name,
|
||||
destination: pkiSync.destination
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { pkiSync };
|
||||
} catch (error) {
|
||||
logger.error("Failed to delete PKI sync");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:pkiSyncId/sync",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Trigger PKI sync",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync triggered successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
try {
|
||||
const result = await server.services.pkiSync.triggerPkiSyncSyncCertificatesById(
|
||||
{
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error("Failed to trigger PKI sync");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:pkiSyncId/import",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Import certificates from PKI sync destination",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync import triggered successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
try {
|
||||
const result = await server.services.pkiSync.triggerPkiSyncImportCertificatesById(
|
||||
{
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error("Failed to trigger PKI sync import certificates");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:pkiSyncId/remove",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
description: "Remove certificates from PKI sync destination",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
pkiSyncId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: {
|
||||
description: "PKI sync remove triggered successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN]),
|
||||
handler: async (req) => {
|
||||
try {
|
||||
const result = await server.services.pkiSync.triggerPkiSyncRemoveCertificatesById(
|
||||
{
|
||||
id: req.params.pkiSyncId,
|
||||
projectId: req.query.projectId
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error("Failed to trigger PKI sync remove certificates");
|
||||
logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user