Add ssh project default cas

This commit is contained in:
Tuan Dang
2025-04-06 14:22:17 -07:00
parent 5671cd5cef
commit c2f2a038ad
141 changed files with 696 additions and 400 deletions
+49 -1
View File
@@ -1,12 +1,15 @@
import crypto from "crypto";
import { ProjectVersion, TProjects } from "@app/db/schemas";
import { createSshCaHelper } from "@app/ee/services/ssh/ssh-certificate-authority-fns";
import { SshCaKeySource } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
import { NotFoundError } from "@app/lib/errors";
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { AddUserToWsDTO } from "./project-types";
import { AddUserToWsDTO, TBootstrapSshProjectDTO } from "./project-types";
export const assignWorkspaceKeysToMembers = ({ members, decryptKey, userPrivateKey }: AddUserToWsDTO) => {
const plaintextProjectKey = decryptAsymmetric({
@@ -102,3 +105,48 @@ export const getProjectKmsCertificateKeyId = async ({
return keyId;
};
/**
* Bootstraps an SSH project.
* - Creates a user and host SSH CA
* - Creates a project SSH config with the user and host SSH CA as defaults
*/
export const bootstrapSshProject = async ({
projectId,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
kmsService,
projectSshConfigDAL,
tx
}: TBootstrapSshProjectDTO) => {
const userSshCa = await createSshCaHelper({
projectId,
friendlyName: "User CA",
keyAlgorithm: SshCertKeyAlgorithm.ED25519,
keySource: SshCaKeySource.INTERNAL,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
kmsService,
tx
});
const hostSshCa = await createSshCaHelper({
projectId,
friendlyName: "Host CA",
keyAlgorithm: SshCertKeyAlgorithm.ED25519,
keySource: SshCaKeySource.INTERNAL,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
kmsService,
tx
});
await projectSshConfigDAL.create(
{
projectId,
defaultHostSshCaId: hostSshCa.id,
defaultUserSshCaId: userSshCa.id
},
tx
);
};
@@ -20,6 +20,7 @@ import {
import { TProjectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-service";
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal";
import { TSshCertificateAuthoritySecretDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-secret-dal";
import { TSshCertificateDALFactory } from "@app/ee/services/ssh-certificate/ssh-certificate-dal";
import { TSshCertificateTemplateDALFactory } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-dal";
import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal";
@@ -60,8 +61,9 @@ import { TProjectSlackConfigDALFactory } from "../slack/project-slack-config-dal
import { TSlackIntegrationDALFactory } from "../slack/slack-integration-dal";
import { TUserDALFactory } from "../user/user-dal";
import { TProjectDALFactory } from "./project-dal";
import { assignWorkspaceKeysToMembers, createProjectKey } from "./project-fns";
import { assignWorkspaceKeysToMembers, bootstrapSshProject, createProjectKey } from "./project-fns";
import { TProjectQueueFactory } from "./project-queue";
import { TProjectSshConfigDALFactory } from "./project-ssh-config-dal";
import {
TCreateProjectDTO,
TDeleteProjectDTO,
@@ -95,8 +97,8 @@ export const DEFAULT_PROJECT_ENVS = [
];
type TProjectServiceFactoryDep = {
// TODO: Pick
projectDAL: TProjectDALFactory;
projectSshConfigDAL: Pick<TProjectSshConfigDALFactory, "create">;
projectQueue: TProjectQueueFactory;
userDAL: TUserDALFactory;
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
@@ -118,7 +120,8 @@ type TProjectServiceFactoryDep = {
certificateTemplateDAL: Pick<TCertificateTemplateDALFactory, "getCertTemplatesByProjectId">;
pkiAlertDAL: Pick<TPkiAlertDALFactory, "find">;
pkiCollectionDAL: Pick<TPkiCollectionDALFactory, "find">;
sshCertificateAuthorityDAL: Pick<TSshCertificateAuthorityDALFactory, "find">;
sshCertificateAuthorityDAL: Pick<TSshCertificateAuthorityDALFactory, "find" | "create" | "transaction">;
sshCertificateAuthoritySecretDAL: Pick<TSshCertificateAuthoritySecretDALFactory, "create">;
sshCertificateDAL: Pick<TSshCertificateDALFactory, "find" | "countSshCertificatesInProject">;
sshCertificateTemplateDAL: Pick<TSshCertificateTemplateDALFactory, "find">;
sshHostDAL: Pick<TSshHostDALFactory, "find" | "findSshHostsWithLoginMappings">;
@@ -139,6 +142,7 @@ type TProjectServiceFactoryDep = {
| "getKmsById"
| "getProjectSecretManagerKmsKeyId"
| "deleteInternalKms"
| "createCipherPairWithDataKey"
>;
projectTemplateService: TProjectTemplateServiceFactory;
};
@@ -147,6 +151,7 @@ export type TProjectServiceFactory = ReturnType<typeof projectServiceFactory>;
export const projectServiceFactory = ({
projectDAL,
projectSshConfigDAL,
secretDAL,
secretV2BridgeDAL,
projectQueue,
@@ -172,6 +177,7 @@ export const projectServiceFactory = ({
pkiCollectionDAL,
pkiAlertDAL,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
sshCertificateDAL,
sshCertificateTemplateDAL,
sshHostDAL,
@@ -261,6 +267,17 @@ export const projectServiceFactory = ({
tx
);
if (type === ProjectType.SSH) {
await bootstrapSshProject({
projectId: project.id,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
kmsService,
projectSshConfigDAL,
tx
});
}
// set ghost user as admin of project
const projectMembership = await projectMembershipDAL.create(
{
@@ -0,0 +1,11 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TProjectSshConfigDALFactory = ReturnType<typeof projectSshConfigDALFactory>;
export const projectSshConfigDALFactory = (db: TDbClient) => {
const projectSshConfigOrm = ormify(db, TableName.ProjectSshConfig);
return projectSshConfigOrm;
};
@@ -1,7 +1,11 @@
import { Knex } from "knex";
import { ProjectType, TProjectKeys } from "@app/db/schemas";
import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal";
import { TSshCertificateAuthoritySecretDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-secret-dal";
import { TProjectPermission } from "@app/lib/types";
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { TProjectSshConfigDALFactory } from "@app/services/project/project-ssh-config-dal";
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
@@ -159,3 +163,12 @@ export type TUpdateProjectSlackConfig = {
isSecretRequestNotificationEnabled: boolean;
secretRequestChannels: string;
} & TProjectPermission;
export type TBootstrapSshProjectDTO = {
projectId: string;
sshCertificateAuthorityDAL: Pick<TSshCertificateAuthorityDALFactory, "transaction" | "create">;
sshCertificateAuthoritySecretDAL: Pick<TSshCertificateAuthoritySecretDALFactory, "create">;
projectSshConfigDAL: Pick<TProjectSshConfigDALFactory, "create">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
tx?: Knex;
};