requested changes and docs
@@ -64,7 +64,7 @@ export const registerExternalMigrationRouter = async (server: FastifyZodProvider
|
|||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
vaultAccessToken: z.string(),
|
vaultAccessToken: z.string(),
|
||||||
vaultNamespace: z.string(),
|
vaultNamespace: z.string().trim().optional(),
|
||||||
vaultUrl: z.string(),
|
vaultUrl: z.string(),
|
||||||
mappingType: z.nativeEnum(VaultMappingType)
|
mappingType: z.nativeEnum(VaultMappingType)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import axios, { AxiosInstance } from "axios";
|
import axios, { AxiosInstance } from "axios";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
import { logger } from "@app/lib/logger";
|
||||||
|
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
|
||||||
|
|
||||||
import { InfisicalImportData, VaultMappingType } from "../external-migration-types";
|
import { InfisicalImportData, VaultMappingType } from "../external-migration-types";
|
||||||
|
|
||||||
type VaultData = {
|
type VaultData = {
|
||||||
@@ -12,18 +16,25 @@ type VaultData = {
|
|||||||
|
|
||||||
const vaultFactory = () => {
|
const vaultFactory = () => {
|
||||||
const getMounts = async (request: AxiosInstance) => {
|
const getMounts = async (request: AxiosInstance) => {
|
||||||
const response = await request.get<
|
const response = await request
|
||||||
Record<
|
.get<
|
||||||
string,
|
Record<
|
||||||
{
|
string,
|
||||||
accessor: string;
|
{
|
||||||
options: {
|
accessor: string;
|
||||||
version?: string;
|
options: {
|
||||||
} | null;
|
version?: string;
|
||||||
type: string;
|
} | null;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>("/v1/sys/mounts")
|
||||||
|
.catch((err) => {
|
||||||
|
if (axios.isAxiosError(err)) {
|
||||||
|
logger.error(err.response?.data, "External migration: Failed to get Vault mounts");
|
||||||
}
|
}
|
||||||
>
|
throw err;
|
||||||
>("/v1/sys/mounts");
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,8 +53,11 @@ const vaultFactory = () => {
|
|||||||
|
|
||||||
return response.data.data.keys;
|
return response.data.data.keys;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (axios.isAxiosError(err) && err.response?.status === 404) {
|
if (axios.isAxiosError(err)) {
|
||||||
return null;
|
logger.error(err.response?.data, "External migration: Failed to get Vault paths");
|
||||||
|
if (err.response?.status === 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@@ -54,17 +68,24 @@ const vaultFactory = () => {
|
|||||||
{ mountPath, secretPath }: { mountPath: string; secretPath: string }
|
{ mountPath, secretPath }: { mountPath: string; secretPath: string }
|
||||||
) => {
|
) => {
|
||||||
// For KV v2: /v1/{mount}/data/{path}
|
// For KV v2: /v1/{mount}/data/{path}
|
||||||
const response = await request.get<{
|
const response = await request
|
||||||
data: {
|
.get<{
|
||||||
data: Record<string, string>; // KV v2 has nested data structure
|
data: {
|
||||||
metadata: {
|
data: Record<string, string>; // KV v2 has nested data structure
|
||||||
created_time: string;
|
metadata: {
|
||||||
deletion_time: string;
|
created_time: string;
|
||||||
destroyed: boolean;
|
deletion_time: string;
|
||||||
version: number;
|
destroyed: boolean;
|
||||||
|
version: number;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}>(`/v1/${mountPath}/data/${secretPath}`)
|
||||||
}>(`/v1/${mountPath}/data/${secretPath}`);
|
.catch((err) => {
|
||||||
|
if (axios.isAxiosError(err)) {
|
||||||
|
logger.error(err.response?.data, "External migration: Failed to get Vault secret");
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
return response.data.data.data;
|
return response.data.data.data;
|
||||||
};
|
};
|
||||||
@@ -110,14 +131,14 @@ const vaultFactory = () => {
|
|||||||
accessToken
|
accessToken
|
||||||
}: {
|
}: {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
namespace: string;
|
namespace?: string;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
}): Promise<VaultData[]> {
|
}): Promise<VaultData[]> {
|
||||||
const request = axios.create({
|
const request = axios.create({
|
||||||
baseURL: baseUrl,
|
baseURL: baseUrl,
|
||||||
headers: {
|
headers: {
|
||||||
"X-Vault-Namespace": namespace,
|
"X-Vault-Token": accessToken,
|
||||||
"X-Vault-Token": accessToken
|
...(namespace ? { "X-Vault-Namespace": namespace } : {})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -152,7 +173,7 @@ const vaultFactory = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
allData.push({
|
allData.push({
|
||||||
namespace,
|
namespace: namespace || "",
|
||||||
mount: mountPath.replace(/\/$/, ""),
|
mount: mountPath.replace(/\/$/, ""),
|
||||||
path: secretPath.replace(`${cleanMountPath}/`, ""),
|
path: secretPath.replace(`${cleanMountPath}/`, ""),
|
||||||
secretData
|
secretData
|
||||||
@@ -190,7 +211,7 @@ export const transformToInfisicalFormatNamespaceToProjects = (
|
|||||||
for (const data of vaultData) {
|
for (const data of vaultData) {
|
||||||
const { namespace, mount, path, secretData } = data;
|
const { namespace, mount, path, secretData } = data;
|
||||||
|
|
||||||
if (mappingType === "namespace") {
|
if (mappingType === VaultMappingType.Namespace) {
|
||||||
// create project (namespace)
|
// create project (namespace)
|
||||||
if (!projectMap.has(namespace)) {
|
if (!projectMap.has(namespace)) {
|
||||||
const projectId = uuidv4();
|
const projectId = uuidv4();
|
||||||
@@ -214,7 +235,7 @@ export const transformToInfisicalFormatNamespaceToProjects = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
environmentId = environmentMap.get(envKey)!;
|
environmentId = environmentMap.get(envKey)!;
|
||||||
} else if (mappingType === "key-vault") {
|
} else if (mappingType === VaultMappingType.KeyVault) {
|
||||||
if (!projectMap.has(mount)) {
|
if (!projectMap.has(mount)) {
|
||||||
const projectId = uuidv4();
|
const projectId = uuidv4();
|
||||||
projectMap.set(mount, projectId);
|
projectMap.set(mount, projectId);
|
||||||
@@ -294,10 +315,18 @@ export const importVaultDataFn = async ({
|
|||||||
mappingType
|
mappingType
|
||||||
}: {
|
}: {
|
||||||
vaultAccessToken: string;
|
vaultAccessToken: string;
|
||||||
vaultNamespace: string;
|
vaultNamespace?: string;
|
||||||
vaultUrl: string;
|
vaultUrl: string;
|
||||||
mappingType: VaultMappingType;
|
mappingType: VaultMappingType;
|
||||||
}) => {
|
}) => {
|
||||||
|
await blockLocalAndPrivateIpAddresses(vaultUrl);
|
||||||
|
|
||||||
|
if (mappingType === VaultMappingType.Namespace && !vaultNamespace) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Vault namespace is required when project mapping type is set to namespace."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const vaultApi = vaultFactory();
|
const vaultApi = vaultFactory();
|
||||||
|
|
||||||
const vaultData = await vaultApi.collectVaultData({
|
const vaultData = await vaultApi.collectVaultData({
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export type TImportEnvKeyDataDTO = {
|
|||||||
|
|
||||||
export type TImportVaultDataDTO = {
|
export type TImportVaultDataDTO = {
|
||||||
vaultAccessToken: string;
|
vaultAccessToken: string;
|
||||||
vaultNamespace: string;
|
vaultNamespace?: string;
|
||||||
mappingType: VaultMappingType;
|
mappingType: VaultMappingType;
|
||||||
vaultUrl: string;
|
vaultUrl: string;
|
||||||
} & Omit<TOrgPermission, "orgId">;
|
} & Omit<TOrgPermission, "orgId">;
|
||||||
|
|||||||
@@ -198,6 +198,21 @@
|
|||||||
"documentation/platform/workflow-integrations/microsoft-teams-integration"
|
"documentation/platform/workflow-integrations/microsoft-teams-integration"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"group": "External Migrations",
|
||||||
|
"pages": [
|
||||||
|
"documentation/platform/external-migrations/overview",
|
||||||
|
"documentation/platform/external-migrations/envkey",
|
||||||
|
"documentation/platform/external-migrations/vault"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "External Migrations",
|
||||||
|
"pages": [
|
||||||
|
"documentation/platform/workflow-integrations/slack-integration",
|
||||||
|
"documentation/platform/workflow-integrations/microsoft-teams-integration"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"group": "Admin Consoles",
|
"group": "Admin Consoles",
|
||||||
"pages": [
|
"pages": [
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Migrating from EnvKey to Infisical"
|
|
||||||
sidebarTitle: "Migration"
|
|
||||||
description: "Learn how to migrate from EnvKey to Infisical in the easiest way possible."
|
|
||||||
---
|
|
||||||
|
|
||||||
## What is Infisical?
|
|
||||||
|
|
||||||
[Infisical](https://infisical.com) is an open-source all-in-one secret management platform that helps developers manage secrets (e.g., API-keys, DB access tokens, [certificates](https://infisical.com/docs/documentation/platform/pki/overview)) across their infrastructure. In addition, Infisical provides [secret sharing](https://infisical.com/docs/documentation/platform/secret-sharing) functionality, ability to [prevent secret leaks](https://infisical.com/docs/cli/scanning-overview), and more.
|
|
||||||
|
|
||||||
Infisical is used by 10,000+ organizations across all industries including First American Financial Corporation, Delivery Hero, and [Hugging Face](https://infisical.com/customers/hugging-face).
|
|
||||||
|
|
||||||
## Migrating from EnvKey
|
|
||||||
|
|
||||||
<Steps>
|
|
||||||
<Step>
|
|
||||||
Open the EnvKey dashboard and go to My Org.
|
|
||||||

|
|
||||||
</Step>
|
|
||||||
<Step>
|
|
||||||
Go to Import/Export on the top right corner, Click on Export Org and save the exported file.
|
|
||||||

|
|
||||||
</Step>
|
|
||||||
<Step>
|
|
||||||
Click on copy to copy the encryption key and save it.
|
|
||||||

|
|
||||||
</Step>
|
|
||||||
<Step>
|
|
||||||
Open the Infisical dashboard and go to Organization Settings > Import.
|
|
||||||

|
|
||||||
</Step>
|
|
||||||
<Step>
|
|
||||||
Upload the exported file from EnvKey, paste the encryption key and click Import.
|
|
||||||

|
|
||||||
</Step>
|
|
||||||
</Steps>
|
|
||||||
|
|
||||||
|
|
||||||
## Talk to our team
|
|
||||||
|
|
||||||
To make the migration process even more seamless, you can [schedule a meeting with our team](https://infisical.cal.com/vlad/migration-from-envkey-to-infisical) to learn more about how Infisical compares to EnvKey and discuss unique needs of your organization. You are also welcome to email us at [[email protected]](mailto:[email protected]) to ask any questions or get any technical help.
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: "Migrating from EnvKey to Infisical"
|
||||||
|
sidebarTitle: "EnvKey"
|
||||||
|
description: "Learn how to migrate secrets from EnvKey to Infisical."
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migrating from EnvKey
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
<Step title="Open the EnvKey dashboard and go to My Org">
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
<Step title="Export your EnvKey organization">
|
||||||
|
Go to Import/Export on the top right corner, Click on Export Org and save the exported file.
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
<Step title="Obtain EnvKey encryption key">
|
||||||
|
Click on copy to copy the encryption key and save it.
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
<Step title="Navigate to Infisical external migrations">
|
||||||
|
Open the Infisical dashboard and go to Organization Settings > External Migrations.
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Select the EnvKey platform">
|
||||||
|
Select the EnvKey platform and click on Next.
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Upload the exported file from EnvKey">
|
||||||
|
Upload the exported file from EnvKey, paste the encryption key and click Import data.
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
It may take several minutes to complete the migration. You will receive an email when the migration is complete, or if there were any errors during the migration process.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
|
||||||
|
## Talk to our team
|
||||||
|
|
||||||
|
To make the migration process even more seamless, you can [schedule a meeting with our team](https://infisical.cal.com/vlad/migration-from-envkey-to-infisical) to learn more about how Infisical compares to EnvKey and discuss unique needs of your organization. You are also welcome to email us at [[email protected]](mailto:[email protected]) to ask any questions or get any technical help.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "External Migrations"
|
||||||
|
sidebarTitle: "Overview"
|
||||||
|
description: "Learn how to migrate secrets from third-party secrets management platforms to Infisical."
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Infisical supports migrating secrets from third-party secrets management platforms to Infisical. This is useful if you're looking to easily switch to Infisical and wish to move over your existing secrets from a different platform.
|
||||||
|
|
||||||
|
## Supported Platforms
|
||||||
|
|
||||||
|
- [EnvKey](./envkey)
|
||||||
|
- [Vault](./vault)
|
||||||
|
|
||||||
|
We're always looking to add more migration paths for other providers. If we're missing a platform, please open an issue on our [GitHub repository](https://github.com/infisical/infisical/issues).
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
title: "Migrating from Vault to Infisical"
|
||||||
|
sidebarTitle: "Vault"
|
||||||
|
description: "Learn how to migrate secrets from Vault to Infisical."
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migrating from Vault
|
||||||
|
|
||||||
|
Migrating from Vault Self-Hosted or Dedicated Vault is a straight forward process with our inbuilt migration option. In order to migrate from Vault, you'll need to provide Infisical an access token to your Vault instance.
|
||||||
|
|
||||||
|
Currently the Vault migration only supports migrating secrets from the KV v2 secrets engine. If you're using a different secrets engine, please open an issue on our [GitHub repository](https://github.com/infisical/infisical/issues).
|
||||||
|
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- A Vault instance with the KV v2 secrets engine enabled.
|
||||||
|
- An access token to your Vault instance.
|
||||||
|
|
||||||
|
|
||||||
|
### Project Mapping
|
||||||
|
|
||||||
|
When migrating from Vault, you'll need to choose how you want to map your Vault resources to Infisical projects.
|
||||||
|
|
||||||
|
There are two options for project mapping:
|
||||||
|
|
||||||
|
- `Namespace`: This will map your selected Vault namespace to a single Infisical project. When you select this option, each KV secret engine within the namespace will be mapped to a single Infisical project. Each KV secret engine will be mapped to a Infisical environment within the project. This means if you have 3 KV secret engines, you'll have 3 environments inside the same project, where the name of the environments correspond to the name of the KV secret engines.
|
||||||
|
- `Key Vault`: This will map all the KV secret engines within your Vault instance to a Infisical project. Each KV engine will be created as a Infisical project. This means if you have 3 KV secret engines, you'll have 3 Infisical projects. For each of the created projects, a single default environment will be created called `Production`, which will contain all your secrets from the corresponding KV secret engine.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
<Step title="Create a Vault policy">
|
||||||
|
In order to migrate from Vault, you'll need to create a Vault policy that allows Infisical to read the secrets and metadata from the KV v2 secrets engines within your Vault instance.
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Allow listing secret engines/mounts
|
||||||
|
path "sys/mounts" {
|
||||||
|
capabilities = ["read", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# For KV v2 engines - access to both data and metadata
|
||||||
|
path "*/data/*" {
|
||||||
|
capabilities = ["read", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "*/metadata/*" {
|
||||||
|
capabilities = ["read", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# If using Vault Enterprise - allow listing namespaces
|
||||||
|
path "sys/namespaces" {
|
||||||
|
capabilities = ["list", "read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cross-namespace access (Enterprise only)
|
||||||
|
path "+/*" {
|
||||||
|
capabilities = ["read", "list"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "+/sys/mounts" {
|
||||||
|
capabilities = ["read", "list"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Save this policy with the name `infisical-migration`.
|
||||||
|
|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Generate an access token">
|
||||||
|
You can use the Vault CLI to easily generate an access token for the new `infisical-migration` policy that you created in the previous step.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vault token create --policy="infisical-migration"
|
||||||
|
```
|
||||||
|
|
||||||
|
After generating the token, you should see the following output:
|
||||||
|
|
||||||
|
```t
|
||||||
|
$ vault token create --policy="infisical-migration"
|
||||||
|
|
||||||
|
Key Value
|
||||||
|
--- -----
|
||||||
|
token <your-access-token>
|
||||||
|
token_accessor p6kJDiBSzYYdabJUIpGCsCBm
|
||||||
|
token_duration 768h
|
||||||
|
token_renewable true
|
||||||
|
token_policies ["default" "infisical-migration"]
|
||||||
|
identity_policies []
|
||||||
|
policies ["default" "infisical-migration"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy the `token` field and save it for later, as you'll need this when configuring the migration to Infisical.
|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Navigate to Infisical external migrations">
|
||||||
|
Open the Infisical dashboard and go to Organization Settings > External Migrations.
|
||||||
|
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Select the Vault platform">
|
||||||
|
Select the Vault platform and click on Next.
|
||||||
|
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
|
||||||
|
<Step title="Configure the Vault migration">
|
||||||
|
Enter the Vault access token that you generated in the previous step and click Import data.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- `Vault URL`: The URL of your Vault instance.
|
||||||
|
- `Vault Namespace`: The namespace of your Vault instance. This is optional, and can be left blank if you're not using namespaces for your Vault instance.
|
||||||
|
- `Vault Access Token`: The access token that you generated in the previous step.
|
||||||
|
|
||||||
|
- `Project Mapping`: Choose how you want to map your Vault resources to Infisical projects. You can review the mapping options in the [Project Mapping](#project-mapping) section.
|
||||||
|
|
||||||
|
Click on Import data to start the migration.
|
||||||
|
|
||||||
|
</Step>
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
It may take several minutes to complete the migration. You will receive an email when the migration is complete, or if there were any errors during the migration process.
|
||||||
|
</Note>
|
||||||
|
Before Width: | Height: | Size: 896 KiB |
|
Before Width: | Height: | Size: 609 KiB |
|
Before Width: | Height: | Size: 403 KiB After Width: | Height: | Size: 403 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 413 KiB After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 193 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 161 KiB |
@@ -49,7 +49,7 @@ export const useImportVault = () => {
|
|||||||
mappingType
|
mappingType
|
||||||
}: {
|
}: {
|
||||||
vaultAccessToken: string;
|
vaultAccessToken: string;
|
||||||
vaultNamespace: string;
|
vaultNamespace?: string;
|
||||||
vaultUrl: string;
|
vaultUrl: string;
|
||||||
mappingType: string;
|
mappingType: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
|||||||
|
|
||||||
import { SelectImportFromPlatformModal } from "./components/SelectImportFromPlatformModal";
|
import { SelectImportFromPlatformModal } from "./components/SelectImportFromPlatformModal";
|
||||||
|
|
||||||
export const ImportTab = () => {
|
export const ExternalMigrationsTab = () => {
|
||||||
const { membership } = useOrgPermission();
|
const { membership } = useOrgPermission();
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["selectImportPlatform"] as const);
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["selectImportPlatform"] as const);
|
||||||
@@ -62,7 +62,7 @@ const MAPPING_TYPE_MENU_ITEMS = [
|
|||||||
export const VaultPlatformModal = ({ onClose }: Props) => {
|
export const VaultPlatformModal = ({ onClose }: Props) => {
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
vaultUrl: z.string().min(1),
|
vaultUrl: z.string().min(1),
|
||||||
vaultNamespace: z.string().min(1),
|
vaultNamespace: z.string().trim().optional(),
|
||||||
vaultAccessToken: z.string().min(1),
|
vaultAccessToken: z.string().min(1),
|
||||||
mappingType: z.nativeEnum(VaultMappingType).default(VaultMappingType.KeyVault)
|
mappingType: z.nativeEnum(VaultMappingType).default(VaultMappingType.KeyVault)
|
||||||
});
|
});
|
||||||
@@ -122,7 +122,7 @@ export const VaultPlatformModal = ({ onClose }: Props) => {
|
|||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Input type="password" placeholder="" {...field} />
|
<Input placeholder="" {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -132,7 +132,6 @@ export const VaultPlatformModal = ({ onClose }: Props) => {
|
|||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Vault Namespace"
|
label="Vault Namespace"
|
||||||
isRequired
|
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ExternalMigrationsTab } from "./ExternalMigrationsTab";
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { ImportTab } from "./ImportTab";
|
|
||||||
@@ -5,7 +5,7 @@ import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
|||||||
import { ROUTE_PATHS } from "@app/const/routes";
|
import { ROUTE_PATHS } from "@app/const/routes";
|
||||||
|
|
||||||
import { AuditLogStreamsTab } from "../AuditLogStreamTab";
|
import { AuditLogStreamsTab } from "../AuditLogStreamTab";
|
||||||
import { ImportTab } from "../ImportTab";
|
import { ExternalMigrationsTab } from "../ExternalMigrationsTab";
|
||||||
import { KmipTab } from "../KmipTab/OrgKmipTab";
|
import { KmipTab } from "../KmipTab/OrgKmipTab";
|
||||||
import { OrgEncryptionTab } from "../OrgEncryptionTab";
|
import { OrgEncryptionTab } from "../OrgEncryptionTab";
|
||||||
import { OrgGeneralTab } from "../OrgGeneralTab";
|
import { OrgGeneralTab } from "../OrgGeneralTab";
|
||||||
@@ -39,7 +39,11 @@ export const OrgTabGroup = () => {
|
|||||||
component: OrgWorkflowIntegrationTab
|
component: OrgWorkflowIntegrationTab
|
||||||
},
|
},
|
||||||
{ name: "Audit Log Streams", key: "tag-audit-log-streams", component: AuditLogStreamsTab },
|
{ name: "Audit Log Streams", key: "tag-audit-log-streams", component: AuditLogStreamsTab },
|
||||||
{ name: "Import", key: "tab-import", component: ImportTab },
|
{
|
||||||
|
name: "External Migrations",
|
||||||
|
key: "tab-external-migrations",
|
||||||
|
component: ExternalMigrationsTab
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Project Templates",
|
name: "Project Templates",
|
||||||
key: "project-templates",
|
key: "project-templates",
|
||||||
|
|||||||