diff --git a/backend/src/ee/routes/v1/ssh-router.ts b/backend/src/ee/routes/v1/ssh-router.ts index 36caa8ff9..8e98d77b7 100644 --- a/backend/src/ee/routes/v1/ssh-router.ts +++ b/backend/src/ee/routes/v1/ssh-router.ts @@ -20,8 +20,10 @@ export const registerSshRouter = async (server: FastifyZodProvider) => { schema: { description: "Sign SSH public key", body: z.object({ - projectId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.projectId), - templateName: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.templateName), + certificateTemplateId: z + .string() + .trim() + .describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.certificateTemplateId), publicKey: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.SIGN_SSH_KEY.publicKey), certType: z .nativeEnum(SshCertType) @@ -87,8 +89,10 @@ export const registerSshRouter = async (server: FastifyZodProvider) => { schema: { description: "Issue SSH credentials (certificate + key)", body: z.object({ - projectId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.projectId), - templateName: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.templateName), + certificateTemplateId: z + .string() + .trim() + .describe(SSH_CERTIFICATE_AUTHORITIES.ISSUE_SSH_CREDENTIALS.certificateTemplateId), keyAlgorithm: z .nativeEnum(CertKeyAlgorithm) .default(CertKeyAlgorithm.RSA_2048) diff --git a/backend/src/ee/services/ssh/ssh-certificate-authority-fns.ts b/backend/src/ee/services/ssh/ssh-certificate-authority-fns.ts index 172362208..f59a5d5bf 100644 --- a/backend/src/ee/services/ssh/ssh-certificate-authority-fns.ts +++ b/backend/src/ee/services/ssh/ssh-certificate-authority-fns.ts @@ -28,9 +28,6 @@ export const createSshCertSerialNumber = () => { /** * Return a pair of SSH CA keys based on the specified key algorithm [keyAlgorithm]. * We use this function because the key format generated by `ssh-keygen` is unique. - * @param keyAlgorithm - The key algorithm to use for generating the SSH key pair - * @param comment - The comment to use for the SSH key pair - * @returns The public and private keys for the SSH key pair */ export const createSshKeyPair = async (keyAlgorithm: CertKeyAlgorithm) => { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "ssh-key-")); @@ -82,7 +79,6 @@ export const createSshKeyPair = async (keyAlgorithm: CertKeyAlgorithm) => { /** * Return the SSH public key for the given SSH private key. - * @param privateKey - The SSH private key to get the public key for */ export const getSshPublicKey = async (privateKey: string) => { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "ssh-key-")); @@ -101,8 +97,6 @@ export const getSshPublicKey = async (privateKey: string) => { /** * Validate the requested SSH certificate type based on the SSH certificate template configuration. - * @param template - The SSH certificate template configuration - * @param certType - The SSH certificate type */ export const validateSshCertificateType = (template: TSshCertificateTemplates, certType: SshCertType) => { if (!template.allowUserCertificates && certType === SshCertType.USER) { @@ -116,10 +110,6 @@ export const validateSshCertificateType = (template: TSshCertificateTemplates, c /** * Validate the requested SSH certificate principals based on the SSH certificate template configuration. - * @param certType - The SSH certificate type - * @param template - The SSH certificate template configuration - * @param principals - The requested SSH certificate principals - * @returns The validated SSH certificate principals */ export const validateSshCertificatePrincipals = ( certType: SshCertType, @@ -128,8 +118,6 @@ export const validateSshCertificatePrincipals = ( ) => { /** * Validate and sanitize a principal string - * @param principal - the principal to validate and sanitize - * @returns the sanitized principal */ const validatePrincipal = (principal: string) => { const sanitized = principal.trim(); @@ -257,9 +245,6 @@ export const validateSshCertificatePrincipals = ( /** * Validate the requested SSH certificate TTL based on the SSH certificate template configuration. - * @param template - The SSH certificate template configuration - * @param ttl - The TTL to validate - * @returns The TTL (in seconds) to use for issuing the SSH certificate */ export const validateSshCertificateTtl = (template: TSshCertificateTemplates, ttl?: string) => { if (!ttl) { @@ -279,7 +264,6 @@ export const validateSshCertificateTtl = (template: TSshCertificateTemplates, tt /** * Validate the requested SSH certificate key ID to ensure * that it only contains alphanumeric characters with no spaces. - * @param keyId - The key ID to validate */ export const validateSshCertificateKeyId = (keyId: string) => { const regex = /^[A-Za-z0-9-]+$/; @@ -299,7 +283,6 @@ export const validateSshCertificateKeyId = (keyId: string) => { /** * Validate the format of the SSH public key - * @param publicKey - the public key to validate */ const validateSshPublicKey = async (publicKey: string) => { const validPrefixes = ["ssh-rsa", "ssh-ed25519", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"]; diff --git a/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts b/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts index c18e3551e..0b408c9dd 100644 --- a/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts +++ b/backend/src/ee/services/ssh/ssh-certificate-authority-service.ts @@ -1,4 +1,5 @@ import { ForbiddenError } from "@casl/ability"; + import { ProjectType } from "@app/db/schemas"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; @@ -10,6 +11,7 @@ import { TSshCertificateTemplateDALFactory } from "@app/ee/services/ssh-certific import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { KmsDataKey } from "@app/services/kms/kms-types"; + import { SshCertTemplateStatus } from "../ssh-certificate-template/ssh-certificate-template-types"; import { createSshCert, createSshKeyPair, getSshPublicKey } from "./ssh-certificate-authority-fns"; import { @@ -30,7 +32,7 @@ type TSshCertificateAuthorityServiceFactoryDep = { "transaction" | "create" | "findById" | "updateById" | "deleteById" | "findOne" >; sshCertificateAuthoritySecretDAL: Pick; - sshCertificateTemplateDAL: Pick; + sshCertificateTemplateDAL: Pick; sshCertificateDAL: Pick; sshCertificateBodyDAL: Pick; kmsService: Pick< @@ -42,8 +44,6 @@ type TSshCertificateAuthorityServiceFactoryDep = { export type TSshCertificateAuthorityServiceFactory = ReturnType; -// TODO: secretManagerEncryptor -> sshEncryptor (cc akhil) - export const sshCertificateAuthorityServiceFactory = ({ sshCertificateAuthorityDAL, sshCertificateAuthoritySecretDAL, @@ -92,7 +92,6 @@ export const sshCertificateAuthorityServiceFactory = ({ const { publicKey, privateKey } = await createSshKeyPair(keyAlgorithm); - // TODO: update to sshEncryptor const { encryptor: secretManagerEncryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId @@ -135,7 +134,6 @@ export const sshCertificateAuthorityServiceFactory = ({ const sshCaSecret = await sshCertificateAuthoritySecretDAL.findOne({ sshCaId: ca.id }); - // TODO: update to sshDecryptor const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: ca.projectId @@ -159,7 +157,6 @@ export const sshCertificateAuthorityServiceFactory = ({ const sshCaSecret = await sshCertificateAuthoritySecretDAL.findOne({ sshCaId: ca.id }); - // TODO: update to sshDecryptor const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: ca.projectId @@ -208,7 +205,6 @@ export const sshCertificateAuthorityServiceFactory = ({ const sshCaSecret = await sshCertificateAuthoritySecretDAL.findOne({ sshCaId: ca.id }); - // TODO: update to sshDecryptor const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: ca.projectId @@ -254,8 +250,7 @@ export const sshCertificateAuthorityServiceFactory = ({ * SSH public key is signed using CA behind SSH certificate with name [templateName]. */ const issueSshCreds = async ({ - projectId, - templateName, + certificateTemplateId, keyAlgorithm, certType, principals, @@ -266,7 +261,7 @@ export const sshCertificateAuthorityServiceFactory = ({ actorAuthMethod, actorOrgId }: TIssueSshCredsDTO) => { - const sshCertificateTemplate = await sshCertificateTemplateDAL.getByName(templateName, projectId); + const sshCertificateTemplate = await sshCertificateTemplateDAL.getById(certificateTemplateId); if (!sshCertificateTemplate) { throw new NotFoundError({ message: "No SSH certificate template found with specified name" @@ -306,10 +301,9 @@ export const sshCertificateAuthorityServiceFactory = ({ const sshCaSecret = await sshCertificateAuthoritySecretDAL.findOne({ sshCaId: sshCertificateTemplate.sshCaId }); - // TODO: update to sshDecryptor const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, - projectId + projectId: sshCertificateTemplate.projectId }); const decryptedCaPrivateKey = secretManagerDecryptor({ @@ -329,7 +323,6 @@ export const sshCertificateAuthorityServiceFactory = ({ certType }); - // TODO: update to sshEncryptor const { encryptor: secretManagerEncryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: sshCertificateTemplate.projectId @@ -379,8 +372,7 @@ export const sshCertificateAuthorityServiceFactory = ({ * using CA behind SSH certificate template with name [templateName] */ const signSshKey = async ({ - projectId, - templateName, + certificateTemplateId, publicKey, certType, principals, @@ -391,7 +383,7 @@ export const sshCertificateAuthorityServiceFactory = ({ actorAuthMethod, actorOrgId }: TSignSshKeyDTO) => { - const sshCertificateTemplate = await sshCertificateTemplateDAL.getByName(templateName, projectId); + const sshCertificateTemplate = await sshCertificateTemplateDAL.getById(certificateTemplateId); if (!sshCertificateTemplate) { throw new NotFoundError({ message: "No SSH certificate template found with specified name" @@ -431,10 +423,9 @@ export const sshCertificateAuthorityServiceFactory = ({ const sshCaSecret = await sshCertificateAuthoritySecretDAL.findOne({ sshCaId: sshCertificateTemplate.sshCaId }); - // TODO: update to sshDecryptor const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, - projectId + projectId: sshCertificateTemplate.projectId }); const decryptedCaPrivateKey = secretManagerDecryptor({ @@ -451,7 +442,6 @@ export const sshCertificateAuthorityServiceFactory = ({ certType }); - // TODO: update to sshEncryptor const { encryptor: secretManagerEncryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId: sshCertificateTemplate.projectId diff --git a/backend/src/ee/services/ssh/ssh-certificate-authority-types.ts b/backend/src/ee/services/ssh/ssh-certificate-authority-types.ts index fa8d543b5..3f202ebf0 100644 --- a/backend/src/ee/services/ssh/ssh-certificate-authority-types.ts +++ b/backend/src/ee/services/ssh/ssh-certificate-authority-types.ts @@ -36,22 +36,22 @@ export type TDeleteSshCaDTO = { } & Omit; export type TIssueSshCredsDTO = { - templateName: string; + certificateTemplateId: string; keyAlgorithm: CertKeyAlgorithm; certType: SshCertType; principals: string[]; ttl?: string; keyId?: string; -} & TProjectPermission; +} & Omit; export type TSignSshKeyDTO = { - templateName: string; + certificateTemplateId: string; publicKey: string; certType: SshCertType; principals: string[]; ttl?: string; keyId?: string; -} & TProjectPermission; +} & Omit; export type TGetSshCaCertificateTemplatesDTO = { caId: string; diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 791877173..473c20924 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -1221,8 +1221,7 @@ export const SSH_CERTIFICATE_AUTHORITIES = { sshCaId: "The ID of the SSH CA to get the certificate templates for." }, SIGN_SSH_KEY: { - projectId: "The ID of the project to sign the SSH public key for.", - templateName: "The name of the SSH certificate template to sign the SSH public key with.", + certificateTemplateId: "The ID of the SSH certificate template to sign the SSH public key with.", publicKey: "The SSH public key to sign.", certType: "The type of certificate to issue. This can be one of user or host.", principals: "The list of principals (usernames, hostnames) to include in the certificate.", @@ -1232,8 +1231,7 @@ export const SSH_CERTIFICATE_AUTHORITIES = { signedKey: "The SSH certificate or signed SSH public key." }, ISSUE_SSH_CREDENTIALS: { - projectId: "The ID of the project to issue the SSH credentials for.", - templateName: "The name of the SSH certificate template to issue the SSH credentials with.", + certificateTemplateId: "The ID of the SSH certificate template to issue the SSH credentials with.", keyAlgorithm: "The type of public key algorithm and size, in bits, of the key pair for the SSH CA.", certType: "The type of certificate to issue. This can be one of user or host.", principals: "The list of principals (usernames, hostnames) to include in the certificate.", diff --git a/frontend/src/hooks/api/ssh-ca/types.ts b/frontend/src/hooks/api/ssh-ca/types.ts index 06089fffc..6e5f02c4d 100644 --- a/frontend/src/hooks/api/ssh-ca/types.ts +++ b/frontend/src/hooks/api/ssh-ca/types.ts @@ -42,7 +42,7 @@ export type TDeleteSshCaDTO = { export type TSignSshKeyDTO = { projectId: string; - templateName: string; + certificateTemplateId: string; publicKey?: string; certType: SshCertType; principals: string[]; @@ -57,7 +57,7 @@ export type TSignSshKeyResponse = { export type TIssueSshCredsDTO = { projectId: string; - templateName: string; + certificateTemplateId: string; keyAlgorithm: CertKeyAlgorithm; certType: SshCertType; principals: string[]; diff --git a/frontend/src/views/Project/SshCaPage/components/SshCertificateModal.tsx b/frontend/src/views/Project/SshCaPage/components/SshCertificateModal.tsx index 625fb9173..878a6a181 100644 --- a/frontend/src/views/Project/SshCaPage/components/SshCertificateModal.tsx +++ b/frontend/src/views/Project/SshCaPage/components/SshCertificateModal.tsx @@ -126,8 +126,8 @@ export const SshCertificateModal = ({ popUp, handlePopUpToggle }: Props) => { switch (operation) { case SshCertificateOperation.SIGN_SSH_KEY: { const { serialNumber, signedKey } = await signSshKey({ - projectId: currentWorkspace?.id || "", - templateName: templateData.name, + projectId, + certificateTemplateId: templateData.id, publicKey: existingPublicKey, certType, principals: principals.split(",").map((user) => user.trim()), @@ -144,7 +144,7 @@ export const SshCertificateModal = ({ popUp, handlePopUpToggle }: Props) => { case SshCertificateOperation.ISSUE_SSH_CREDS: { const { serialNumber, publicKey, privateKey, signedKey } = await issueSshCreds({ projectId, - templateName: templateData.name, + certificateTemplateId: templateData.id, keyAlgorithm, certType, principals: principals.split(",").map((user) => user.trim()),