mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 09:30:09 +00:00
merge main
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
/* eslint-disable no-console */
|
||||
import { Redis } from "ioredis";
|
||||
import { Knex } from "knex";
|
||||
import { createTransport } from "nodemailer";
|
||||
|
||||
import { formatSmtpConfig, getConfig } from "@app/lib/config/env";
|
||||
import { buildRedisFromConfig } from "@app/lib/config/redis";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||
|
||||
@@ -65,12 +65,15 @@ export const bootstrapCheck = async ({ db }: BootstrapOpt) => {
|
||||
});
|
||||
|
||||
console.log("Testing redis connection");
|
||||
const redis = new Redis(appCfg.REDIS_URL);
|
||||
const redis = buildRedisFromConfig(appCfg);
|
||||
const redisPing = await redis?.ping();
|
||||
if (!redisPing) {
|
||||
console.error("Redis - Failed to connect");
|
||||
} else {
|
||||
console.error("Redis successfully connected");
|
||||
console.log("Redis successfully connected");
|
||||
if (appCfg.isRedisSentinelMode) {
|
||||
console.log("Redis Sentinel Mode");
|
||||
}
|
||||
redis.disconnect();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
||||
import { Redis } from "ioredis";
|
||||
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { buildRedisFromConfig } from "@app/lib/config/redis";
|
||||
import { RateLimitError } from "@app/lib/errors";
|
||||
|
||||
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
||||
const appCfg = getConfig();
|
||||
const redis = appCfg.isRedisConfigured
|
||||
? new Redis(appCfg.REDIS_URL, { connectTimeout: 500, maxRetriesPerRequest: 1 })
|
||||
: null;
|
||||
const redis = appCfg.isRedisConfigured ? buildRedisFromConfig(appCfg) : null;
|
||||
|
||||
return {
|
||||
errorResponseBuilder: (_, context) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ interface SlugSchemaInputs {
|
||||
field?: string;
|
||||
}
|
||||
|
||||
export const slugSchema = ({ min = 1, max = 32, field = "Slug" }: SlugSchemaInputs = {}) => {
|
||||
export const slugSchema = ({ min = 1, max = 64, field = "Slug" }: SlugSchemaInputs = {}) => {
|
||||
return z
|
||||
.string()
|
||||
.trim()
|
||||
|
||||
@@ -123,6 +123,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
switch (authMode) {
|
||||
case AuthMode.JWT: {
|
||||
const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token);
|
||||
requestContext.set("orgId", orgId);
|
||||
req.auth = {
|
||||
authMode: AuthMode.JWT,
|
||||
user,
|
||||
@@ -138,6 +139,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
case AuthMode.IDENTITY_ACCESS_TOKEN: {
|
||||
const identity = await server.services.identityAccessToken.fnValidateIdentityAccessToken(token, req.realIp);
|
||||
const serverCfg = await getServerCfg();
|
||||
requestContext.set("orgId", identity.orgId);
|
||||
req.auth = {
|
||||
authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
|
||||
actor,
|
||||
@@ -157,6 +159,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
}
|
||||
case AuthMode.SERVICE_TOKEN: {
|
||||
const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token);
|
||||
requestContext.set("orgId", serviceToken.orgId);
|
||||
req.auth = {
|
||||
orgId: serviceToken.orgId,
|
||||
authMode: AuthMode.SERVICE_TOKEN as const,
|
||||
@@ -181,6 +184,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
}
|
||||
case AuthMode.SCIM_TOKEN: {
|
||||
const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token);
|
||||
requestContext.set("orgId", orgId);
|
||||
req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null };
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@ import { z } from "zod";
|
||||
import { registerCertificateEstRouter } from "@app/ee/routes/est/certificate-est-router";
|
||||
import { registerV1EERoutes } from "@app/ee/routes/v1";
|
||||
import { registerV2EERoutes } from "@app/ee/routes/v2";
|
||||
import { accessApprovalPolicyApproverDALFactory } from "@app/ee/services/access-approval-policy/access-approval-policy-approver-dal";
|
||||
import {
|
||||
accessApprovalPolicyApproverDALFactory,
|
||||
accessApprovalPolicyBypasserDALFactory
|
||||
} from "@app/ee/services/access-approval-policy/access-approval-policy-approver-dal";
|
||||
import { accessApprovalPolicyDALFactory } from "@app/ee/services/access-approval-policy/access-approval-policy-dal";
|
||||
import { accessApprovalPolicyServiceFactory } from "@app/ee/services/access-approval-policy/access-approval-policy-service";
|
||||
import { accessApprovalRequestDALFactory } from "@app/ee/services/access-approval-request/access-approval-request-dal";
|
||||
@@ -67,7 +70,10 @@ import { samlConfigDALFactory } from "@app/ee/services/saml-config/saml-config-d
|
||||
import { samlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||
import { scimDALFactory } from "@app/ee/services/scim/scim-dal";
|
||||
import { scimServiceFactory } from "@app/ee/services/scim/scim-service";
|
||||
import { secretApprovalPolicyApproverDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-approver-dal";
|
||||
import {
|
||||
secretApprovalPolicyApproverDALFactory,
|
||||
secretApprovalPolicyBypasserDALFactory
|
||||
} from "@app/ee/services/secret-approval-policy/secret-approval-policy-approver-dal";
|
||||
import { secretApprovalPolicyDALFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-dal";
|
||||
import { secretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
||||
import { secretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal";
|
||||
@@ -136,6 +142,10 @@ import { certificateAuthorityDALFactory } from "@app/services/certificate-author
|
||||
import { certificateAuthorityQueueFactory } from "@app/services/certificate-authority/certificate-authority-queue";
|
||||
import { certificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
|
||||
import { certificateAuthorityServiceFactory } from "@app/services/certificate-authority/certificate-authority-service";
|
||||
import { externalCertificateAuthorityDALFactory } from "@app/services/certificate-authority/external-certificate-authority-dal";
|
||||
import { internalCertificateAuthorityDALFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-dal";
|
||||
import { InternalCertificateAuthorityFns } from "@app/services/certificate-authority/internal/internal-certificate-authority-fns";
|
||||
import { internalCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-service";
|
||||
import { certificateTemplateDALFactory } from "@app/services/certificate-template/certificate-template-dal";
|
||||
import { certificateTemplateEstConfigDALFactory } from "@app/services/certificate-template/certificate-template-est-config-dal";
|
||||
import { certificateTemplateServiceFactory } from "@app/services/certificate-template/certificate-template-service";
|
||||
@@ -203,7 +213,10 @@ import { pkiCollectionDALFactory } from "@app/services/pki-collection/pki-collec
|
||||
import { pkiCollectionItemDALFactory } from "@app/services/pki-collection/pki-collection-item-dal";
|
||||
import { pkiCollectionServiceFactory } from "@app/services/pki-collection/pki-collection-service";
|
||||
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 { 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";
|
||||
import { projectQueueFactory } from "@app/services/project/project-queue";
|
||||
import { projectServiceFactory } from "@app/services/project/project-service";
|
||||
@@ -387,9 +400,11 @@ export const registerRoutes = async (
|
||||
const accessApprovalPolicyDAL = accessApprovalPolicyDALFactory(db);
|
||||
const accessApprovalRequestDAL = accessApprovalRequestDALFactory(db);
|
||||
const accessApprovalPolicyApproverDAL = accessApprovalPolicyApproverDALFactory(db);
|
||||
const accessApprovalPolicyBypasserDAL = accessApprovalPolicyBypasserDALFactory(db);
|
||||
const accessApprovalRequestReviewerDAL = accessApprovalRequestReviewerDALFactory(db);
|
||||
|
||||
const sapApproverDAL = secretApprovalPolicyApproverDALFactory(db);
|
||||
const sapBypasserDAL = secretApprovalPolicyBypasserDALFactory(db);
|
||||
const secretApprovalPolicyDAL = secretApprovalPolicyDALFactory(db);
|
||||
const secretApprovalRequestDAL = secretApprovalRequestDALFactory(db);
|
||||
const secretApprovalRequestReviewerDAL = secretApprovalRequestReviewerDALFactory(db);
|
||||
@@ -522,6 +537,7 @@ export const registerRoutes = async (
|
||||
const secretApprovalPolicyService = secretApprovalPolicyServiceFactory({
|
||||
projectEnvDAL,
|
||||
secretApprovalPolicyApproverDAL: sapApproverDAL,
|
||||
secretApprovalPolicyBypasserDAL: sapBypasserDAL,
|
||||
permissionService,
|
||||
secretApprovalPolicyDAL,
|
||||
licenseService,
|
||||
@@ -633,7 +649,6 @@ export const registerRoutes = async (
|
||||
|
||||
const userService = userServiceFactory({
|
||||
userDAL,
|
||||
userAliasDAL,
|
||||
orgMembershipDAL,
|
||||
tokenService,
|
||||
permissionService,
|
||||
@@ -734,12 +749,14 @@ export const registerRoutes = async (
|
||||
userAliasDAL,
|
||||
identityTokenAuthDAL,
|
||||
identityAccessTokenDAL,
|
||||
orgMembershipDAL,
|
||||
identityOrgMembershipDAL,
|
||||
authService: loginService,
|
||||
serverCfgDAL: superAdminDAL,
|
||||
kmsRootConfigDAL,
|
||||
orgService,
|
||||
keyStore,
|
||||
orgDAL,
|
||||
licenseService,
|
||||
kmsService,
|
||||
microsoftTeamsService,
|
||||
@@ -798,7 +815,8 @@ export const registerRoutes = async (
|
||||
const projectUserAdditionalPrivilegeService = projectUserAdditionalPrivilegeServiceFactory({
|
||||
permissionService,
|
||||
projectMembershipDAL,
|
||||
projectUserAdditionalPrivilegeDAL
|
||||
projectUserAdditionalPrivilegeDAL,
|
||||
accessApprovalRequestDAL
|
||||
});
|
||||
const projectKeyService = projectKeyServiceFactory({
|
||||
permissionService,
|
||||
@@ -826,6 +844,8 @@ export const registerRoutes = async (
|
||||
});
|
||||
|
||||
const certificateAuthorityDAL = certificateAuthorityDALFactory(db);
|
||||
const internalCertificateAuthorityDAL = internalCertificateAuthorityDALFactory(db);
|
||||
const externalCertificateAuthorityDAL = externalCertificateAuthorityDALFactory(db);
|
||||
const certificateAuthorityCertDAL = certificateAuthorityCertDALFactory(db);
|
||||
const certificateAuthoritySecretDAL = certificateAuthoritySecretDALFactory(db);
|
||||
const certificateAuthorityCrlDAL = certificateAuthorityCrlDALFactory(db);
|
||||
@@ -840,6 +860,7 @@ export const registerRoutes = async (
|
||||
const pkiCollectionDAL = pkiCollectionDALFactory(db);
|
||||
const pkiCollectionItemDAL = pkiCollectionItemDALFactory(db);
|
||||
const pkiSubscriberDAL = pkiSubscriberDALFactory(db);
|
||||
const pkiTemplatesDAL = pkiTemplatesDALFactory(db);
|
||||
|
||||
const certificateService = certificateServiceFactory({
|
||||
certificateDAL,
|
||||
@@ -851,17 +872,9 @@ export const registerRoutes = async (
|
||||
certificateAuthoritySecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService
|
||||
});
|
||||
|
||||
const certificateAuthorityQueue = certificateAuthorityQueueFactory({
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
queueService
|
||||
permissionService,
|
||||
pkiCollectionDAL,
|
||||
pkiCollectionItemDAL
|
||||
});
|
||||
|
||||
const sshCertificateAuthorityService = sshCertificateAuthorityServiceFactory({
|
||||
@@ -910,23 +923,6 @@ export const registerRoutes = async (
|
||||
groupDAL
|
||||
});
|
||||
|
||||
const certificateAuthorityService = certificateAuthorityServiceFactory({
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateTemplateDAL,
|
||||
certificateAuthorityQueue,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
pkiCollectionDAL,
|
||||
pkiCollectionItemDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService
|
||||
});
|
||||
|
||||
const certificateAuthorityCrlService = certificateAuthorityCrlServiceFactory({
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
@@ -946,17 +942,6 @@ export const registerRoutes = async (
|
||||
licenseService
|
||||
});
|
||||
|
||||
const certificateEstService = certificateEstServiceFactory({
|
||||
certificateAuthorityService,
|
||||
certificateTemplateService,
|
||||
certificateTemplateDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthorityDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
licenseService
|
||||
});
|
||||
|
||||
const pkiAlertService = pkiAlertServiceFactory({
|
||||
pkiAlertDAL,
|
||||
pkiCollectionDAL,
|
||||
@@ -974,20 +959,6 @@ export const registerRoutes = async (
|
||||
projectDAL
|
||||
});
|
||||
|
||||
const pkiSubscriberService = pkiSubscriberServiceFactory({
|
||||
pkiSubscriberDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService
|
||||
});
|
||||
|
||||
const projectTemplateService = projectTemplateServiceFactory({
|
||||
licenseService,
|
||||
permissionService,
|
||||
@@ -1023,7 +994,8 @@ export const registerRoutes = async (
|
||||
secretVersionV2BridgeDAL,
|
||||
secretVersionTagV2BridgeDAL,
|
||||
resourceMetadataDAL,
|
||||
appConnectionDAL
|
||||
appConnectionDAL,
|
||||
licenseService
|
||||
});
|
||||
|
||||
const secretQueueService = secretQueueFactory({
|
||||
@@ -1269,6 +1241,7 @@ export const registerRoutes = async (
|
||||
const accessApprovalPolicyService = accessApprovalPolicyServiceFactory({
|
||||
accessApprovalPolicyDAL,
|
||||
accessApprovalPolicyApproverDAL,
|
||||
accessApprovalPolicyBypasserDAL,
|
||||
groupDAL,
|
||||
permissionService,
|
||||
projectEnvDAL,
|
||||
@@ -1277,7 +1250,8 @@ export const registerRoutes = async (
|
||||
userDAL,
|
||||
accessApprovalRequestDAL,
|
||||
additionalPrivilegeDAL: projectUserAdditionalPrivilegeDAL,
|
||||
accessApprovalRequestReviewerDAL
|
||||
accessApprovalRequestReviewerDAL,
|
||||
orgMembershipDAL
|
||||
});
|
||||
|
||||
const accessApprovalRequestService = accessApprovalRequestServiceFactory({
|
||||
@@ -1640,7 +1614,8 @@ export const registerRoutes = async (
|
||||
const appConnectionService = appConnectionServiceFactory({
|
||||
appConnectionDAL,
|
||||
permissionService,
|
||||
kmsService
|
||||
kmsService,
|
||||
licenseService
|
||||
});
|
||||
|
||||
const secretSyncService = secretSyncServiceFactory({
|
||||
@@ -1651,7 +1626,54 @@ export const registerRoutes = async (
|
||||
folderDAL,
|
||||
secretSyncQueue,
|
||||
projectBotService,
|
||||
keyStore
|
||||
keyStore,
|
||||
licenseService
|
||||
});
|
||||
|
||||
const certificateAuthorityQueue = certificateAuthorityQueueFactory({
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
queueService,
|
||||
pkiSubscriberDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
externalCertificateAuthorityDAL,
|
||||
keyStore,
|
||||
appConnectionDAL,
|
||||
appConnectionService
|
||||
});
|
||||
|
||||
const internalCertificateAuthorityService = internalCertificateAuthorityServiceFactory({
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateTemplateDAL,
|
||||
certificateAuthorityQueue,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
pkiCollectionDAL,
|
||||
pkiCollectionItemDAL,
|
||||
projectDAL,
|
||||
internalCertificateAuthorityDAL,
|
||||
kmsService,
|
||||
permissionService
|
||||
});
|
||||
|
||||
const certificateEstService = certificateEstServiceFactory({
|
||||
internalCertificateAuthorityService,
|
||||
certificateTemplateService,
|
||||
certificateTemplateDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthorityDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
licenseService
|
||||
});
|
||||
|
||||
const kmipService = kmipServiceFactory({
|
||||
@@ -1693,6 +1715,74 @@ export const registerRoutes = async (
|
||||
appConnectionDAL
|
||||
});
|
||||
|
||||
const certificateAuthorityService = certificateAuthorityServiceFactory({
|
||||
certificateAuthorityDAL,
|
||||
projectDAL,
|
||||
permissionService,
|
||||
appConnectionDAL,
|
||||
appConnectionService,
|
||||
externalCertificateAuthorityDAL,
|
||||
internalCertificateAuthorityService,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
kmsService,
|
||||
pkiSubscriberDAL
|
||||
});
|
||||
|
||||
const internalCaFns = InternalCertificateAuthorityFns({
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
projectDAL,
|
||||
kmsService
|
||||
});
|
||||
|
||||
const pkiSubscriberQueue = pkiSubscriberQueueServiceFactory({
|
||||
queueService,
|
||||
pkiSubscriberDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityQueue,
|
||||
certificateDAL,
|
||||
auditLogService,
|
||||
internalCaFns
|
||||
});
|
||||
|
||||
const pkiSubscriberService = pkiSubscriberServiceFactory({
|
||||
pkiSubscriberDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService,
|
||||
certificateAuthorityQueue,
|
||||
internalCaFns
|
||||
});
|
||||
|
||||
const pkiTemplateService = pkiTemplatesServiceFactory({
|
||||
pkiTemplatesDAL,
|
||||
certificateAuthorityDAL,
|
||||
certificateAuthorityCertDAL,
|
||||
certificateAuthoritySecretDAL,
|
||||
certificateAuthorityCrlDAL,
|
||||
certificateDAL,
|
||||
certificateBodyDAL,
|
||||
certificateSecretDAL,
|
||||
projectDAL,
|
||||
kmsService,
|
||||
permissionService,
|
||||
internalCaFns
|
||||
});
|
||||
|
||||
await secretRotationV2QueueServiceFactory({
|
||||
secretRotationV2Service,
|
||||
secretRotationV2DAL,
|
||||
@@ -1733,6 +1823,7 @@ export const registerRoutes = async (
|
||||
await telemetryQueue.startTelemetryCheck();
|
||||
await dailyResourceCleanUp.startCleanUp();
|
||||
await dailyExpiringPkiItemAlert.startSendingAlerts();
|
||||
await pkiSubscriberQueue.startDailyAutoRenewalJob();
|
||||
await kmsService.startService();
|
||||
await microsoftTeamsService.start();
|
||||
|
||||
@@ -1798,12 +1889,14 @@ export const registerRoutes = async (
|
||||
sshHost: sshHostService,
|
||||
sshHostGroup: sshHostGroupService,
|
||||
certificateAuthority: certificateAuthorityService,
|
||||
internalCertificateAuthority: internalCertificateAuthorityService,
|
||||
certificateTemplate: certificateTemplateService,
|
||||
certificateAuthorityCrl: certificateAuthorityCrlService,
|
||||
certificateEst: certificateEstService,
|
||||
pkiAlert: pkiAlertService,
|
||||
pkiCollection: pkiCollectionService,
|
||||
pkiSubscriber: pkiSubscriberService,
|
||||
pkiTemplate: pkiTemplateService,
|
||||
secretScanning: secretScanningService,
|
||||
license: licenseService,
|
||||
trustedIp: trustedIpService,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
CertificateAuthoritiesSchema,
|
||||
DynamicSecretsSchema,
|
||||
IdentityProjectAdditionalPrivilegeSchema,
|
||||
IntegrationAuthsSchema,
|
||||
InternalCertificateAuthoritiesSchema,
|
||||
ProjectRolesSchema,
|
||||
ProjectsSchema,
|
||||
SecretApprovalPoliciesSchema,
|
||||
@@ -233,11 +235,9 @@ export const SanitizedDynamicSecretSchema = DynamicSecretsSchema.omit({
|
||||
inputIV: true,
|
||||
inputTag: true,
|
||||
algorithm: true
|
||||
}).merge(
|
||||
z.object({
|
||||
metadata: ResourceMetadataSchema.optional()
|
||||
})
|
||||
);
|
||||
}).extend({
|
||||
metadata: ResourceMetadataSchema.optional()
|
||||
});
|
||||
|
||||
export const SanitizedAuditLogStreamSchema = z.object({
|
||||
id: z.string(),
|
||||
@@ -272,3 +272,15 @@ export const SanitizedTagSchema = SecretTagsSchema.pick({
|
||||
}).extend({
|
||||
name: z.string()
|
||||
});
|
||||
|
||||
export const InternalCertificateAuthorityResponseSchema = CertificateAuthoritiesSchema.merge(
|
||||
InternalCertificateAuthoritiesSchema.omit({
|
||||
caId: true,
|
||||
notAfter: true,
|
||||
notBefore: true
|
||||
})
|
||||
).extend({
|
||||
requireTemplateForIssuance: z.boolean().optional(),
|
||||
notAfter: z.string().optional(),
|
||||
notBefore: z.string().optional()
|
||||
});
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import DOMPurify from "isomorphic-dompurify";
|
||||
import { z } from "zod";
|
||||
|
||||
import { IdentitiesSchema, OrganizationsSchema, SuperAdminSchema, UsersSchema } from "@app/db/schemas";
|
||||
import {
|
||||
IdentitiesSchema,
|
||||
OrganizationsSchema,
|
||||
OrgMembershipsSchema,
|
||||
SuperAdminSchema,
|
||||
UsersSchema
|
||||
} from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { invalidateCacheLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
@@ -161,6 +167,129 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/organization-management/organizations",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
searchTerm: z.string().default(""),
|
||||
offset: z.coerce.number().default(0),
|
||||
limit: z.coerce.number().max(100).default(20)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
organizations: OrganizationsSchema.extend({
|
||||
members: z
|
||||
.object({
|
||||
user: z.object({
|
||||
id: z.string(),
|
||||
email: z.string().nullish(),
|
||||
username: z.string(),
|
||||
firstName: z.string().nullish(),
|
||||
lastName: z.string().nullish()
|
||||
}),
|
||||
membershipId: z.string(),
|
||||
role: z.string(),
|
||||
roleId: z.string().nullish()
|
||||
})
|
||||
.array(),
|
||||
projects: z
|
||||
.object({
|
||||
name: z.string(),
|
||||
id: z.string(),
|
||||
slug: z.string(),
|
||||
createdAt: z.date()
|
||||
})
|
||||
.array()
|
||||
}).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: (req, res, done) => {
|
||||
verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN])(req, res, () => {
|
||||
verifySuperAdmin(req, res, done);
|
||||
});
|
||||
},
|
||||
handler: async (req) => {
|
||||
const organizations = await server.services.superAdmin.getOrganizations({
|
||||
...req.query
|
||||
});
|
||||
|
||||
return {
|
||||
organizations
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/organization-management/organizations/:organizationId/memberships/:membershipId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string(),
|
||||
membershipId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
organizationMembership: OrgMembershipsSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: (req, res, done) => {
|
||||
verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN])(req, res, () => {
|
||||
verifySuperAdmin(req, res, done);
|
||||
});
|
||||
},
|
||||
handler: async (req) => {
|
||||
const organizationMembership = await server.services.superAdmin.deleteOrganizationMembership(
|
||||
req.params.organizationId,
|
||||
req.params.membershipId,
|
||||
req.permission.id,
|
||||
req.permission.type
|
||||
);
|
||||
|
||||
return {
|
||||
organizationMembership
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/organization-management/organizations/:organizationId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
organizationId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
organization: OrganizationsSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: (req, res, done) => {
|
||||
verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN])(req, res, () => {
|
||||
verifySuperAdmin(req, res, done);
|
||||
});
|
||||
},
|
||||
handler: async (req) => {
|
||||
const organization = await server.services.superAdmin.deleteOrganization(req.params.organizationId);
|
||||
|
||||
return {
|
||||
organization
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/identity-management/identities",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import z from "zod";
|
||||
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import {
|
||||
CreateOnePassConnectionSchema,
|
||||
SanitizedOnePassConnectionSchema,
|
||||
UpdateOnePassConnectionSchema
|
||||
} from "@app/services/app-connection/1password";
|
||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
||||
|
||||
export const registerOnePassConnectionRouter = async (server: FastifyZodProvider) => {
|
||||
registerAppConnectionEndpoints({
|
||||
app: AppConnection.OnePass,
|
||||
server,
|
||||
sanitizedResponseSchema: SanitizedOnePassConnectionSchema,
|
||||
createSchema: CreateOnePassConnectionSchema,
|
||||
updateSchema: UpdateOnePassConnectionSchema
|
||||
});
|
||||
|
||||
// The following endpoints are for internal Infisical App use only and not part of the public API
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/:connectionId/vaults`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
connectionId: z.string().uuid()
|
||||
}),
|
||||
response: {
|
||||
200: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
type: z.string(),
|
||||
items: z.number(),
|
||||
|
||||
attributeVersion: z.number(),
|
||||
contentVersion: z.number(),
|
||||
|
||||
// Corresponds to ISO8601 date string
|
||||
createdAt: z.string(),
|
||||
updatedAt: z.string()
|
||||
})
|
||||
.array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { connectionId } = req.params;
|
||||
const vaults = await server.services.appConnection.onepass.listVaults(connectionId, req.permission);
|
||||
return vaults;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,9 +1,14 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/ee/services/app-connections/oci";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import {
|
||||
OnePassConnectionListItemSchema,
|
||||
SanitizedOnePassConnectionSchema
|
||||
} from "@app/services/app-connection/1password";
|
||||
import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0";
|
||||
import { AwsConnectionListItemSchema, SanitizedAwsConnectionSchema } from "@app/services/app-connection/aws";
|
||||
import {
|
||||
@@ -42,7 +47,7 @@ import {
|
||||
} from "@app/services/app-connection/humanitec";
|
||||
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
||||
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
||||
import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/services/app-connection/oci";
|
||||
import { MySqlConnectionListItemSchema, SanitizedMySqlConnectionSchema } from "@app/services/app-connection/mysql";
|
||||
import {
|
||||
PostgresConnectionListItemSchema,
|
||||
SanitizedPostgresConnectionSchema
|
||||
@@ -76,6 +81,7 @@ const SanitizedAppConnectionSchema = z.union([
|
||||
...SanitizedVercelConnectionSchema.options,
|
||||
...SanitizedPostgresConnectionSchema.options,
|
||||
...SanitizedMsSqlConnectionSchema.options,
|
||||
...SanitizedMySqlConnectionSchema.options,
|
||||
...SanitizedCamundaConnectionSchema.options,
|
||||
...SanitizedAuth0ConnectionSchema.options,
|
||||
...SanitizedHCVaultConnectionSchema.options,
|
||||
@@ -83,7 +89,8 @@ const SanitizedAppConnectionSchema = z.union([
|
||||
...SanitizedWindmillConnectionSchema.options,
|
||||
...SanitizedLdapConnectionSchema.options,
|
||||
...SanitizedTeamCityConnectionSchema.options,
|
||||
...SanitizedOCIConnectionSchema.options
|
||||
...SanitizedOCIConnectionSchema.options,
|
||||
...SanitizedOnePassConnectionSchema.options
|
||||
]);
|
||||
|
||||
const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
||||
@@ -99,6 +106,7 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
||||
VercelConnectionListItemSchema,
|
||||
PostgresConnectionListItemSchema,
|
||||
MsSqlConnectionListItemSchema,
|
||||
MySqlConnectionListItemSchema,
|
||||
CamundaConnectionListItemSchema,
|
||||
Auth0ConnectionListItemSchema,
|
||||
HCVaultConnectionListItemSchema,
|
||||
@@ -106,7 +114,8 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
||||
WindmillConnectionListItemSchema,
|
||||
LdapConnectionListItemSchema,
|
||||
TeamCityConnectionListItemSchema,
|
||||
OCIConnectionListItemSchema
|
||||
OCIConnectionListItemSchema,
|
||||
OnePassConnectionListItemSchema
|
||||
]);
|
||||
|
||||
export const registerAppConnectionRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { registerOCIConnectionRouter } from "@app/ee/routes/v1/app-connection-routers/oci-connection-router";
|
||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||
|
||||
import { registerOnePassConnectionRouter } from "./1password-connection-router";
|
||||
import { registerAuth0ConnectionRouter } from "./auth0-connection-router";
|
||||
import { registerAwsConnectionRouter } from "./aws-connection-router";
|
||||
import { registerAzureAppConfigurationConnectionRouter } from "./azure-app-configuration-connection-router";
|
||||
@@ -14,7 +16,7 @@ import { registerHCVaultConnectionRouter } from "./hc-vault-connection-router";
|
||||
import { registerHumanitecConnectionRouter } from "./humanitec-connection-router";
|
||||
import { registerLdapConnectionRouter } from "./ldap-connection-router";
|
||||
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
|
||||
import { registerOCIConnectionRouter } from "./oci-connection-router";
|
||||
import { registerMySqlConnectionRouter } from "./mysql-connection-router";
|
||||
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
|
||||
import { registerTeamCityConnectionRouter } from "./teamcity-connection-router";
|
||||
import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router";
|
||||
@@ -38,11 +40,13 @@ export const APP_CONNECTION_REGISTER_ROUTER_MAP: Record<AppConnection, (server:
|
||||
[AppConnection.Vercel]: registerVercelConnectionRouter,
|
||||
[AppConnection.Postgres]: registerPostgresConnectionRouter,
|
||||
[AppConnection.MsSql]: registerMsSqlConnectionRouter,
|
||||
[AppConnection.MySql]: registerMySqlConnectionRouter,
|
||||
[AppConnection.Camunda]: registerCamundaConnectionRouter,
|
||||
[AppConnection.Windmill]: registerWindmillConnectionRouter,
|
||||
[AppConnection.Auth0]: registerAuth0ConnectionRouter,
|
||||
[AppConnection.HCVault]: registerHCVaultConnectionRouter,
|
||||
[AppConnection.LDAP]: registerLdapConnectionRouter,
|
||||
[AppConnection.TeamCity]: registerTeamCityConnectionRouter,
|
||||
[AppConnection.OCI]: registerOCIConnectionRouter
|
||||
[AppConnection.OCI]: registerOCIConnectionRouter,
|
||||
[AppConnection.OnePass]: registerOnePassConnectionRouter
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||
import {
|
||||
CreateMySqlConnectionSchema,
|
||||
SanitizedMySqlConnectionSchema,
|
||||
UpdateMySqlConnectionSchema
|
||||
} from "@app/services/app-connection/mysql";
|
||||
|
||||
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
||||
|
||||
export const registerMySqlConnectionRouter = async (server: FastifyZodProvider) => {
|
||||
registerAppConnectionEndpoints({
|
||||
app: AppConnection.MySql,
|
||||
server,
|
||||
sanitizedResponseSchema: SanitizedMySqlConnectionSchema,
|
||||
createSchema: CreateMySqlConnectionSchema,
|
||||
updateSchema: UpdateMySqlConnectionSchema
|
||||
});
|
||||
};
|
||||
@@ -1,123 +0,0 @@
|
||||
import z from "zod";
|
||||
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||
import {
|
||||
CreateOCIConnectionSchema,
|
||||
SanitizedOCIConnectionSchema,
|
||||
UpdateOCIConnectionSchema
|
||||
} from "@app/services/app-connection/oci";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
||||
|
||||
export const registerOCIConnectionRouter = async (server: FastifyZodProvider) => {
|
||||
registerAppConnectionEndpoints({
|
||||
app: AppConnection.OCI,
|
||||
server,
|
||||
sanitizedResponseSchema: SanitizedOCIConnectionSchema,
|
||||
createSchema: CreateOCIConnectionSchema,
|
||||
updateSchema: UpdateOCIConnectionSchema
|
||||
});
|
||||
|
||||
// The following endpoints are for internal Infisical App use only and not part of the public API
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/:connectionId/compartments`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
connectionId: z.string().uuid()
|
||||
}),
|
||||
response: {
|
||||
200: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
})
|
||||
.array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { connectionId } = req.params;
|
||||
|
||||
const compartments = await server.services.appConnection.oci.listCompartments(connectionId, req.permission);
|
||||
return compartments;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/:connectionId/vaults`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
connectionId: z.string().uuid()
|
||||
}),
|
||||
querystring: z.object({
|
||||
compartmentOcid: z.string().min(1, "Compartment OCID required")
|
||||
}),
|
||||
response: {
|
||||
200: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
displayName: z.string()
|
||||
})
|
||||
.array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { connectionId } = req.params;
|
||||
const { compartmentOcid } = req.query;
|
||||
|
||||
const vaults = await server.services.appConnection.oci.listVaults(
|
||||
{ connectionId, compartmentOcid },
|
||||
req.permission
|
||||
);
|
||||
return vaults;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/:connectionId/vault-keys`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
connectionId: z.string().uuid()
|
||||
}),
|
||||
querystring: z.object({
|
||||
compartmentOcid: z.string().min(1, "Compartment OCID required"),
|
||||
vaultOcid: z.string().min(1, "Vault OCID required")
|
||||
}),
|
||||
response: {
|
||||
200: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
displayName: z.string()
|
||||
})
|
||||
.array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { connectionId } = req.params;
|
||||
const { compartmentOcid, vaultOcid } = req.query;
|
||||
|
||||
const keys = await server.services.appConnection.oci.listVaultKeys(
|
||||
{ connectionId, compartmentOcid, vaultOcid },
|
||||
req.permission
|
||||
);
|
||||
return keys;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import { z } from "zod";
|
||||
|
||||
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
|
||||
import { CertificateTemplatesSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||
import { ms } from "@app/lib/ms";
|
||||
@@ -10,13 +10,19 @@ import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { CertExtendedKeyUsage, CertKeyAlgorithm, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
||||
import { CaRenewalType, CaStatus, CaType } from "@app/services/certificate-authority/certificate-authority-types";
|
||||
import {
|
||||
CaRenewalType,
|
||||
CaStatus,
|
||||
InternalCaType
|
||||
} from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
import {
|
||||
validateAltNamesField,
|
||||
validateCaDateField
|
||||
} from "@app/services/certificate-authority/certificate-authority-validators";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
import { InternalCertificateAuthorityResponseSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
@@ -32,7 +38,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
body: z
|
||||
.object({
|
||||
projectSlug: z.string().trim().describe(CERTIFICATE_AUTHORITIES.CREATE.projectSlug),
|
||||
type: z.nativeEnum(CaType).describe(CERTIFICATE_AUTHORITIES.CREATE.type),
|
||||
type: z.nativeEnum(InternalCaType).describe(CERTIFICATE_AUTHORITIES.CREATE.type),
|
||||
friendlyName: z.string().optional().describe(CERTIFICATE_AUTHORITIES.CREATE.friendlyName),
|
||||
commonName: z.string().trim().describe(CERTIFICATE_AUTHORITIES.CREATE.commonName),
|
||||
organization: z.string().trim().describe(CERTIFICATE_AUTHORITIES.CREATE.organization),
|
||||
@@ -68,16 +74,18 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
),
|
||||
response: {
|
||||
200: z.object({
|
||||
ca: CertificateAuthoritiesSchema
|
||||
ca: InternalCertificateAuthorityResponseSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const ca = await server.services.certificateAuthority.createCa({
|
||||
const ca = await server.services.internalCertificateAuthority.createCa({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
isInternal: false,
|
||||
actorOrgId: req.permission.orgId,
|
||||
enableDirectIssuance: !req.body.requireTemplateForIssuance,
|
||||
...req.body
|
||||
});
|
||||
|
||||
@@ -87,6 +95,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
event: {
|
||||
type: EventType.CREATE_CA,
|
||||
metadata: {
|
||||
name: ca.name,
|
||||
caId: ca.id,
|
||||
dn: ca.dn
|
||||
}
|
||||
@@ -115,12 +124,12 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
ca: CertificateAuthoritiesSchema
|
||||
ca: InternalCertificateAuthorityResponseSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const ca = await server.services.certificateAuthority.getCaById({
|
||||
const ca = await server.services.internalCertificateAuthority.getCaById({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -135,6 +144,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
type: EventType.GET_CA,
|
||||
metadata: {
|
||||
caId: ca.id,
|
||||
name: ca.name,
|
||||
dn: ca.dn
|
||||
}
|
||||
}
|
||||
@@ -167,7 +177,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req, res) => {
|
||||
const caCert = await server.services.certificateAuthority.getCaCertById(req.params);
|
||||
const caCert = await server.services.internalCertificateAuthority.getCaCertById(req.params);
|
||||
|
||||
res.header("Content-Type", "application/pkix-cert");
|
||||
|
||||
@@ -198,17 +208,19 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
ca: CertificateAuthoritiesSchema
|
||||
ca: InternalCertificateAuthorityResponseSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const ca = await server.services.certificateAuthority.updateCaById({
|
||||
const ca = await server.services.internalCertificateAuthority.updateCaById({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
isInternal: false,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
enableDirectIssuance: !req.body.requireTemplateForIssuance,
|
||||
...req.body
|
||||
});
|
||||
|
||||
@@ -220,6 +232,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
metadata: {
|
||||
caId: ca.id,
|
||||
dn: ca.dn,
|
||||
name: ca.name,
|
||||
status: ca.status as CaStatus
|
||||
}
|
||||
}
|
||||
@@ -247,12 +260,12 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
ca: CertificateAuthoritiesSchema
|
||||
ca: InternalCertificateAuthorityResponseSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const ca = await server.services.certificateAuthority.deleteCaById({
|
||||
const ca = await server.services.internalCertificateAuthority.deleteCaById({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -266,6 +279,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
event: {
|
||||
type: EventType.DELETE_CA,
|
||||
metadata: {
|
||||
name: ca.name,
|
||||
caId: ca.id,
|
||||
dn: ca.dn
|
||||
}
|
||||
@@ -299,7 +313,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { ca, csr } = await server.services.certificateAuthority.getCaCsr({
|
||||
const { ca, csr } = await server.services.internalCertificateAuthority.getCaCsr({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -353,7 +367,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, serialNumber, ca } =
|
||||
await server.services.certificateAuthority.renewCaCert({
|
||||
await server.services.internalCertificateAuthority.renewCaCert({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -408,7 +422,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { caCerts, ca } = await server.services.certificateAuthority.getCaCerts({
|
||||
const { caCerts, ca } = await server.services.internalCertificateAuthority.getCaCerts({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -455,13 +469,14 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, serialNumber, ca } = await server.services.certificateAuthority.getCaCert({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
const { certificate, certificateChain, serialNumber, ca } =
|
||||
await server.services.internalCertificateAuthority.getCaCert({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
@@ -517,7 +532,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca } =
|
||||
await server.services.certificateAuthority.signIntermediate({
|
||||
await server.services.internalCertificateAuthority.signIntermediate({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -574,7 +589,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { ca } = await server.services.certificateAuthority.importCertToCa({
|
||||
const { ca } = await server.services.internalCertificateAuthority.importCertToCa({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -653,7 +668,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
|
||||
await server.services.certificateAuthority.issueCertFromCa({
|
||||
await server.services.internalCertificateAuthority.issueCertFromCa({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -746,7 +761,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } =
|
||||
await server.services.certificateAuthority.signCertFromCa({
|
||||
await server.services.internalCertificateAuthority.signCertFromCa({
|
||||
isInternal: false,
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
@@ -809,13 +824,15 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificateTemplates, ca } = await server.services.certificateAuthority.getCaCertificateTemplates({
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
const { certificateTemplates, ca } = await server.services.internalCertificateAuthority.getCaCertificateTemplates(
|
||||
{
|
||||
caId: req.params.caId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
}
|
||||
);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import {
|
||||
AcmeCertificateAuthoritySchema,
|
||||
CreateAcmeCertificateAuthoritySchema,
|
||||
UpdateAcmeCertificateAuthoritySchema
|
||||
} from "@app/services/certificate-authority/acme/acme-certificate-authority-schemas";
|
||||
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
|
||||
import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints";
|
||||
|
||||
export const registerAcmeCertificateAuthorityRouter = async (server: FastifyZodProvider) => {
|
||||
registerCertificateAuthorityEndpoints({
|
||||
caType: CaType.ACME,
|
||||
server,
|
||||
responseSchema: AcmeCertificateAuthoritySchema,
|
||||
createSchema: CreateAcmeCertificateAuthoritySchema,
|
||||
updateSchema: UpdateAcmeCertificateAuthoritySchema
|
||||
});
|
||||
};
|
||||
+258
@@ -0,0 +1,258 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { CaStatus, CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
import {
|
||||
TCertificateAuthority,
|
||||
TCertificateAuthorityInput
|
||||
} from "@app/services/certificate-authority/certificate-authority-types";
|
||||
|
||||
export const registerCertificateAuthorityEndpoints = <
|
||||
T extends TCertificateAuthority,
|
||||
I extends TCertificateAuthorityInput
|
||||
>({
|
||||
server,
|
||||
caType,
|
||||
createSchema,
|
||||
updateSchema,
|
||||
responseSchema
|
||||
}: {
|
||||
caType: CaType;
|
||||
server: FastifyZodProvider;
|
||||
createSchema: z.ZodType<{
|
||||
name: string;
|
||||
projectId: string;
|
||||
status: CaStatus;
|
||||
configuration: I["configuration"];
|
||||
enableDirectIssuance: boolean;
|
||||
}>;
|
||||
updateSchema: z.ZodType<{
|
||||
projectId: string;
|
||||
name?: string;
|
||||
status?: CaStatus;
|
||||
configuration?: I["configuration"];
|
||||
enableDirectIssuance?: boolean;
|
||||
}>;
|
||||
responseSchema: z.ZodTypeAny;
|
||||
}) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: `/`,
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().min(1, "Project ID required")
|
||||
}),
|
||||
response: {
|
||||
200: responseSchema.array()
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const {
|
||||
query: { projectId }
|
||||
} = req;
|
||||
|
||||
const certificateAuthorities = (await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId(
|
||||
{ projectId, type: caType },
|
||||
req.permission
|
||||
)) as T[];
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId,
|
||||
event: {
|
||||
type: EventType.GET_CAS,
|
||||
metadata: {
|
||||
caIds: certificateAuthorities.map((ca) => ca.id)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return certificateAuthorities;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:caName",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
params: z.object({
|
||||
caName: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().uuid()
|
||||
}),
|
||||
response: {
|
||||
200: responseSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { caName } = req.params;
|
||||
const { projectId } = req.query;
|
||||
|
||||
const certificateAuthority =
|
||||
(await server.services.certificateAuthority.findCertificateAuthorityByNameAndProjectId(
|
||||
{ caName, type: caType, projectId },
|
||||
req.permission
|
||||
)) as T;
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: certificateAuthority.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CA,
|
||||
metadata: {
|
||||
caId: certificateAuthority.id,
|
||||
name: certificateAuthority.name
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return certificateAuthority;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
body: createSchema,
|
||||
response: {
|
||||
200: responseSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const certificateAuthority = (await server.services.certificateAuthority.createCertificateAuthority(
|
||||
{ ...req.body, type: caType },
|
||||
req.permission
|
||||
)) as T;
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: certificateAuthority.projectId,
|
||||
event: {
|
||||
type: EventType.CREATE_CA,
|
||||
metadata: {
|
||||
name: certificateAuthority.name,
|
||||
caId: certificateAuthority.id
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return certificateAuthority;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:caName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
params: z.object({
|
||||
caName: z.string()
|
||||
}),
|
||||
body: updateSchema,
|
||||
response: {
|
||||
200: responseSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { caName } = req.params;
|
||||
|
||||
const certificateAuthority = (await server.services.certificateAuthority.updateCertificateAuthority(
|
||||
{
|
||||
...req.body,
|
||||
type: caType,
|
||||
caName
|
||||
},
|
||||
req.permission
|
||||
)) as T;
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: certificateAuthority.projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_CA,
|
||||
metadata: {
|
||||
name: certificateAuthority.name,
|
||||
caId: certificateAuthority.id,
|
||||
status: certificateAuthority.status
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return certificateAuthority;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:caName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
params: z.object({
|
||||
caName: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().uuid()
|
||||
}),
|
||||
response: {
|
||||
200: responseSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { caName } = req.params;
|
||||
const { projectId } = req.body;
|
||||
|
||||
const certificateAuthority = (await server.services.certificateAuthority.deleteCertificateAuthority(
|
||||
{ caName, type: caType, projectId },
|
||||
req.permission
|
||||
)) as T;
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: certificateAuthority.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_CA,
|
||||
metadata: {
|
||||
name: certificateAuthority.name,
|
||||
caId: certificateAuthority.id
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return certificateAuthority;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
|
||||
import { registerAcmeCertificateAuthorityRouter } from "./acme-certificate-authority-router";
|
||||
import { registerInternalCertificateAuthorityRouter } from "./internal-certificate-authority-router";
|
||||
|
||||
export * from "./internal-certificate-authority-router";
|
||||
|
||||
export const CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP: Record<CaType, (server: FastifyZodProvider) => Promise<void>> =
|
||||
{
|
||||
[CaType.INTERNAL]: registerInternalCertificateAuthorityRouter,
|
||||
[CaType.ACME]: registerAcmeCertificateAuthorityRouter
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
import {
|
||||
CreateInternalCertificateAuthoritySchema,
|
||||
InternalCertificateAuthoritySchema,
|
||||
UpdateInternalCertificateAuthoritySchema
|
||||
} from "@app/services/certificate-authority/internal/internal-certificate-authority-schemas";
|
||||
|
||||
import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints";
|
||||
|
||||
export const registerInternalCertificateAuthorityRouter = async (server: FastifyZodProvider) => {
|
||||
registerCertificateAuthorityEndpoints({
|
||||
caType: CaType.INTERNAL,
|
||||
server,
|
||||
responseSchema: InternalCertificateAuthoritySchema,
|
||||
createSchema: CreateInternalCertificateAuthoritySchema,
|
||||
updateSchema: UpdateInternalCertificateAuthoritySchema
|
||||
});
|
||||
};
|
||||
@@ -39,7 +39,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { cert, ca } = await server.services.certificate.getCert({
|
||||
const { cert } = await server.services.certificate.getCert({
|
||||
serialNumber: req.params.serialNumber,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -49,7 +49,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: ca.projectId,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CERT,
|
||||
metadata: {
|
||||
@@ -86,7 +86,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req, reply) => {
|
||||
const { ca, cert, certPrivateKey } = await server.services.certificate.getCertPrivateKey({
|
||||
const { cert, certPrivateKey } = await server.services.certificate.getCertPrivateKey({
|
||||
serialNumber: req.params.serialNumber,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -96,7 +96,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: ca.projectId,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CERT_PRIVATE_KEY,
|
||||
metadata: {
|
||||
@@ -138,7 +138,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req, reply) => {
|
||||
const { certificate, certificateChain, serialNumber, cert, ca, privateKey } =
|
||||
const { certificate, certificateChain, serialNumber, cert, privateKey } =
|
||||
await server.services.certificate.getCertBundle({
|
||||
serialNumber: req.params.serialNumber,
|
||||
actor: req.permission.type,
|
||||
@@ -149,7 +149,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: ca.projectId,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CERT_BUNDLE,
|
||||
metadata: {
|
||||
@@ -242,7 +242,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
|
||||
await server.services.certificateAuthority.issueCertFromCa({
|
||||
await server.services.internalCertificateAuthority.issueCertFromCa({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
@@ -284,6 +284,68 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/import-certificate",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificates],
|
||||
description: "Import certificate",
|
||||
body: z.object({
|
||||
projectSlug: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.projectSlug),
|
||||
|
||||
certificatePem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.certificatePem),
|
||||
privateKeyPem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.privateKeyPem),
|
||||
chainPem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.chainPem),
|
||||
|
||||
friendlyName: z.string().trim().optional().describe(CERTIFICATES.IMPORT.friendlyName),
|
||||
pkiCollectionId: z.string().trim().optional().describe(CERTIFICATES.IMPORT.pkiCollectionId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificate: z.string().trim().describe(CERTIFICATES.IMPORT.certificate),
|
||||
certificateChain: z.string().trim().describe(CERTIFICATES.IMPORT.certificateChain),
|
||||
privateKey: z.string().trim().describe(CERTIFICATES.IMPORT.privateKey),
|
||||
serialNumber: z.string().trim().describe(CERTIFICATES.IMPORT.serialNumber)
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, privateKey, serialNumber, cert } =
|
||||
await server.services.certificate.importCert({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.IMPORT_CERT,
|
||||
metadata: {
|
||||
certId: cert.id,
|
||||
cn: cert.commonName,
|
||||
serialNumber
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
certificate,
|
||||
certificateChain,
|
||||
privateKey,
|
||||
serialNumber
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/sign-certificate",
|
||||
@@ -355,7 +417,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } =
|
||||
await server.services.certificateAuthority.signCertFromCa({
|
||||
await server.services.internalCertificateAuthority.signCertFromCa({
|
||||
isInternal: false,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -474,7 +536,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { deletedCert, ca } = await server.services.certificate.deleteCert({
|
||||
const { deletedCert } = await server.services.certificate.deleteCert({
|
||||
serialNumber: req.params.serialNumber,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -484,7 +546,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: ca.projectId,
|
||||
projectId: deletedCert.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_CERT,
|
||||
metadata: {
|
||||
@@ -524,7 +586,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { certificate, certificateChain, serialNumber, cert, ca } = await server.services.certificate.getCertBody({
|
||||
const { certificate, certificateChain, serialNumber, cert } = await server.services.certificate.getCertBody({
|
||||
serialNumber: req.params.serialNumber,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
@@ -534,7 +596,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: ca.projectId,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CERT_BODY,
|
||||
metadata: {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
||||
@@ -72,7 +73,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
||||
body: z.object({
|
||||
caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId),
|
||||
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId),
|
||||
name: z.string().min(1).describe(CERTIFICATE_TEMPLATES.CREATE.name),
|
||||
name: slugSchema().describe(CERTIFICATE_TEMPLATES.CREATE.name),
|
||||
commonName: validateTemplateRegexField.describe(CERTIFICATE_TEMPLATES.CREATE.commonName),
|
||||
subjectAlternativeName: validateTemplateRegexField.describe(
|
||||
CERTIFICATE_TEMPLATES.CREATE.subjectAlternativeName
|
||||
@@ -141,7 +142,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
||||
body: z.object({
|
||||
caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId),
|
||||
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId),
|
||||
name: z.string().min(1).optional().describe(CERTIFICATE_TEMPLATES.UPDATE.name),
|
||||
name: slugSchema().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.name),
|
||||
commonName: validateTemplateRegexField.optional().describe(CERTIFICATE_TEMPLATES.UPDATE.commonName),
|
||||
subjectAlternativeName: validateTemplateRegexField
|
||||
.optional()
|
||||
|
||||
@@ -114,10 +114,12 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
|
||||
CharacterType.Numbers,
|
||||
CharacterType.Colon,
|
||||
CharacterType.Period,
|
||||
CharacterType.ForwardSlash
|
||||
CharacterType.ForwardSlash,
|
||||
CharacterType.Hyphen
|
||||
])(val),
|
||||
{
|
||||
message: "Kubernetes host must only contain alphabets, numbers, colons, periods, and forward slashes."
|
||||
message:
|
||||
"Kubernetes host must only contain alphabets, numbers, colons, periods, hyphen, and forward slashes."
|
||||
}
|
||||
),
|
||||
caCert: z.string().trim().default("").describe(KUBERNETES_AUTH.ATTACH.caCert),
|
||||
@@ -234,11 +236,13 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
|
||||
CharacterType.Numbers,
|
||||
CharacterType.Colon,
|
||||
CharacterType.Period,
|
||||
CharacterType.ForwardSlash
|
||||
CharacterType.ForwardSlash,
|
||||
CharacterType.Hyphen
|
||||
])(val);
|
||||
},
|
||||
{
|
||||
message: "Kubernetes host must only contain alphabets, numbers, colons, periods, and forward slashes."
|
||||
message:
|
||||
"Kubernetes host must only contain alphabets, numbers, colons, periods, hyphen, and forward slashes."
|
||||
}
|
||||
),
|
||||
caCert: z.string().trim().optional().describe(KUBERNETES_AUTH.UPDATE.caCert),
|
||||
|
||||
@@ -47,8 +47,15 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const { identityUa, accessToken, identityAccessToken, validClientSecretInfo, identityMembershipOrg } =
|
||||
await server.services.identityUa.login(req.body.clientId, req.body.clientSecret, req.realIp);
|
||||
const {
|
||||
identityUa,
|
||||
accessToken,
|
||||
identityAccessToken,
|
||||
validClientSecretInfo,
|
||||
identityMembershipOrg,
|
||||
accessTokenTTL,
|
||||
accessTokenMaxTTL
|
||||
} = await server.services.identityUa.login(req.body.clientId, req.body.clientSecret, req.realIp);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
@@ -63,11 +70,12 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
accessToken,
|
||||
tokenType: "Bearer" as const,
|
||||
expiresIn: identityUa.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityUa.accessTokenMaxTTL
|
||||
expiresIn: accessTokenTTL,
|
||||
accessTokenMaxTTL
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -128,7 +136,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
.int()
|
||||
.min(0)
|
||||
.default(0)
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenNumUsesLimit)
|
||||
.describe(UNIVERSAL_AUTH.ATTACH.accessTokenNumUsesLimit),
|
||||
accessTokenPeriod: z.number().int().min(0).default(0).describe(UNIVERSAL_AUTH.ATTACH.accessTokenPeriod)
|
||||
})
|
||||
.refine(
|
||||
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
|
||||
@@ -227,7 +236,14 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
|
||||
.min(0)
|
||||
.max(315360000)
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenMaxTTL)
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenMaxTTL),
|
||||
accessTokenPeriod: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.max(315360000)
|
||||
.optional()
|
||||
.describe(UNIVERSAL_AUTH.UPDATE.accessTokenPeriod)
|
||||
})
|
||||
.refine(
|
||||
(val) => (val.accessTokenMaxTTL && val.accessTokenTTL ? val.accessTokenTTL <= val.accessTokenMaxTTL : true),
|
||||
|
||||
@@ -10,6 +10,7 @@ import { registerAdminRouter } from "./admin-router";
|
||||
import { registerAuthRoutes } from "./auth-router";
|
||||
import { registerProjectBotRouter } from "./bot-router";
|
||||
import { registerCaRouter } from "./certificate-authority-router";
|
||||
import { CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP } from "./certificate-authority-routers";
|
||||
import { registerCertRouter } from "./certificate-router";
|
||||
import { registerCertificateTemplateRouter } from "./certificate-template-router";
|
||||
import { registerExternalGroupOrgRoleMappingRouter } from "./external-group-org-role-mapping-router";
|
||||
@@ -104,6 +105,16 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
|
||||
await server.register(
|
||||
async (pkiRouter) => {
|
||||
await pkiRouter.register(registerCaRouter, { prefix: "/ca" });
|
||||
await pkiRouter.register(
|
||||
async (caRouter) => {
|
||||
for await (const [caType, router] of Object.entries(CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP)) {
|
||||
await caRouter.register(router, { prefix: `/${caType}` });
|
||||
}
|
||||
},
|
||||
{
|
||||
prefix: "/ca"
|
||||
}
|
||||
);
|
||||
await pkiRouter.register(registerCertRouter, { prefix: "/certificates" });
|
||||
await pkiRouter.register(registerCertificateTemplateRouter, { prefix: "/certificate-templates" });
|
||||
await pkiRouter.register(registerPkiAlertRouter, { prefix: "/alerts" });
|
||||
|
||||
@@ -16,7 +16,12 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
method: "POST",
|
||||
schema: {
|
||||
body: z.object({
|
||||
inviteeEmails: z.array(z.string().trim().email()),
|
||||
inviteeEmails: z
|
||||
.string()
|
||||
.trim()
|
||||
.email()
|
||||
.array()
|
||||
.refine((val) => val.every((el) => el === el.toLowerCase()), "Email must be lowercase"),
|
||||
organizationId: z.string().trim(),
|
||||
projects: z
|
||||
.object({
|
||||
@@ -115,7 +120,11 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
email: z.string().trim().email(),
|
||||
email: z
|
||||
.string()
|
||||
.trim()
|
||||
.email()
|
||||
.refine((val) => val === val.toLowerCase(), "Email must be lowercase"),
|
||||
organizationId: z.string().trim(),
|
||||
code: z.string().trim()
|
||||
}),
|
||||
|
||||
@@ -281,7 +281,18 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
kmsProductEnabled: z.boolean().optional(),
|
||||
sshProductEnabled: z.boolean().optional(),
|
||||
scannerProductEnabled: z.boolean().optional(),
|
||||
shareSecretsProductEnabled: z.boolean().optional()
|
||||
shareSecretsProductEnabled: z.boolean().optional(),
|
||||
maxSharedSecretLifetime: z
|
||||
.number()
|
||||
.min(300, "Max Shared Secret lifetime cannot be under 5 minutes")
|
||||
.max(2592000, "Max Shared Secret lifetime cannot exceed 30 days")
|
||||
.optional(),
|
||||
maxSharedSecretViewLimit: z
|
||||
.number()
|
||||
.min(1, "Max Shared Secret view count cannot be lower than 1")
|
||||
.max(1000, "Max Shared Secret view count cannot exceed 1000")
|
||||
.nullable()
|
||||
.optional()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -301,8 +312,17 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
data: req.body
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
event: {
|
||||
type: EventType.UPDATE_ORG,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully changed organization name",
|
||||
message: "Successfully updated organization",
|
||||
organization
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, PKI_SUBSCRIBERS } from "@app/lib/api-docs";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { addNoCacheHeaders } from "@app/server/lib/caching";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@@ -90,7 +91,8 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
ttl: z
|
||||
.string()
|
||||
.trim()
|
||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||
.refine((val) => !val || ms(val) > 0, "TTL must be a positive number")
|
||||
.optional()
|
||||
.describe(PKI_SUBSCRIBERS.CREATE.ttl),
|
||||
subjectAlternativeNames: validateAltNameField
|
||||
.array()
|
||||
@@ -108,7 +110,9 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
.array()
|
||||
.default([])
|
||||
.transform((arr) => Array.from(new Set(arr)))
|
||||
.describe(PKI_SUBSCRIBERS.CREATE.extendedKeyUsages)
|
||||
.describe(PKI_SUBSCRIBERS.CREATE.extendedKeyUsages),
|
||||
enableAutoRenewal: z.boolean().optional().describe(PKI_SUBSCRIBERS.CREATE.enableAutoRenewal),
|
||||
autoRenewalPeriodInDays: z.number().min(1).optional().describe(PKI_SUBSCRIBERS.CREATE.autoRenewalPeriodInDays)
|
||||
}),
|
||||
response: {
|
||||
200: sanitizedPkiSubscriber
|
||||
@@ -134,7 +138,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
caId: subscriber.caId ?? undefined,
|
||||
name: subscriber.name,
|
||||
commonName: subscriber.commonName,
|
||||
ttl: subscriber.ttl,
|
||||
ttl: subscriber.ttl ?? undefined,
|
||||
subjectAlternativeNames: subscriber.subjectAlternativeNames,
|
||||
keyUsages: subscriber.keyUsages as CertKeyUsage[],
|
||||
extendedKeyUsages: subscriber.extendedKeyUsages as CertExtendedKeyUsage[]
|
||||
@@ -179,7 +183,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
ttl: z
|
||||
.string()
|
||||
.trim()
|
||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||
.refine((val) => !val || ms(val) > 0, "TTL must be a positive number")
|
||||
.optional()
|
||||
.describe(PKI_SUBSCRIBERS.UPDATE.ttl),
|
||||
keyUsages: z
|
||||
@@ -193,7 +197,9 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
.array()
|
||||
.transform((arr) => Array.from(new Set(arr)))
|
||||
.optional()
|
||||
.describe(PKI_SUBSCRIBERS.UPDATE.extendedKeyUsages)
|
||||
.describe(PKI_SUBSCRIBERS.UPDATE.extendedKeyUsages),
|
||||
enableAutoRenewal: z.boolean().optional().describe(PKI_SUBSCRIBERS.UPDATE.enableAutoRenewal),
|
||||
autoRenewalPeriodInDays: z.number().min(1).optional().describe(PKI_SUBSCRIBERS.UPDATE.autoRenewalPeriodInDays)
|
||||
}),
|
||||
response: {
|
||||
200: sanitizedPkiSubscriber
|
||||
@@ -219,7 +225,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
caId: subscriber.caId ?? undefined,
|
||||
name: subscriber.name,
|
||||
commonName: subscriber.commonName,
|
||||
ttl: subscriber.ttl,
|
||||
ttl: subscriber.ttl ?? undefined,
|
||||
subjectAlternativeNames: subscriber.subjectAlternativeNames,
|
||||
keyUsages: subscriber.keyUsages as CertKeyUsage[],
|
||||
extendedKeyUsages: subscriber.extendedKeyUsages as CertExtendedKeyUsage[]
|
||||
@@ -278,6 +284,67 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:subscriberName/order-certificate",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiSubscribers],
|
||||
description: "Order certificate",
|
||||
params: z.object({
|
||||
subscriberName: z.string().describe(PKI_SUBSCRIBERS.ISSUE_CERT.subscriberName)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string().trim().describe(PKI_SUBSCRIBERS.ISSUE_CERT.projectId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string().trim()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const subscriber = await server.services.pkiSubscriber.orderSubscriberCert({
|
||||
subscriberName: req.params.subscriberName,
|
||||
projectId: req.body.projectId,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: subscriber.projectId,
|
||||
event: {
|
||||
type: EventType.ISSUE_PKI_SUBSCRIBER_CERT,
|
||||
metadata: {
|
||||
subscriberId: subscriber.id,
|
||||
name: subscriber.name
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await server.services.telemetry.sendPostHogEvents({
|
||||
event: PostHogEventTypes.IssueCert,
|
||||
distinctId: getTelemetryDistinctId(req),
|
||||
properties: {
|
||||
subscriberId: subscriber.id,
|
||||
commonName: subscriber.commonName,
|
||||
...req.auditLogInfo
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully placed order for certificate"
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:subscriberName/issue-certificate",
|
||||
@@ -420,6 +487,72 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:subscriberName/latest-certificate-bundle",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiSubscribers],
|
||||
description: "Get latest certificate bundle of a subscriber",
|
||||
params: z.object({
|
||||
subscriberName: z.string().describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.subscriberName)
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string().trim().describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.projectId)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificate: z.string().trim().describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.certificate),
|
||||
certificateChain: z
|
||||
.string()
|
||||
.trim()
|
||||
.nullable()
|
||||
.describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.certificateChain),
|
||||
privateKey: z.string().trim().describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.privateKey),
|
||||
serialNumber: z.string().trim().describe(PKI_SUBSCRIBERS.GET_LATEST_CERT_BUNDLE.serialNumber)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req, reply) => {
|
||||
const { certificate, certificateChain, serialNumber, cert, privateKey, subscriber } =
|
||||
await server.services.pkiSubscriber.getSubscriberActiveCertBundle({
|
||||
subscriberName: req.params.subscriberName,
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: cert.projectId,
|
||||
event: {
|
||||
type: EventType.GET_SUBSCRIBER_ACTIVE_CERT_BUNDLE,
|
||||
metadata: {
|
||||
subscriberId: subscriber.id,
|
||||
name: subscriber.name,
|
||||
certId: cert.id,
|
||||
serialNumber: cert.serialNumber
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addNoCacheHeaders(reply);
|
||||
|
||||
return {
|
||||
certificate,
|
||||
certificateChain,
|
||||
serialNumber,
|
||||
privateKey
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:subscriberName/certificates",
|
||||
|
||||
@@ -270,6 +270,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
event: {
|
||||
type: EventType.DELETE_PROJECT,
|
||||
metadata: workspace
|
||||
}
|
||||
});
|
||||
|
||||
return { workspace };
|
||||
}
|
||||
});
|
||||
@@ -304,6 +315,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
projectId: req.params.workspaceId,
|
||||
name: req.body.name
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully changed workspace name",
|
||||
workspace
|
||||
@@ -382,6 +404,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type,
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
workspace
|
||||
};
|
||||
@@ -418,6 +451,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
projectId: req.params.workspaceId,
|
||||
autoCapitalization: req.body.autoCapitalization
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully changed workspace settings",
|
||||
workspace
|
||||
@@ -455,6 +499,17 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
projectId: req.params.workspaceId,
|
||||
hasDeleteProtection: req.body.hasDeleteProtection
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: req.params.workspaceId,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully changed workspace settings",
|
||||
workspace
|
||||
@@ -493,6 +548,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
workspaceSlug: req.params.workspaceSlug
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: workspace.id,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully changed workspace version limit",
|
||||
workspace
|
||||
@@ -531,6 +596,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
auditLogsRetentionDays: req.body.auditLogsRetentionDays
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: workspace.id,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
message: "Successfully updated project's audit logs retention period",
|
||||
workspace
|
||||
|
||||
@@ -62,9 +62,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
||||
}),
|
||||
body: z.object({
|
||||
hashedHex: z.string().min(1).optional(),
|
||||
password: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
hash: z.string().optional()
|
||||
password: z.string().optional()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -91,8 +89,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
||||
hashedHex: req.body.hashedHex,
|
||||
password: req.body.password,
|
||||
orgId: req.permission?.orgId,
|
||||
email: req.body.email,
|
||||
hash: req.body.hash
|
||||
actorId: req.permission?.id
|
||||
});
|
||||
|
||||
if (sharedSecret.secret?.orgId) {
|
||||
@@ -156,7 +153,13 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
||||
expiresAt: z.string(),
|
||||
expiresAfterViews: z.number().min(1).optional(),
|
||||
accessType: z.nativeEnum(SecretSharingAccessType).default(SecretSharingAccessType.Organization),
|
||||
emails: z.string().email().array().max(100).optional()
|
||||
emails: z
|
||||
.string()
|
||||
.email()
|
||||
.array()
|
||||
.max(100)
|
||||
.optional()
|
||||
.transform((val) => (val ? [...new Set(val)] : undefined))
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
CreateOnePassSyncSchema,
|
||||
OnePassSyncSchema,
|
||||
UpdateOnePassSyncSchema
|
||||
} from "@app/services/secret-sync/1password";
|
||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
||||
|
||||
import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
|
||||
|
||||
export const registerOnePassSyncRouter = async (server: FastifyZodProvider) =>
|
||||
registerSyncSecretsEndpoints({
|
||||
destination: SecretSync.OnePass,
|
||||
server,
|
||||
responseSchema: OnePassSyncSchema,
|
||||
createSchema: CreateOnePassSyncSchema,
|
||||
updateSchema: UpdateOnePassSyncSchema
|
||||
});
|
||||
@@ -1,5 +1,7 @@
|
||||
import { registerOCIVaultSyncRouter } from "@app/ee/routes/v1/secret-sync-routers/oci-vault-sync-router";
|
||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
||||
|
||||
import { registerOnePassSyncRouter } from "./1password-sync-router";
|
||||
import { registerAwsParameterStoreSyncRouter } from "./aws-parameter-store-sync-router";
|
||||
import { registerAwsSecretsManagerSyncRouter } from "./aws-secrets-manager-sync-router";
|
||||
import { registerAzureAppConfigurationSyncRouter } from "./azure-app-configuration-sync-router";
|
||||
@@ -10,7 +12,6 @@ import { registerGcpSyncRouter } from "./gcp-sync-router";
|
||||
import { registerGitHubSyncRouter } from "./github-sync-router";
|
||||
import { registerHCVaultSyncRouter } from "./hc-vault-sync-router";
|
||||
import { registerHumanitecSyncRouter } from "./humanitec-sync-router";
|
||||
import { registerOCIVaultSyncRouter } from "./oci-vault-sync-router";
|
||||
import { registerTeamCitySyncRouter } from "./teamcity-sync-router";
|
||||
import { registerTerraformCloudSyncRouter } from "./terraform-cloud-sync-router";
|
||||
import { registerVercelSyncRouter } from "./vercel-sync-router";
|
||||
@@ -33,5 +34,6 @@ export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record<SecretSync, (server: Fastif
|
||||
[SecretSync.Windmill]: registerWindmillSyncRouter,
|
||||
[SecretSync.HCVault]: registerHCVaultSyncRouter,
|
||||
[SecretSync.TeamCity]: registerTeamCitySyncRouter,
|
||||
[SecretSync.OCIVault]: registerOCIVaultSyncRouter
|
||||
[SecretSync.OCIVault]: registerOCIVaultSyncRouter,
|
||||
[SecretSync.OnePass]: registerOnePassSyncRouter
|
||||
};
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import {
|
||||
CreateOCIVaultSyncSchema,
|
||||
OCIVaultSyncSchema,
|
||||
UpdateOCIVaultSyncSchema
|
||||
} from "@app/services/secret-sync/oci-vault";
|
||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
||||
|
||||
import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
|
||||
|
||||
export const registerOCIVaultSyncRouter = async (server: FastifyZodProvider) =>
|
||||
registerSyncSecretsEndpoints({
|
||||
destination: SecretSync.OCIVault,
|
||||
server,
|
||||
responseSchema: OCIVaultSyncSchema,
|
||||
createSchema: CreateOCIVaultSyncSchema,
|
||||
updateSchema: UpdateOCIVaultSyncSchema
|
||||
});
|
||||
@@ -1,10 +1,12 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "@app/ee/services/secret-sync/oci-vault";
|
||||
import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
|
||||
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 { OnePassSyncListItemSchema, OnePassSyncSchema } from "@app/services/secret-sync/1password";
|
||||
import {
|
||||
AwsParameterStoreSyncListItemSchema,
|
||||
AwsParameterStoreSyncSchema
|
||||
@@ -24,7 +26,6 @@ import { GcpSyncListItemSchema, GcpSyncSchema } from "@app/services/secret-sync/
|
||||
import { GitHubSyncListItemSchema, GitHubSyncSchema } from "@app/services/secret-sync/github";
|
||||
import { HCVaultSyncListItemSchema, HCVaultSyncSchema } from "@app/services/secret-sync/hc-vault";
|
||||
import { HumanitecSyncListItemSchema, HumanitecSyncSchema } from "@app/services/secret-sync/humanitec";
|
||||
import { OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "@app/services/secret-sync/oci-vault";
|
||||
import { TeamCitySyncListItemSchema, TeamCitySyncSchema } from "@app/services/secret-sync/teamcity";
|
||||
import { TerraformCloudSyncListItemSchema, TerraformCloudSyncSchema } from "@app/services/secret-sync/terraform-cloud";
|
||||
import { VercelSyncListItemSchema, VercelSyncSchema } from "@app/services/secret-sync/vercel";
|
||||
@@ -45,7 +46,8 @@ const SecretSyncSchema = z.discriminatedUnion("destination", [
|
||||
WindmillSyncSchema,
|
||||
HCVaultSyncSchema,
|
||||
TeamCitySyncSchema,
|
||||
OCIVaultSyncSchema
|
||||
OCIVaultSyncSchema,
|
||||
OnePassSyncSchema
|
||||
]);
|
||||
|
||||
const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [
|
||||
@@ -63,7 +65,8 @@ const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [
|
||||
WindmillSyncListItemSchema,
|
||||
HCVaultSyncListItemSchema,
|
||||
TeamCitySyncListItemSchema,
|
||||
OCIVaultSyncListItemSchema
|
||||
OCIVaultSyncListItemSchema,
|
||||
OnePassSyncListItemSchema
|
||||
]);
|
||||
|
||||
export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
|
||||
|
||||
@@ -46,6 +46,54 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/duplicate-accounts",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
users: UsersSchema.extend({
|
||||
isMyAccount: z.boolean(),
|
||||
organizations: z.object({ name: z.string(), slug: z.string() }).array()
|
||||
}).array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
if (req.auth.authMode === AuthMode.JWT && req.auth.user.email) {
|
||||
const users = await server.services.user.getAllMyAccounts(req.auth.user.email, req.permission.id);
|
||||
return { users };
|
||||
}
|
||||
return { users: [] };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/remove-duplicate-accounts",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
if (req.auth.authMode === AuthMode.JWT && req.auth.user.email) {
|
||||
await server.services.user.removeMyDuplicateAccounts(req.auth.user.email, req.permission.id);
|
||||
}
|
||||
return { message: "Removed all duplicate accounts" };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/private-key",
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||
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 { AcmeCertificateAuthoritySchema } from "@app/services/certificate-authority/acme/acme-certificate-authority-schemas";
|
||||
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
import { InternalCertificateAuthoritySchema } from "@app/services/certificate-authority/internal/internal-certificate-authority-schemas";
|
||||
|
||||
const CertificateAuthoritySchema = z.discriminatedUnion("type", [
|
||||
InternalCertificateAuthoritySchema,
|
||||
AcmeCertificateAuthoritySchema
|
||||
]);
|
||||
|
||||
export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||
description: "Get Certificate Authorities",
|
||||
querystring: z.object({
|
||||
projectId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateAuthorities: CertificateAuthoritySchema.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const internalCas = await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId(
|
||||
{
|
||||
projectId: req.query.projectId,
|
||||
type: CaType.INTERNAL
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
const acmeCas = await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId(
|
||||
{
|
||||
projectId: req.query.projectId,
|
||||
type: CaType.ACME
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.GET_CAS,
|
||||
metadata: {
|
||||
caIds: [...(internalCas ?? []).map((ca) => ca.id), ...(acmeCas ?? []).map((ca) => ca.id)]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
certificateAuthorities: [...(internalCas ?? []), ...(acmeCas ?? [])]
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,9 +1,11 @@
|
||||
import { registerCaRouter } from "./certificate-authority-router";
|
||||
import { registerGroupProjectRouter } from "./group-project-router";
|
||||
import { registerIdentityOrgRouter } from "./identity-org-router";
|
||||
import { registerIdentityProjectRouter } from "./identity-project-router";
|
||||
import { registerMfaRouter } from "./mfa-router";
|
||||
import { registerOrgRouter } from "./organization-router";
|
||||
import { registerPasswordRouter } from "./password-router";
|
||||
import { registerPkiTemplatesRouter } from "./pki-templates-router";
|
||||
import { registerProjectMembershipRouter } from "./project-membership-router";
|
||||
import { registerProjectRouter } from "./project-router";
|
||||
import { registerServiceTokenRouter } from "./service-token-router";
|
||||
@@ -14,6 +16,15 @@ export const registerV2Routes = async (server: FastifyZodProvider) => {
|
||||
await server.register(registerUserRouter, { prefix: "/users" });
|
||||
await server.register(registerServiceTokenRouter, { prefix: "/service-token" });
|
||||
await server.register(registerPasswordRouter, { prefix: "/password" });
|
||||
|
||||
await server.register(
|
||||
async (pkiRouter) => {
|
||||
await pkiRouter.register(registerCaRouter, { prefix: "/ca" });
|
||||
await pkiRouter.register(registerPkiTemplatesRouter, { prefix: "/certificate-templates" });
|
||||
},
|
||||
{ prefix: "/pki" }
|
||||
);
|
||||
|
||||
await server.register(
|
||||
async (orgRouter) => {
|
||||
await orgRouter.register(registerOrgRouter);
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { CertificateTemplatesSchema } from "@app/db/schemas";
|
||||
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||
import { ms } from "@app/lib/ms";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/services/certificate/certificate-types";
|
||||
import {
|
||||
validateAltNamesField,
|
||||
validateCaDateField
|
||||
} from "@app/services/certificate-authority/certificate-authority-validators";
|
||||
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
|
||||
|
||||
export const registerPkiTemplatesRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
body: z.object({
|
||||
name: slugSchema(),
|
||||
caName: slugSchema({ field: "caName" }),
|
||||
projectId: z.string(),
|
||||
commonName: validateTemplateRegexField,
|
||||
subjectAlternativeName: validateTemplateRegexField,
|
||||
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
|
||||
keyUsages: z
|
||||
.nativeEnum(CertKeyUsage)
|
||||
.array()
|
||||
.optional()
|
||||
.default([CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT]),
|
||||
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsage).array().optional().default([])
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateTemplate: CertificateTemplatesSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const certificateTemplate = await server.services.pkiTemplate.createTemplate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.body
|
||||
});
|
||||
|
||||
return { certificateTemplate };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:templateName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
params: z.object({
|
||||
templateName: slugSchema()
|
||||
}),
|
||||
body: z.object({
|
||||
name: slugSchema().optional(),
|
||||
caName: slugSchema(),
|
||||
projectId: z.string(),
|
||||
commonName: validateTemplateRegexField.optional(),
|
||||
subjectAlternativeName: validateTemplateRegexField.optional(),
|
||||
ttl: z
|
||||
.string()
|
||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||
.optional(),
|
||||
keyUsages: z
|
||||
.nativeEnum(CertKeyUsage)
|
||||
.array()
|
||||
.optional()
|
||||
.default([CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT]),
|
||||
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsage).array().optional().default([])
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateTemplate: CertificateTemplatesSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const certificateTemplate = await server.services.pkiTemplate.updateTemplate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
templateName: req.params.templateName,
|
||||
...req.body
|
||||
});
|
||||
|
||||
return { certificateTemplate };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/:templateName",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
params: z.object({
|
||||
templateName: z.string().min(1)
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateTemplate: CertificateTemplatesSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const certificateTemplate = await server.services.pkiTemplate.deleteTemplate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
templateName: req.params.templateName,
|
||||
projectId: req.body.projectId
|
||||
});
|
||||
|
||||
return { certificateTemplate };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:templateName",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
params: z.object({
|
||||
templateName: slugSchema()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateTemplate: CertificateTemplatesSchema.extend({
|
||||
ca: z.object({ id: z.string(), name: z.string() })
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const certificateTemplate = await server.services.pkiTemplate.getTemplateByName({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
templateName: req.params.templateName,
|
||||
projectId: req.query.projectId
|
||||
});
|
||||
|
||||
return { certificateTemplate };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
querystring: z.object({
|
||||
projectId: z.string(),
|
||||
limit: z.coerce.number().default(100),
|
||||
offset: z.coerce.number().default(0)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateTemplates: CertificateTemplatesSchema.extend({
|
||||
ca: z.object({ id: z.string(), name: z.string() })
|
||||
}).array(),
|
||||
totalCount: z.number()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const { certificateTemplates, totalCount } = await server.services.pkiTemplate.listTemplate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
...req.query
|
||||
});
|
||||
|
||||
return { certificateTemplates, totalCount };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:templateName/issue-certificate",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
params: z.object({
|
||||
templateName: slugSchema()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
commonName: validateTemplateRegexField,
|
||||
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
|
||||
keyUsages: z.nativeEnum(CertKeyUsage).array().optional(),
|
||||
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsage).array().optional(),
|
||||
notBefore: validateCaDateField.optional(),
|
||||
notAfter: validateCaDateField.optional(),
|
||||
altNames: validateAltNamesField
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificate: z.string().trim(),
|
||||
issuingCaCertificate: z.string().trim(),
|
||||
certificateChain: z.string().trim(),
|
||||
privateKey: z.string().trim(),
|
||||
serialNumber: z.string().trim()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const data = await server.services.pkiTemplate.issueCertificate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
templateName: req.params.templateName,
|
||||
...req.body
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:templateName/sign-certificate",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||
params: z.object({
|
||||
templateName: slugSchema()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
|
||||
csr: z.string().trim().min(1).max(4096)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificate: z.string().trim(),
|
||||
issuingCaCertificate: z.string().trim(),
|
||||
certificateChain: z.string().trim(),
|
||||
serialNumber: z.string().trim()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const data = await server.services.pkiTemplate.signCertificate({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
templateName: req.params.templateName,
|
||||
...req.body
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -27,8 +27,19 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
projectId: z.string().describe(PROJECT_USERS.INVITE_MEMBER.projectId)
|
||||
}),
|
||||
body: z.object({
|
||||
emails: z.string().email().array().default([]).describe(PROJECT_USERS.INVITE_MEMBER.emails),
|
||||
usernames: z.string().array().default([]).describe(PROJECT_USERS.INVITE_MEMBER.usernames),
|
||||
emails: z
|
||||
.string()
|
||||
.email()
|
||||
.array()
|
||||
.default([])
|
||||
.describe(PROJECT_USERS.INVITE_MEMBER.emails)
|
||||
.refine((val) => val.every((el) => el === el.toLowerCase()), "Email must be lowercase"),
|
||||
usernames: z
|
||||
.string()
|
||||
.array()
|
||||
.default([])
|
||||
.describe(PROJECT_USERS.INVITE_MEMBER.usernames)
|
||||
.refine((val) => val.every((el) => el === el.toLowerCase()), "Username must be lowercase"),
|
||||
roleSlugs: z.string().array().min(1).optional().describe(PROJECT_USERS.INVITE_MEMBER.roleSlugs)
|
||||
}),
|
||||
response: {
|
||||
@@ -92,8 +103,19 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
|
||||
projectId: z.string().describe(PROJECT_USERS.REMOVE_MEMBER.projectId)
|
||||
}),
|
||||
body: z.object({
|
||||
emails: z.string().email().array().default([]).describe(PROJECT_USERS.REMOVE_MEMBER.emails),
|
||||
usernames: z.string().array().default([]).describe(PROJECT_USERS.REMOVE_MEMBER.usernames)
|
||||
emails: z
|
||||
.string()
|
||||
.email()
|
||||
.array()
|
||||
.default([])
|
||||
.describe(PROJECT_USERS.REMOVE_MEMBER.emails)
|
||||
.refine((val) => val.every((el) => el === el.toLowerCase()), "Email must be lowercase"),
|
||||
usernames: z
|
||||
.string()
|
||||
.array()
|
||||
.default([])
|
||||
.describe(PROJECT_USERS.REMOVE_MEMBER.usernames)
|
||||
.refine((val) => val.every((el) => el === el.toLowerCase()), "Username must be lowercase")
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
CertificateAuthoritiesSchema,
|
||||
CertificatesSchema,
|
||||
PkiAlertsSchema,
|
||||
PkiCollectionsSchema,
|
||||
@@ -22,13 +21,13 @@ import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-types";
|
||||
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||
import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema";
|
||||
import { sanitizedPkiSubscriber } from "@app/services/pki-subscriber/pki-subscriber-schema";
|
||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||
|
||||
import { SanitizedProjectSchema } from "../sanitizedSchemas";
|
||||
import { InternalCertificateAuthorityResponseSchema, SanitizedProjectSchema } from "../sanitizedSchemas";
|
||||
|
||||
const projectWithEnv = SanitizedProjectSchema.extend({
|
||||
_id: z.string(),
|
||||
@@ -206,19 +205,18 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
if (req.body.template) {
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
event: {
|
||||
type: EventType.APPLY_PROJECT_TEMPLATE,
|
||||
metadata: {
|
||||
template: req.body.template,
|
||||
projectId: project.id
|
||||
}
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: project.id,
|
||||
event: {
|
||||
type: EventType.CREATE_PROJECT,
|
||||
metadata: {
|
||||
...req.body,
|
||||
name: req.body.projectName
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { project };
|
||||
}
|
||||
@@ -262,6 +260,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
actor: req.permission.type
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: project.id,
|
||||
event: {
|
||||
type: EventType.DELETE_PROJECT,
|
||||
metadata: project
|
||||
}
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
});
|
||||
@@ -341,6 +349,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
actorOrgId: req.permission.orgId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
projectId: project.id,
|
||||
event: {
|
||||
type: EventType.UPDATE_PROJECT,
|
||||
metadata: req.body
|
||||
}
|
||||
});
|
||||
|
||||
return project;
|
||||
}
|
||||
});
|
||||
@@ -366,7 +384,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
cas: z.array(CertificateAuthoritiesSchema)
|
||||
cas: z.array(InternalCertificateAuthorityResponseSchema)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user