Preliminary scaffolding for CA structures

This commit is contained in:
Tuan Dang
2024-05-22 21:33:06 -07:00
parent 303edadb1e
commit 26ea949a4e
41 changed files with 1656 additions and 8 deletions
+17
View File
@@ -71,6 +71,11 @@ import { authPaswordServiceFactory } from "@app/services/auth/auth-password-serv
import { authSignupServiceFactory } from "@app/services/auth/auth-signup-service";
import { tokenDALFactory } from "@app/services/auth-token/auth-token-dal";
import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service";
import { certificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
// ca / certs
import { certificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
import { certificateAuthorityServiceFactory } from "@app/services/certificate-authority/certificate-authority-service";
import { certificateAuthoritySkDALFactory } from "@app/services/certificate-authority/certificate-authority-sk-dal";
import { groupProjectDALFactory } from "@app/services/group-project/group-project-dal";
import { groupProjectMembershipRoleDALFactory } from "@app/services/group-project/group-project-membership-role-dal";
import { groupProjectServiceFactory } from "@app/services/group-project/group-project-service";
@@ -221,6 +226,16 @@ export const registerRoutes = async (
const trustedIpDAL = trustedIpDALFactory(db);
const telemetryDAL = telemetryDALFactory(db);
const certificateAuthorityDAL = certificateAuthorityDALFactory(db);
const certificateAuthorityCertDAL = certificateAuthorityCertDALFactory(db);
const certificateAuthoritySkDAL = certificateAuthoritySkDALFactory(db);
const certificateAuthorityService = certificateAuthorityServiceFactory({
certificateAuthorityDAL,
certificateAuthorityCertDAL,
certificateAuthoritySkDAL,
projectDAL
});
// ee db layer ops
const permissionDAL = permissionDALFactory(db);
const samlConfigDAL = samlConfigDALFactory(db);
@@ -504,6 +519,7 @@ export const registerRoutes = async (
projectMembershipDAL,
folderDAL,
licenseService,
certificateAuthorityDAL,
projectUserMembershipRoleDAL,
identityProjectMembershipRoleDAL,
keyStore
@@ -826,6 +842,7 @@ export const registerRoutes = async (
ldap: ldapService,
auditLog: auditLogService,
auditLogStream: auditLogStreamService,
certificateAuthority: certificateAuthorityService,
secretScanning: secretScanningService,
license: licenseService,
trustedIp: trustedIpService,
@@ -0,0 +1,151 @@
import { z } from "zod";
import { CertificateAuthoritiesSchema } from "@app/db/schemas";
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 { CAType } from "@app/services/certificate-authority/certificate-authority-types";
export const registerCaRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Create CA",
body: z.object({
projectSlug: z.string().trim(),
type: z.enum([CAType.ROOT, CAType.INTERMEDIATE]),
commonName: z.string().trim(),
organization: z.string().trim(),
ou: z.string().trim(),
country: z.string().trim(),
province: z.string().trim(),
locality: z.string().trim()
}),
response: {
200: CertificateAuthoritiesSchema
}
},
handler: async (req) => {
const ca = await server.services.certificateAuthority.createCa({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
...req.body
});
return ca;
}
});
server.route({
method: "GET",
url: "/:caId/csr",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Get CA CSR",
params: z.object({
caId: z.string().trim()
}),
response: {
200: z.object({
csr: z.string()
})
}
},
handler: async (req) => {
const csr = await server.services.certificateAuthority.getCaCsr({
caId: req.params.caId,
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId
});
return {
csr
};
}
});
server.route({
method: "GET",
url: ":caId/certificate",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Get cert and cert chain of a CA",
params: z.object({
caId: z.string().trim()
}),
response: {
200: z.object({
certificate: z.string(),
certificateChain: z.string()
})
}
},
handler: async (req) => {
const { certificate, certificateChain } = 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
});
return {
certificate,
certificateChain
};
}
});
server.route({
method: "POST",
url: ":caId/issue-certificate",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Issue (leaf) certificate from CA",
params: z.object({
caId: z.string().trim()
}),
body: z.object({
csr: z.string().trim(),
notBefore: z.string().trim(),
notAfter: z.string().trim()
}),
response: {
200: z.object({
certificateId: z.string().trim()
})
}
},
handler: async () => {
// await server.services.certificateAuthority.issueCertFromCa({
// caId: req.params.caId,
// actor: req.permission.type,
// actorId: req.permission.id,
// actorAuthMethod: req.permission.authMethod,
// actorOrgId: req.permission.orgId,
// ...req.body
// });
return {
certificateId: "111"
};
}
});
// TODO 2: logic for creating intermediary ca
// TODO 1: get certificate + certificate chain for the root and intermediary CA GET /ca/:caId/certificate
};
+8
View File
@@ -1,6 +1,7 @@
import { registerAdminRouter } from "./admin-router";
import { registerAuthRoutes } from "./auth-router";
import { registerProjectBotRouter } from "./bot-router";
import { registerCaRouter } from "./certificate-authority-router";
import { registerIdentityAccessTokenRouter } from "./identity-access-token-router";
import { registerIdentityAwsAuthRouter } from "./identity-aws-iam-auth-router";
import { registerIdentityGcpAuthRouter } from "./identity-gcp-auth-router";
@@ -58,6 +59,13 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
{ prefix: "/workspace" }
);
await server.register(
async (certRouter) => {
await certRouter.register(registerCaRouter);
},
{ prefix: "/ca" }
);
await server.register(registerProjectBotRouter, { prefix: "/bot" });
await server.register(registerIntegrationRouter, { prefix: "/integration" });
await server.register(registerIntegrationAuthRouter, { prefix: "/integration-auth" });
+35 -1
View File
@@ -1,7 +1,7 @@
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { ProjectKeysSchema, ProjectsSchema } from "@app/db/schemas";
import { CertificateAuthoritiesSchema, ProjectKeysSchema, ProjectsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs";
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -307,4 +307,38 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
return project;
}
});
server.route({
method: "GET",
url: "/:slug/cas",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to list CAs.")
}),
response: {
200: z.object({
cas: z.array(CertificateAuthoritiesSchema)
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const cas = await server.services.project.listProjectCas({
filter: {
slug: req.params.slug,
orgId: req.permission.orgId,
type: ProjectFilterType.SLUG
},
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type
});
return { cas };
}
});
};