Merge branch 'main' into ENG-2633

This commit is contained in:
x
2025-04-30 00:54:37 -04:00
19 changed files with 248 additions and 76 deletions

View File

@@ -2,6 +2,8 @@
import { Knex } from "knex";
import { Tables } from "knex/types/tables";
import { TableName } from "@app/db/schemas";
import { DatabaseError } from "../errors";
import { buildDynamicKnexQuery, TKnexDynamicOperator } from "./dynamic";
@@ -25,28 +27,41 @@ export type TFindFilter<R extends object = object> = Partial<R> & {
$search?: Partial<{ [k in keyof R]: R[k] }>;
$complex?: TKnexDynamicOperator<R>;
};
export const buildFindFilter =
<R extends object = object>({ $in, $notNull, $search, $complex, ...filter }: TFindFilter<R>) =>
<R extends object = object>(
{ $in, $notNull, $search, $complex, ...filter }: TFindFilter<R>,
tableName?: TableName,
excludeKeys?: Array<keyof R>
) =>
(bd: Knex.QueryBuilder<R, R>) => {
void bd.where(filter);
const processedFilter = tableName
? Object.fromEntries(
Object.entries(filter)
.filter(([key]) => !excludeKeys || !excludeKeys.includes(key as keyof R))
.map(([key, value]) => [`${tableName}.${key}`, value])
)
: filter;
void bd.where(processedFilter);
if ($in) {
Object.entries($in).forEach(([key, val]) => {
if (val) {
void bd.whereIn(key as never, val as never);
void bd.whereIn([`${tableName ? `${tableName}.` : ""}${key}`] as never, val as never);
}
});
}
if ($notNull?.length) {
$notNull.forEach((key) => {
void bd.whereNotNull(key as never);
void bd.whereNotNull([`${tableName ? `${tableName}.` : ""}${key as string}`] as never);
});
}
if ($search) {
Object.entries($search).forEach(([key, val]) => {
if (val) {
void bd.whereILike(key as never, val as never);
void bd.whereILike([`${tableName ? `${tableName}.` : ""}${key}`] as never, val as never);
}
});
}

View File

@@ -15,13 +15,13 @@ export const blockLocalAndPrivateIpAddresses = async (url: string) => {
const validUrl = new URL(url);
const inputHostIps: string[] = [];
if (isIPv4(validUrl.host)) {
inputHostIps.push(validUrl.host);
if (isIPv4(validUrl.hostname)) {
inputHostIps.push(validUrl.hostname);
} else {
if (validUrl.host === "localhost" || validUrl.host === "host.docker.internal") {
if (validUrl.hostname === "localhost" || validUrl.hostname === "host.docker.internal") {
throw new BadRequestError({ message: "Local IPs not allowed as URL" });
}
const resolvedIps = await dns.resolve4(validUrl.host);
const resolvedIps = await dns.resolve4(validUrl.hostname);
inputHostIps.push(...resolvedIps);
}
const isInternalIp = inputHostIps.some((el) => isPrivateIp(el));

View File

@@ -10,7 +10,7 @@ import {
TTeamCitySyncWithCredentials
} from "@app/services/secret-sync/teamcity/teamcity-sync-types";
// Note: Most variables won't be returned with a value due to them being a "password" type (starting with "env.").
// Note: Most variables won't be returned with a value due to them being a "password" type.
// TeamCity API returns empty string for password-type variables for security reasons.
const listTeamCityVariables = async ({ instanceUrl, accessToken, project, buildConfig }: TTeamCityListVariables) => {
const { data } = await request.get<TTeamCityListVariablesResponse>(
@@ -25,12 +25,16 @@ const listTeamCityVariables = async ({ instanceUrl, accessToken, project, buildC
}
);
// Filters for only non-inherited environment variables
// Strips out "env." from map key, but the "name" field still has the original unaltered key.
return Object.fromEntries(
data.property.map((variable) => [
variable.name.startsWith("env.") ? variable.name.substring(4) : variable.name,
{ ...variable, value: variable.value || "" } // Password values will be empty strings from the API for security
])
data.property
.filter((variable) => !variable.inherited)
.filter((variable) => variable.name.startsWith("env."))
.map((variable) => [
variable.name.substring(4),
{ ...variable, value: variable.value || "" } // Password values will be empty strings from the API for security
])
);
};

View File

@@ -64,7 +64,8 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
const findOne = async (filter: Partial<TSecretsV2>, tx?: Knex) => {
try {
const docs = await (tx || db)(TableName.SecretV2)
.where(filter)
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.where(buildFindFilter(filter, TableName.SecretV2))
.leftJoin(
TableName.SecretV2JnTag,
`${TableName.SecretV2}.id`,

View File

@@ -2,7 +2,7 @@ import path from "node:path";
import RE2 from "re2";
import { TableName, TSecretFolders, TSecretsV2 } from "@app/db/schemas";
import { SecretType, TableName, TSecretFolders, TSecretsV2 } from "@app/db/schemas";
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { logger } from "@app/lib/logger";
@@ -720,7 +720,7 @@ export const reshapeBridgeSecret = (
secretReminderRecipients: secret.secretReminderRecipients || [],
...(secretValueHidden
? {
secretValue: INFISICAL_SECRET_VALUE_HIDDEN_MASK,
secretValue: secret.type === SecretType.Personal ? secret.value : INFISICAL_SECRET_VALUE_HIDDEN_MASK,
secretValueHidden: true
}
: {

View File

@@ -0,0 +1,40 @@
---
title: "Assume Privileges"
description: "Learn how to temporarily assume the privileges of a user or machine identity within a project."
---
This feature allows authorized users to temporarily take on the permissions of another user or identity. It helps administrators and access managers test and verify permissions before granting access, ensuring everything is set up correctly.
It also reduces back-and-forth with end users when troubleshooting permission-related issues.
## How It Works
When an authorized user activates assume privileges mode, they temporarily inherit the target user or identity’s permissions for up to one hour.
During this time, they can perform actions within the system with the same level of access as the target user.
- **Permission-based**: Only permissions are inherited, not the full identity
- **Time-limited**: Access automatically expires after one hour
- **Audited**: All actions are logged under the original user's account. This means any action taken during the session will be recorded under the entity assuming the privileges, not the target entity.
- **Authorization required**: Only users with the specific **assume privilege** permission can use this feature
- **Scoped to a single project**: You can only assume privileges for one project at a time
## How to Assume Privileges
<Steps>
<Step title="Go to Project Access">
Click on the user or identity you want to assume.
![Access control page](/images/platform/access-controls/assume-privileges/access-control.png)
</Step>
<Step title="Click Assume Privilege">
Click **Assume Privilege**, then type `assume` to confirm and start your session.
![Access control detail page](/images/platform/access-controls/assume-privileges/access-control-detail.png)
</Step>
<Step title="Session is Active">
You will see a yellow banner indicating that your assume privilege session is active. You can exit at any time by clicking **Exit**.
![session start](/images/platform/access-controls/assume-privileges/session-start.png)
</Step>
</Steps>

View File

@@ -9,6 +9,9 @@ This guide will walk you through the steps needed to configure external KMS supp
## Prerequisites
- An AWS KMS Key configured as a `Symmetric` key and with `Encrypt and Decrypt` key usage.
![Create AWS KMS Key](/images/platform/kms/aws/aws-kms-key-create.png)
Before you begin, you'll first need to choose a method of authentication with AWS from below.
<Tabs>

View File

@@ -268,11 +268,11 @@ For organizations that work with US government agencies, FIPS compliance is almo
<Steps>
<Step title="Create HSM client folder">
When using Kubernetes, you need to mount the path containing the HSM client files. This section covers how to configure your Infisical instance to use an HSM with Kubernetes.
When using Kubernetes, you need to mount the path containing the HSM client files. This section covers how to configure your Infisical instance to use an HSM with Kubernetes. In this example, we are going to be using `/etc/luna-docker`.
```bash
mkdir /etc/hsm-client
mkdir /etc/luna-docker
```
After [setting up your Luna Cloud HSM client](https://thalesdocs.com/gphsm/luna/7/docs/network/Content/install/client_install/add_dpod.htm), you should have a set of files, referred to as the HSM client. You don't need all the files, but for simplicity we recommend copying all the files from the client.
@@ -306,20 +306,60 @@ For organizations that work with US government agencies, FIPS compliance is almo
The most important parts of the client folder is the `Chrystoki.conf` file, and the `libs`, `plugins`, and `jsp` folders. You need to copy these files to the folder you created in the first step.
```bash
cp -r /<path-to-where-your-hsm-client-is-located> /etc/hsm-client
cp -r /<path-to-where-your-luna-client-is-located>/* /etc/luna-docker
```
<Note>
The `/*` wildcard will copy all files and folders within the HSM client. The wildcard is important to ensure that the file structure is inline with the rest of this guide.
</Note>
After copying the files, the `/etc/luna-docker` directory should have the following file structure:
```bash
$ ls -R /etc/luna-docker
Chrystoki.conf etc lock server-certificate.pem
Chrystoki.conf.tmp2E jsp partition-ca-certificate.pem setenv
lch-support-linux-64bit partition-certificate.pem
bin libs plugins
/etc/luna-docker/bin:
64
/etc/luna-docker/bin/64:
ckdemo cmu lunacm multitoken vtl
/etc/luna-docker/etc:
openssl.cnf
/etc/luna-docker/jsp:
64 LunaProvider.jar
/etc/luna-docker/jsp/64:
libLunaAPI.so
/etc/luna-docker/libs:
64
/etc/luna-docker/libs/64:
libCryptoki2.so
/etc/luna-docker/lock:
/etc/luna-docker/plugins:
libcloud.plugin
```
</Step>
<Step title="Update Chrystoki.conf">
The `Chrystoki.conf` file is used to configure the HSM client. You need to update the `Chrystoki.conf` file to point to the correct file paths.
In this example, we will be mounting the `/etc/hsm-client` folder from the host to containers in our deployment's pods at the path `/hsm-client`. This means the contents of `/etc/hsm-client` on the host will be accessible at `/hsm-client` within the containers.
In this example, we will be mounting the `/etc/luna-docker` folder from the host to containers in our deployment's pods at the path `/usr/safenet/lunaclient`. This means the contents of `/etc/luna-docker` on the host will be accessible at `/usr/safenet/lunaclient` within the containers.
An example config file will look like this:
```Chrystoki.conf
Chrystoki2 = {
# This path points to the mounted path, /hsm-client
LibUNIX64 = /hsm-client/libs/64/libCryptoki2.so;
# This path points to the mounted path, /usr/safenet/lunaclient
LibUNIX64 = /usr/safenet/lunaclient/libs/64/libCryptoki2.so;
}
Luna = {
@@ -339,8 +379,8 @@ For organizations that work with US government agencies, FIPS compliance is almo
Misc = {
# Update the paths to point to the mounted path if your folder structure is different from the one mentioned in the previous step.
PluginModuleDir = /hsm-client/plugins;
MutexFolder = /hsm-client/lock;
PluginModuleDir = /usr/safenet/lunaclient/plugins;
MutexFolder = /usr/safenet/lunaclient/lock;
PE1746Enabled = 1;
ToolsDir = /usr/bin;
@@ -353,7 +393,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
LunaSA Client = {
ReceiveTimeout = 20000;
# Update the paths to point to the mounted path if your folder structure is different from the one mentioned in the previous step.
SSLConfigFile = /hsm-client/etc/openssl.cnf;
SSLConfigFile = /usr/safenet/lunaclient/etc/openssl.cnf;
ClientPrivKeyFile = ./etc/ClientNameKey.pem;
ClientCertFile = ./etc/ClientNameCert.pem;
ServerCAFile = ./etc/CAFile.pem;
@@ -441,7 +481,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
```bash
kubectl exec hsm-setup-pod -- mkdir -p /data/ # Create the data directory
kubectl cp ./hsm-client/ hsm-setup-pod:/data/ # Copy the HSM client files into the PVC
kubectl cp /etc/luna-docker/. hsm-setup-pod:/data/ # Copy the HSM client files into the PVC
kubectl exec hsm-setup-pod -- chmod -R 755 /data/ # Set the correct permissions for the HSM client files
```
@@ -456,7 +496,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
Next we need to update the environment variables used for the deployment. If you followed the [setup instructions for Kubernetes deployments](/self-hosting/deployment-options/kubernetes-helm), you should have a Kubernetes secret called `infisical-secrets`.
We need to update the secret with the following environment variables:
- `HSM_LIB_PATH` - The path to the HSM client library _(mapped to `/hsm-client/libs/64/libCryptoki2.so`)_
- `HSM_LIB_PATH` - The path to the HSM client library _(mapped to `/usr/safenet/lunaclient/libs/64/libCryptoki2.so`)_
- `HSM_PIN` - The PIN for the HSM device that you created when setting up your Luna Cloud HSM client
- `HSM_SLOT` - The slot number for the HSM device that you selected when setting up your Luna Cloud HSM client
- `HSM_KEY_LABEL` - The label for the HSM key. If no key is found with the provided key label, the HSM will create a new key with the provided label.
@@ -471,7 +511,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
type: Opaque
stringData:
# ... Other environment variables ...
HSM_LIB_PATH: "/hsm-client/libs/64/libCryptoki2.so" # If you followed this guide, this will be the path of the Luna Cloud HSM client
HSM_LIB_PATH: "/usr/safenet/lunaclient/libs/64/libCryptoki2.so" # If you followed this guide, this will be the path of the Luna Cloud HSM client
HSM_PIN: "<your-hsm-device-pin>"
HSM_SLOT: "<hsm-device-slot>"
HSM_KEY_LABEL: "<your-key-label>"
@@ -487,7 +527,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
<Step title="Updating the Deployment">
After we've successfully configured the PVC and updated our environment variables, we are ready to update the deployment configuration so that the pods it creates can access the HSM client files.
We need to update the Docker image of the deployment to use `infisical/infisical-fips`. The `infisical/infisical-fips` image is a functionally identical image to the `infisical/infisical` image, but it is built with support for HSM encryption.
We need to update the Docker image of the deployment to use `infisical/infisical-fips`. The `infisical/infisical-fips` image is a functionally identical image to the `infisical/infisical` image, but it is built with HSM support.
```yaml
# ... The rest of the values.yaml file ...
@@ -499,8 +539,7 @@ For organizations that work with US government agencies, FIPS compliance is almo
extraVolumeMounts:
- name: hsm-data
mountPath: /hsm-client # The path we will mount the HSM client files to
subPath: ./hsm-client
mountPath: /usr/safenet/lunaclient # The path we will mount the HSM client files to
extraVolumes:
- name: hsm-data

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View File

@@ -34,7 +34,7 @@ description: "Learn how to configure a TeamCity Sync for Infisical."
- **Build Configuration**: The build configuration to sync secrets to.
<Note>
Not including a Build Configuration will sync secrets to the entire project.
Not including a Build Configuration will sync secrets to the project.
</Note>
5. Configure the **Sync Options** to specify how secrets should be synced, then click **Next**.
@@ -44,6 +44,11 @@ description: "Learn how to configure a TeamCity Sync for Infisical."
- **Overwrite Destination Secrets**: Removes any secrets at the destination endpoint not present in Infisical.
- **Import Secrets (Prioritize Infisical)**: Imports secrets from the destination endpoint before syncing, prioritizing values from Infisical over TeamCity when keys conflict.
- **Import Secrets (Prioritize TeamCity)**: Imports secrets from the destination endpoint before syncing, prioritizing values from TeamCity over Infisical when keys conflict.
<Note>
Infisical only syncs secrets from within the target scope; inherited secrets will not be imported.
</Note>
- **Auto-Sync Enabled**: If enabled, secrets will automatically be synced from the source location when changes occur. Disable to enforce manual syncing only.
- **Disable Secret Deletion**: If enabled, Infisical will not remove secrets from the sync destination. Enable this option if you intend to manage some secrets manually outside of Infisical.

View File

@@ -160,6 +160,7 @@
},
"documentation/platform/access-controls/additional-privileges",
"documentation/platform/access-controls/temporary-access",
"documentation/platform/access-controls/assume-privilege",
"documentation/platform/access-controls/access-requests",
"documentation/platform/access-controls/project-access-requests",
"documentation/platform/pr-workflows",
@@ -889,8 +890,8 @@
]
},
{
"group": "LDAP Password",
"pages": [
"group": "LDAP Password",
"pages": [
"api-reference/endpoints/secret-rotations/ldap-password/create",
"api-reference/endpoints/secret-rotations/ldap-password/delete",
"api-reference/endpoints/secret-rotations/ldap-password/get-by-id",

View File

@@ -93,6 +93,7 @@ export const SecretInput = forwardRef<HTMLTextAreaElement, Props>(
onFocus={(evt) => {
onFocus?.(evt);
setIsSecretFocused.on();
evt.currentTarget.select();
}}
disabled={isDisabled}
spellCheck={false}

View File

@@ -4,6 +4,7 @@ import { subject } from "@casl/ability";
import {
faCheck,
faCopy,
faEyeSlash,
faProjectDiagram,
faTrash,
faXmark
@@ -25,7 +26,6 @@ import {
ModalTrigger,
Tooltip
} from "@app/components/v2";
import { Blur } from "@app/components/v2/Blur";
import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput";
import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission } from "@app/context";
import { ProjectPermissionSecretActions } from "@app/context/ProjectPermissionContext/types";
@@ -124,7 +124,13 @@ export const SecretEditRow = ({
);
}
}
reset({ value });
if (secretValueHidden && !isOverride) {
setTimeout(() => {
reset({ value: defaultValue || null });
}, 50);
} else {
reset({ value });
}
};
const canReadSecretValue = hasSecretReadValueOrDescribePermission(
@@ -132,6 +138,16 @@ export const SecretEditRow = ({
ProjectPermissionSecretActions.ReadValue
);
const canEditSecretValue = permission.can(
ProjectPermissionSecretActions.Edit,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath,
secretName,
secretTags: ["*"]
})
);
const handleDeleteSecret = useCallback(async () => {
setIsDeleting.on();
setIsModalOpen(false);
@@ -153,29 +169,32 @@ export const SecretEditRow = ({
deleteKey={secretName}
onDeleteApproved={handleDeleteSecret}
/>
{secretValueHidden && !isOverride && (
<Tooltip
content={`You do not have access to view the current value${canEditSecretValue && !isRotatedSecret ? ", but you can set a new one" : "."}`}
>
<FontAwesomeIcon className="pl-2" size="sm" icon={faEyeSlash} />
</Tooltip>
)}
<div className="flex-grow border-r border-r-mineshaft-600 pl-1 pr-2">
{secretValueHidden ? (
<Blur tooltipText="You do not have permission to read the value of this secret." />
) : (
<Controller
disabled={isImportedSecret && !defaultValue}
control={control}
name="value"
render={({ field }) => (
<InfisicalSecretInput
{...field}
isReadOnly={isImportedSecret || isRotatedSecret}
value={field.value as string}
key="secret-input"
isVisible={isVisible}
secretPath={secretPath}
environment={environment}
isImport={isImportedSecret}
/>
)}
/>
)}
<Controller
disabled={isImportedSecret && !defaultValue}
control={control}
name="value"
render={({ field }) => (
<InfisicalSecretInput
{...field}
isReadOnly={isImportedSecret || (isRotatedSecret && !isOverride)}
value={field.value as string}
key="secret-input"
isVisible={isVisible && !secretValueHidden}
secretPath={secretPath}
environment={environment}
isImport={isImportedSecret}
defaultValue={secretValueHidden ? "" : undefined}
/>
)}
/>
</div>
<div

View File

@@ -1,3 +1,4 @@
import { subject } from "@casl/ability";
import { faCircle } from "@fortawesome/free-regular-svg-icons";
import {
faAngleDown,
@@ -14,6 +15,11 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { Button, Checkbox, TableContainer, Td, Tooltip, Tr } from "@app/components/v2";
import { useProjectPermission } from "@app/context";
import {
ProjectPermissionSecretActions,
ProjectPermissionSub
} from "@app/context/ProjectPermissionContext/types";
import { useToggle } from "@app/hooks";
import { SecretType, SecretV3RawSanitized } from "@app/hooks/api/secrets/types";
import { WorkspaceEnv } from "@app/hooks/api/types";
@@ -64,6 +70,28 @@ export const SecretOverviewTableRow = ({
const totalCols = environments.length + 1; // secret key row
const [isSecretVisible, setIsSecretVisible] = useToggle();
const { permission } = useProjectPermission();
const getDefaultValue = (
secret: SecretV3RawSanitized | undefined,
importedSecret: { secret?: SecretV3RawSanitized } | undefined
) => {
const canEditSecretValue = permission.can(
ProjectPermissionSecretActions.Edit,
subject(ProjectPermissionSub.Secrets, {
environment: secret?.env || "",
secretPath: secret?.path || "",
secretName: secret?.key || "",
secretTags: ["*"]
})
);
if (secret?.secretValueHidden && !secret?.valueOverride) {
return canEditSecretValue ? "******" : "";
}
return secret?.valueOverride || secret?.value || importedSecret?.secret?.value || "";
};
return (
<>
<Tr isHoverable isSelectable onClick={() => setIsFormExpanded.toggle()} className="group">
@@ -228,13 +256,7 @@ export const SecretOverviewTableRow = ({
isVisible={isSecretVisible}
secretName={secretKey}
secretValueHidden={secret?.secretValueHidden || false}
defaultValue={
secret?.secretValueHidden
? ""
: secret?.valueOverride ||
secret?.value ||
importedSecret?.secret?.value
}
defaultValue={getDefaultValue(secret, importedSecret)}
secretId={secret?.id}
isOverride={Boolean(secret?.valueOverride)}
isImportedSecret={isImportedSecret}

View File

@@ -46,10 +46,9 @@ import {
} from "@app/components/secrets/SecretReferenceDetails";
import { ProjectPermissionSecretActions } from "@app/context/ProjectPermissionContext/types";
import { Blur } from "@app/components/v2/Blur";
import { hasSecretReadValueOrDescribePermission } from "@app/lib/fn/permission";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faKey, faRotate } from "@fortawesome/free-solid-svg-icons";
import { faEyeSlash, faKey, faRotate } from "@fortawesome/free-solid-svg-icons";
import {
FontAwesomeSpriteName,
formSchema,
@@ -57,6 +56,8 @@ import {
TFormSchema
} from "./SecretListView.utils";
const hiddenValue = "******";
type Props = {
secret: SecretV3RawSanitized;
onSaveSecret: (
@@ -95,6 +96,23 @@ export const SecretItem = memo(
const { permission } = useProjectPermission();
const { isRotatedSecret } = secret;
const canEditSecretValue = permission.can(
ProjectPermissionSecretActions.Edit,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath,
secretName: secret.key,
secretTags: ["*"]
})
);
const getDefaultValue = () => {
if (secret.secretValueHidden) {
return canEditSecretValue ? hiddenValue : "";
}
return secret.valueOverride || secret.value || "";
};
const {
handleSubmit,
control,
@@ -108,11 +126,11 @@ export const SecretItem = memo(
} = useForm<TFormSchema>({
defaultValues: {
...secret,
value: secret.secretValueHidden ? "" : secret.value
value: getDefaultValue()
},
values: {
...secret,
value: secret.secretValueHidden ? "" : secret.value
value: getDefaultValue()
},
resolver: zodResolver(formSchema)
});
@@ -154,6 +172,7 @@ export const SecretItem = memo(
secretTags: selectedTagSlugs
})
);
const { secretValueHidden } = secret;
const [isSecValueCopied, setIsSecValueCopied] = useToggle(false);
@@ -286,6 +305,13 @@ export const SecretItem = memo(
tabIndex={0}
role="button"
>
{secretValueHidden && !isOverriden && (
<Tooltip
content={`You do not have access to view the current value${canEditSecretValue && !isRotatedSecret ? ", but you can set a new one" : "."}`}
>
<FontAwesomeIcon className="pr-2" size="sm" icon={faEyeSlash} />
</Tooltip>
)}
{isOverriden ? (
<Controller
name="valueOverride"
@@ -301,8 +327,6 @@ export const SecretItem = memo(
/>
)}
/>
) : secretValueHidden ? (
<Blur tooltipText="You do not have permission to read the value of this secret." />
) : (
<Controller
name="value"
@@ -312,11 +336,11 @@ export const SecretItem = memo(
<InfisicalSecretInput
isReadOnly={isReadOnly || isRotatedSecret}
key="secret-value"
isVisible={isVisible}
isVisible={isVisible && !secretValueHidden}
environment={environment}
secretPath={secretPath}
{...field}
defaultValue={secretValueHidden ? "" : undefined}
defaultValue={secretValueHidden ? hiddenValue : undefined}
containerClassName="py-1.5 rounded-md transition-all"
/>
)}

View File

@@ -49,8 +49,6 @@ export const SecretListView = ({
isProtectedBranch = false,
importedBy
}: Props) => {
console.log("secretssssss", secrets);
const queryClient = useQueryClient();
const { popUp, handlePopUpToggle, handlePopUpOpen, handlePopUpClose } = usePopUp([
"deleteSecret",