diff --git a/backend/src/@types/fastify.d.ts b/backend/src/@types/fastify.d.ts index 8f5c12e3a..9ed72e782 100644 --- a/backend/src/@types/fastify.d.ts +++ b/backend/src/@types/fastify.d.ts @@ -3,6 +3,8 @@ import "fastify"; import { TUsers } from "@app/db/schemas"; import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service"; import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types"; +import { TDynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service"; +import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service"; import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; @@ -21,8 +23,6 @@ import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service"; import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type"; import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service"; -import { TDynamicSecretServiceFactory } from "@app/services/dynamic-secret/dynamic-secret-service"; -import { TDynamicSecretLeaseServiceFactory } from "@app/services/dynamic-secret-lease/dynamic-secret-lease-service"; import { TIdentityServiceFactory } from "@app/services/identity/identity-service"; import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service"; import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service"; diff --git a/backend/src/server/routes/v1/dynamic-secret-lease-router.ts b/backend/src/ee/routes/v1/dynamic-secret-lease-router.ts similarity index 98% rename from backend/src/server/routes/v1/dynamic-secret-lease-router.ts rename to backend/src/ee/routes/v1/dynamic-secret-lease-router.ts index b4f88e2ba..c830e2a7f 100644 --- a/backend/src/server/routes/v1/dynamic-secret-lease-router.ts +++ b/backend/src/ee/routes/v1/dynamic-secret-lease-router.ts @@ -6,10 +6,9 @@ import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs"; import { daysToMillisecond } from "@app/lib/dates"; import { removeTrailingSlash } from "@app/lib/fn"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas"; import { AuthMode } from "@app/services/auth/auth-type"; -import { SanitizedDynamicSecretSchema } from "../sanitizedSchemas"; - export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvider) => { server.route({ url: "/", diff --git a/backend/src/server/routes/v1/dynamic-secret-router.ts b/backend/src/ee/routes/v1/dynamic-secret-router.ts similarity index 98% rename from backend/src/server/routes/v1/dynamic-secret-router.ts rename to backend/src/ee/routes/v1/dynamic-secret-router.ts index 85d8e8596..0cbf8a312 100644 --- a/backend/src/server/routes/v1/dynamic-secret-router.ts +++ b/backend/src/ee/routes/v1/dynamic-secret-router.ts @@ -3,14 +3,13 @@ import ms from "ms"; import { z } from "zod"; import { DynamicSecretLeasesSchema } from "@app/db/schemas"; +import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models"; import { DYNAMIC_SECRETS } from "@app/lib/api-docs"; import { daysToMillisecond } from "@app/lib/dates"; import { removeTrailingSlash } from "@app/lib/fn"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas"; import { AuthMode } from "@app/services/auth/auth-type"; -import { DynamicSecretProviderSchema } from "@app/services/dynamic-secret/providers/models"; - -import { SanitizedDynamicSecretSchema } from "../sanitizedSchemas"; export const registerDynamicSecretRouter = async (server: FastifyZodProvider) => { server.route({ diff --git a/backend/src/ee/routes/v1/index.ts b/backend/src/ee/routes/v1/index.ts index 7d1492f84..b3fafcfdf 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -1,3 +1,5 @@ +import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router"; +import { registerDynamicSecretRouter } from "./dynamic-secret-router"; import { registerLdapRouter } from "./ldap-router"; import { registerLicenseRouter } from "./license-router"; import { registerOrgRoleRouter } from "./org-role-router"; @@ -34,6 +36,15 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => { await server.register(registerSecretRotationProviderRouter, { prefix: "/secret-rotation-providers" }); + + await server.register( + async (dynamicSecretRouter) => { + await dynamicSecretRouter.register(registerDynamicSecretRouter); + await dynamicSecretRouter.register(registerDynamicSecretLeaseRouter, { prefix: "/leases" }); + }, + { prefix: "/dynamic-secrets" } + ); + await server.register(registerSamlRouter, { prefix: "/sso" }); await server.register(registerScimRouter, { prefix: "/scim" }); await server.register(registerLdapRouter, { prefix: "/ldap" }); diff --git a/backend/src/services/dynamic-secret-lease/dynamic-secret-lease-dal.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-dal.ts similarity index 100% rename from backend/src/services/dynamic-secret-lease/dynamic-secret-lease-dal.ts rename to backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-dal.ts diff --git a/backend/src/services/dynamic-secret-lease/dynamic-secret-lease-queue.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-queue.ts similarity index 100% rename from backend/src/services/dynamic-secret-lease/dynamic-secret-lease-queue.ts rename to backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-queue.ts diff --git a/backend/src/services/dynamic-secret-lease/dynamic-secret-lease-service.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts similarity index 97% rename from backend/src/services/dynamic-secret-lease/dynamic-secret-lease-service.ts rename to backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts index 99358175f..e46c3c6ee 100644 --- a/backend/src/services/dynamic-secret-lease/dynamic-secret-lease-service.ts +++ b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-service.ts @@ -8,11 +8,12 @@ import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services import { getConfig } from "@app/lib/config/env"; import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption"; import { BadRequestError } from "@app/lib/errors"; +import { logger } from "@app/lib/logger"; +import { TProjectDALFactory } from "@app/services/project/project-dal"; +import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal"; import { TDynamicSecretDALFactory } from "../dynamic-secret/dynamic-secret-dal"; import { DynamicSecretProviders, TDynamicProviderFns } from "../dynamic-secret/providers/models"; -import { TProjectDALFactory } from "../project/project-dal"; -import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; import { TDynamicSecretLeaseDALFactory } from "./dynamic-secret-lease-dal"; import { TDynamicSecretLeaseQueueServiceFactory } from "./dynamic-secret-lease-queue"; import { @@ -248,6 +249,7 @@ export const dynamicSecretLeaseServiceFactory = ({ if ((revokeResponse as { error?: Error })?.error) { const { error } = revokeResponse as { error?: Error }; + logger.error("Failed to revoke lease", { error: error?.message }); const deletedDynamicSecretLease = await dynamicSecretLeaseDAL.updateById(dynamicSecretLease.id, { status: DynamicSecretLeaseStatus.FailedDeletion, statusDetails: error?.message?.slice(0, 255) diff --git a/backend/src/services/dynamic-secret-lease/dynamic-secret-lease-types.ts b/backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-types.ts similarity index 100% rename from backend/src/services/dynamic-secret-lease/dynamic-secret-lease-types.ts rename to backend/src/ee/services/dynamic-secret-lease/dynamic-secret-lease-types.ts diff --git a/backend/src/services/dynamic-secret/dynamic-secret-dal.ts b/backend/src/ee/services/dynamic-secret/dynamic-secret-dal.ts similarity index 100% rename from backend/src/services/dynamic-secret/dynamic-secret-dal.ts rename to backend/src/ee/services/dynamic-secret/dynamic-secret-dal.ts diff --git a/backend/src/services/dynamic-secret/dynamic-secret-service.ts b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts similarity index 98% rename from backend/src/services/dynamic-secret/dynamic-secret-service.ts rename to backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts index a8064659a..1aef3cc86 100644 --- a/backend/src/services/dynamic-secret/dynamic-secret-service.ts +++ b/backend/src/ee/services/dynamic-secret/dynamic-secret-service.ts @@ -6,11 +6,11 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; import { BadRequestError } from "@app/lib/errors"; +import { TProjectDALFactory } from "@app/services/project/project-dal"; +import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal"; import { TDynamicSecretLeaseDALFactory } from "../dynamic-secret-lease/dynamic-secret-lease-dal"; import { TDynamicSecretLeaseQueueServiceFactory } from "../dynamic-secret-lease/dynamic-secret-lease-queue"; -import { TProjectDALFactory } from "../project/project-dal"; -import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; import { TDynamicSecretDALFactory } from "./dynamic-secret-dal"; import { DynamicSecretStatus, diff --git a/backend/src/services/dynamic-secret/dynamic-secret-types.ts b/backend/src/ee/services/dynamic-secret/dynamic-secret-types.ts similarity index 100% rename from backend/src/services/dynamic-secret/dynamic-secret-types.ts rename to backend/src/ee/services/dynamic-secret/dynamic-secret-types.ts diff --git a/backend/src/services/dynamic-secret/providers/index.ts b/backend/src/ee/services/dynamic-secret/providers/index.ts similarity index 100% rename from backend/src/services/dynamic-secret/providers/index.ts rename to backend/src/ee/services/dynamic-secret/providers/index.ts diff --git a/backend/src/services/dynamic-secret/providers/models.ts b/backend/src/ee/services/dynamic-secret/providers/models.ts similarity index 100% rename from backend/src/services/dynamic-secret/providers/models.ts rename to backend/src/ee/services/dynamic-secret/providers/models.ts diff --git a/backend/src/services/dynamic-secret/providers/sql-database.ts b/backend/src/ee/services/dynamic-secret/providers/sql-database.ts similarity index 90% rename from backend/src/services/dynamic-secret/providers/sql-database.ts rename to backend/src/ee/services/dynamic-secret/providers/sql-database.ts index c0744031e..7107fe3a3 100644 --- a/backend/src/services/dynamic-secret/providers/sql-database.ts +++ b/backend/src/ee/services/dynamic-secret/providers/sql-database.ts @@ -23,7 +23,17 @@ export const SqlDatabaseProvider = (): TDynamicProviderFns => { const dbHost = appCfg.DB_HOST || getDbConnectionHost(appCfg.DB_CONNECTION_URI); const providerInputs = await DynamicSecretSqlDBSchema.parseAsync(inputs); - if (providerInputs.host === "localhost" || providerInputs.host === "127.0.0.1" || dbHost === providerInputs.host) + if ( + // localhost + providerInputs.host === "localhost" || + providerInputs.host === "127.0.0.1" || + // database infisical uses + dbHost === providerInputs.host || + // internal ips + providerInputs.host === "host.docker.internal" || + providerInputs.host.match(/^10\.\d+\.\d+\.\d+/) || + providerInputs.host.match(/^192\.168\.\d+\.\d+/) + ) throw new BadRequestError({ message: "Invalid db host" }); return providerInputs; }; diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue-fn.ts b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue-fn.ts index 5a2e478e1..8eade1626 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue-fn.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue-fn.ts @@ -90,7 +90,17 @@ export const secretRotationDbFn = async ({ const appCfg = getConfig(); const ssl = ca ? { rejectUnauthorized: false, ca } : undefined; - if (host === "localhost" || host === "127.0.0.1" || getDbConnectionHost(appCfg.DB_CONNECTION_URI) === host) + const dbHost = appCfg.DB_HOST || getDbConnectionHost(appCfg.DB_CONNECTION_URI); + if ( + host === "localhost" || + host === "127.0.0.1" || + // database infisical uses + dbHost === host || + // internal ips + host === "host.docker.internal" || + host.match(/^10\.\d+\.\d+\.\d+/) || + host.match(/^192\.168\.\d+\.\d+/) + ) throw new Error("Invalid db host"); const db = knex({ diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index aea5baa94..940c414e8 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -5,6 +5,12 @@ import { registerV1EERoutes } from "@app/ee/routes/v1"; import { auditLogDALFactory } from "@app/ee/services/audit-log/audit-log-dal"; import { auditLogQueueServiceFactory } from "@app/ee/services/audit-log/audit-log-queue"; import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service"; +import { dynamicSecretDALFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-dal"; +import { dynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dynamic-secret-service"; +import { buildDynamicSecretProviders } from "@app/ee/services/dynamic-secret/providers"; +import { dynamicSecretLeaseDALFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-dal"; +import { dynamicSecretLeaseQueueServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-queue"; +import { dynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service"; import { ldapConfigDALFactory } from "@app/ee/services/ldap-config/ldap-config-dal"; import { ldapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service"; import { licenseDALFactory } from "@app/ee/services/license/license-dal"; @@ -47,12 +53,6 @@ import { authPaswordServiceFactory } from "@app/services/auth/auth-password-serv import { authSignupServiceFactory } from "@app/services/auth/auth-signup-service"; import { tokenDALFactory } from "@app/services/auth-token/auth-token-dal"; import { tokenServiceFactory } from "@app/services/auth-token/auth-token-service"; -import { dynamicSecretDALFactory } from "@app/services/dynamic-secret/dynamic-secret-dal"; -import { dynamicSecretServiceFactory } from "@app/services/dynamic-secret/dynamic-secret-service"; -import { buildDynamicSecretProviders } from "@app/services/dynamic-secret/providers"; -import { dynamicSecretLeaseDALFactory } from "@app/services/dynamic-secret-lease/dynamic-secret-lease-dal"; -import { dynamicSecretLeaseQueueServiceFactory } from "@app/services/dynamic-secret-lease/dynamic-secret-lease-queue"; -import { dynamicSecretLeaseServiceFactory } from "@app/services/dynamic-secret-lease/dynamic-secret-lease-service"; import { identityDALFactory } from "@app/services/identity/identity-dal"; import { identityOrgDALFactory } from "@app/services/identity/identity-org-dal"; import { identityServiceFactory } from "@app/services/identity/identity-service"; diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index 917514b72..fbc68d974 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -1,8 +1,6 @@ import { registerAdminRouter } from "./admin-router"; import { registerAuthRoutes } from "./auth-router"; import { registerProjectBotRouter } from "./bot-router"; -import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router"; -import { registerDynamicSecretRouter } from "./dynamic-secret-router"; import { registerIdentityAccessTokenRouter } from "./identity-access-token-router"; import { registerIdentityRouter } from "./identity-router"; import { registerIdentityUaRouter } from "./identity-ua"; @@ -54,14 +52,6 @@ export const registerV1Routes = async (server: FastifyZodProvider) => { { prefix: "/workspace" } ); - await server.register( - async (dynamicSecretRouter) => { - await dynamicSecretRouter.register(registerDynamicSecretRouter); - await dynamicSecretRouter.register(registerDynamicSecretLeaseRouter, { prefix: "/leases" }); - }, - { prefix: "/dynamic-secrets" } - ); - await server.register(registerProjectBotRouter, { prefix: "/bot" }); await server.register(registerIntegrationRouter, { prefix: "/integration" }); await server.register(registerIntegrationAuthRouter, { prefix: "/integration-auth" }); diff --git a/frontend/src/components/v2/Card/Card.tsx b/frontend/src/components/v2/Card/Card.tsx index 0e86d0357..a0a1f8338 100644 --- a/frontend/src/components/v2/Card/Card.tsx +++ b/frontend/src/components/v2/Card/Card.tsx @@ -1,4 +1,4 @@ -import { forwardRef, ReactNode } from "react"; +import { CSSProperties, forwardRef, ReactNode } from "react"; import { twMerge } from "tailwind-merge"; export type CardTitleProps = { @@ -31,10 +31,13 @@ export const CardFooter = ({ children, className }: CardFooterProps) => ( export type CardBodyProps = { children: ReactNode; className?: string; + style?: CSSProperties; }; -export const CardBody = ({ children, className }: CardBodyProps) => ( -
{children}
+export const CardBody = ({ children, className, style }: CardBodyProps) => ( +
+ {children} +
); export type CardProps = { @@ -44,10 +47,14 @@ export type CardProps = { isRounded?: boolean; isPlain?: boolean; isHoverable?: boolean; + style?: CSSProperties; }; export const Card = forwardRef( - ({ children, isFullHeight, isRounded, isHoverable, isPlain, className }, ref): JSX.Element => { + ( + { children, isFullHeight, isRounded, isHoverable, isPlain, className, style }, + ref + ): JSX.Element => { return (
( isHoverable && "hover:shadow-xl", className )} + style={style} > {children}
diff --git a/frontend/src/components/v2/Modal/Modal.tsx b/frontend/src/components/v2/Modal/Modal.tsx index 250feeff1..90abfecbd 100644 --- a/frontend/src/components/v2/Modal/Modal.tsx +++ b/frontend/src/components/v2/Modal/Modal.tsx @@ -29,12 +29,15 @@ export const ModalContent = forwardRef( {title && {title}} - {children} + + {children} + {footerContent && {footerContent}} void; - projectSlug:string; + projectSlug: string; environment: string; secretPath: string; }; @@ -42,7 +42,7 @@ export const CreateDynamicSecretForm = ({ {wizardStep === WizardSteps.SelectProvider && ( @@ -56,7 +56,7 @@ export const CreateDynamicSecretForm = ({
Select a service to connect to:
{ diff --git a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx index 75b347361..674b25dd0 100644 --- a/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx +++ b/frontend/src/views/SecretMainPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx @@ -25,7 +25,7 @@ const formSchema = z.object({ provider: z.object({ client: z.nativeEnum(SqlProviders), host: z.string().toLowerCase().min(1), - port: z.number(), + port: z.coerce.number(), database: z.string().min(1), username: z.string().min(1), password: z.string().min(1), @@ -54,9 +54,7 @@ const formSchema = z.object({ if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); }), - name: z - .string() - .refine((val) => val.toLowerCase() === val, "Must be lowercase") + name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase") }); type TForm = z.infer; @@ -84,14 +82,14 @@ export const SqlDatabaseInputForm = ({ defaultValues: { provider: { creationStatement: - "CREATE USER \"{{username}}\" WITH SUPERUSER ENCRYPTED PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';\nGRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"{{username}}\";", + "CREATE USER \"{{username}}\" WITH ENCRYPTED PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';\nGRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"{{username}}\";", renewStatement: "ALTER ROLE \"{{username}}\" VALID UNTIL '{{expiration}}';", revocationStatement: - 'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM "{{username}}";\nDROP OWNED BY "{{username}}";\nDROP ROLE "{{username}}";' + 'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM "{{username}}";\nDROP ROLE "{{username}}";' } } }); - + const createDynamicSecret = useCreateDynamicSecret(); const handleCreateDynamicSecret = async ({ name, maxTTL, provider, defaultTTL }: TForm) => { @@ -119,238 +117,236 @@ export const SqlDatabaseInputForm = ({ return (
-
-
- ( - - - - )} - /> -
-
- ( - } - isError={Boolean(error?.message)} - errorText={error?.message} - > - - - )} - /> -
-
- ( - } - isError={Boolean(error?.message)} - errorText={error?.message} - > - - - )} - /> -
-
-
- Configuration +
+
+ ( + + + + )} + /> +
+
+ ( + } + isError={Boolean(error?.message)} + errorText={error?.message} + > + + + )} + /> +
+
+ ( + } + isError={Boolean(error?.message)} + errorText={error?.message} + > + + + )} + /> +
-
-
Service
- ( - - - - )} - /> -
- ( - - - - )} - /> - ( - - field.onChange(parseInt(el.target.value, 10))} - /> - - )} - /> +
+
+ Configuration
-
+
+
Service
( - - + name="provider.client" + defaultValue={SqlProviders.Postgres} + render={({ field: { value, onChange }, fieldState: { error } }) => ( + + )} /> - ( - - - - )} - /> - ( - - - - )} - /> -
-
- ( - - - - )} - /> - - - Modify SQL Statements - - ( - -