mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 04:14:38 +00:00
fix: view secret value permission (requested changes)
This commit is contained in:
@@ -31,7 +31,7 @@ export type TImportDataIntoInfisicalDTO = {
|
||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findLastEnvPosition" | "create" | "findOne">;
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "find">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "create">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "create" | "find">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany" | "create">;
|
||||
|
||||
@@ -27,7 +27,7 @@ export type TExternalMigrationQueueFactoryDep = {
|
||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findLastEnvPosition" | "create" | "findOne">;
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "find">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "create">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "create" | "find">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany" | "create">;
|
||||
|
||||
@@ -68,7 +68,8 @@ const getIntegrationSecretsV2 = async (
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
secretImportDAL,
|
||||
secretImports,
|
||||
hasSecretAccess: () => true
|
||||
hasSecretAccess: () => true,
|
||||
viewSecretValue: true
|
||||
});
|
||||
|
||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { TSecretDALFactory } from "../secret/secret-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
|
||||
import { TSecretImportDALFactory } from "./secret-import-dal";
|
||||
import { INFISICAL_SECRET_VALUE_HIDDEN_MASK } from "../secret/secret-fns";
|
||||
|
||||
type TSecretImportSecrets = {
|
||||
secretPath: string;
|
||||
@@ -39,6 +40,7 @@ type TSecretImportSecretsV2 = {
|
||||
// akhilmhdh: yes i know you can put ?.
|
||||
// But for somereason ts consider ? and undefined explicit as different just ts things
|
||||
secretValue: string;
|
||||
secretValueHidden: boolean;
|
||||
secretComment: string;
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
})[];
|
||||
@@ -150,12 +152,14 @@ export const fnSecretsV2FromImports = async ({
|
||||
secretImportDAL,
|
||||
decryptor,
|
||||
expandSecretReferences,
|
||||
hasSecretAccess
|
||||
hasSecretAccess,
|
||||
viewSecretValue
|
||||
}: {
|
||||
secretImports: (Omit<TSecretImports, "importEnv"> & {
|
||||
importEnv: { id: string; slug: string; name: string };
|
||||
})[];
|
||||
folderDAL: Pick<TSecretFolderDALFactory, "findByManySecretPath">;
|
||||
viewSecretValue: boolean;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "find">;
|
||||
secretImportDAL: Pick<TSecretImportDALFactory, "findByFolderIds">;
|
||||
decryptor: (value?: Buffer | null) => string;
|
||||
@@ -168,9 +172,11 @@ export const fnSecretsV2FromImports = async ({
|
||||
hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean;
|
||||
}) => {
|
||||
const cyclicDetector = new Set();
|
||||
const stack: { secretImports: typeof rootSecretImports; depth: number; parentImportedSecrets: TSecretsV2[] }[] = [
|
||||
{ secretImports: rootSecretImports, depth: 0, parentImportedSecrets: [] }
|
||||
];
|
||||
const stack: {
|
||||
secretImports: typeof rootSecretImports;
|
||||
depth: number;
|
||||
parentImportedSecrets: (TSecretsV2 & { secretValueHidden: boolean })[];
|
||||
}[] = [{ secretImports: rootSecretImports, depth: 0, parentImportedSecrets: [] }];
|
||||
|
||||
const processedImports: TSecretImportSecretsV2[] = [];
|
||||
|
||||
@@ -229,7 +235,8 @@ export const fnSecretsV2FromImports = async ({
|
||||
.map((item) => ({
|
||||
...item,
|
||||
secretKey: item.key,
|
||||
secretValue: decryptor(item.encryptedValue),
|
||||
secretValue: viewSecretValue ? decryptor(item.encryptedValue) : INFISICAL_SECRET_VALUE_HIDDEN_MASK,
|
||||
secretValueHidden: !viewSecretValue,
|
||||
secretComment: decryptor(item.encryptedComment),
|
||||
environment: importEnv.slug,
|
||||
workspace: "", // This field should not be used, it's only here to keep the older Python SDK versions backwards compatible with the new Postgres backend.
|
||||
@@ -267,6 +274,8 @@ export const fnSecretsV2FromImports = async ({
|
||||
processedImport.secrets = unique(processedImport.secrets, (i) => i.key);
|
||||
return Promise.allSettled(
|
||||
processedImport.secrets.map(async (decryptedSecret, index) => {
|
||||
if (decryptedSecret.secretValueHidden) return;
|
||||
|
||||
const expandedSecretValue = await expandSecretReferences({
|
||||
value: decryptedSecret.secretValue,
|
||||
secretPath: processedImport.secretPath,
|
||||
|
||||
@@ -94,7 +94,7 @@ export const secretImportServiceFactory = ({
|
||||
|
||||
// check if user has permission to import from target path
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
ProjectPermissionSecretActions.DescribeSecret,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment: data.environment,
|
||||
secretPath: data.path
|
||||
@@ -406,7 +406,7 @@ export const secretImportServiceFactory = ({
|
||||
|
||||
// check if user has permission to import from target path
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
ProjectPermissionSecretActions.DescribeSecret,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment: secretImportDoc.importEnv.slug,
|
||||
secretPath: secretImportDoc.importPath
|
||||
@@ -646,6 +646,7 @@ export const secretImportServiceFactory = ({
|
||||
const importedSecrets = await fnSecretsV2FromImports({
|
||||
secretImports,
|
||||
folderDAL,
|
||||
viewSecretValue: true,
|
||||
secretDAL: secretV2BridgeDAL,
|
||||
secretImportDAL,
|
||||
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
||||
|
||||
@@ -249,7 +249,8 @@ export const secretSyncQueueFactory = ({
|
||||
expandSecretReferences,
|
||||
secretImportDAL,
|
||||
secretImports,
|
||||
hasSecretAccess: () => true
|
||||
hasSecretAccess: () => true,
|
||||
viewSecretValue: true
|
||||
});
|
||||
|
||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||
|
||||
@@ -148,7 +148,16 @@ export const fnSecretBulkInsert = async ({
|
||||
await secretVersionTagDAL.insertMany(newSecretVersionTags, tx);
|
||||
}
|
||||
|
||||
return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
|
||||
const secretsWithTags = await secretDAL.find(
|
||||
{
|
||||
$in: {
|
||||
[`${TableName.SecretV2}.id` as "id"]: newSecrets.map((s) => s.id)
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
|
||||
return secretsWithTags.map((secret) => ({ ...secret, _id: secret.id }));
|
||||
};
|
||||
|
||||
export const fnSecretBulkUpdate = async ({
|
||||
@@ -286,7 +295,15 @@ export const fnSecretBulkUpdate = async ({
|
||||
tx
|
||||
);
|
||||
|
||||
return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
|
||||
const secretsWithTags = await secretDAL.find(
|
||||
{
|
||||
$in: {
|
||||
[`${TableName.SecretV2}.id` as "id"]: newSecrets.map((s) => s.id)
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
return secretsWithTags.map((secret) => ({ ...secret, _id: secret.id }));
|
||||
};
|
||||
|
||||
export const fnSecretBulkDelete = async ({
|
||||
@@ -627,7 +644,7 @@ export const reshapeBridgeSecret = (
|
||||
}[];
|
||||
secretMetadata?: ResourceMetadataDTO;
|
||||
},
|
||||
secretValueHidden?: boolean
|
||||
secretValueHidden: boolean
|
||||
) => ({
|
||||
secretKey: secret.key,
|
||||
secretPath,
|
||||
|
||||
@@ -323,11 +323,17 @@ export const secretV2BridgeServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
return reshapeBridgeSecret(projectId, environment, secretPath, {
|
||||
...secret,
|
||||
value: inputSecret.secretValue,
|
||||
comment: inputSecret.secretComment || ""
|
||||
});
|
||||
return reshapeBridgeSecret(
|
||||
projectId,
|
||||
environment,
|
||||
secretPath,
|
||||
{
|
||||
...secret,
|
||||
value: inputSecret.secretValue,
|
||||
comment: inputSecret.secretComment || ""
|
||||
},
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
const updateSecret = async ({
|
||||
@@ -407,9 +413,9 @@ export const secretV2BridgeServiceFactory = ({
|
||||
|
||||
// validate tags
|
||||
// fetch all tags and if not same count throw error meaning one was invalid tags
|
||||
const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
|
||||
if ((inputSecret.tagIds || []).length !== tags.length)
|
||||
throw new NotFoundError({ message: `Tag not found. Found ${tags.map((el) => el.slug).join(",")}` });
|
||||
const newTags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
|
||||
if ((inputSecret.tagIds || []).length !== newTags.length)
|
||||
throw new NotFoundError({ message: `Tag not found. Found ${newTags.map((el) => el.slug).join(",")}` });
|
||||
|
||||
// now check with new ids
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
@@ -418,7 +424,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
environment,
|
||||
secretPath,
|
||||
secretName: inputSecret.secretName,
|
||||
secretTags: tags?.map((el) => el.slug)
|
||||
secretTags: newTags?.map((el) => el.slug)
|
||||
})
|
||||
);
|
||||
|
||||
@@ -435,7 +441,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
environment,
|
||||
secretPath,
|
||||
secretName: inputSecret.newSecretName,
|
||||
secretTags: tags?.map((el) => el.slug)
|
||||
secretTags: newTags?.map((el) => el.slug)
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -513,13 +519,14 @@ export const secretV2BridgeServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const tagsToCheck = newTags?.length ? newTags : secret.tags;
|
||||
const secretValueHidden = !permission.can(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment,
|
||||
secretPath,
|
||||
secretName: inputSecret.secretName, // ! Note(Daniel): We are checking for the EXISTING secret name, not the new secret name.
|
||||
secretTags: tags?.map((el) => el.slug) // ! Note(Daniel): Same here
|
||||
secretName: inputSecret.secretName,
|
||||
secretTags: tagsToCheck.length ? tagsToCheck.map((el) => el.slug) : undefined
|
||||
})
|
||||
);
|
||||
|
||||
@@ -738,7 +745,13 @@ export const secretV2BridgeServiceFactory = ({
|
||||
};
|
||||
|
||||
const getSecretsByFolderMappings = async (
|
||||
{ projectId, userId, filters, folderMappings, filterByAction }: TGetSecretsRawByFolderMappingsDTO,
|
||||
{
|
||||
projectId,
|
||||
userId,
|
||||
filters,
|
||||
folderMappings,
|
||||
filterByAction = ProjectPermissionSecretActions.ReadValue
|
||||
}: TGetSecretsRawByFolderMappingsDTO,
|
||||
projectPermission: Awaited<ReturnType<typeof permissionService.getProjectPermission>>["permission"]
|
||||
) => {
|
||||
const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId);
|
||||
@@ -755,13 +768,10 @@ export const secretV2BridgeServiceFactory = ({
|
||||
projectId
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
if (!filterByAction) filterByAction = ProjectPermissionSecretActions.ReadValue;
|
||||
|
||||
const decryptedSecrets = secrets
|
||||
.filter((el) =>
|
||||
projectPermission.can(
|
||||
filterByAction as ProjectPermissionSecretActions, // ? Typescript assumes that filterByAction may be undefined, which is not true, so we are casting it to ProjectPermissionSecretActions
|
||||
filterByAction,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment: groupedFolderMappings[el.folderId][0].environment,
|
||||
secretPath: groupedFolderMappings[el.folderId][0].path,
|
||||
@@ -870,6 +880,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
includeImports,
|
||||
recursive,
|
||||
expandSecretReferences: shouldExpandSecretReferences,
|
||||
throwOnMissingReadValuePermission = true,
|
||||
...params
|
||||
}: TGetSecretsDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission({
|
||||
@@ -927,19 +938,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
|
||||
const decryptedSecrets = secrets
|
||||
.filter((el) => {
|
||||
if (viewSecretValue) {
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment,
|
||||
secretPath: groupedPaths[el.folderId][0].path,
|
||||
secretName: el.key,
|
||||
secretTags: el.tags.map((i) => i.slug)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return permission.can(
|
||||
const canDescribeSecret = permission.can(
|
||||
ProjectPermissionSecretActions.DescribeSecret,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment,
|
||||
@@ -948,6 +947,43 @@ export const secretV2BridgeServiceFactory = ({
|
||||
secretTags: el.tags.map((i) => i.slug)
|
||||
})
|
||||
);
|
||||
|
||||
if (!canDescribeSecret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (viewSecretValue) {
|
||||
// Recursive secret, should be filtered out
|
||||
if (groupedPaths[el.folderId][0].path !== path) {
|
||||
const canReadRecursiveSecretValue = permission.can(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment,
|
||||
secretPath: groupedPaths[el.folderId][0].path,
|
||||
secretName: el.key,
|
||||
secretTags: el.tags.map((i) => i.slug)
|
||||
})
|
||||
);
|
||||
|
||||
if (!canReadRecursiveSecretValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (throwOnMissingReadValuePermission) {
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment,
|
||||
secretPath: groupedPaths[el.folderId][0].path,
|
||||
secretName: el.key,
|
||||
secretTags: el.tags.map((i) => i.slug)
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return canDescribeSecret;
|
||||
})
|
||||
.map((secret) => {
|
||||
const isPersonalSecret = secret.userId === actorId && secret.type === SecretType.Personal;
|
||||
@@ -1027,6 +1063,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
|
||||
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
|
||||
const importedSecrets = await fnSecretsV2FromImports({
|
||||
viewSecretValue,
|
||||
secretImports: allowedImports,
|
||||
secretDAL,
|
||||
folderDAL,
|
||||
@@ -1174,6 +1211,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
|
||||
const importedSecrets = await fnSecretsV2FromImports({
|
||||
secretImports,
|
||||
viewSecretValue,
|
||||
secretDAL,
|
||||
folderDAL,
|
||||
secretImportDAL,
|
||||
@@ -1207,11 +1245,17 @@ export const secretV2BridgeServiceFactory = ({
|
||||
for (let j = 0; j < importedSecrets[i].secrets.length; j += 1) {
|
||||
const importedSecret = importedSecrets[i].secrets[j];
|
||||
if (secretName === importedSecret.key) {
|
||||
return reshapeBridgeSecret(projectId, importedSecrets[i].environment, importedSecrets[i].secretPath, {
|
||||
...importedSecret,
|
||||
value: importedSecret.secretValue || "",
|
||||
comment: importedSecret.secretComment || ""
|
||||
});
|
||||
return reshapeBridgeSecret(
|
||||
projectId,
|
||||
importedSecrets[i].environment,
|
||||
importedSecrets[i].secretPath,
|
||||
{
|
||||
...importedSecret,
|
||||
value: importedSecret.secretValue || "",
|
||||
comment: importedSecret.secretComment || ""
|
||||
},
|
||||
importedSecret.secretValueHidden
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1365,8 +1409,8 @@ export const secretV2BridgeServiceFactory = ({
|
||||
const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } =
|
||||
await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId });
|
||||
|
||||
const newSecrets = await secretDAL.transaction(async (tx) => {
|
||||
const createdSecrets = await fnSecretBulkInsert({
|
||||
const newSecrets = await secretDAL.transaction(async (tx) =>
|
||||
fnSecretBulkInsert({
|
||||
inputSecrets: inputSecrets.map((el) => {
|
||||
const references = secretReferencesGroupByInputSecretKey[el.secretKey]?.nestedReferences;
|
||||
|
||||
@@ -1395,19 +1439,8 @@ export const secretV2BridgeServiceFactory = ({
|
||||
secretTagDAL,
|
||||
secretVersionTagDAL,
|
||||
tx
|
||||
});
|
||||
|
||||
const secs = await secretDAL.find(
|
||||
{
|
||||
$in: {
|
||||
[`${TableName.SecretV2}.id` as "id"]: createdSecrets.map((el) => el.id)
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
|
||||
return secs;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
await snapshotService.performSnapshot(folderId);
|
||||
await secretQueueService.syncSecrets({
|
||||
@@ -1656,7 +1689,7 @@ export const secretV2BridgeServiceFactory = ({
|
||||
});
|
||||
await $validateSecretReferences(projectId, permission, secretReferences, tx);
|
||||
|
||||
const bulkUpdatedSecretsRes = await fnSecretBulkUpdate({
|
||||
const bulkUpdatedSecrets = await fnSecretBulkUpdate({
|
||||
folderId,
|
||||
orgId: actorOrgId,
|
||||
tx,
|
||||
@@ -1694,20 +1727,9 @@ export const secretV2BridgeServiceFactory = ({
|
||||
resourceMetadataDAL
|
||||
});
|
||||
|
||||
const bulkUpdatedSecrets = await secretDAL.find(
|
||||
{
|
||||
$in: {
|
||||
[`${TableName.SecretV2}.id` as "id"]: bulkUpdatedSecretsRes.map((el) => el.id)
|
||||
}
|
||||
},
|
||||
{
|
||||
tx
|
||||
}
|
||||
);
|
||||
|
||||
updatedSecrets.push(...bulkUpdatedSecrets.map((el) => ({ ...el, secretPath: folder.path })));
|
||||
if (updateMode === SecretUpdateMode.Upsert) {
|
||||
const bulkInsertedSecretsRes = await fnSecretBulkInsert({
|
||||
const bulkInsertedSecrets = await fnSecretBulkInsert({
|
||||
inputSecrets: secretsToCreate.map((el) => {
|
||||
const references = secretReferencesGroupByInputSecretKey[el.secretKey]?.nestedReferences;
|
||||
|
||||
@@ -1738,15 +1760,6 @@ export const secretV2BridgeServiceFactory = ({
|
||||
tx
|
||||
});
|
||||
|
||||
const bulkInsertedSecrets = await secretDAL.find(
|
||||
{
|
||||
$in: {
|
||||
[`${TableName.SecretV2}.id` as "id"]: bulkInsertedSecretsRes.map((el) => el.id)
|
||||
}
|
||||
},
|
||||
{ tx }
|
||||
);
|
||||
|
||||
updatedSecrets.push(...bulkInsertedSecrets.map((el) => ({ ...el, secretPath: folder.path })));
|
||||
}
|
||||
}
|
||||
@@ -1957,11 +1970,17 @@ export const secretV2BridgeServiceFactory = ({
|
||||
|
||||
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
|
||||
return secretVersions.map((el) =>
|
||||
reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", {
|
||||
...el,
|
||||
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
|
||||
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
|
||||
})
|
||||
reshapeBridgeSecret(
|
||||
folder.projectId,
|
||||
folder.environment.envSlug,
|
||||
"/",
|
||||
{
|
||||
...el,
|
||||
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
|
||||
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
|
||||
},
|
||||
false
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ export type TGetSecretsDTO = {
|
||||
recursive?: boolean;
|
||||
tagSlugs?: string[];
|
||||
viewSecretValue: boolean;
|
||||
throwOnMissingReadValuePermission?: boolean;
|
||||
metadataFilter?: {
|
||||
key?: string;
|
||||
value?: string;
|
||||
@@ -50,6 +51,11 @@ export type TGetSecretsDTO = {
|
||||
keys?: string[];
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TGetSecretsMissingReadValuePermissionDTO = Omit<
|
||||
TGetSecretsDTO,
|
||||
"viewSecretValue" | "recursive" | "expandSecretReferences"
|
||||
>;
|
||||
|
||||
export type TGetASecretDTO = {
|
||||
secretName: string;
|
||||
path: string;
|
||||
@@ -167,7 +173,7 @@ export type TFnSecretBulkInsert = {
|
||||
}
|
||||
>;
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "find">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "find">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
@@ -191,7 +197,7 @@ export type TFnSecretBulkUpdate = {
|
||||
data: TRequireReferenceIfValue & { tags?: string[]; secretMetadata?: ResourceMetadataDTO };
|
||||
}[];
|
||||
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences">;
|
||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences" | "find">;
|
||||
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
|
||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "deleteTagsToSecretV2" | "find">;
|
||||
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
|
||||
@@ -402,7 +402,8 @@ export const secretQueueFactory = ({
|
||||
expandSecretReferences,
|
||||
secretImportDAL,
|
||||
secretImports,
|
||||
hasSecretAccess: () => true
|
||||
hasSecretAccess: () => true,
|
||||
viewSecretValue: true
|
||||
});
|
||||
|
||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||
|
||||
@@ -667,7 +667,15 @@ export const secretServiceFactory = ({
|
||||
environment,
|
||||
secretPath: groupedPaths[secret.folderId][0].path
|
||||
})),
|
||||
imports: importedSecrets
|
||||
imports: importedSecrets.map((el) => {
|
||||
return {
|
||||
...el,
|
||||
secrets: el.secrets.map((secret) => ({
|
||||
...secret,
|
||||
secretValueHidden: false
|
||||
}))
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
@@ -974,7 +982,7 @@ export const secretServiceFactory = ({
|
||||
});
|
||||
|
||||
const secretValueHidden = !permission.can(
|
||||
ProjectPermissionSecretActions.Edit,
|
||||
ProjectPermissionSecretActions.ReadValue,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -1299,6 +1307,7 @@ export const secretServiceFactory = ({
|
||||
expandSecretReferences,
|
||||
recursive,
|
||||
tagSlugs = [],
|
||||
throwOnMissingReadValuePermission = true,
|
||||
...paramsV2
|
||||
}: TGetSecretsRawDTO) => {
|
||||
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
|
||||
@@ -1310,6 +1319,7 @@ export const secretServiceFactory = ({
|
||||
actor,
|
||||
actorOrgId,
|
||||
viewSecretValue,
|
||||
throwOnMissingReadValuePermission,
|
||||
environment,
|
||||
path,
|
||||
recursive,
|
||||
@@ -1318,6 +1328,7 @@ export const secretServiceFactory = ({
|
||||
tagSlugs,
|
||||
...paramsV2
|
||||
});
|
||||
|
||||
return { secrets, imports };
|
||||
}
|
||||
|
||||
@@ -1370,6 +1381,7 @@ export const secretServiceFactory = ({
|
||||
const importedEntries = decryptedImportSecrets.reduce(
|
||||
(
|
||||
accum: {
|
||||
secretValueHidden: boolean;
|
||||
secretKey: string;
|
||||
secretPath: string;
|
||||
workspace: string;
|
||||
@@ -1413,6 +1425,7 @@ export const secretServiceFactory = ({
|
||||
Object.keys(secretsGroupByPath).map((groupedPath) =>
|
||||
Promise.allSettled(
|
||||
secretsGroupByPath[groupedPath].map(async (decryptedSecret, index) => {
|
||||
if (decryptedSecret.secretValueHidden) return;
|
||||
const expandedSecretValue = await expandSecret({
|
||||
value: decryptedSecret.secretValue,
|
||||
secretPath: groupedPath,
|
||||
@@ -1429,6 +1442,7 @@ export const secretServiceFactory = ({
|
||||
processedImports.map((processedImport) =>
|
||||
Promise.allSettled(
|
||||
processedImport.secrets.map(async (decryptedSecret, index) => {
|
||||
if (decryptedSecret.secretValueHidden) return;
|
||||
const expandedSecretValue = await expandSecret({
|
||||
value: decryptedSecret.secretValue,
|
||||
secretPath: path,
|
||||
|
||||
@@ -181,6 +181,7 @@ export type TGetSecretsRawDTO = {
|
||||
path: string;
|
||||
environment: string;
|
||||
viewSecretValue: boolean;
|
||||
throwOnMissingReadValuePermission?: boolean;
|
||||
includeImports?: boolean;
|
||||
recursive?: boolean;
|
||||
tagSlugs?: string[];
|
||||
@@ -411,7 +412,7 @@ export type TCreateManySecretsRawFnFactory = {
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
secretV2BridgeDAL: Pick<
|
||||
TSecretV2BridgeDALFactory,
|
||||
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany"
|
||||
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany" | "find"
|
||||
>;
|
||||
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
||||
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
@@ -448,7 +449,7 @@ export type TUpdateManySecretsRawFnFactory = {
|
||||
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||
secretV2BridgeDAL: Pick<
|
||||
TSecretV2BridgeDALFactory,
|
||||
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany"
|
||||
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany" | "find"
|
||||
>;
|
||||
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
|
||||
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
|
||||
|
||||
Reference in New Issue
Block a user