mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 13:28:27 +00:00
193 lines
7.0 KiB
TypeScript
193 lines
7.0 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
|
import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types";
|
|
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
|
|
import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
|
import { ms } from "@app/lib/ms";
|
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
|
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 { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
|
|
|
export const registerSshCertRouter = async (server: FastifyZodProvider) => {
|
|
server.route({
|
|
method: "POST",
|
|
url: "/sign",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshCertificates],
|
|
description: "Sign SSH public key",
|
|
body: z.object({
|
|
certificateTemplateId: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.certificateTemplateId),
|
|
publicKey: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.publicKey),
|
|
certType: z
|
|
.nativeEnum(SshCertType)
|
|
.default(SshCertType.USER)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.certType),
|
|
principals: z
|
|
.array(z.string().transform((val) => val.trim()))
|
|
.nonempty("Principals array must not be empty")
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.principals),
|
|
ttl: z
|
|
.string()
|
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
|
.optional()
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.ttl),
|
|
keyId: z.string().trim().max(50).optional().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.keyId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
serialNumber: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.serialNumber),
|
|
signedKey: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.signedKey)
|
|
})
|
|
}
|
|
},
|
|
handler: async (req) => {
|
|
const { serialNumber, signedPublicKey, certificateTemplate, ttl, keyId } =
|
|
await server.services.sshCertificateAuthority.signSshKey({
|
|
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,
|
|
orgId: req.permission.orgId,
|
|
event: {
|
|
type: EventType.SIGN_SSH_KEY,
|
|
metadata: {
|
|
certificateTemplateId: certificateTemplate.id,
|
|
certType: req.body.certType,
|
|
principals: req.body.principals,
|
|
ttl: String(ttl),
|
|
keyId
|
|
}
|
|
}
|
|
});
|
|
|
|
await server.services.telemetry.sendPostHogEvents({
|
|
event: PostHogEventTypes.SignSshKey,
|
|
distinctId: getTelemetryDistinctId(req),
|
|
organizationId: req.permission.orgId,
|
|
properties: {
|
|
certificateTemplateId: req.body.certificateTemplateId,
|
|
principals: req.body.principals,
|
|
...req.auditLogInfo
|
|
}
|
|
});
|
|
|
|
return {
|
|
serialNumber,
|
|
signedKey: signedPublicKey
|
|
};
|
|
}
|
|
});
|
|
|
|
server.route({
|
|
method: "POST",
|
|
url: "/issue",
|
|
config: {
|
|
rateLimit: writeLimit
|
|
},
|
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
schema: {
|
|
hide: false,
|
|
tags: [ApiDocsTags.SshCertificates],
|
|
description: "Issue SSH credentials (certificate + key)",
|
|
body: z.object({
|
|
certificateTemplateId: z
|
|
.string()
|
|
.trim()
|
|
.min(1)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.certificateTemplateId),
|
|
keyAlgorithm: z
|
|
.nativeEnum(SshCertKeyAlgorithm)
|
|
.default(SshCertKeyAlgorithm.ED25519)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.keyAlgorithm),
|
|
certType: z
|
|
.nativeEnum(SshCertType)
|
|
.default(SshCertType.USER)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.certType),
|
|
principals: z
|
|
.array(z.string().transform((val) => val.trim()))
|
|
.nonempty("Principals array must not be empty")
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.principals),
|
|
ttl: z
|
|
.string()
|
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
|
.optional()
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.ttl),
|
|
keyId: z.string().trim().max(50).optional().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.keyId)
|
|
}),
|
|
response: {
|
|
200: z.object({
|
|
serialNumber: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.serialNumber),
|
|
signedKey: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.signedKey),
|
|
privateKey: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.privateKey),
|
|
publicKey: z.string().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.publicKey),
|
|
keyAlgorithm: z
|
|
.nativeEnum(SshCertKeyAlgorithm)
|
|
.describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.keyAlgorithm)
|
|
})
|
|
}
|
|
},
|
|
handler: async (req) => {
|
|
const { serialNumber, signedPublicKey, privateKey, publicKey, certificateTemplate, ttl, keyId } =
|
|
await server.services.sshCertificateAuthority.issueSshCreds({
|
|
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,
|
|
orgId: req.permission.orgId,
|
|
event: {
|
|
type: EventType.ISSUE_SSH_CREDS,
|
|
metadata: {
|
|
certificateTemplateId: certificateTemplate.id,
|
|
keyAlgorithm: req.body.keyAlgorithm,
|
|
certType: req.body.certType,
|
|
principals: req.body.principals,
|
|
ttl: String(ttl),
|
|
keyId
|
|
}
|
|
}
|
|
});
|
|
|
|
await server.services.telemetry.sendPostHogEvents({
|
|
event: PostHogEventTypes.IssueSshCreds,
|
|
distinctId: getTelemetryDistinctId(req),
|
|
organizationId: req.permission.orgId,
|
|
properties: {
|
|
certificateTemplateId: req.body.certificateTemplateId,
|
|
principals: req.body.principals,
|
|
...req.auditLogInfo
|
|
}
|
|
});
|
|
|
|
return {
|
|
serialNumber,
|
|
signedKey: signedPublicKey,
|
|
privateKey,
|
|
publicKey,
|
|
keyAlgorithm: req.body.keyAlgorithm
|
|
};
|
|
}
|
|
});
|
|
};
|