mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 05:26:11 +00:00
improvement: rollback deprecate all secret rotation v1 create, update UI to only prevent pg/mssql
This commit is contained in:
@@ -23,7 +23,8 @@ export const registerSecretRotationProviderRouter = async (server: FastifyZodPro
|
|||||||
title: z.string(),
|
title: z.string(),
|
||||||
image: z.string().optional(),
|
image: z.string().optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
template: z.any()
|
template: z.any(),
|
||||||
|
isDeprecated: z.boolean().optional()
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SecretRotationOutputsSchema, SecretRotationsSchema } from "@app/db/schemas";
|
import { SecretRotationOutputsSchema, SecretRotationsSchema } from "@app/db/schemas";
|
||||||
import { BadRequestError } from "@app/lib/errors";
|
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@@ -41,10 +40,16 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT]),
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
handler: async () => {
|
handler: async (req) => {
|
||||||
throw new BadRequestError({
|
const secretRotation = await server.services.secretRotation.createRotation({
|
||||||
message: `This version of Secret Rotations has been deprecated. Please see docs for new version.`
|
actor: req.permission.type,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
...req.body,
|
||||||
|
projectId: req.body.workspaceId
|
||||||
});
|
});
|
||||||
|
return { secretRotation };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,13 @@ export const secretRotationServiceFactory = ({
|
|||||||
});
|
});
|
||||||
if (selectedSecrets.length !== Object.values(outputs).length)
|
if (selectedSecrets.length !== Object.values(outputs).length)
|
||||||
throw new NotFoundError({ message: `Secrets not found in folder with ID '${folder.id}'` });
|
throw new NotFoundError({ message: `Secrets not found in folder with ID '${folder.id}'` });
|
||||||
|
const rotatedSecrets = selectedSecrets.filter(({ isRotatedSecret }) => isRotatedSecret);
|
||||||
|
if (rotatedSecrets.length)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Selected secrets are already used for rotation: ${rotatedSecrets
|
||||||
|
.map((secret) => secret.key)
|
||||||
|
.join(", ")}`
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const selectedSecrets = await secretDAL.find({
|
const selectedSecrets = await secretDAL.find({
|
||||||
folderId: folder.id,
|
folderId: folder.id,
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ export const rotationTemplates: TSecretRotationProviderTemplate[] = [
|
|||||||
title: "PostgreSQL",
|
title: "PostgreSQL",
|
||||||
image: "postgres.png",
|
image: "postgres.png",
|
||||||
description: "Rotate PostgreSQL/CockroachDB user credentials",
|
description: "Rotate PostgreSQL/CockroachDB user credentials",
|
||||||
template: POSTGRES_TEMPLATE
|
template: POSTGRES_TEMPLATE,
|
||||||
|
isDeprecated: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mysql",
|
name: "mysql",
|
||||||
@@ -32,7 +33,8 @@ export const rotationTemplates: TSecretRotationProviderTemplate[] = [
|
|||||||
title: "Microsoft SQL Server",
|
title: "Microsoft SQL Server",
|
||||||
image: "mssqlserver.png",
|
image: "mssqlserver.png",
|
||||||
description: "Rotate Microsoft SQL server user credentials",
|
description: "Rotate Microsoft SQL server user credentials",
|
||||||
template: MSSQL_TEMPLATE
|
template: MSSQL_TEMPLATE,
|
||||||
|
isDeprecated: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "aws-iam",
|
name: "aws-iam",
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export type TSecretRotationProviderTemplate = {
|
|||||||
image?: string;
|
image?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
template: THttpProviderTemplate | TDbProviderTemplate | TAwsProviderTemplate;
|
template: THttpProviderTemplate | TDbProviderTemplate | TAwsProviderTemplate;
|
||||||
|
isDeprecated?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type THttpProviderTemplate = {
|
export type THttpProviderTemplate = {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { ProjectType, TProjectKeys, SortDirection } from "@app/db/schemas";
|
import { ProjectType, SortDirection, TProjectKeys } from "@app/db/schemas";
|
||||||
import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal";
|
import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal";
|
||||||
import { TSshCertificateAuthoritySecretDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-secret-dal";
|
import { TSshCertificateAuthoritySecretDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-secret-dal";
|
||||||
|
import { OrgServiceActor, TProjectPermission } from "@app/lib/types";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
import { TProjectSshConfigDALFactory } from "@app/services/project/project-ssh-config-dal";
|
import { TProjectSshConfigDALFactory } from "@app/services/project/project-ssh-config-dal";
|
||||||
import { OrgServiceActor, TProjectPermission } from "@app/lib/types";
|
|
||||||
|
|
||||||
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
|
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export type TSecretRotationProviderTemplate = {
|
|||||||
image?: string;
|
image?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
template: THttpProviderTemplate | TDbProviderTemplate;
|
template: THttpProviderTemplate | TDbProviderTemplate;
|
||||||
|
isDeprecated?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type THttpProviderTemplate = {
|
export type THttpProviderTemplate = {
|
||||||
|
|||||||
@@ -38,7 +38,12 @@ import {
|
|||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { NoticeBannerV2 } from "@app/components/v2/NoticeBannerV2/NoticeBannerV2";
|
import { NoticeBannerV2 } from "@app/components/v2/NoticeBannerV2/NoticeBannerV2";
|
||||||
import { ProjectPermissionSub, useWorkspace } from "@app/context";
|
import {
|
||||||
|
ProjectPermissionSub,
|
||||||
|
useProjectPermission,
|
||||||
|
useSubscription,
|
||||||
|
useWorkspace
|
||||||
|
} from "@app/context";
|
||||||
import { ProjectPermissionSecretRotationActions } from "@app/context/ProjectPermissionContext/types";
|
import { ProjectPermissionSecretRotationActions } from "@app/context/ProjectPermissionContext/types";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import {
|
import {
|
||||||
@@ -47,20 +52,29 @@ import {
|
|||||||
useGetSecretRotations,
|
useGetSecretRotations,
|
||||||
useRestartSecretRotation
|
useRestartSecretRotation
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
|
import { TSecretRotationProviderTemplate } from "@app/hooks/api/secretRotation/types";
|
||||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
import { CreateRotationForm } from "@app/pages/secret-manager/SecretRotationPage/components/CreateRotationForm";
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
|
const { permission } = useProjectPermission();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
||||||
|
"createRotation",
|
||||||
"activeBot",
|
"activeBot",
|
||||||
"deleteRotation",
|
"deleteRotation",
|
||||||
"upgradePlan",
|
"upgradePlan",
|
||||||
"secretRotationV2"
|
"secretRotationV2"
|
||||||
] as const);
|
] as const);
|
||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
|
const canCreateRotation = permission.can(
|
||||||
|
ProjectPermissionSecretRotationActions.Create,
|
||||||
|
ProjectPermissionSub.SecretRotation
|
||||||
|
);
|
||||||
|
const { subscription } = useSubscription();
|
||||||
|
|
||||||
const { data: secretRotationProviders, isPending: isRotationProviderLoading } =
|
const { data: secretRotationProviders, isPending: isRotationProviderLoading } =
|
||||||
useGetSecretRotationProviders({ workspaceId });
|
useGetSecretRotationProviders({ workspaceId });
|
||||||
@@ -119,6 +133,18 @@ const Page = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCreateRotation = (provider: TSecretRotationProviderTemplate) => {
|
||||||
|
if (subscription && !subscription?.secretRotation) {
|
||||||
|
handlePopUpOpen("upgradePlan");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!canCreateRotation) {
|
||||||
|
createNotification({ type: "error", text: "Access permission denied!!" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handlePopUpOpen("createRotation", provider);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto w-full max-w-7xl bg-bunker-800 text-white">
|
<div className="container mx-auto w-full max-w-7xl bg-bunker-800 text-white">
|
||||||
<PageHeader
|
<PageHeader
|
||||||
@@ -144,7 +170,7 @@ const Page = () => {
|
|||||||
Infisical is revamping its Secret Rotation experience.
|
Infisical is revamping its Secret Rotation experience.
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-2 text-sm text-bunker-200">
|
<p className="mt-2 text-sm text-bunker-200">
|
||||||
Secret Rotations can now be created from the{" "}
|
PostgreSQL and Microsoft SQL Server Rotations can now be created from the{" "}
|
||||||
<Link
|
<Link
|
||||||
className="text-mineshaft-100 underline decoration-primary underline-offset-2 hover:text-mineshaft-200"
|
className="text-mineshaft-100 underline decoration-primary underline-offset-2 hover:text-mineshaft-200"
|
||||||
to={`/${ProjectType.SecretManager}/$projectId/overview` as const}
|
to={`/${ProjectType.SecretManager}/$projectId/overview` as const}
|
||||||
@@ -308,11 +334,20 @@ const Page = () => {
|
|||||||
key={`infisical-rotation-provider-${provider.name}`}
|
key={`infisical-rotation-provider-${provider.name}`}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
role="button"
|
role="button"
|
||||||
onKeyDown={() => {
|
onKeyDown={(evt) => {
|
||||||
handlePopUpOpen("secretRotationV2", provider.title);
|
if (evt.key !== "Enter") return;
|
||||||
|
if (provider.isDeprecated) {
|
||||||
|
handlePopUpOpen("secretRotationV2", provider.title);
|
||||||
|
} else {
|
||||||
|
handleCreateRotation(provider);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("secretRotationV2", provider.title);
|
if (provider.isDeprecated) {
|
||||||
|
handlePopUpOpen("secretRotationV2", provider.title);
|
||||||
|
} else {
|
||||||
|
handleCreateRotation(provider);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
@@ -344,6 +379,12 @@ const Page = () => {
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<CreateRotationForm
|
||||||
|
isOpen={popUp.createRotation.isOpen}
|
||||||
|
workspaceId={workspaceId}
|
||||||
|
onToggle={(isOpen) => handlePopUpToggle("createRotation", isOpen)}
|
||||||
|
provider={(popUp.createRotation.data as TSecretRotationProviderTemplate) || {}}
|
||||||
|
/>
|
||||||
<DeleteActionModal
|
<DeleteActionModal
|
||||||
isOpen={popUp.deleteRotation.isOpen}
|
isOpen={popUp.deleteRotation.isOpen}
|
||||||
title="Are you sure want to delete this rotation?"
|
title="Are you sure want to delete this rotation?"
|
||||||
@@ -372,7 +413,7 @@ const Page = () => {
|
|||||||
>
|
>
|
||||||
Secret Manager Dashboard
|
Secret Manager Dashboard
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
to create a Secret Rotation.
|
to create a {popUp.secretRotationV2.data} Rotation.
|
||||||
</p>
|
</p>
|
||||||
<div className="overflow-clip rounded border border-mineshaft-600">
|
<div className="overflow-clip rounded border border-mineshaft-600">
|
||||||
<img
|
<img
|
||||||
|
|||||||
Reference in New Issue
Block a user