improvements: address feedback

This commit is contained in:
Scott Wilson
2025-01-24 20:21:21 -08:00
parent 598d14fc54
commit 79a616dc1c
8 changed files with 278 additions and 226 deletions

View File

@@ -21,7 +21,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
secretVersioning: true,
pitRecovery: false,
ipAllowlisting: false,
rbac: false,
rbac: true,
customRateLimits: false,
customAlerts: false,
secretAccessInsights: false,

View File

@@ -278,13 +278,7 @@ export const IdentityJwtAuthForm = ({
<form
onSubmit={handleSubmit(onFormSubmit, (fields) => {
setTabValue(
[
"accessTokenTrustedIps",
"boundIssuer",
"boundAudiences",
"boundSubject",
"boundClaims"
].includes(Object.keys(fields)[0])
["accessTokenTrustedIps"].includes(Object.keys(fields)[0])
? IdentityFormTab.Advanced
: IdentityFormTab.Configuration
);
@@ -365,7 +359,6 @@ export const IdentityJwtAuthForm = ({
/>
</>
)}
{selectedConfigurationType === IdentityJwtConfigurationType.STATIC && (
<>
{publicKeyFields.map(({ id }, index) => (
@@ -430,50 +423,6 @@ export const IdentityJwtAuthForm = ({
</div>
</>
)}
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
</TabPanel>
<TabPanel value={IdentityFormTab.Advanced}>
<Controller
control={control}
name="boundIssuer"
@@ -604,6 +553,50 @@ export const IdentityJwtAuthForm = ({
Add Claims
</Button>
</div>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
name="accessTokenMaxTTL"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max TTL (seconds)"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="2592000" type="number" min="1" step="1" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="0"
name="accessTokenNumUsesLimit"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Access Token Max Number of Uses"
isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="0" type="number" min="0" step="1" />
</FormControl>
)}
/>
</TabPanel>
<TabPanel value={IdentityFormTab.Advanced}>
{accessTokenTrustedIpsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller

View File

@@ -219,7 +219,9 @@ export const IdentityKubernetesAuthForm = ({
"tokenReviewerJwt",
"accessTokenTTL",
"accessTokenMaxTTL",
"accessTokenNumUsesLimit"
"accessTokenNumUsesLimit",
"allowedNames",
"allowedNamespaces"
].includes(Object.keys(fields)[0])
? IdentityFormTab.Configuration
: IdentityFormTab.Advanced
@@ -263,6 +265,35 @@ export const IdentityKubernetesAuthForm = ({
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedNamespaces"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Namespaces"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="A comma-separated list of trusted namespaces that service accounts must belong to authenticate with Infisical."
>
<Input {...field} placeholder="namespaceA, namespaceB" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="allowedNames"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Account Names"
isError={Boolean(error)}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any service account."
errorText={error?.message}
>
<Input {...field} placeholder="service-account-1-name, service-account-1-name" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
@@ -310,35 +341,6 @@ export const IdentityKubernetesAuthForm = ({
/>
</TabPanel>
<TabPanel value={IdentityFormTab.Advanced}>
<Controller
control={control}
name="allowedNames"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Service Account Names"
isError={Boolean(error)}
tooltipText="An optional comma-separated list of trusted service account names that are allowed to authenticate with Infisical. Leave empty to allow any service account."
errorText={error?.message}
>
<Input {...field} placeholder="service-account-1-name, service-account-1-name" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""
name="allowedNamespaces"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Allowed Namespaces"
isError={Boolean(error)}
errorText={error?.message}
tooltipText="A comma-separated list of trusted namespaces that service accounts must belong to authenticate with Infisical."
>
<Input {...field} placeholder="namespaceA, namespaceB" type="text" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue=""

View File

@@ -223,13 +223,7 @@ export const IdentityOidcAuthForm = ({
<form
onSubmit={handleSubmit(onFormSubmit, (fields) => {
setTabValue(
[
"accessTokenTrustedIps",
"caCert",
"boundAudiences",
"boundSubject",
"boundClaims"
].includes(Object.keys(fields)[0])
["accessTokenTrustedIps", "caCert", "boundClaims"].includes(Object.keys(fields)[0])
? IdentityFormTab.Advanced
: IdentityFormTab.Configuration
);
@@ -277,6 +271,48 @@ export const IdentityOidcAuthForm = ({
</FormControl>
)}
/>
<Controller
control={control}
name="boundSubject"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Subject"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="boundAudiences"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Audiences"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" placeholder="service1, service2" />
</FormControl>
)}
/>
<Controller
control={control}
defaultValue="2592000"
@@ -334,48 +370,6 @@ export const IdentityOidcAuthForm = ({
</FormControl>
)}
/>
<Controller
control={control}
name="boundSubject"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Subject"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" />
</FormControl>
)}
/>
<Controller
control={control}
name="boundAudiences"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Audiences"
isError={Boolean(error)}
errorText={error?.message}
icon={
<Tooltip
className="text-center"
content={<span>This field supports glob patterns</span>}
>
<FontAwesomeIcon icon={faQuestionCircle} size="sm" />
</Tooltip>
}
>
<Input {...field} type="text" placeholder="service1, service2" />
</FormControl>
)}
/>
{boundClaimsFields.map(({ id }, index) => (
<div className="mb-3 flex items-end space-x-2" key={id}>
<Controller

View File

@@ -1,7 +1,9 @@
import { faCog, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { OrgPermissionCan } from "@app/components/permissions";
import { Button } from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { IdentityAuthMethod, identityAuthToNameMap, useGetIdentityById } from "@app/hooks/api";
import { UsePopUpState } from "@app/hooks/usePopUp";
@@ -45,21 +47,26 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
{!Object.values(IdentityAuthMethod).every((method) =>
data.identity.authMethods.includes(method)
) && (
<Button
onClick={() => {
handlePopUpOpen("identityAuthMethod", {
identityId,
name: data.identity.name,
allAuthMethods: data.identity.authMethods
});
}}
variant="outline_bg"
className="mt-3 w-full"
size="xs"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
{data.identity.authMethods.length ? "Add" : "Create"} Auth Method
</Button>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Identity}>
{(isAllowed) => (
<Button
isDisabled={!isAllowed}
onClick={() => {
handlePopUpOpen("identityAuthMethod", {
identityId,
name: data.identity.name,
allAuthMethods: data.identity.authMethods
});
}}
variant="outline_bg"
className="mt-3 w-full"
size="xs"
leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
{data.identity.authMethods.length ? "Add" : "Create"} Auth Method
</Button>
)}
</OrgPermissionCan>
)}
</div>
) : (

View File

@@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
Button,
DeleteActionModal,
@@ -19,6 +20,7 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { usePopUp } from "@app/hooks";
import { useRevokeIdentityTokenAuthToken } from "@app/hooks/api";
import { IdentityAccessToken } from "@app/hooks/api/identities/types";
@@ -77,18 +79,23 @@ export const IdentityTokenAuthTokensTable = ({ tokens, identityId }: Props) => {
<div className="col-span-2 mt-3">
<div className="flex items-end justify-between border-b border-mineshaft-500 pb-2">
<span className="text-bunker-300">Access Tokens</span>
<Button
size="xs"
onClick={() => {
handlePopUpOpen("token", {
identityId
});
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
colorSchema="secondary"
>
Add Token
</Button>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Identity}>
{(isAllowed) => (
<Button
size="xs"
isDisabled={!isAllowed}
onClick={() => {
handlePopUpOpen("token", {
identityId
});
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
colorSchema="secondary"
>
Add Token
</Button>
)}
</OrgPermissionCan>
</div>
<TableContainer className="mt-4 rounded-none border-none">
<Table>
@@ -136,40 +143,56 @@ export const IdentityTokenAuthTokensTable = ({ tokens, identityId }: Props) => {
</Td>
<Td>
<div className="flex items-center gap-2">
<Tooltip content="Edit Token">
<IconButton
onClick={() => {
handlePopUpOpen("token", {
identityId,
tokenId: id,
name
});
}}
size="xs"
variant="plain"
ariaLabel="Edit token"
>
<FontAwesomeIcon icon={faEdit} />
</IconButton>
</Tooltip>
<OrgPermissionCan
I={OrgPermissionActions.Edit}
a={OrgPermissionSubjects.Identity}
>
{(isAllowed) => (
<Tooltip content={isAllowed ? "Edit Token" : "Access Restricted"}>
<IconButton
isDisabled={!isAllowed}
onClick={() => {
handlePopUpOpen("token", {
identityId,
tokenId: id,
name
});
}}
size="xs"
variant="plain"
ariaLabel="Edit token"
>
<FontAwesomeIcon icon={faEdit} />
</IconButton>
</Tooltip>
)}
</OrgPermissionCan>
{!isAccessTokenRevoked && (
<Tooltip content="Revoke Token">
<IconButton
onClick={() => {
handlePopUpOpen("revokeToken", {
identityId,
tokenId: id,
name
});
}}
size="xs"
colorSchema="danger"
variant="plain"
ariaLabel="Revoke token"
>
<FontAwesomeIcon icon={faBan} />
</IconButton>
</Tooltip>
<OrgPermissionCan
I={OrgPermissionActions.Edit}
a={OrgPermissionSubjects.Identity}
>
{(isAllowed) => (
<Tooltip content={isAllowed ? "Revoke Token" : "Access Restricted"}>
<IconButton
isDisabled={!isAllowed}
onClick={() => {
handlePopUpOpen("revokeToken", {
identityId,
tokenId: id,
name
});
}}
size="xs"
colorSchema="danger"
variant="plain"
ariaLabel="Revoke token"
>
<FontAwesomeIcon icon={faBan} />
</IconButton>
</Tooltip>
)}
</OrgPermissionCan>
)}
</div>
</Td>

View File

@@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
Button,
DeleteActionModal,
@@ -19,6 +20,7 @@ import {
Tooltip,
Tr
} from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
import { usePopUp } from "@app/hooks";
import { useRevokeIdentityUniversalAuthClientSecret } from "@app/hooks/api";
import { ClientSecretData } from "@app/hooks/api/identities/types";
@@ -66,18 +68,23 @@ export const IdentityUniversalAuthClientSecretsTable = ({ clientSecrets, identit
<div className="col-span-2">
<div className="flex items-end justify-between border-b border-mineshaft-500 pb-2">
<span className="text-bunker-300">Client Secrets</span>
<Button
size="xs"
onClick={() => {
handlePopUpOpen("clientSecret", {
identityId
});
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
colorSchema="secondary"
>
Add Client Secret
</Button>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Identity}>
{(isAllowed) => (
<Button
isDisabled={!isAllowed}
size="xs"
onClick={() => {
handlePopUpOpen("clientSecret", {
identityId
});
}}
leftIcon={<FontAwesomeIcon icon={faPlus} />}
colorSchema="secondary"
>
Add Client Secret
</Button>
)}
</OrgPermissionCan>
</div>
<TableContainer className="mt-4 rounded-none border-none">
<Table>
@@ -121,22 +128,30 @@ export const IdentityUniversalAuthClientSecretsTable = ({ clientSecrets, identit
{expiresAt ? format(expiresAt, "yyyy-MM-dd") : "-"}
</Td>
<Td>
<Tooltip content="Delete Secret">
<IconButton
onClick={() => {
handlePopUpOpen("revokeClientSecret", {
clientSecretPrefix,
clientSecretId: id
});
}}
size="xs"
colorSchema="danger"
variant="plain"
ariaLabel="Delete secret"
>
<FontAwesomeIcon icon={faTrash} />
</IconButton>
</Tooltip>
<OrgPermissionCan
I={OrgPermissionActions.Edit}
a={OrgPermissionSubjects.Identity}
>
{(isAllowed) => (
<Tooltip content={isAllowed ? "Delete Secret" : "Access Restricted"}>
<IconButton
isDisabled={!isAllowed}
onClick={() => {
handlePopUpOpen("revokeClientSecret", {
clientSecretPrefix,
clientSecretId: id
});
}}
size="xs"
colorSchema="danger"
variant="plain"
ariaLabel="Delete secret"
>
<FontAwesomeIcon icon={faTrash} />
</IconButton>
</Tooltip>
)}
</OrgPermissionCan>
</Td>
</Tr>
);

View File

@@ -2,6 +2,7 @@ import { ReactNode } from "react";
import { faChevronDown, faEdit, faTrash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { OrgPermissionCan } from "@app/components/permissions";
import {
Button,
DropdownMenu,
@@ -9,6 +10,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger
} from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
type Props = {
children: ReactNode;
@@ -34,12 +36,28 @@ export const ViewIdentityContentWrapper = ({ children, onDelete, onEdit }: Props
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="min-w-[120px]" align="end">
<DropdownMenuItem onClick={onEdit} icon={<FontAwesomeIcon icon={faEdit} />}>
Edit
</DropdownMenuItem>
<DropdownMenuItem onClick={onDelete} icon={<FontAwesomeIcon icon={faTrash} />}>
Delete
</DropdownMenuItem>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Identity}>
{(isAllowed) => (
<DropdownMenuItem
isDisabled={!isAllowed}
onClick={onEdit}
icon={<FontAwesomeIcon icon={faEdit} />}
>
Edit
</DropdownMenuItem>
)}
</OrgPermissionCan>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Identity}>
{(isAllowed) => (
<DropdownMenuItem
isDisabled={!isAllowed}
onClick={onDelete}
icon={<FontAwesomeIcon icon={faTrash} />}
>
Delete
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent>
</DropdownMenu>
</div>