mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 21:37:59 +00:00
PKI revamp - backend initial changes
This commit is contained in:
@@ -8,6 +8,25 @@ import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
export const registerCertificateEstRouter = async (server: FastifyZodProvider) => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
const getIdentifierType = async (identifier: string): Promise<"template" | "profile" | null> => {
|
||||
try {
|
||||
await server.services.certificateProfile.getEstConfigurationByProfile({
|
||||
profileId: identifier
|
||||
});
|
||||
return "profile";
|
||||
} catch {
|
||||
try {
|
||||
await server.services.certificateTemplate.getEstConfiguration({
|
||||
isInternal: true,
|
||||
certificateTemplateId: identifier
|
||||
});
|
||||
return "template";
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// add support for CSR bodies
|
||||
server.addContentTypeParser("application/pkcs10", { parseAs: "string" }, (_, body, done) => {
|
||||
try {
|
||||
@@ -59,11 +78,28 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
return;
|
||||
}
|
||||
|
||||
const certificateTemplateId = urlFragments.slice(-2)[0];
|
||||
const estConfig = await server.services.certificateTemplate.getEstConfiguration({
|
||||
isInternal: true,
|
||||
certificateTemplateId
|
||||
});
|
||||
const identifier = urlFragments.slice(-2)[0];
|
||||
|
||||
const identifierType = await getIdentifierType(identifier);
|
||||
if (!identifierType) {
|
||||
res.raw.statusCode = 404;
|
||||
res.raw.setHeader("Content-Type", "text/plain");
|
||||
res.raw.write("Certificate template or profile not found");
|
||||
res.raw.flushHeaders();
|
||||
return;
|
||||
}
|
||||
|
||||
let estConfig;
|
||||
if (identifierType === "profile") {
|
||||
estConfig = await server.services.certificateProfile.getEstConfigurationByProfile({
|
||||
profileId: identifier
|
||||
});
|
||||
} else {
|
||||
estConfig = await server.services.certificateTemplate.getEstConfiguration({
|
||||
isInternal: true,
|
||||
certificateTemplateId: identifier
|
||||
});
|
||||
}
|
||||
|
||||
if (!estConfig.isEnabled) {
|
||||
throw new BadRequestError({
|
||||
@@ -95,14 +131,14 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:certificateTemplateId/simpleenroll",
|
||||
url: "/:identifier/simpleenroll",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.string().min(1),
|
||||
params: z.object({
|
||||
certificateTemplateId: z.string().min(1)
|
||||
identifier: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.string()
|
||||
@@ -112,9 +148,23 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
void res.header("Content-Type", "application/pkcs7-mime; smime-type=certs-only");
|
||||
void res.header("Content-Transfer-Encoding", "base64");
|
||||
|
||||
const { identifier } = req.params;
|
||||
const identifierType = await getIdentifierType(identifier);
|
||||
|
||||
if (!identifierType) {
|
||||
throw new BadRequestError({ message: "Certificate template or profile not found" });
|
||||
}
|
||||
|
||||
if (identifierType === "profile") {
|
||||
return server.services.certificateEstV3.simpleEnrollByProfile({
|
||||
csr: req.body,
|
||||
profileId: identifier,
|
||||
sslClientCert: req.headers[appCfg.SSL_CLIENT_CERTIFICATE_HEADER_KEY] as string
|
||||
});
|
||||
}
|
||||
return server.services.certificateEst.simpleEnroll({
|
||||
csr: req.body,
|
||||
certificateTemplateId: req.params.certificateTemplateId,
|
||||
certificateTemplateId: identifier,
|
||||
sslClientCert: req.headers[appCfg.SSL_CLIENT_CERTIFICATE_HEADER_KEY] as string
|
||||
});
|
||||
}
|
||||
@@ -122,14 +172,14 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/:certificateTemplateId/simplereenroll",
|
||||
url: "/:identifier/simplereenroll",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.string().min(1),
|
||||
params: z.object({
|
||||
certificateTemplateId: z.string().min(1)
|
||||
identifier: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.string()
|
||||
@@ -139,9 +189,23 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
void res.header("Content-Type", "application/pkcs7-mime; smime-type=certs-only");
|
||||
void res.header("Content-Transfer-Encoding", "base64");
|
||||
|
||||
const { identifier } = req.params;
|
||||
const identifierType = await getIdentifierType(identifier);
|
||||
|
||||
if (!identifierType) {
|
||||
throw new BadRequestError({ message: "Certificate template or profile not found" });
|
||||
}
|
||||
|
||||
if (identifierType === "profile") {
|
||||
return server.services.certificateEstV3.simpleReenrollByProfile({
|
||||
csr: req.body,
|
||||
profileId: identifier,
|
||||
sslClientCert: req.headers[appCfg.SSL_CLIENT_CERTIFICATE_HEADER_KEY] as string
|
||||
});
|
||||
}
|
||||
return server.services.certificateEst.simpleReenroll({
|
||||
csr: req.body,
|
||||
certificateTemplateId: req.params.certificateTemplateId,
|
||||
certificateTemplateId: identifier,
|
||||
sslClientCert: req.headers[appCfg.SSL_CLIENT_CERTIFICATE_HEADER_KEY] as string
|
||||
});
|
||||
}
|
||||
@@ -149,13 +213,13 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:certificateTemplateId/cacerts",
|
||||
url: "/:identifier/cacerts",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
certificateTemplateId: z.string().min(1)
|
||||
identifier: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.string()
|
||||
@@ -165,8 +229,20 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
|
||||
void res.header("Content-Type", "application/pkcs7-mime; smime-type=certs-only");
|
||||
void res.header("Content-Transfer-Encoding", "base64");
|
||||
|
||||
const { identifier } = req.params;
|
||||
const identifierType = await getIdentifierType(identifier);
|
||||
|
||||
if (!identifierType) {
|
||||
throw new BadRequestError({ message: "Certificate template or profile not found" });
|
||||
}
|
||||
|
||||
if (identifierType === "profile") {
|
||||
return server.services.certificateEstV3.getCaCertsByProfile({
|
||||
profileId: identifier
|
||||
});
|
||||
}
|
||||
return server.services.certificateEst.getCaCerts({
|
||||
certificateTemplateId: req.params.certificateTemplateId
|
||||
certificateTemplateId: identifier
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -355,6 +355,19 @@ export enum EventType {
|
||||
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
||||
UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "update-certificate-template-est-config",
|
||||
GET_CERTIFICATE_TEMPLATE_EST_CONFIG = "get-certificate-template-est-config",
|
||||
CREATE_CERTIFICATE_TEMPLATE_V2 = "create-certificate-template-v2",
|
||||
UPDATE_CERTIFICATE_TEMPLATE_V2 = "update-certificate-template-v2",
|
||||
DELETE_CERTIFICATE_TEMPLATE_V2 = "delete-certificate-template-v2",
|
||||
GET_CERTIFICATE_TEMPLATE_V2 = "get-certificate-template-v2",
|
||||
LIST_CERTIFICATE_TEMPLATES_V2 = "list-certificate-templates-v2",
|
||||
CREATE_CERTIFICATE_PROFILE = "create-certificate-profile",
|
||||
UPDATE_CERTIFICATE_PROFILE = "update-certificate-profile",
|
||||
DELETE_CERTIFICATE_PROFILE = "delete-certificate-profile",
|
||||
GET_CERTIFICATE_PROFILE = "get-certificate-profile",
|
||||
LIST_CERTIFICATE_PROFILES = "list-certificate-profiles",
|
||||
ISSUE_CERTIFICATE_FROM_PROFILE = "issue-certificate-from-profile",
|
||||
SIGN_CERTIFICATE_FROM_PROFILE = "sign-certificate-from-profile",
|
||||
ORDER_CERTIFICATE_FROM_PROFILE = "order-certificate-from-profile",
|
||||
ATTEMPT_CREATE_SLACK_INTEGRATION = "attempt-create-slack-integration",
|
||||
ATTEMPT_REINSTALL_SLACK_INTEGRATION = "attempt-reinstall-slack-integration",
|
||||
GET_PROJECT_SLACK_CONFIG = "get-project-slack-config",
|
||||
@@ -2598,6 +2611,109 @@ interface GetCertificateTemplateEstConfig {
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateCertificateTemplateV2 {
|
||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE_V2;
|
||||
metadata: {
|
||||
certificateTemplateId: string;
|
||||
name: string;
|
||||
projectId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateCertificateTemplateV2 {
|
||||
type: EventType.UPDATE_CERTIFICATE_TEMPLATE_V2;
|
||||
metadata: {
|
||||
certificateTemplateId: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteCertificateTemplateV2 {
|
||||
type: EventType.DELETE_CERTIFICATE_TEMPLATE_V2;
|
||||
metadata: {
|
||||
certificateTemplateId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCertificateTemplateV2 {
|
||||
type: EventType.GET_CERTIFICATE_TEMPLATE_V2;
|
||||
metadata: {
|
||||
certificateTemplateId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ListCertificateTemplatesV2 {
|
||||
type: EventType.LIST_CERTIFICATE_TEMPLATES_V2;
|
||||
metadata: {
|
||||
projectId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateCertificateProfile {
|
||||
type: EventType.CREATE_CERTIFICATE_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
name: string;
|
||||
projectId: string;
|
||||
enrollmentType: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateCertificateProfile {
|
||||
type: EventType.UPDATE_CERTIFICATE_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteCertificateProfile {
|
||||
type: EventType.DELETE_CERTIFICATE_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCertificateProfile {
|
||||
type: EventType.GET_CERTIFICATE_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ListCertificateProfiles {
|
||||
type: EventType.LIST_CERTIFICATE_PROFILES;
|
||||
metadata: {
|
||||
projectId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IssueCertificateFromProfile {
|
||||
type: EventType.ISSUE_CERTIFICATE_FROM_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
certificateId: string;
|
||||
commonName: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface SignCertificateFromProfile {
|
||||
type: EventType.SIGN_CERTIFICATE_FROM_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
certificateId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface OrderCertificateFromProfile {
|
||||
type: EventType.ORDER_CERTIFICATE_FROM_PROFILE;
|
||||
metadata: {
|
||||
certificateProfileId: string;
|
||||
orderId: string;
|
||||
identifiers: string[];
|
||||
};
|
||||
}
|
||||
|
||||
interface AttemptCreateSlackIntegration {
|
||||
type: EventType.ATTEMPT_CREATE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
@@ -4058,6 +4174,19 @@ export type Event =
|
||||
| CreateCertificateTemplateEstConfig
|
||||
| UpdateCertificateTemplateEstConfig
|
||||
| GetCertificateTemplateEstConfig
|
||||
| CreateCertificateTemplateV2
|
||||
| UpdateCertificateTemplateV2
|
||||
| DeleteCertificateTemplateV2
|
||||
| GetCertificateTemplateV2
|
||||
| ListCertificateTemplatesV2
|
||||
| CreateCertificateProfile
|
||||
| UpdateCertificateProfile
|
||||
| DeleteCertificateProfile
|
||||
| GetCertificateProfile
|
||||
| ListCertificateProfiles
|
||||
| IssueCertificateFromProfile
|
||||
| SignCertificateFromProfile
|
||||
| OrderCertificateFromProfile
|
||||
| GetAzureAdCsTemplatesEvent
|
||||
| AttemptCreateSlackIntegration
|
||||
| AttemptReinstallSlackIntegration
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ProjectPermissionAppConnectionActions,
|
||||
ProjectPermissionAuditLogsActions,
|
||||
ProjectPermissionCertificateActions,
|
||||
ProjectPermissionCertificateProfileActions,
|
||||
ProjectPermissionCmekActions,
|
||||
ProjectPermissionCommitsActions,
|
||||
ProjectPermissionDynamicSecretActions,
|
||||
@@ -72,8 +73,8 @@ const buildAdminPermissionRules = () => {
|
||||
ProjectPermissionPkiTemplateActions.Edit,
|
||||
ProjectPermissionPkiTemplateActions.Create,
|
||||
ProjectPermissionPkiTemplateActions.Delete,
|
||||
ProjectPermissionPkiTemplateActions.IssueCert,
|
||||
ProjectPermissionPkiTemplateActions.ListCerts
|
||||
ProjectPermissionPkiTemplateActions.IssueCert, // deprecated
|
||||
ProjectPermissionPkiTemplateActions.ListCerts // deprecated
|
||||
],
|
||||
ProjectPermissionSub.CertificateTemplates
|
||||
);
|
||||
@@ -99,6 +100,17 @@ const buildAdminPermissionRules = () => {
|
||||
ProjectPermissionSub.Certificates
|
||||
);
|
||||
|
||||
can(
|
||||
[
|
||||
ProjectPermissionCertificateProfileActions.Read,
|
||||
ProjectPermissionCertificateProfileActions.Edit,
|
||||
ProjectPermissionCertificateProfileActions.Create,
|
||||
ProjectPermissionCertificateProfileActions.Delete,
|
||||
ProjectPermissionCertificateProfileActions.IssueCert
|
||||
],
|
||||
ProjectPermissionSub.CertificateProfiles
|
||||
);
|
||||
|
||||
can(
|
||||
[ProjectPermissionCommitsActions.Read, ProjectPermissionCommitsActions.PerformRollback],
|
||||
ProjectPermissionSub.Commits
|
||||
@@ -454,7 +466,15 @@ const buildMemberPermissionRules = () => {
|
||||
ProjectPermissionSub.Certificates
|
||||
);
|
||||
|
||||
can([ProjectPermissionPkiTemplateActions.Read], ProjectPermissionSub.CertificateTemplates);
|
||||
can(
|
||||
[
|
||||
ProjectPermissionCertificateProfileActions.Read,
|
||||
ProjectPermissionCertificateProfileActions.Edit,
|
||||
ProjectPermissionCertificateProfileActions.Create,
|
||||
ProjectPermissionCertificateProfileActions.Delete
|
||||
],
|
||||
ProjectPermissionSub.CertificateProfiles
|
||||
);
|
||||
|
||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiAlerts);
|
||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiCollections);
|
||||
|
||||
@@ -110,6 +110,14 @@ export enum ProjectPermissionPkiSubscriberActions {
|
||||
ListCerts = "list-certs"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionCertificateProfileActions {
|
||||
Read = "read",
|
||||
Create = "create",
|
||||
Edit = "edit",
|
||||
Delete = "delete",
|
||||
IssueCert = "issue-cert"
|
||||
}
|
||||
|
||||
export enum ProjectPermissionSecretSyncActions {
|
||||
Read = "read",
|
||||
Create = "create",
|
||||
@@ -245,7 +253,8 @@ export enum ProjectPermissionSub {
|
||||
PamFolders = "pam-folders",
|
||||
PamResources = "pam-resources",
|
||||
PamAccounts = "pam-accounts",
|
||||
PamSessions = "pam-sessions"
|
||||
PamSessions = "pam-sessions",
|
||||
CertificateProfiles = "certificate-profiles"
|
||||
}
|
||||
|
||||
export type SecretSubjectFields = {
|
||||
@@ -434,7 +443,8 @@ export type ProjectPermissionSet =
|
||||
ProjectPermissionPamAccountActions,
|
||||
ProjectPermissionSub.PamAccounts | (ForcedSubject<ProjectPermissionSub.PamAccounts> & PamAccountSubjectFields)
|
||||
]
|
||||
| [ProjectPermissionPamSessionActions, ProjectPermissionSub.PamSessions];
|
||||
| [ProjectPermissionPamSessionActions, ProjectPermissionSub.PamSessions]
|
||||
| [ProjectPermissionCertificateProfileActions, ProjectPermissionSub.CertificateProfiles];
|
||||
|
||||
const SECRET_PATH_MISSING_SLASH_ERR_MSG = "Invalid Secret Path; it must start with a '/'";
|
||||
const SECRET_PATH_PERMISSION_OPERATOR_SCHEMA = z.union([
|
||||
|
||||
Reference in New Issue
Block a user