mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 09:28:06 +00:00
feat: updated all services with permission changes
This commit is contained in:
Generated
+348
-266
File diff suppressed because it is too large
Load Diff
@@ -853,7 +853,7 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath, secretName: "", secretTags: [] })
|
||||||
);
|
);
|
||||||
|
|
||||||
await projectDAL.checkProjectUpgradeStatus(projectId);
|
await projectDAL.checkProjectUpgradeStatus(projectId);
|
||||||
@@ -1125,10 +1125,6 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
|
||||||
ProjectPermissionActions.Read,
|
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
|
||||||
);
|
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
|
||||||
if (!folder)
|
if (!folder)
|
||||||
@@ -1292,6 +1288,23 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
const tagIds = unique(Object.values(commitTagIds).flat());
|
const tagIds = unique(Object.values(commitTagIds).flat());
|
||||||
const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : [];
|
const tags = tagIds.length ? await secretTagDAL.findManyTagsById(projectId, tagIds) : [];
|
||||||
if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
if (tagIds.length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
||||||
|
const tagsGroupById = groupBy(tags, (i) => i.id);
|
||||||
|
|
||||||
|
commits.forEach((commit) => {
|
||||||
|
let action = ProjectPermissionActions.Create;
|
||||||
|
if (commit.op === SecretOperations.Update) action = ProjectPermissionActions.Edit;
|
||||||
|
if (commit.op === SecretOperations.Delete) action = ProjectPermissionActions.Delete;
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
action,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
secretName: commit.key,
|
||||||
|
secretTags: commitTagIds[commit.key].map((secretTagId) => tagsGroupById[secretTagId][0].slug)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => {
|
const secretApprovalRequest = await secretApprovalRequestDAL.transaction(async (tx) => {
|
||||||
const doc = await secretApprovalRequestDAL.create(
|
const doc = await secretApprovalRequestDAL.create(
|
||||||
|
|||||||
@@ -253,11 +253,13 @@ export const secretReplicationServiceFactory = ({
|
|||||||
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
|
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
|
||||||
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
|
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
|
||||||
const sourceImportedSecrets = await fnSecretsV2FromImports({
|
const sourceImportedSecrets = await fnSecretsV2FromImports({
|
||||||
allowedImports: sourceSecretImports,
|
secretImports: sourceSecretImports,
|
||||||
secretDAL: secretV2BridgeDAL,
|
secretDAL: secretV2BridgeDAL,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "")
|
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
||||||
|
// TODO(casl): check with team
|
||||||
|
hasSecretAccess: () => true
|
||||||
});
|
});
|
||||||
// secrets that gets replicated across imports
|
// secrets that gets replicated across imports
|
||||||
const sourceDecryptedLocalSecrets = sourceLocalSecrets.map((el) => ({
|
const sourceDecryptedLocalSecrets = sourceLocalSecrets.map((el) => ({
|
||||||
|
|||||||
@@ -192,15 +192,15 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
req.permission.orgId
|
req.permission.orgId
|
||||||
);
|
);
|
||||||
|
|
||||||
const permissiveEnvs = // filter envs user has access to
|
const allowedDynamicSecretEnviroments = // filter envs user has access to
|
||||||
environments.filter((environment) =>
|
environments.filter((environment) =>
|
||||||
permission.can(
|
permission.can(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
subject(ProjectPermissionSub.DynamicSecrets, { environment, secretPath })
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (includeDynamicSecrets && permissiveEnvs.length) {
|
if (includeDynamicSecrets && allowedDynamicSecretEnviroments.length) {
|
||||||
// this is the unique count, ie duplicate secrets across envs only count as 1
|
// this is the unique count, ie duplicate secrets across envs only count as 1
|
||||||
totalDynamicSecretCount = await server.services.dynamicSecret.getCountMultiEnv({
|
totalDynamicSecretCount = await server.services.dynamicSecret.getCountMultiEnv({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
@@ -209,7 +209,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
projectId,
|
projectId,
|
||||||
search,
|
search,
|
||||||
environmentSlugs: permissiveEnvs,
|
environmentSlugs: allowedDynamicSecretEnviroments,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
isInternal: true
|
isInternal: true
|
||||||
});
|
});
|
||||||
@@ -224,7 +224,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
search,
|
search,
|
||||||
orderBy,
|
orderBy,
|
||||||
orderDirection,
|
orderDirection,
|
||||||
environmentSlugs: permissiveEnvs,
|
environmentSlugs: allowedDynamicSecretEnviroments,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
limit: remainingLimit,
|
limit: remainingLimit,
|
||||||
offset: adjustedOffset,
|
offset: adjustedOffset,
|
||||||
@@ -241,13 +241,13 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeSecrets && permissiveEnvs.length) {
|
if (includeSecrets) {
|
||||||
// this is the unique count, ie duplicate secrets across envs only count as 1
|
// this is the unique count, ie duplicate secrets across envs only count as 1
|
||||||
totalSecretCount = await server.services.secret.getSecretsCountMultiEnv({
|
totalSecretCount = await server.services.secret.getSecretsCountMultiEnv({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
environments: permissiveEnvs,
|
environments,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
projectId,
|
projectId,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
@@ -260,7 +260,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
environments: permissiveEnvs,
|
environments,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
projectId,
|
projectId,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
@@ -272,7 +272,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
isInternal: true
|
isInternal: true
|
||||||
});
|
});
|
||||||
|
|
||||||
for await (const environment of permissiveEnvs) {
|
for await (const environment of environments) {
|
||||||
const secretCountFromEnv = secrets.filter((secret) => secret.environment === environment).length;
|
const secretCountFromEnv = secrets.filter((secret) => secret.environment === environment).length;
|
||||||
|
|
||||||
if (secretCountFromEnv) {
|
if (secretCountFromEnv) {
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ const getIntegrationSecretsV2 = async (
|
|||||||
folderDAL,
|
folderDAL,
|
||||||
secretDAL: secretV2BridgeDAL,
|
secretDAL: secretV2BridgeDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
allowedImports: secretImports
|
secretImports,
|
||||||
|
hasSecretAccess: () => true
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type TSecretImportSecretsV2 = {
|
|||||||
slug: string;
|
slug: string;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
id: string;
|
||||||
folderId: string | undefined;
|
folderId: string | undefined;
|
||||||
importFolderId: string;
|
importFolderId: string;
|
||||||
secrets: (TSecretsV2 & {
|
secrets: (TSecretsV2 & {
|
||||||
@@ -139,24 +140,22 @@ export const fnSecretsFromImports = async ({
|
|||||||
return secrets;
|
return secrets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* eslint-disable no-await-in-loop, no-continue */
|
||||||
export const fnSecretsV2FromImports = async ({
|
export const fnSecretsV2FromImports = async ({
|
||||||
allowedImports: possibleCyclicImports,
|
secretImports: rootSecretImports,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
secretDAL,
|
secretDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
depth = 0,
|
|
||||||
cyclicDetector = new Set(),
|
|
||||||
decryptor,
|
decryptor,
|
||||||
expandSecretReferences
|
expandSecretReferences,
|
||||||
|
hasSecretAccess
|
||||||
}: {
|
}: {
|
||||||
allowedImports: (Omit<TSecretImports, "importEnv"> & {
|
secretImports: (Omit<TSecretImports, "importEnv"> & {
|
||||||
importEnv: { id: string; slug: string; name: string };
|
importEnv: { id: string; slug: string; name: string };
|
||||||
})[];
|
})[];
|
||||||
folderDAL: Pick<TSecretFolderDALFactory, "findByManySecretPath">;
|
folderDAL: Pick<TSecretFolderDALFactory, "findByManySecretPath">;
|
||||||
secretDAL: Pick<TSecretV2BridgeDALFactory, "find">;
|
secretDAL: Pick<TSecretV2BridgeDALFactory, "find">;
|
||||||
secretImportDAL: Pick<TSecretImportDALFactory, "findByFolderIds">;
|
secretImportDAL: Pick<TSecretImportDALFactory, "findByFolderIds">;
|
||||||
depth?: number;
|
|
||||||
cyclicDetector?: Set<string>;
|
|
||||||
decryptor: (value?: Buffer | null) => string;
|
decryptor: (value?: Buffer | null) => string;
|
||||||
expandSecretReferences?: (inputSecret: {
|
expandSecretReferences?: (inputSecret: {
|
||||||
value?: string;
|
value?: string;
|
||||||
@@ -164,92 +163,108 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
secretPath: string;
|
secretPath: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
}) => Promise<string | undefined>;
|
}) => Promise<string | undefined>;
|
||||||
|
hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean;
|
||||||
}) => {
|
}) => {
|
||||||
// avoid going more than a depth
|
const cyclicDetector = new Set();
|
||||||
if (depth >= LEVEL_BREAK) return [];
|
const stack: { secretImports: typeof rootSecretImports; depth: number; parentImportedSecrets: TSecretsV2[] }[] = [
|
||||||
|
{ secretImports: rootSecretImports, depth: 0, parentImportedSecrets: [] }
|
||||||
|
];
|
||||||
|
|
||||||
const allowedImports = possibleCyclicImports.filter(
|
const processedImports: TSecretImportSecretsV2[] = [];
|
||||||
({ importPath, importEnv }) => !cyclicDetector.has(getImportUniqKey(importEnv.slug, importPath))
|
|
||||||
);
|
|
||||||
|
|
||||||
const importedFolders = (
|
while (stack.length) {
|
||||||
await folderDAL.findByManySecretPath(
|
const { secretImports, depth, parentImportedSecrets } = stack.pop()!;
|
||||||
allowedImports.map(({ importEnv, importPath }) => ({
|
|
||||||
|
if (depth > LEVEL_BREAK) continue;
|
||||||
|
const sanitizedImports = secretImports.filter(
|
||||||
|
({ importPath, importEnv }) => !cyclicDetector.has(getImportUniqKey(importEnv.slug, importPath))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sanitizedImports.length) continue;
|
||||||
|
|
||||||
|
const importedFolders = await folderDAL.findByManySecretPath(
|
||||||
|
sanitizedImports.map(({ importEnv, importPath }) => ({
|
||||||
envId: importEnv.id,
|
envId: importEnv.id,
|
||||||
secretPath: importPath
|
secretPath: importPath
|
||||||
}))
|
}))
|
||||||
)
|
);
|
||||||
).filter(Boolean); // remove undefined ones
|
if (!importedFolders.length) continue;
|
||||||
if (!importedFolders.length) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const importedFolderIds = importedFolders.map((el) => el?.id) as string[];
|
const importedFolderIds = importedFolders.map((el) => el?.id) as string[];
|
||||||
const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`);
|
const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`);
|
||||||
const importedSecrets = await secretDAL.find(
|
|
||||||
{
|
|
||||||
$in: { folderId: importedFolderIds },
|
|
||||||
type: SecretType.Shared
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sort: [["id", "asc"]]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId);
|
const importedSecrets = await secretDAL.find(
|
||||||
|
{
|
||||||
|
$in: { folderId: importedFolderIds },
|
||||||
|
type: SecretType.Shared
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sort: [["id", "asc"]]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId);
|
||||||
|
|
||||||
allowedImports.forEach(({ importPath, importEnv }) => {
|
sanitizedImports.forEach(({ importPath, importEnv }) => {
|
||||||
cyclicDetector.add(getImportUniqKey(importEnv.slug, importPath));
|
cyclicDetector.add(getImportUniqKey(importEnv.slug, importPath));
|
||||||
});
|
});
|
||||||
// now we need to check recursively deeper imports made inside other imports
|
// now we need to check recursively deeper imports made inside other imports
|
||||||
// we go level wise meaning we take all imports of a tree level and then go deeper ones level by level
|
// we go level wise meaning we take all imports of a tree level and then go deeper ones level by level
|
||||||
const deeperImports = await secretImportDAL.findByFolderIds(importedFolderIds);
|
const deeperImports = await secretImportDAL.findByFolderIds(importedFolderIds);
|
||||||
let secretsFromDeeperImports: TSecretImportSecretsV2[] = [];
|
const deeperImportsGroupByFolderId = groupBy(deeperImports, (i) => i.folderId);
|
||||||
if (deeperImports.length) {
|
|
||||||
secretsFromDeeperImports = await fnSecretsV2FromImports({
|
const isFirstIteration = processedImports.length;
|
||||||
allowedImports: deeperImports.filter(({ isReplication }) => !isReplication),
|
sanitizedImports.forEach(({ importPath, importEnv, id, folderId }, i) => {
|
||||||
secretImportDAL,
|
const sourceImportFolder = importedFolderGroupBySourceImport[`${importEnv.id}-${importPath}`]?.[0];
|
||||||
folderDAL,
|
const secretsWithDuplicate = (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
|
||||||
secretDAL,
|
.filter((item) =>
|
||||||
depth: depth + 1,
|
hasSecretAccess(
|
||||||
cyclicDetector,
|
importEnv.slug,
|
||||||
decryptor,
|
importPath,
|
||||||
expandSecretReferences
|
item.key,
|
||||||
|
item.tags.map((el) => el.slug)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.map((item) => ({
|
||||||
|
...item,
|
||||||
|
secretKey: item.key,
|
||||||
|
secretValue: decryptor(item.encryptedValue),
|
||||||
|
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.
|
||||||
|
_id: item.id // The old Python SDK depends on the _id field being returned. We return this to keep the older Python SDK versions backwards compatible with the new Postgres backend.
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (deeperImportsGroupByFolderId?.[sourceImportFolder?.id || ""]) {
|
||||||
|
stack.push({
|
||||||
|
secretImports: deeperImportsGroupByFolderId[sourceImportFolder?.id || ""],
|
||||||
|
depth: depth + 1,
|
||||||
|
parentImportedSecrets: secretsWithDuplicate
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFirstIteration) {
|
||||||
|
processedImports.push({
|
||||||
|
secretPath: importPath,
|
||||||
|
environment: importEnv.slug,
|
||||||
|
environmentInfo: importEnv,
|
||||||
|
folderId: importedFolders?.[i]?.id,
|
||||||
|
id,
|
||||||
|
importFolderId: folderId,
|
||||||
|
secrets: unique(secretsWithDuplicate, (el) => el.secretKey)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
parentImportedSecrets.push(...secretsWithDuplicate);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const secretsFromdeeperImportGroupedByFolderId = groupBy(secretsFromDeeperImports, (i) => i.importFolderId);
|
/* eslint-enable */
|
||||||
|
|
||||||
const processedImports = allowedImports.map(({ importPath, importEnv, id, folderId }, i) => {
|
|
||||||
const sourceImportFolder = importedFolderGroupBySourceImport[`${importEnv.id}-${importPath}`]?.[0];
|
|
||||||
const folderDeeperImportSecrets =
|
|
||||||
secretsFromdeeperImportGroupedByFolderId?.[sourceImportFolder?.id || ""]?.[0]?.secrets || [];
|
|
||||||
const secretsWithDuplicate = (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
|
|
||||||
.map((item) => ({
|
|
||||||
...item,
|
|
||||||
secretKey: item.key,
|
|
||||||
secretValue: decryptor(item.encryptedValue),
|
|
||||||
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.
|
|
||||||
_id: item.id // The old Python SDK depends on the _id field being returned. We return this to keep the older Python SDK versions backwards compatible with the new Postgres backend.
|
|
||||||
}))
|
|
||||||
.concat(folderDeeperImportSecrets);
|
|
||||||
|
|
||||||
return {
|
|
||||||
secretPath: importPath,
|
|
||||||
environment: importEnv.slug,
|
|
||||||
environmentInfo: importEnv,
|
|
||||||
folderId: importedFolders?.[i]?.id,
|
|
||||||
id,
|
|
||||||
importFolderId: folderId,
|
|
||||||
secrets: unique(secretsWithDuplicate, (el) => el.secretKey)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (expandSecretReferences) {
|
if (expandSecretReferences) {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
processedImports.map((processedImport) =>
|
processedImports.map((processedImport) => {
|
||||||
Promise.allSettled(
|
// eslint-disable-next-line
|
||||||
|
processedImport.secrets = unique(processedImport.secrets, (i) => i.key);
|
||||||
|
return Promise.allSettled(
|
||||||
processedImport.secrets.map(async (decryptedSecret, index) => {
|
processedImport.secrets.map(async (decryptedSecret, index) => {
|
||||||
const expandedSecretValue = await expandSecretReferences({
|
const expandedSecretValue = await expandSecretReferences({
|
||||||
value: decryptedSecret.secretValue,
|
value: decryptedSecret.secretValue,
|
||||||
@@ -260,8 +275,8 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
processedImport.secrets[index].secretValue = expandedSecretValue || "";
|
processedImport.secrets[index].secretValue = expandedSecretValue || "";
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
)
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -581,11 +581,21 @@ export const secretImportServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
});
|
});
|
||||||
const importedSecrets = await fnSecretsV2FromImports({
|
const importedSecrets = await fnSecretsV2FromImports({
|
||||||
allowedImports: secretImports,
|
secretImports,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
secretDAL: secretV2BridgeDAL,
|
secretDAL: secretV2BridgeDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "")
|
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
||||||
|
hasSecretAccess: (expandEnvironment, expandSecretPath, expandSecretKey, expandSecretTags) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment: expandEnvironment,
|
||||||
|
secretPath: expandSecretPath,
|
||||||
|
secretName: expandSecretKey,
|
||||||
|
secretTags: expandSecretTags
|
||||||
|
})
|
||||||
|
)
|
||||||
});
|
});
|
||||||
return importedSecrets;
|
return importedSecrets;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,12 +381,14 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
});
|
});
|
||||||
const encryptedValue = secretValue
|
const encryptedValue = secretValue
|
||||||
? secretManagerEncryptor({ plainText: Buffer.from(secretValue) }).cipherTextBlob
|
? {
|
||||||
: undefined;
|
encryptedValue: secretManagerEncryptor({ plainText: Buffer.from(secretValue) }).cipherTextBlob,
|
||||||
const secretReferences = secretValue ? getAllSecretReferences(secretValue) : undefined;
|
references: getAllSecretReferences(secretValue).nestedReferences
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
if (secretReferences) {
|
if (secretValue) {
|
||||||
const { nestedReferences, localReferences } = secretReferences;
|
const { nestedReferences, localReferences } = getAllSecretReferences(secretValue);
|
||||||
const allSecretReferences = nestedReferences.concat(
|
const allSecretReferences = nestedReferences.concat(
|
||||||
localReferences.map((el) => ({ secretKey: el, secretPath, environment }))
|
localReferences.map((el) => ({ secretKey: el, secretPath, environment }))
|
||||||
);
|
);
|
||||||
@@ -409,7 +411,7 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
skipMultilineEncoding: inputSecret.skipMultilineEncoding,
|
skipMultilineEncoding: inputSecret.skipMultilineEncoding,
|
||||||
key: inputSecret.newSecretName || secretName,
|
key: inputSecret.newSecretName || secretName,
|
||||||
tags: inputSecret.tagIds,
|
tags: inputSecret.tagIds,
|
||||||
...(encryptedValue ? { encryptedValue, references: secretReferences?.nestedReferences || [] } : {})
|
...encryptedValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -671,22 +673,34 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
projectId
|
projectId
|
||||||
});
|
});
|
||||||
|
|
||||||
const decryptedSecrets = secrets.map((secret) =>
|
const decryptedSecrets = secrets
|
||||||
reshapeBridgeSecret(
|
.filter((el) =>
|
||||||
projectId,
|
permission.can(
|
||||||
groupedPaths[secret.folderId][0].environment,
|
ProjectPermissionActions.Read,
|
||||||
groupedPaths[secret.folderId][0].path,
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
{
|
environment: groupedPaths[el.folderId][0].environment,
|
||||||
...secret,
|
secretPath: groupedPaths[el.folderId][0].path,
|
||||||
value: secret.encryptedValue
|
secretName: el.key,
|
||||||
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
|
secretTags: el.tags.map((i) => i.slug)
|
||||||
: "",
|
})
|
||||||
comment: secret.encryptedComment
|
)
|
||||||
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedComment }).toString()
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
.map((secret) =>
|
||||||
|
reshapeBridgeSecret(
|
||||||
|
projectId,
|
||||||
|
groupedPaths[secret.folderId][0].environment,
|
||||||
|
groupedPaths[secret.folderId][0].path,
|
||||||
|
{
|
||||||
|
...secret,
|
||||||
|
value: secret.encryptedValue
|
||||||
|
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
|
||||||
|
: "",
|
||||||
|
comment: secret.encryptedComment
|
||||||
|
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedComment }).toString()
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return decryptedSecrets;
|
return decryptedSecrets;
|
||||||
};
|
};
|
||||||
@@ -819,12 +833,22 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
|
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
|
||||||
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
|
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
|
||||||
const importedSecrets = await fnSecretsV2FromImports({
|
const importedSecrets = await fnSecretsV2FromImports({
|
||||||
allowedImports,
|
secretImports: allowedImports,
|
||||||
secretDAL,
|
secretDAL,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
expandSecretReferences,
|
expandSecretReferences,
|
||||||
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "")
|
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
||||||
|
hasSecretAccess: (expandEnvironment, expandSecretPath, expandSecretKey, expandSecretTags) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment: expandEnvironment,
|
||||||
|
secretPath: expandSecretPath,
|
||||||
|
secretName: expandSecretKey,
|
||||||
|
secretTags: expandSecretTags
|
||||||
|
})
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -936,12 +960,22 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
if (!secret && includeImports) {
|
if (!secret && includeImports) {
|
||||||
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
|
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
|
||||||
const importedSecrets = await fnSecretsV2FromImports({
|
const importedSecrets = await fnSecretsV2FromImports({
|
||||||
allowedImports: secretImports,
|
secretImports,
|
||||||
secretDAL,
|
secretDAL,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
|
||||||
expandSecretReferences: shouldExpandSecretReferences ? expandSecretReferences : undefined
|
expandSecretReferences: shouldExpandSecretReferences ? expandSecretReferences : undefined,
|
||||||
|
hasSecretAccess: (expandEnvironment, expandSecretPath, expandSecretKey, expandSecretTags) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment: expandEnvironment,
|
||||||
|
secretPath: expandSecretPath,
|
||||||
|
secretName: expandSecretKey,
|
||||||
|
secretTags: expandSecretTags
|
||||||
|
})
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||||
|
|||||||
@@ -342,7 +342,8 @@ export const secretQueueFactory = ({
|
|||||||
secretDAL: secretV2BridgeDAL,
|
secretDAL: secretV2BridgeDAL,
|
||||||
expandSecretReferences,
|
expandSecretReferences,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
allowedImports: secretImports
|
secretImports,
|
||||||
|
hasSecretAccess: () => true
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user