mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 08:28:59 +00:00
misc: migrated to use multiple app connections
This commit is contained in:
Vendored
+7
-7
@@ -83,9 +83,6 @@ import {
|
||||
TExternalKms,
|
||||
TExternalKmsInsert,
|
||||
TExternalKmsUpdate,
|
||||
TExternalMigrationConfigs,
|
||||
TExternalMigrationConfigsInsert,
|
||||
TExternalMigrationConfigsUpdate,
|
||||
TFolderCheckpointResources,
|
||||
TFolderCheckpointResourcesInsert,
|
||||
TFolderCheckpointResourcesUpdate,
|
||||
@@ -521,6 +518,9 @@ import {
|
||||
TUsers,
|
||||
TUsersInsert,
|
||||
TUsersUpdate,
|
||||
TVaultExternalMigrationConfigs,
|
||||
TVaultExternalMigrationConfigsInsert,
|
||||
TVaultExternalMigrationConfigsUpdate,
|
||||
TWebhooks,
|
||||
TWebhooksInsert,
|
||||
TWebhooksUpdate,
|
||||
@@ -1348,10 +1348,10 @@ declare module "knex/types/tables" {
|
||||
TAdditionalPrivilegesInsert,
|
||||
TAdditionalPrivilegesUpdate
|
||||
>;
|
||||
[TableName.ExternalMigrationConfig]: KnexOriginal.CompositeTableType<
|
||||
TExternalMigrationConfigs,
|
||||
TExternalMigrationConfigsInsert,
|
||||
TExternalMigrationConfigsUpdate
|
||||
[TableName.VaultExternalMigrationConfig]: KnexOriginal.CompositeTableType<
|
||||
TVaultExternalMigrationConfigs,
|
||||
TVaultExternalMigrationConfigsInsert,
|
||||
TVaultExternalMigrationConfigsUpdate
|
||||
>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,25 +4,26 @@ import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.ExternalMigrationConfig))) {
|
||||
await knex.schema.createTable(TableName.ExternalMigrationConfig, (t) => {
|
||||
if (!(await knex.schema.hasTable(TableName.VaultExternalMigrationConfig))) {
|
||||
await knex.schema.createTable(TableName.VaultExternalMigrationConfig, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.string("platform").notNullable();
|
||||
|
||||
t.string("namespace").notNullable();
|
||||
|
||||
t.uuid("connectionId");
|
||||
t.foreign("connectionId").references("id").inTable(TableName.AppConnection);
|
||||
|
||||
t.timestamps(true, true, true);
|
||||
t.unique(["orgId", "platform"]);
|
||||
t.unique(["orgId", "namespace"]);
|
||||
});
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.ExternalMigrationConfig);
|
||||
await createOnUpdateTrigger(knex, TableName.VaultExternalMigrationConfig);
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ExternalMigrationConfig);
|
||||
await dropOnUpdateTrigger(knex, TableName.ExternalMigrationConfig);
|
||||
await knex.schema.dropTableIfExists(TableName.VaultExternalMigrationConfig);
|
||||
await dropOnUpdateTrigger(knex, TableName.VaultExternalMigrationConfig);
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const ExternalMigrationConfigsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
orgId: z.string().uuid(),
|
||||
platform: z.string(),
|
||||
connectionId: z.string().uuid().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
export type TExternalMigrationConfigs = z.infer<typeof ExternalMigrationConfigsSchema>;
|
||||
export type TExternalMigrationConfigsInsert = Omit<z.input<typeof ExternalMigrationConfigsSchema>, TImmutableDBKeys>;
|
||||
export type TExternalMigrationConfigsUpdate = Partial<
|
||||
Omit<z.input<typeof ExternalMigrationConfigsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
@@ -25,7 +25,6 @@ export * from "./dynamic-secrets";
|
||||
export * from "./external-certificate-authorities";
|
||||
export * from "./external-group-org-role-mappings";
|
||||
export * from "./external-kms";
|
||||
export * from "./external-migration-configs";
|
||||
export * from "./folder-checkpoint-resources";
|
||||
export * from "./folder-checkpoints";
|
||||
export * from "./folder-commit-changes";
|
||||
@@ -177,5 +176,6 @@ export * from "./user-aliases";
|
||||
export * from "./user-encryption-keys";
|
||||
export * from "./user-group-membership";
|
||||
export * from "./users";
|
||||
export * from "./vault-external-migration-configs";
|
||||
export * from "./webhooks";
|
||||
export * from "./workflow-integrations";
|
||||
|
||||
@@ -205,7 +205,7 @@ export enum TableName {
|
||||
PamAccount = "pam_accounts",
|
||||
PamSession = "pam_sessions",
|
||||
|
||||
ExternalMigrationConfig = "external_migration_configs"
|
||||
VaultExternalMigrationConfig = "vault_external_migration_configs"
|
||||
}
|
||||
|
||||
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt" | "commitId";
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const VaultExternalMigrationConfigsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
orgId: z.string().uuid(),
|
||||
namespace: z.string(),
|
||||
connectionId: z.string().uuid().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
export type TVaultExternalMigrationConfigs = z.infer<typeof VaultExternalMigrationConfigsSchema>;
|
||||
export type TVaultExternalMigrationConfigsInsert = Omit<
|
||||
z.input<typeof VaultExternalMigrationConfigsSchema>,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TVaultExternalMigrationConfigsUpdate = Partial<
|
||||
Omit<z.input<typeof VaultExternalMigrationConfigsSchema>, TImmutableDBKeys>
|
||||
>;
|
||||
@@ -174,9 +174,9 @@ import { cmekServiceFactory } from "@app/services/cmek/cmek-service";
|
||||
import { convertorServiceFactory } from "@app/services/convertor/convertor-service";
|
||||
import { externalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal";
|
||||
import { externalGroupOrgRoleMappingServiceFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-service";
|
||||
import { externalMigrationConfigDALFactory } from "@app/services/external-migration/external-migration-config-dal";
|
||||
import { externalMigrationQueueFactory } from "@app/services/external-migration/external-migration-queue";
|
||||
import { externalMigrationServiceFactory } from "@app/services/external-migration/external-migration-service";
|
||||
import { vaultExternalMigrationConfigDALFactory } from "@app/services/external-migration/vault-external-migration-config-dal";
|
||||
import { folderCheckpointDALFactory } from "@app/services/folder-checkpoint/folder-checkpoint-dal";
|
||||
import { folderCheckpointResourcesDALFactory } from "@app/services/folder-checkpoint-resources/folder-checkpoint-resources-dal";
|
||||
import { folderCommitDALFactory } from "@app/services/folder-commit/folder-commit-dal";
|
||||
@@ -534,7 +534,7 @@ export const registerRoutes = async (
|
||||
const membershipRoleDAL = membershipRoleDALFactory(db);
|
||||
const roleDAL = roleDALFactory(db);
|
||||
|
||||
const externalMigrationConfigDAL = externalMigrationConfigDALFactory(db);
|
||||
const vaultExternalMigrationConfigDAL = vaultExternalMigrationConfigDALFactory(db);
|
||||
|
||||
const eventBusService = eventBusFactory(server.redis);
|
||||
const sseService = sseServiceFactory(eventBusService, server.redis);
|
||||
@@ -2199,7 +2199,7 @@ export const registerRoutes = async (
|
||||
gatewayService,
|
||||
kmsService,
|
||||
appConnectionService,
|
||||
externalMigrationConfigDAL,
|
||||
vaultExternalMigrationConfigDAL,
|
||||
secretService,
|
||||
auditLogService
|
||||
});
|
||||
|
||||
@@ -117,33 +117,64 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/config",
|
||||
url: "/vault/configs",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
platform: z.nativeEnum(ExternalMigrationProviders)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
config: z
|
||||
configs: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
orgId: z.string(),
|
||||
platform: z.string(),
|
||||
namespace: z.string(),
|
||||
connectionId: z.string().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
})
|
||||
.nullable()
|
||||
.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const config = await server.services.migration.getExternalMigrationConfig({
|
||||
platform: req.query.platform,
|
||||
const configs = await server.services.migration.getVaultExternalMigrationConfigs({
|
||||
actor: req.permission
|
||||
});
|
||||
|
||||
return { configs };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/vault/configs",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
connectionId: z.string(),
|
||||
namespace: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
config: z.object({
|
||||
id: z.string(),
|
||||
orgId: z.string(),
|
||||
namespace: z.string(),
|
||||
connectionId: z.string().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const config = await server.services.migration.createVaultExternalMigration({
|
||||
...req.body,
|
||||
actor: req.permission
|
||||
});
|
||||
|
||||
@@ -153,21 +184,24 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
||||
|
||||
server.route({
|
||||
method: "PUT",
|
||||
url: "/config",
|
||||
url: "/vault/configs/:id",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
id: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
connectionId: z.string().nullable(),
|
||||
platform: z.nativeEnum(ExternalMigrationProviders)
|
||||
connectionId: z.string(),
|
||||
namespace: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
config: z.object({
|
||||
id: z.string(),
|
||||
orgId: z.string(),
|
||||
platform: z.string(),
|
||||
namespace: z.string(),
|
||||
connectionId: z.string().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
@@ -175,12 +209,48 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const config = await server.services.migration.configureExternalMigration({
|
||||
const config = await server.services.migration.updateVaultExternalMigration({
|
||||
id: req.params.id,
|
||||
...req.body,
|
||||
actor: req.permission
|
||||
});
|
||||
|
||||
return { config };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "DELETE",
|
||||
url: "/vault/configs/:id",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
params: z.object({
|
||||
id: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
config: z.object({
|
||||
id: z.string(),
|
||||
orgId: z.string(),
|
||||
namespace: z.string(),
|
||||
connectionId: z.string().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const config = await server.services.migration.deleteVaultExternalMigration({
|
||||
id: req.params.id,
|
||||
actor: req.permission
|
||||
});
|
||||
|
||||
return { config };
|
||||
}
|
||||
});
|
||||
@@ -243,7 +313,7 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
||||
},
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
namespace: z.string().optional()
|
||||
namespace: z.string()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
getHCVaultSecretsForPath,
|
||||
HCVaultAuthType,
|
||||
listHCVaultMounts,
|
||||
listHCVaultNamespaces,
|
||||
listHCVaultPolicies,
|
||||
listHCVaultSecretPaths,
|
||||
THCVaultConnection
|
||||
@@ -29,7 +28,6 @@ import { TKmsServiceFactory } from "../kms/kms-service";
|
||||
import { TSecretServiceFactory } from "../secret/secret-service";
|
||||
import { SecretProtectionType } from "../secret/secret-types";
|
||||
import { TUserDALFactory } from "../user/user-dal";
|
||||
import { TExternalMigrationConfigDALFactory } from "./external-migration-config-dal";
|
||||
import {
|
||||
decryptEnvKeyDataFn,
|
||||
importVaultDataFn,
|
||||
@@ -40,12 +38,15 @@ import { TExternalMigrationQueueFactory } from "./external-migration-queue";
|
||||
import {
|
||||
ExternalMigrationProviders,
|
||||
ExternalPlatforms,
|
||||
TConfigureExternalMigrationDTO,
|
||||
TCreateVaultExternalMigrationDTO,
|
||||
TDeleteVaultExternalMigrationDTO,
|
||||
THasCustomVaultMigrationDTO,
|
||||
TImportEnvKeyDataDTO,
|
||||
TImportVaultDataDTO,
|
||||
TUpdateVaultExternalMigrationDTO,
|
||||
VaultImportStatus
|
||||
} from "./external-migration-types";
|
||||
import { TVaultExternalMigrationConfigDALFactory } from "./vault-external-migration-config-dal";
|
||||
|
||||
type TExternalMigrationServiceFactoryDep = {
|
||||
permissionService: TPermissionServiceFactory;
|
||||
@@ -53,7 +54,10 @@ type TExternalMigrationServiceFactoryDep = {
|
||||
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
|
||||
externalMigrationQueue: TExternalMigrationQueueFactory;
|
||||
appConnectionService: Pick<TAppConnectionServiceFactory, "connectAppConnectionById">;
|
||||
externalMigrationConfigDAL: Pick<TExternalMigrationConfigDALFactory, "create" | "upsert" | "findOne" | "transaction">;
|
||||
vaultExternalMigrationConfigDAL: Pick<
|
||||
TVaultExternalMigrationConfigDALFactory,
|
||||
"create" | "findOne" | "transaction" | "find" | "updateById" | "deleteById" | "findById"
|
||||
>;
|
||||
userDAL: Pick<TUserDALFactory, "findById">;
|
||||
gatewayService: Pick<TGatewayServiceFactory, "fnGetGatewayClientTlsByGatewayId">;
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
@@ -69,7 +73,7 @@ export const externalMigrationServiceFactory = ({
|
||||
secretService,
|
||||
auditLogService,
|
||||
appConnectionService,
|
||||
externalMigrationConfigDAL,
|
||||
vaultExternalMigrationConfigDAL,
|
||||
kmsService
|
||||
}: TExternalMigrationServiceFactoryDep) => {
|
||||
const importEnvKeyData = async ({
|
||||
@@ -208,7 +212,35 @@ export const externalMigrationServiceFactory = ({
|
||||
return actorOrgId in vaultMigrationTransformMappings;
|
||||
};
|
||||
|
||||
const configureExternalMigration = async ({ platform, connectionId, actor }: TConfigureExternalMigrationDTO) => {
|
||||
const validateVaultExternalMigrationConnection = async ({
|
||||
connection,
|
||||
namespace
|
||||
}: {
|
||||
connection: THCVaultConnection;
|
||||
namespace: string;
|
||||
}) => {
|
||||
// Allow root namespace access when no namespace is configured on the connection
|
||||
const isRootAccess = namespace === "root" || namespace === "/";
|
||||
const hasNoNamespace = connection.credentials.namespace === undefined;
|
||||
|
||||
if (hasNoNamespace && isRootAccess) {
|
||||
// Skip validation for root access with no configured namespace
|
||||
} else if (connection.credentials.namespace !== namespace) {
|
||||
throw new BadRequestError({ message: "Namespace value does not match the namespace of the connection" });
|
||||
}
|
||||
|
||||
try {
|
||||
await listHCVaultPolicies(namespace, connection, gatewayService);
|
||||
await listHCVaultSecretPaths(namespace, connection, gatewayService);
|
||||
await listHCVaultMounts(connection, gatewayService);
|
||||
} catch (error) {
|
||||
throw new BadRequestError({
|
||||
message: `Failed to establish namespace confiugration. ${error instanceof Error ? error.message : "Unknown error"}`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const createVaultExternalMigration = async ({ namespace, connectionId, actor }: TCreateVaultExternalMigrationDTO) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
@@ -218,19 +250,22 @@ export const externalMigrationServiceFactory = ({
|
||||
);
|
||||
|
||||
if (!hasRole(OrgMembershipRole.Admin)) {
|
||||
throw new ForbiddenRequestError({ message: "Only admins can configure external migration" });
|
||||
throw new ForbiddenRequestError({ message: "Only admins can configure vault external migration" });
|
||||
}
|
||||
|
||||
if (connectionId) {
|
||||
if (platform === ExternalMigrationProviders.Vault) {
|
||||
await appConnectionService.connectAppConnectionById(AppConnection.HCVault, connectionId, actor);
|
||||
} else {
|
||||
throw new BadRequestError({ message: "Invalid platform" });
|
||||
}
|
||||
}
|
||||
const connection = await appConnectionService.connectAppConnectionById<THCVaultConnection>(
|
||||
AppConnection.HCVault,
|
||||
connectionId,
|
||||
actor
|
||||
);
|
||||
|
||||
const config = await externalMigrationConfigDAL.upsert({
|
||||
platform,
|
||||
await validateVaultExternalMigrationConnection({
|
||||
connection,
|
||||
namespace
|
||||
});
|
||||
|
||||
const config = await vaultExternalMigrationConfigDAL.create({
|
||||
namespace,
|
||||
connectionId,
|
||||
orgId: actor.orgId
|
||||
});
|
||||
@@ -238,7 +273,12 @@ export const externalMigrationServiceFactory = ({
|
||||
return config;
|
||||
};
|
||||
|
||||
const getExternalMigrationConfig = async ({ platform, actor }: { platform: string; actor: OrgServiceActor }) => {
|
||||
const updateVaultExternalMigration = async ({
|
||||
id,
|
||||
namespace,
|
||||
connectionId,
|
||||
actor
|
||||
}: TUpdateVaultExternalMigrationDTO) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
@@ -248,19 +288,48 @@ export const externalMigrationServiceFactory = ({
|
||||
);
|
||||
|
||||
if (!hasRole(OrgMembershipRole.Admin)) {
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view external migration config" });
|
||||
throw new ForbiddenRequestError({ message: "Only admins can update vault external migration" });
|
||||
}
|
||||
|
||||
const config = await externalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform
|
||||
if (connectionId) {
|
||||
const connection = await appConnectionService.connectAppConnectionById<THCVaultConnection>(
|
||||
AppConnection.HCVault,
|
||||
connectionId,
|
||||
actor
|
||||
);
|
||||
|
||||
await validateVaultExternalMigrationConnection({
|
||||
connection,
|
||||
namespace
|
||||
});
|
||||
}
|
||||
|
||||
const config = await vaultExternalMigrationConfigDAL.updateById(id, {
|
||||
namespace,
|
||||
connectionId
|
||||
});
|
||||
|
||||
if (!config) {
|
||||
throw new NotFoundError({ message: "External migration config not found" });
|
||||
return config;
|
||||
};
|
||||
|
||||
const getVaultExternalMigrationConfigs = async ({ actor }: { actor: OrgServiceActor }) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
actor.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
if (!hasRole(OrgMembershipRole.Admin)) {
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault external migration configs" });
|
||||
}
|
||||
|
||||
return config;
|
||||
const configs = await vaultExternalMigrationConfigDAL.find({
|
||||
orgId: actor.orgId
|
||||
});
|
||||
|
||||
return configs;
|
||||
};
|
||||
|
||||
const getVaultNamespaces = async ({ actor }: { actor: OrgServiceActor }) => {
|
||||
@@ -276,32 +345,18 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault namespaces" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
// Get all configured namespaces for this org
|
||||
const vaultConfigs = await vaultExternalMigrationConfigDAL.find({
|
||||
orgId: actor.orgId
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new BadRequestError({ message: "Vault migration config not found" });
|
||||
}
|
||||
// Return the configured namespaces as an array of objects with id and name
|
||||
// where both id and name are the namespace path
|
||||
const namespaces = vaultConfigs.map((config) => ({
|
||||
id: config.namespace,
|
||||
name: config.namespace
|
||||
}));
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
orgId: vaultConfig.orgId,
|
||||
encryptedCredentials: vaultConfig.connection.encryptedCredentials,
|
||||
kmsService,
|
||||
projectId: null
|
||||
});
|
||||
|
||||
const connection = {
|
||||
...vaultConfig.connection,
|
||||
credentials
|
||||
} as THCVaultConnection;
|
||||
|
||||
const namespaces = await listHCVaultNamespaces(connection, gatewayService);
|
||||
return namespaces;
|
||||
};
|
||||
|
||||
@@ -318,17 +373,17 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault policies" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
const vaultConfig = await vaultExternalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
namespace
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
throw new NotFoundError({ message: "Vault migration config not found for this namespace" });
|
||||
}
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured for this namespace" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
@@ -347,7 +402,7 @@ export const externalMigrationServiceFactory = ({
|
||||
return policies;
|
||||
};
|
||||
|
||||
const getVaultMounts = async ({ actor, namespace }: { actor: OrgServiceActor; namespace?: string }) => {
|
||||
const getVaultMounts = async ({ actor, namespace }: { actor: OrgServiceActor; namespace: string }) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
@@ -360,17 +415,17 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault mounts" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
const vaultConfig = await vaultExternalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
namespace
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
throw new NotFoundError({ message: "Vault migration config not found for this namespace" });
|
||||
}
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured for this namespace" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
@@ -402,17 +457,17 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault secret paths" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
const vaultConfig = await vaultExternalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
namespace
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
throw new NotFoundError({ message: "Vault migration config not found for this namespace" });
|
||||
}
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured for this namespace" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
@@ -461,17 +516,17 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can import vault secrets" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
const vaultConfig = await vaultExternalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
namespace: vaultNamespace
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
throw new NotFoundError({ message: "Vault migration config not found for this namespace" });
|
||||
}
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured for this namespace" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
@@ -534,6 +589,34 @@ export const externalMigrationServiceFactory = ({
|
||||
}
|
||||
};
|
||||
|
||||
const deleteVaultExternalMigration = async ({ id, actor }: TDeleteVaultExternalMigrationDTO) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
actor.id,
|
||||
actor.orgId,
|
||||
actor.authMethod,
|
||||
actor.orgId
|
||||
);
|
||||
|
||||
if (!hasRole(OrgMembershipRole.Admin)) {
|
||||
throw new ForbiddenRequestError({ message: "Only admins can delete vault external migration configs" });
|
||||
}
|
||||
|
||||
const config = await vaultExternalMigrationConfigDAL.findById(id);
|
||||
|
||||
if (!config) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
}
|
||||
|
||||
if (config.orgId !== actor.orgId) {
|
||||
throw new ForbiddenRequestError({ message: "Config does not belong to this organization" });
|
||||
}
|
||||
|
||||
const deletedConfig = await vaultExternalMigrationConfigDAL.deleteById(id);
|
||||
|
||||
return deletedConfig;
|
||||
};
|
||||
|
||||
const getVaultKubernetesAuthRoles = async ({ actor, namespace }: { actor: OrgServiceActor; namespace: string }) => {
|
||||
const { hasRole } = await permissionService.getOrgPermission(
|
||||
actor.type,
|
||||
@@ -547,17 +630,17 @@ export const externalMigrationServiceFactory = ({
|
||||
throw new ForbiddenRequestError({ message: "Only admins can view vault Kubernetes auth roles" });
|
||||
}
|
||||
|
||||
const vaultConfig = await externalMigrationConfigDAL.findOne({
|
||||
const vaultConfig = await vaultExternalMigrationConfigDAL.findOne({
|
||||
orgId: actor.orgId,
|
||||
platform: ExternalMigrationProviders.Vault
|
||||
namespace
|
||||
});
|
||||
|
||||
if (!vaultConfig) {
|
||||
throw new NotFoundError({ message: "Vault migration config not found" });
|
||||
throw new NotFoundError({ message: "Vault migration config not found for this namespace" });
|
||||
}
|
||||
|
||||
if (!vaultConfig.connection) {
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured" });
|
||||
throw new BadRequestError({ message: "Vault migration connection is not configured for this namespace" });
|
||||
}
|
||||
|
||||
const credentials = await decryptAppConnectionCredentials({
|
||||
@@ -590,8 +673,10 @@ export const externalMigrationServiceFactory = ({
|
||||
importEnvKeyData,
|
||||
importVaultData,
|
||||
hasCustomVaultMigration,
|
||||
configureExternalMigration,
|
||||
getExternalMigrationConfig,
|
||||
createVaultExternalMigration,
|
||||
getVaultExternalMigrationConfigs,
|
||||
updateVaultExternalMigration,
|
||||
deleteVaultExternalMigration,
|
||||
getVaultNamespaces,
|
||||
getVaultPolicies,
|
||||
getVaultMounts,
|
||||
|
||||
@@ -127,8 +127,20 @@ export enum VaultImportStatus {
|
||||
ApprovalRequired = "approval_required"
|
||||
}
|
||||
|
||||
export type TConfigureExternalMigrationDTO = {
|
||||
platform: ExternalMigrationProviders;
|
||||
export type TCreateVaultExternalMigrationDTO = {
|
||||
namespace: string;
|
||||
connectionId: string;
|
||||
actor: OrgServiceActor;
|
||||
};
|
||||
|
||||
export type TUpdateVaultExternalMigrationDTO = {
|
||||
id: string;
|
||||
namespace: string;
|
||||
connectionId: string | null;
|
||||
actor: OrgServiceActor;
|
||||
};
|
||||
|
||||
export type TDeleteVaultExternalMigrationDTO = {
|
||||
id: string;
|
||||
actor: OrgServiceActor;
|
||||
};
|
||||
|
||||
+10
-23
@@ -1,39 +1,26 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName, TExternalMigrationConfigsInsert } from "@app/db/schemas";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { buildFindFilter, ormify, prependTableNameToFindFilter, selectAllTableCols } from "@app/lib/knex";
|
||||
|
||||
export type TExternalMigrationConfigDALFactory = ReturnType<typeof externalMigrationConfigDALFactory>;
|
||||
export type TVaultExternalMigrationConfigDALFactory = ReturnType<typeof vaultExternalMigrationConfigDALFactory>;
|
||||
|
||||
export const externalMigrationConfigDALFactory = (db: TDbClient) => {
|
||||
const orm = ormify(db, TableName.ExternalMigrationConfig);
|
||||
export const vaultExternalMigrationConfigDALFactory = (db: TDbClient) => {
|
||||
const orm = ormify(db, TableName.VaultExternalMigrationConfig);
|
||||
|
||||
const upsert = async (data: TExternalMigrationConfigsInsert, tx?: Knex) => {
|
||||
const findOne = async (filter: { orgId: string; namespace: string }, tx?: Knex) => {
|
||||
try {
|
||||
const [doc] = await (tx || db)(TableName.ExternalMigrationConfig)
|
||||
.insert(data)
|
||||
.onConflict(["orgId", "platform"])
|
||||
.merge()
|
||||
.returning("*");
|
||||
return doc;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "UpsertExternalMigrationConfig" });
|
||||
}
|
||||
};
|
||||
|
||||
const findOne = async (filter: { orgId: string; platform: string }, tx?: Knex) => {
|
||||
try {
|
||||
const result = await (tx || db?.replicaNode?.() || db)(TableName.ExternalMigrationConfig)
|
||||
const result = await (tx || db?.replicaNode?.() || db)(TableName.VaultExternalMigrationConfig)
|
||||
.leftJoin(
|
||||
TableName.AppConnection,
|
||||
`${TableName.AppConnection}.id`,
|
||||
`${TableName.ExternalMigrationConfig}.connectionId`
|
||||
`${TableName.VaultExternalMigrationConfig}.connectionId`
|
||||
)
|
||||
/* eslint-disable @typescript-eslint/no-misused-promises */
|
||||
.where(buildFindFilter(prependTableNameToFindFilter(TableName.ExternalMigrationConfig, filter)))
|
||||
.select(selectAllTableCols(TableName.ExternalMigrationConfig))
|
||||
.where(buildFindFilter(prependTableNameToFindFilter(TableName.VaultExternalMigrationConfig, filter)))
|
||||
.select(selectAllTableCols(TableName.VaultExternalMigrationConfig))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.AppConnection).as("appConnectionId"),
|
||||
db.ref("name").withSchema(TableName.AppConnection).as("appConnectionName"),
|
||||
@@ -76,5 +63,5 @@ export const externalMigrationConfigDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
return { ...orm, upsert, findOne };
|
||||
return { ...orm, findOne };
|
||||
};
|
||||
Reference in New Issue
Block a user