mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: revisions to import secret flow
This commit is contained in:
@@ -7,6 +7,7 @@ import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
import {
|
||||
ExternalMigrationProviders,
|
||||
VaultImportStatus,
|
||||
VaultMappingType
|
||||
} from "@app/services/external-migration/external-migration-types";
|
||||
|
||||
@@ -277,19 +278,19 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string()
|
||||
status: z.nativeEnum(VaultImportStatus)
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
await server.services.migration.importVaultSecrets({
|
||||
const result = await server.services.migration.importVaultSecrets({
|
||||
actor: req.permission,
|
||||
auditLogInfo: req.auditLogInfo,
|
||||
...req.body
|
||||
});
|
||||
|
||||
return { message: "Successfully imported vault secrets" };
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -43,7 +43,8 @@ import {
|
||||
TConfigureExternalMigrationDTO,
|
||||
THasCustomVaultMigrationDTO,
|
||||
TImportEnvKeyDataDTO,
|
||||
TImportVaultDataDTO
|
||||
TImportVaultDataDTO,
|
||||
VaultImportStatus
|
||||
} from "./external-migration-types";
|
||||
|
||||
type TExternalMigrationServiceFactoryDep = {
|
||||
@@ -487,41 +488,49 @@ export const externalMigrationServiceFactory = ({
|
||||
|
||||
const vaultSecrets = await getHCVaultSecretsForPath(vaultNamespace, vaultSecretPath, connection, gatewayService);
|
||||
|
||||
const secretOperation = await secretService.createManySecretsRaw({
|
||||
actorId: actor.id,
|
||||
actor: actor.type,
|
||||
actorAuthMethod: actor.authMethod,
|
||||
actorOrgId: actor.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
projectId,
|
||||
secrets: Object.entries(vaultSecrets).map(([secretKey, secretValue]) => ({
|
||||
secretKey,
|
||||
secretValue
|
||||
}))
|
||||
});
|
||||
|
||||
if (secretOperation.type === SecretProtectionType.Approval) {
|
||||
await auditLogService.createAuditLog({
|
||||
try {
|
||||
const secretOperation = await secretService.createManySecretsRaw({
|
||||
actorId: actor.id,
|
||||
actor: actor.type,
|
||||
actorAuthMethod: actor.authMethod,
|
||||
actorOrgId: actor.orgId,
|
||||
secretPath,
|
||||
environment,
|
||||
projectId,
|
||||
...auditLogInfo,
|
||||
event: {
|
||||
type: EventType.SECRET_APPROVAL_REQUEST,
|
||||
metadata: {
|
||||
committedBy: secretOperation.approval.committerUserId,
|
||||
secretApprovalRequestId: secretOperation.approval.id,
|
||||
secretApprovalRequestSlug: secretOperation.approval.slug,
|
||||
secretPath,
|
||||
environment,
|
||||
secrets: Object.entries(vaultSecrets).map(([secretKey]) => ({
|
||||
secretKey
|
||||
})),
|
||||
eventType: SecretApprovalEvent.CreateMany
|
||||
}
|
||||
}
|
||||
secrets: Object.entries(vaultSecrets).map(([secretKey, secretValue]) => ({
|
||||
secretKey,
|
||||
secretValue
|
||||
}))
|
||||
});
|
||||
|
||||
return { approval: secretOperation.approval };
|
||||
if (secretOperation.type === SecretProtectionType.Approval) {
|
||||
await auditLogService.createAuditLog({
|
||||
projectId,
|
||||
...auditLogInfo,
|
||||
event: {
|
||||
type: EventType.SECRET_APPROVAL_REQUEST,
|
||||
metadata: {
|
||||
committedBy: secretOperation.approval.committerUserId,
|
||||
secretApprovalRequestId: secretOperation.approval.id,
|
||||
secretApprovalRequestSlug: secretOperation.approval.slug,
|
||||
secretPath,
|
||||
environment,
|
||||
secrets: Object.entries(vaultSecrets).map(([secretKey]) => ({
|
||||
secretKey
|
||||
})),
|
||||
eventType: SecretApprovalEvent.CreateMany
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { status: VaultImportStatus.ApprovalRequired };
|
||||
}
|
||||
|
||||
return { status: VaultImportStatus.Imported };
|
||||
} catch (error) {
|
||||
throw new BadRequestError({
|
||||
message: `Failed to import Vault secrets. ${error instanceof Error ? error.message : "Unknown error"}`
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -122,6 +122,11 @@ export enum ExternalMigrationProviders {
|
||||
EnvKey = "env-key"
|
||||
}
|
||||
|
||||
export enum VaultImportStatus {
|
||||
Imported = "imported",
|
||||
ApprovalRequired = "approval_required"
|
||||
}
|
||||
|
||||
export type TConfigureExternalMigrationDTO = {
|
||||
platform: ExternalMigrationProviders;
|
||||
connectionId: string | null;
|
||||
|
||||
@@ -9,7 +9,8 @@ import { externalMigrationQueryKeys } from "./queries";
|
||||
import {
|
||||
ExternalMigrationProviders,
|
||||
TExternalMigrationConfig,
|
||||
TImportVaultSecretsDTO
|
||||
TImportVaultSecretsDTO,
|
||||
VaultImportStatus
|
||||
} from "./types";
|
||||
|
||||
export const useImportEnvKey = () => {
|
||||
@@ -100,9 +101,9 @@ export const useUpdateExternalMigrationConfig = (platform: ExternalMigrationProv
|
||||
export const useImportVaultSecrets = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<{ message: string }, object, TImportVaultSecretsDTO>({
|
||||
return useMutation<{ status: VaultImportStatus }, object, TImportVaultSecretsDTO>({
|
||||
mutationFn: async (dto) => {
|
||||
const { data } = await apiRequest.post<{ message: string }>(
|
||||
const { data } = await apiRequest.post<{ status: VaultImportStatus }>(
|
||||
"/api/v3/external-migration/vault/import-secrets",
|
||||
dto
|
||||
);
|
||||
|
||||
@@ -3,6 +3,11 @@ export enum ExternalMigrationProviders {
|
||||
EnvKey = "env-key"
|
||||
}
|
||||
|
||||
export enum VaultImportStatus {
|
||||
Imported = "imported",
|
||||
ApprovalRequired = "approval_required"
|
||||
}
|
||||
|
||||
export type TExternalMigrationConfig = {
|
||||
id: string;
|
||||
orgId: string;
|
||||
|
||||
@@ -78,7 +78,7 @@ import {
|
||||
} from "@app/hooks/api/dashboard/queries";
|
||||
import { UsedBySecretSyncs } from "@app/hooks/api/dashboard/types";
|
||||
import { useGetExternalMigrationConfig, useImportVaultSecrets } from "@app/hooks/api/migration";
|
||||
import { ExternalMigrationProviders } from "@app/hooks/api/migration/types";
|
||||
import { ExternalMigrationProviders, VaultImportStatus } from "@app/hooks/api/migration/types";
|
||||
import { secretApprovalRequestKeys } from "@app/hooks/api/secretApprovalRequest/queries";
|
||||
import { PendingAction } from "@app/hooks/api/secretFolders/types";
|
||||
import { fetchProjectSecrets, secretKeys } from "@app/hooks/api/secrets/queries";
|
||||
@@ -672,7 +672,7 @@ export const ActionBar = ({
|
||||
|
||||
const handleVaultImport = async (vaultPath: string, namespace: string) => {
|
||||
try {
|
||||
await importVaultSecrets({
|
||||
const result = await importVaultSecrets({
|
||||
projectId,
|
||||
environment,
|
||||
secretPath,
|
||||
@@ -680,10 +680,17 @@ export const ActionBar = ({
|
||||
vaultSecretPath: vaultPath
|
||||
});
|
||||
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully imported secrets from HashiCorp Vault"
|
||||
});
|
||||
if (result.status === VaultImportStatus.ApprovalRequired) {
|
||||
createNotification({
|
||||
type: "info",
|
||||
text: "Secret change request created successfully. Awaiting approval."
|
||||
});
|
||||
} else {
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Successfully imported secrets from HashiCorp Vault"
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Vault import error:", err);
|
||||
const error = err as AxiosError<{ message?: string }>;
|
||||
|
||||
@@ -88,13 +88,9 @@ const Content = ({ onClose, environment, secretPath, onImport }: ContentProps) =
|
||||
<div className="space-y-1.5 text-xs leading-relaxed">
|
||||
<p>
|
||||
Select a Vault namespace and secret path to import secrets into the current
|
||||
environment (<code className="text-xs">{environment}</code>) at path{" "}
|
||||
Infisical environment (<code className="text-xs">{environment}</code>) at path{" "}
|
||||
<code className="text-xs">{secretPath}</code>.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Note:</strong> Existing secrets with the same key will be overwritten.
|
||||
Secrets will be imported from the selected Vault path.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user