mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 04:27:38 +00:00
Implement acme secret reveal
This commit is contained in:
@@ -20,5 +20,3 @@ Feature: ACME Cert Profile
|
|||||||
Then the value response with jq .certificateProfile.caId should be equal to "{CERT_CA_ID}"
|
Then the value response with jq .certificateProfile.caId should be equal to "{CERT_CA_ID}"
|
||||||
Then the value response with jq .certificateProfile.certificateTemplateId should be equal to "{CERT_TEMPLATE_ID}"
|
Then the value response with jq .certificateProfile.certificateTemplateId should be equal to "{CERT_TEMPLATE_ID}"
|
||||||
Then the value response with jq .certificateProfile.enrollmentType should be equal to "acme"
|
Then the value response with jq .certificateProfile.enrollmentType should be equal to "acme"
|
||||||
Then the value response with jq .certificateProfile.eabKid should be present
|
|
||||||
Then the value response with jq .certificateProfile.eabSecret should be present
|
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ const buildAdminPermissionRules = () => {
|
|||||||
ProjectPermissionCertificateProfileActions.Edit,
|
ProjectPermissionCertificateProfileActions.Edit,
|
||||||
ProjectPermissionCertificateProfileActions.Create,
|
ProjectPermissionCertificateProfileActions.Create,
|
||||||
ProjectPermissionCertificateProfileActions.Delete,
|
ProjectPermissionCertificateProfileActions.Delete,
|
||||||
ProjectPermissionCertificateProfileActions.IssueCert
|
ProjectPermissionCertificateProfileActions.IssueCert,
|
||||||
|
ProjectPermissionCertificateProfileActions.RevealAcmeEabSecret,
|
||||||
|
ProjectPermissionCertificateProfileActions.RotateAcmeEabSecret
|
||||||
],
|
],
|
||||||
ProjectPermissionSub.CertificateProfiles
|
ProjectPermissionSub.CertificateProfiles
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ export enum ProjectPermissionCertificateProfileActions {
|
|||||||
Create = "create",
|
Create = "create",
|
||||||
Edit = "edit",
|
Edit = "edit",
|
||||||
Delete = "delete",
|
Delete = "delete",
|
||||||
IssueCert = "issue-cert"
|
IssueCert = "issue-cert",
|
||||||
|
RevealAcmeEabSecret = "reveal-acme-eab-secret",
|
||||||
|
RotateAcmeEabSecret = "rotate-acme-eab-secret"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProjectPermissionSecretSyncActions {
|
export enum ProjectPermissionSecretSyncActions {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { ApiDocsTags } from "@app/lib/api-docs";
|
|||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { CertStatus } from "@app/services/certificate/certificate-types";
|
|
||||||
import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types";
|
import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types";
|
||||||
|
import { CertStatus } from "@app/services/certificate/certificate-types";
|
||||||
|
|
||||||
export const registerCertificateProfilesRouter = async (server: FastifyZodProvider) => {
|
export const registerCertificateProfilesRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
@@ -491,4 +491,35 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
|||||||
return { certificates };
|
return { certificates };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/:id/acme/eab-secret/reveal",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateProfiles],
|
||||||
|
params: z.object({
|
||||||
|
id: z.string().uuid()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
eabSecret: z.string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const eabSecret = await server.services.certificateProfile.revealAcmeEabSecret({
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
profileId: req.params.id
|
||||||
|
});
|
||||||
|
return { eabSecret };
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -782,6 +782,59 @@ export const certificateProfileServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const revealAcmeEabSecret = async ({
|
||||||
|
actor,
|
||||||
|
actorId,
|
||||||
|
actorAuthMethod,
|
||||||
|
actorOrgId,
|
||||||
|
profileId
|
||||||
|
}: {
|
||||||
|
actor: ActorType;
|
||||||
|
actorId: string;
|
||||||
|
actorAuthMethod: ActorAuthMethod;
|
||||||
|
actorOrgId: string;
|
||||||
|
profileId: string;
|
||||||
|
}) => {
|
||||||
|
const profile = await certificateProfileDAL.findByIdWithConfigs(profileId);
|
||||||
|
if (!profile) {
|
||||||
|
throw new NotFoundError({ message: "Certificate profile not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor,
|
||||||
|
actorId,
|
||||||
|
projectId: profile.projectId,
|
||||||
|
actorAuthMethod,
|
||||||
|
actorOrgId,
|
||||||
|
actionProjectType: ActionProjectType.CertificateManager
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionCertificateProfileActions.RevealAcmeEabSecret,
|
||||||
|
ProjectPermissionSub.CertificateProfiles
|
||||||
|
);
|
||||||
|
|
||||||
|
if (profile.enrollmentType !== EnrollmentType.ACME) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Profile is not configured for ACME enrollment"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!profile.acmeConfig) {
|
||||||
|
throw new NotFoundError({ message: "ACME configuration not found for this profile" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
||||||
|
projectId: profile.projectId,
|
||||||
|
projectDAL,
|
||||||
|
kmsService
|
||||||
|
});
|
||||||
|
|
||||||
|
const kmsDecryptor = await kmsService.decryptWithKmsKey({
|
||||||
|
kmsId: certificateManagerKmsId
|
||||||
|
});
|
||||||
|
const eabSecret = await kmsDecryptor({ cipherTextBlob: profile.acmeConfig.encryptedEabSecret });
|
||||||
|
return eabSecret.toString();
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createProfile,
|
createProfile,
|
||||||
updateProfile,
|
updateProfile,
|
||||||
@@ -791,6 +844,7 @@ export const certificateProfileServiceFactory = ({
|
|||||||
listProfiles,
|
listProfiles,
|
||||||
deleteProfile,
|
deleteProfile,
|
||||||
getProfileCertificates,
|
getProfileCertificates,
|
||||||
getEstConfigurationByProfile
|
getEstConfigurationByProfile,
|
||||||
|
revealAcmeEabSecret
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export type TCertificateProfileWithConfigs = TCertificateProfile & {
|
|||||||
};
|
};
|
||||||
acmeConfig?: {
|
acmeConfig?: {
|
||||||
id: string;
|
id: string;
|
||||||
|
encryptedEabSecret: Buffer;
|
||||||
};
|
};
|
||||||
metrics?: TCertificateProfileMetrics;
|
metrics?: TCertificateProfileMetrics;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user