mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: addressed comments
This commit is contained in:
@@ -8,7 +8,8 @@ import {
|
||||
import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { DatabaseErrorCode } from "@app/lib/error-codes";
|
||||
import { BadRequestError, DatabaseError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||
import { OrgServiceActor } from "@app/lib/types";
|
||||
|
||||
import { AppConnection } from "../app-connection/app-connection-enums";
|
||||
@@ -231,8 +232,13 @@ export const externalMigrationServiceFactory = ({
|
||||
|
||||
try {
|
||||
await listHCVaultPolicies(namespace, connection, gatewayService);
|
||||
await listHCVaultSecretPaths(namespace, connection, gatewayService);
|
||||
await listHCVaultMounts(connection, gatewayService);
|
||||
await getHCVaultAuthMounts(namespace, HCVaultAuthType.Kubernetes, connection, gatewayService);
|
||||
|
||||
const mounts = await listHCVaultMounts(connection, gatewayService);
|
||||
const sampleKvMount = mounts.find((mount) => mount.type === "kv");
|
||||
if (sampleKvMount) {
|
||||
await listHCVaultSecretPaths(namespace, connection, gatewayService, sampleKvMount.path);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new BadRequestError({
|
||||
message: `Failed to establish namespace confiugration. ${error instanceof Error ? error.message : "Unknown error"}`
|
||||
@@ -264,13 +270,26 @@ export const externalMigrationServiceFactory = ({
|
||||
namespace
|
||||
});
|
||||
|
||||
const config = await vaultExternalMigrationConfigDAL.create({
|
||||
namespace,
|
||||
connectionId,
|
||||
orgId: actor.orgId
|
||||
});
|
||||
try {
|
||||
const config = await vaultExternalMigrationConfigDAL.create({
|
||||
namespace,
|
||||
connectionId,
|
||||
orgId: actor.orgId
|
||||
});
|
||||
|
||||
return config;
|
||||
return config;
|
||||
} catch (error) {
|
||||
if (
|
||||
error instanceof DatabaseError &&
|
||||
(error.error as { code: string })?.code === DatabaseErrorCode.UniqueViolation
|
||||
) {
|
||||
throw new BadRequestError({
|
||||
message: `Vault external migration already exists for this namespace`
|
||||
});
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const updateVaultExternalMigration = async ({
|
||||
|
||||
@@ -124,7 +124,7 @@ export enum ExternalMigrationProviders {
|
||||
|
||||
export enum VaultImportStatus {
|
||||
Imported = "imported",
|
||||
ApprovalRequired = "approval_required"
|
||||
ApprovalRequired = "approval-required"
|
||||
}
|
||||
|
||||
export type TCreateVaultExternalMigrationDTO = {
|
||||
|
||||
@@ -33,7 +33,7 @@ This migration approach lets you set up a connection to your Vault instance once
|
||||
In your Vault instance, create a policy that allows Infisical to read your secrets, policies, and authentication configurations. This policy grants read-only access and doesn't allow Infisical to modify anything in Vault.
|
||||
|
||||
<Accordion title="View the complete policy">
|
||||
```python
|
||||
```hcl
|
||||
# System endpoints - for listing namespaces, policies, mounts, and auth methods
|
||||
path "sys/namespaces" {
|
||||
capabilities = ["list"]
|
||||
@@ -162,7 +162,17 @@ The authentication settings (service accounts, TTL, policies, etc.) will be auto
|
||||
|
||||
#### Import and Translate Access Control Policies
|
||||
|
||||
When configuring project role-based access control, you can import Vault HCL policies and automatically translate them to Infisical permissions:
|
||||
When configuring project role-based access control, you can import Vault HCL policies and automatically translate them to Infisical permissions.
|
||||
|
||||
<Note>
|
||||
Policy translation is best-effort and provides a starting point based on your
|
||||
Vault configuration. The translated permissions should be reviewed and
|
||||
adjusted as needed since Vault and Infisical have different access control
|
||||
models. Infisical will analyze path patterns and capabilities to suggest
|
||||
equivalent permissions.
|
||||
</Note>
|
||||
|
||||
**To import and translate a policy:**
|
||||
|
||||
1. Navigate to your project, then go to **Access Control > Roles** and create or edit a role
|
||||
2. In the policy configuration, click **"Add from HashiCorp Vault"**
|
||||
@@ -177,12 +187,16 @@ When configuring project role-based access control, you can import Vault HCL pol
|
||||
5. Review the automatically translated Infisical permissions
|
||||
6. Make any adjustments and save
|
||||
|
||||
**How policy translation works:**
|
||||
|
||||
- Vault path patterns are analyzed to identify KV secret engines and environments
|
||||
- Vault capabilities (`read`, `list`, `create`, etc.) are mapped to Infisical permissions
|
||||
- Wildcards in paths are converted to glob patterns
|
||||
- Secret paths are preserved for granular access control
|
||||
<Tip>
|
||||
**How policy translation works:**
|
||||
|
||||
- Vault path patterns are analyzed to identify KV secret engines and environments
|
||||
- Vault capabilities (`read`,`list`, `create`, etc.) are mapped to Infisical permissions
|
||||
- Wildcards in paths are converted to glob patterns
|
||||
- Secret paths are preserved for granular access control
|
||||
|
||||
Always review the translated permissions carefully, as Vault's capability-based model may not map 1:1 with Infisical's permission structure.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
@@ -219,7 +233,7 @@ Before starting the bulk import, you need to decide how your Vault structure wil
|
||||
In your Vault instance, create a policy that allows Infisical to read all secrets and metadata. This policy grants read-only access.
|
||||
|
||||
<Accordion title="View the bulk import policy">
|
||||
```python
|
||||
```hcl
|
||||
# Allow listing secret engines/mounts
|
||||
path "sys/mounts" {
|
||||
capabilities = ["read", "list"]
|
||||
|
||||
@@ -5,7 +5,7 @@ export enum ExternalMigrationProviders {
|
||||
|
||||
export enum VaultImportStatus {
|
||||
Imported = "imported",
|
||||
ApprovalRequired = "approval_required"
|
||||
ApprovalRequired = "approval-required"
|
||||
}
|
||||
|
||||
export type TVaultExternalMigrationConfig = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { faEdit, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
@@ -162,7 +163,14 @@ export const VaultConnectionSection = () => {
|
||||
|
||||
<p className="mt-4 text-xs text-mineshaft-400">
|
||||
Configure namespace-specific connections to enable in-platform migration features. Manage
|
||||
connections in the App Connections section.
|
||||
connections in the{" "}
|
||||
<Link
|
||||
to="/organization/app-connections"
|
||||
className="text-primary underline hover:text-primary-300"
|
||||
>
|
||||
App Connections
|
||||
</Link>{" "}
|
||||
section.
|
||||
</p>
|
||||
|
||||
<VaultNamespaceConfigModal
|
||||
|
||||
@@ -21,7 +21,9 @@ import {
|
||||
import { TVaultExternalMigrationConfig } from "@app/hooks/api/migration/types";
|
||||
|
||||
const schema = z.object({
|
||||
namespace: z.string().min(1, "Namespace is required"),
|
||||
namespace: z
|
||||
.string()
|
||||
.min(1, "Namespace is required. If you intend to use the root namespace, use root or /."),
|
||||
connectionId: z.string().min(1, "Connection is required")
|
||||
});
|
||||
|
||||
|
||||
@@ -94,38 +94,25 @@ const Content = ({ onClose }: ContentProps) => {
|
||||
}
|
||||
|
||||
// Apply the parsed permissions to the form
|
||||
Object.entries(parsedPermissions).forEach(([subject, value]) => {
|
||||
(Object.keys(parsedPermissions) as ProjectPermissionSub[]).forEach((subjectKey) => {
|
||||
const value = parsedPermissions[subjectKey];
|
||||
if (!value) return;
|
||||
|
||||
const subjectKey = subject as ProjectPermissionSub;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const existingValue = rootForm.getValues(`permissions.${subjectKey}`) as any;
|
||||
const existingValue = rootForm.getValues(`permissions.${subjectKey}`) as unknown[];
|
||||
|
||||
if (Array.isArray(existingValue) && existingValue.length > 0) {
|
||||
// Merge with existing permissions
|
||||
rootForm.setValue(
|
||||
`permissions.${subjectKey}`,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore-error
|
||||
[...existingValue, ...value],
|
||||
{
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
shouldValidate: true
|
||||
}
|
||||
);
|
||||
rootForm.setValue(`permissions.${subjectKey}`, [...existingValue, ...value] as never, {
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
shouldValidate: true
|
||||
});
|
||||
} else {
|
||||
rootForm.setValue(
|
||||
`permissions.${subjectKey}`,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore-error
|
||||
value,
|
||||
{
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
shouldValidate: true
|
||||
}
|
||||
);
|
||||
rootForm.setValue(`permissions.${subjectKey}`, value as never, {
|
||||
shouldDirty: true,
|
||||
shouldTouch: true,
|
||||
shouldValidate: true
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user