Compare commits

..

9 Commits

Author SHA1 Message Date
51d68505d3 Merge pull request #1268 from Infisical/posthog-revamp
removed posthog cli export events
2023-12-29 15:18:59 -05:00
683c512bce Merge pull request #1266 from Infisical/ui-improvements
ui and docs improvements
2023-12-25 14:33:47 -05:00
43ff28b5fb added terraform useragent 2023-12-24 17:13:29 -08:00
ce41855e84 added sdk useragent and channel 2023-12-24 16:58:48 -08:00
d24461b17c removed posthog cli export events 2023-12-24 15:49:18 -08:00
1797e56f9f fixed sdk guides 2023-12-24 13:30:59 -08:00
74f3ca5356 Merge pull request #1267 from Infisical/sdk/docs-update-2
Sdk/docs update 2
2023-12-24 21:57:52 +04:00
597c9d6f2a fix docs sdk errors 2023-12-23 17:17:10 -08:00
24d2eea930 ui and docs improvements 2023-12-23 16:06:00 -08:00
22 changed files with 174 additions and 92 deletions

View File

@ -8,7 +8,10 @@ export enum UserAgentType {
WEB = "web",
CLI = "cli",
K8_OPERATOR = "k8-operator",
OTHER = "other"
TERRAFORM = "terraform",
OTHER = "other",
PYTHON_SDK = "InfisicalPythonSDK",
NODE_SDK = "InfisicalNodeSDK"
}
export enum EventType {

View File

@ -7,8 +7,14 @@ export const getUserAgentType = function (userAgent: string | undefined) {
return UserAgentType.CLI;
} else if (userAgent == UserAgentType.K8_OPERATOR) {
return UserAgentType.K8_OPERATOR;
} else if (userAgent == UserAgentType.TERRAFORM) {
return UserAgentType.TERRAFORM;
} else if (userAgent.toLowerCase().includes("mozilla")) {
return UserAgentType.WEB;
} else if (userAgent.includes(UserAgentType.NODE_SDK)) {
return UserAgentType.NODE_SDK;
} else if (userAgent.includes(UserAgentType.PYTHON_SDK)) {
return UserAgentType.PYTHON_SDK;
} else {
return UserAgentType.OTHER;
}

View File

@ -102,7 +102,7 @@ var exportCmd = &cobra.Command{
fmt.Print(output)
Telemetry.CaptureEvent("cli-command:export", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("version", util.CLI_VERSION))
// Telemetry.CaptureEvent("cli-command:export", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("version", util.CLI_VERSION))
},
}

View File

@ -7,6 +7,7 @@ The changelog below reflects new product developments and updates on a monthly b
## December 2023
- Added ability to [manage folders via CLI](https://infisical.com/docs/cli/commands/secrets).
- Created new cross-language SDKs for [Python](https://infisical.com/docs/sdks/languages/python), [Node](https://infisical.com/docs/sdks/languages/node), and [Java](https://infisical.com/docs/sdks/languages/java).
## November 2023

View File

@ -13,7 +13,8 @@ Prerequisites:
Follow the instructions for your language use the SDK for it:
- [Node SDK](https://github.com/Infisical/infisical-node)
- [Python SDK](https://github.com/Infisical/infisical-python)
- [Node SDK](https://infisical.com/docs/sdks/languages/node)
- [Python SDK](https://infisical.com/docs/sdks/languages/python)
- [Java SDK](https://infisical.com/docs/sdks/languages/java)
Missing a language? [Throw in a request](https://github.com/Infisical/infisical/issues).

View File

@ -240,12 +240,6 @@ At this stage, you know how to use the Infisical-Vercel integration to sync prod
Check out the [security guide](/security/overview).
</Accordion>
<Accordion title="Is there way to retain end-to-end encryption for syncing production secrets to Vercel?">
Yes. You can also use the Infisical [Node SDK](https://github.com/Infisical/infisical-node) to fetch secrets back to your Next.js app
in both development and production.
Depending on how you use it, however, it may require certain pages to be server-side rendered.
</Accordion>
</AccordionGroup>
See also:

View File

@ -4,8 +4,7 @@ description: "Programmatically interact with Infisical"
---
<Note>
Currently, identities can only be used to make authenticated requests to the Infisical API and do not work with any clients such as [Node SDK](https://github.com/Infisical/infisical-node)
, [Python SDK](https://github.com/Infisical/infisical-python), CLI, K8s operator, Terraform Provider, etc.
Currently, identities can only be used to make authenticated requests to the Infisical API and SDKs. They do not work with clients such as CLI, K8s Operator, Terraform Provider, etc.
We will be releasing compatibility with it across clients in the coming quarter.
</Note>

View File

@ -12,8 +12,8 @@ This means that updating the value of a base secret propagates directly to other
Currently, the secret referencing feature is only supported by the
[Infisical CLI](/cli/overview) and [native integrations](/integrations/overview).
We intend to add support for it to the [Node SDK](https://github.com/Infisical/infisical-node)
and [Python SDK](https://github.com/Infisical/infisical-python) this quarter.
We intend to add support for it to the [Node SDK](https://infisical.com/docs/sdks/languages/node),
[Python SDK](https://infisical.com/docs/sdks/languages/python), and [Java SDK](https://infisical.com/docs/sdks/languages/java) this quarter.
</Note>
![secret referencing](../../images/platform/secret-references-imports/secret-reference.png)

View File

@ -25,6 +25,6 @@ The Web UI is the browser-based portal that connects to the Infisical API.
Clients are any application or infrastructure that connecting to the Infisical API using one of the below methods:
- Public API: Making API requests directly to the Infisical API.
- Client SDK: A platform-specific library with method abstractions for working with secrets. Currently, there are two official SDKs: [Node SDK](https://github.com/Infisical/infisical-node) and [Python SDK](https://github.com/Infisical/infisical-python).
- Client SDK: A platform-specific library with method abstractions for working with secrets. Currently, there are three official SDKs: [Node SDK](https://infisical.com/docs/sdks/languages/node), [Python SDK](https://infisical.com/docs/sdks/languages/python), and [Java SDK](https://infisical.com/docs/sdks/languages/java).
- CLI: A terminal-based interface for interacting with the Infisical API.
- Kubernetes Operator: This operator retrieves secrets from Infisical and securely store

View File

@ -50,5 +50,8 @@ export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
[UserAgentType.WEB]: "Web",
[UserAgentType.CLI]: "CLI",
[UserAgentType.K8_OPERATOR]: "K8s operator",
[UserAgentType.TERRAFORM]: "Terraform",
[UserAgentType.NODE_SDK]: "InfisicalNodeSDK",
[UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK",
[UserAgentType.OTHER]: "Other",
};

View File

@ -8,6 +8,9 @@ export enum UserAgentType {
WEB = "web",
CLI = "cli",
K8_OPERATOR = "k8-operator",
TERRAFORM = "terraform",
NODE_SDK = "node-sdk",
PYTHON_SDK = "python-sdk",
OTHER = "other"
}

View File

@ -716,6 +716,12 @@ export const AppLayout = ({ children }: LayoutProps) => {
</a>
</DropdownMenuItem>
))}
{infisicalPlatformVersion && (
<div className="cursor-default mb-2 mt-2 w-full pl-5 duration-200 hover:text-mineshaft-200 text-sm">
<FontAwesomeIcon icon={faInfo} className="mr-4 px-[0.1rem]" />
Version: {infisicalPlatformVersion}
</div>
)}
</DropdownMenuContent>
</DropdownMenu>
{subscription &&
@ -745,12 +751,6 @@ export const AppLayout = ({ children }: LayoutProps) => {
</div>
</button>
)}
{infisicalPlatformVersion && (
<div className="mb-2 w-full pl-5 duration-200 hover:text-mineshaft-200">
<FontAwesomeIcon icon={faInfo} className="mr-4 px-[0.1rem]" />
Version: {infisicalPlatformVersion}
</div>
)}
</div>
</nav>
</aside>

View File

@ -67,8 +67,16 @@ const features = [
{
_id: 0,
name: "Kubernetes Operator",
link: "https://infisical.com/docs/documentation/getting-started/kubernetes",
description:
"Pull secrets into your Kubernetes containers and automatically redeploy upon secret changes."
},
{
_id: 1,
name: "Infisical Agent",
link: "https://infisical.com/docs/infisical-agent/overview",
description:
"Inject secrets into your apps without modifying any application logic."
}
];
@ -691,11 +699,44 @@ const OrganizationPage = withPermission(
</div>
)}
</div>
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-6 text-3xl">
<p className="mr-4 font-semibold text-white">Explore Infisical</p>
<div className="mt-4 grid grid-cols-3 w-full gap-4">
{features.map((feature) => (
<div
key={feature._id}
className="flex h-44 w-full flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
>
<div className="mt-0 text-lg text-mineshaft-100">{feature.name}</div>
<div className="mb-4 mt-2 text-[15px] font-light text-mineshaft-300">
{feature.description}
</div>
<div className="flex w-full items-center">
<div className="text-[15px] font-light text-mineshaft-300">
Setup time: 20 min
</div>
<a
target="_blank"
rel="noopener noreferrer"
className="group ml-auto w-max cursor-default rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200"
href={feature.link}
>
Learn more{" "}
<FontAwesomeIcon
icon={faArrowRight}
className="pl-1.5 pr-0.5 duration-200 group-hover:pl-2 group-hover:pr-0"
/>
</a>
</div>
</div>
))}
</div>
</div>
{!(
new Date().getTime() - new Date(user?.createdAt).getTime() <
30 * 24 * 60 * 60 * 1000
) && (
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl">
<div className="mb-4 flex flex-col items-start justify-start px-6 pb-6 pb-0 text-3xl">
<p className="mr-4 mb-4 font-semibold text-white">Onboarding Guide</p>
<div className="mb-3 grid w-full grid-cols-1 gap-3 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
<LearningItemSquare
@ -784,42 +825,6 @@ const OrganizationPage = withPermission(
)}
</div>
)}
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-6 text-3xl">
<p className="mr-4 font-semibold text-white">Explore More</p>
<div
className="mt-4 grid w-full grid-flow-dense gap-4"
style={{ gridTemplateColumns: "repeat(auto-fill, minmax(256px, 4fr))" }}
>
{features.map((feature) => (
<div
key={feature._id}
className="flex h-44 w-96 flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
>
<div className="mt-0 text-lg text-mineshaft-100">{feature.name}</div>
<div className="mb-4 mt-2 text-[15px] font-light text-mineshaft-300">
{feature.description}
</div>
<div className="flex w-full items-center">
<div className="text-[15px] font-light text-mineshaft-300">
Setup time: 20 min
</div>
<a
target="_blank"
rel="noopener noreferrer"
className="group ml-auto w-max cursor-default rounded-full border border-mineshaft-600 bg-mineshaft-900 py-2 px-4 text-sm text-mineshaft-300 hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200"
href="https://infisical.com/docs/documentation/getting-started/kubernetes"
>
Learn more{" "}
<FontAwesomeIcon
icon={faArrowRight}
className="pl-1.5 pr-0.5 duration-200 group-hover:pl-2 group-hover:pr-0"
/>
</a>
</div>
</div>
))}
</div>
</div>
<Modal
isOpen={popUp.addNewWs.isOpen}
onOpenChange={(isModalOpen) => {

View File

@ -1,4 +1,5 @@
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import Link from "next/link";
import { faArrowUpRightFromSquare, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
@ -65,17 +66,24 @@ export const IdentitySection = withPermission(
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<div className="flex justify-between mb-4">
<p className="text-xl font-semibold text-mineshaft-100">
Identities
</p>
<div className="flex justify-end w-full pr-4">
<Link href="https://infisical.com/docs/documentation/platform/identities/overview">
<span className="rounded-md px-4 py-2 w-max text-mineshaft-200 hover:text-white bg-mineshaft-600 border border-mineshaft-500 hover:bg-primary/10 hover:border-primary/40 duration-200 cursor-pointer">
Documentation <FontAwesomeIcon icon={faArrowUpRightFromSquare} className="text-xs mb-[0.06rem] ml-1"/>
</span>
</Link>
</div>
<OrgPermissionCan
I={OrgPermissionActions.Create}
a={OrgPermissionSubjects.Identity}
>
{(isAllowed) => (
<Button
colorSchema="secondary"
colorSchema="primary"
type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen("identity")}

View File

@ -89,7 +89,7 @@ export const OrgMembersSection = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<div className="flex justify-between mb-4">
<p className="text-xl font-semibold text-mineshaft-100">
Members
</p>
@ -99,7 +99,7 @@ export const OrgMembersSection = () => {
>
{(isAllowed) => (
<Button
colorSchema="secondary"
colorSchema="primary"
type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handleAddMemberModal()}

View File

@ -191,9 +191,9 @@ export const IdentityModal = ({
</form>
) : (
<div className="flex flex-col space-y-4">
<div>All identities in your organization are already added.</div>
<div className="text-sm">All identities in your organization have already been added to this project.</div>
<Link href={`/org/${currentWorkspace?.organization}/members`}>
<Button variant="outline_bg">Create a new/another identities</Button>
<Button variant="outline_bg">Create a new identity</Button>
</Link>
</div>
)}

View File

@ -1,4 +1,5 @@
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import Link from "next/link";
import { faArrowUpRightFromSquare, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
@ -61,17 +62,24 @@ export const IdentitySection = withProjectPermission(
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<div className="flex justify-between items-center mb-4">
<p className="text-xl font-semibold text-mineshaft-100">
Identities
</p>
<div className="flex justify-end w-full pr-4">
<Link href="https://infisical.com/docs/documentation/platform/identities/overview">
<span className="rounded-md px-4 py-2 w-max text-mineshaft-200 hover:text-white bg-mineshaft-600 border border-mineshaft-500 hover:bg-primary/10 hover:border-primary/40 duration-200 cursor-pointer">
Documentation <FontAwesomeIcon icon={faArrowUpRightFromSquare} className="text-xs mb-[0.06rem] ml-1"/>
</span>
</Link>
</div>
<ProjectPermissionCan
I={ProjectPermissionActions.Create}
a={ProjectPermissionSub.Identity}
>
{(isAllowed) => (
<Button
colorSchema="secondary"
colorSchema="primary"
type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen("identity")}

View File

@ -254,7 +254,7 @@ export const MemberListTab = () => {
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between mb-8">
<div className="flex justify-between items-center mb-4">
<p className="text-xl font-semibold text-mineshaft-100">
Members
</p>
@ -264,7 +264,7 @@ export const MemberListTab = () => {
>
{(isAllowed) => (
<Button
colorSchema="secondary"
colorSchema="primary"
type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen("addMember")}

View File

@ -1,3 +1,7 @@
import Link from "next/link";
import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
import { useWorkspace } from "@app/context";
@ -15,8 +19,18 @@ export const SecretApprovalPage = () => {
return (
<div className="container mx-auto bg-bunker-800 text-white w-full h-full max-w-7xl px-6">
<div className="my-6">
<p className="text-3xl font-semibold text-gray-200">Secret Approvals</p>
<div className="py-6 flex justify-between items-center">
<div className="flex flex-col w-full">
<h2 className="text-3xl font-semibold text-gray-200">Secret Approval Workflows</h2>
<p className="text-bunker-300">Create approval policies for any modifications to secrets in sensitive environments and folders.</p>
</div>
<div className="flex justify-center w-max">
<Link href="https://infisical.com/docs/documentation/platform/pr-workflows">
<span className="rounded-md px-4 py-2 w-max text-mineshaft-200 hover:text-white bg-mineshaft-600 border border-mineshaft-500 hover:bg-primary/10 hover:border-primary/40 duration-200 cursor-pointer">
Documentation <FontAwesomeIcon icon={faArrowUpRightFromSquare} className="text-xs mb-[0.06rem] ml-1"/>
</span>
</Link>
</div>
</div>
<Tabs defaultValue={TabSection.ApprovalRequests}>
<TabList>

View File

@ -108,11 +108,11 @@ export const FolderListView = ({
key={id}
className="flex group border-b border-mineshaft-600 hover:bg-mineshaft-700 cursor-pointer"
>
<div className="w-12 px-4 py-2 text-yellow-700 flex items-center">
<div className="w-11 px-5 py-3 text-yellow-700 flex items-center">
<FontAwesomeIcon icon={faFolder} />
</div>
<div
className="flex-grow px-4 py-2 flex items-center"
className="flex-grow px-4 py-3 flex items-center"
role="button"
tabIndex={0}
onKeyDown={(evt) => {
@ -122,7 +122,7 @@ export const FolderListView = ({
>
{name}
</div>
<div className="px-3 py-2 flex items-center space-x-4 border-l border-mineshaft-600">
<div className="px-3 py-3 flex items-center space-x-4 border-l border-mineshaft-600">
<ProjectPermissionCan
I={ProjectPermissionActions.Edit}
a={subject(ProjectPermissionSub.Secrets, { environment, secretPath })}

View File

@ -270,22 +270,39 @@ export const SecretOverviewPage = () => {
<p className="text-md text-bunker-300">
Inject your secrets using
<a
className="mx-1 text-primary/80 hover:text-primary"
className="ml-1 text-mineshaft-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
href="https://infisical.com/docs/cli/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical CLI
</a>
or
</a>,
<a
className="mx-1 text-primary/80 hover:text-primary"
className="ml-1 text-mineshaft-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
href="https://infisical.com/docs/documentation/getting-started/api"
target="_blank"
rel="noopener noreferrer"
>
Infisical API
</a>
,
<a
className="ml-1 text-mineshaft-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
href="https://infisical.com/docs/sdks/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical SDKs
</a>
, and
<a
className="ml-1 text-mineshaft-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
href="https://infisical.com/docs/documentation/getting-started/introduction"
target="_blank"
rel="noopener noreferrer"
>
more
</a>.
</p>
</div>
<div className="mt-8 flex items-center justify-between">
@ -306,7 +323,7 @@ export const SecretOverviewPage = () => {
<THead>
<Tr className="sticky top-0 z-20 border-0">
<Th className="sticky left-0 z-20 min-w-[20rem] border-b-0 p-0">
<div className="flex items-center border-b border-r border-mineshaft-600 px-5 pt-4 pb-3.5">
<div className="flex items-center border-b border-r border-mineshaft-600 px-5 pt-3.5 pb-3">
Name
<IconButton
variant="plain"
@ -326,7 +343,7 @@ export const SecretOverviewPage = () => {
className="min-table-row min-w-[11rem] border-b-0 p-0 text-center"
key={`secret-overview-${name}-${index + 1}`}
>
<div className="flex items-center justify-center border-b border-mineshaft-600 px-5 pt-3.5 pb-3">
<div className="flex items-center justify-center border-b border-mineshaft-600 px-5 pt-3.5 pb-[0.83rem]">
<button
type="button"
className="text-sm font-medium duration-100 hover:text-mineshaft-100"
@ -382,7 +399,7 @@ export const SecretOverviewPage = () => {
</Td>
</Tr>
)}
{filteredFolderNames.map((folderName, index) => (
{!isTableLoading && filteredFolderNames.map((folderName, index) => (
<SecretOverviewFolderRow
folderName={folderName}
isFolderPresentInEnv={isFolderPresentInEnv}
@ -391,7 +408,7 @@ export const SecretOverviewPage = () => {
onClick={handleFolderClick}
/>
))}
{userAvailableEnvs?.length > 0 ? (
{!isTableLoading && (userAvailableEnvs?.length > 0 ? (
filteredSecretNames.map((key, index) => (
<SecretOverviewTableRow
secretPath={secretPath}
@ -407,7 +424,7 @@ export const SecretOverviewPage = () => {
))
) : (
<PermissionDeniedBanner />
)}
))}
</TBody>
<TFoot>
<Tr className="sticky bottom-0 z-10 border-0 bg-mineshaft-800">

View File

@ -1,9 +1,12 @@
import { useTranslation } from "react-i18next";
import Link from "next/link";
import {
faArrowsSpin,
faArrowUpRightFromSquare,
faExclamationTriangle,
faFolder,
faInfoCircle,
faPlus,
faRotate,
faTrash
} from "@fortawesome/free-solid-svg-icons";
@ -180,12 +183,21 @@ export const SecretRotationPage = withProjectPermission(
return (
<div className="container mx-auto bg-bunker-800 text-white w-full h-full max-w-7xl px-6">
<div className="my-6">
<h2 className="text-3xl font-semibold text-gray-200">Secret Rotation</h2>
<p className="text-bunker-300">Auto rotate secrets for better security</p>
<div className="py-6 flex justify-between items-center">
<div className="flex flex-col w-full">
<h2 className="text-3xl font-semibold text-gray-200">Secret Rotation</h2>
<p className="text-bunker-300">Stop manually rotating secrets and automate credential rotation.</p>
</div>
<div className="flex justify-center w-max">
<Link href="https://infisical.com/docs/documentation/platform/secret-rotation/overview">
<span className="rounded-md px-4 py-2 w-max text-mineshaft-200 hover:text-white bg-mineshaft-600 border border-mineshaft-500 hover:bg-primary/10 hover:border-primary/40 duration-200 cursor-pointer">
Documentation <FontAwesomeIcon icon={faArrowUpRightFromSquare} className="text-xs mb-[0.06rem] ml-1"/>
</span>
</Link>
</div>
</div>
<div className="mb-6">
<div className="text-xl font-semibold text-gray-200 mb-2">Rotated Secrets</div>
<div className="text-xl font-semibold text-gray-200 mb-2 mt-6">Rotated Secrets</div>
<div className="flex flex-col space-y-2">
<TableContainer>
<Table>
@ -322,7 +334,7 @@ export const SecretRotationPage = withProjectPermission(
</TableContainer>
</div>
</div>
<div className="text-xl font-semibold text-gray-200 mb-2">Infisical Rotation Providers</div>
<div className="text-xl font-semibold text-gray-200 mb-2 mt-12">Infisical Rotation Providers</div>
<div className="grid grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-4">
{isRotationProviderLoading &&
Array.from({ length: 12 }).map((_, index) => (
@ -331,7 +343,7 @@ export const SecretRotationPage = withProjectPermission(
{!isRotationProviderLoading &&
secretRotationProviders?.providers.map((provider) => (
<div
className="group relative cursor-pointer h-32 flex flex-row items-center rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
className="group relative cursor-pointer h-32 flex flex-row items-center rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4 hover:border-primary/40 hover:bg-primary/10"
key={`infisical-rotation-provider-${provider.name}`}
tabIndex={0}
role="button"
@ -349,13 +361,21 @@ export const SecretRotationPage = withProjectPermission(
<div className="ml-4 max-w-xs text-xl font-semibold text-gray-300 duration-200 group-hover:text-gray-200">
{provider.title}
</div>
<div className="group-hover:opacity-100 transition-all opacity-0 absolute top-1 right-1">
<div className="group-hover:opacity-100 transition-all opacity-0 absolute top-1 right-1.5">
<Tooltip content={provider.description} sideOffset={10}>
<FontAwesomeIcon icon={faInfoCircle} className="text-bunker-300" />
<FontAwesomeIcon icon={faInfoCircle} className="text-primary" />
</Tooltip>
</div>
</div>
))}
<Link href="https://github.com/Infisical/infisical/issues">
<div className="group relative cursor-pointer h-32 flex flex-row items-center rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4 hover:border-primary/40 hover:bg-primary/10">
<FontAwesomeIcon icon={faPlus} className="text-gray-300 text-3xl pl-3 pr-2" />
<div className="ml-4 max-w-xs text-xl font-semibold text-gray-300 duration-200 group-hover:text-gray-200">
Request or create your own template
</div>
</div>
</Link>
</div>
<CreateRotationForm
isOpen={popUp.createRotation.isOpen}