mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 15:27:46 +00:00
Merge pull request #1617 from Infisical/daniel/improve-create-project
Feat: Recursively get all secrets from all folders in specified path
This commit is contained in:
@@ -215,6 +215,7 @@ export const SECRETS = {
|
|||||||
|
|
||||||
export const RAW_SECRETS = {
|
export const RAW_SECRETS = {
|
||||||
LIST: {
|
LIST: {
|
||||||
|
recursive: "Whether or not to fetch all secrets from the specified base path, and all of its subdirectories.",
|
||||||
workspaceId: "The ID of the project to list secrets from.",
|
workspaceId: "The ID of the project to list secrets from.",
|
||||||
workspaceSlug: "The slug of the project to list secrets from. This parameter is only usable by machine identities.",
|
workspaceSlug: "The slug of the project to list secrets from. This parameter is only usable by machine identities.",
|
||||||
environment: "The slug of the environment to list secrets from.",
|
environment: "The slug of the environment to list secrets from.",
|
||||||
|
|||||||
@@ -490,6 +490,7 @@ export const registerRoutes = async (
|
|||||||
snapshotService,
|
snapshotService,
|
||||||
secretQueueService,
|
secretQueueService,
|
||||||
secretImportDAL,
|
secretImportDAL,
|
||||||
|
projectEnvDAL,
|
||||||
projectBotService
|
projectBotService
|
||||||
});
|
});
|
||||||
const sarService = secretApprovalRequestServiceFactory({
|
const sarService = secretApprovalRequestServiceFactory({
|
||||||
|
|||||||
@@ -157,6 +157,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
workspaceSlug: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceSlug),
|
workspaceSlug: z.string().trim().optional().describe(RAW_SECRETS.LIST.workspaceSlug),
|
||||||
environment: z.string().trim().optional().describe(RAW_SECRETS.LIST.environment),
|
environment: z.string().trim().optional().describe(RAW_SECRETS.LIST.environment),
|
||||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.LIST.secretPath),
|
secretPath: z.string().trim().default("/").transform(removeTrailingSlash).describe(RAW_SECRETS.LIST.secretPath),
|
||||||
|
recursive: z
|
||||||
|
.enum(["true", "false"])
|
||||||
|
.default("false")
|
||||||
|
.transform((value) => value === "true")
|
||||||
|
.describe(RAW_SECRETS.LIST.recursive),
|
||||||
include_imports: z
|
include_imports: z
|
||||||
.enum(["true", "false"])
|
.enum(["true", "false"])
|
||||||
.default("false")
|
.default("false")
|
||||||
@@ -165,7 +170,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
secrets: secretRawSchema.array(),
|
secrets: secretRawSchema
|
||||||
|
.extend({
|
||||||
|
secretPath: z.string().optional()
|
||||||
|
})
|
||||||
|
.array(),
|
||||||
imports: z
|
imports: z
|
||||||
.object({
|
.object({
|
||||||
secretPath: z.string(),
|
secretPath: z.string(),
|
||||||
@@ -218,7 +227,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
projectId: workspaceId,
|
projectId: workspaceId,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
includeImports: req.query.include_imports
|
includeImports: req.query.include_imports,
|
||||||
|
recursive: req.query.recursive
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.services.auditLog.createAuditLog({
|
await server.services.auditLog.createAuditLog({
|
||||||
@@ -596,6 +606,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
workspaceId: z.string().trim(),
|
workspaceId: z.string().trim(),
|
||||||
environment: z.string().trim(),
|
environment: z.string().trim(),
|
||||||
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||||
|
recursive: z
|
||||||
|
.enum(["true", "false"])
|
||||||
|
.default("false")
|
||||||
|
.transform((value) => value === "true"),
|
||||||
include_imports: z
|
include_imports: z
|
||||||
.enum(["true", "false"])
|
.enum(["true", "false"])
|
||||||
.default("false")
|
.default("false")
|
||||||
@@ -604,19 +618,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
secrets: SecretsSchema.omit({ secretBlindIndex: true })
|
secrets: SecretsSchema.omit({ secretBlindIndex: true })
|
||||||
.merge(
|
.extend({
|
||||||
z.object({
|
_id: z.string(),
|
||||||
_id: z.string(),
|
workspace: z.string(),
|
||||||
workspace: z.string(),
|
environment: z.string(),
|
||||||
environment: z.string(),
|
secretPath: z.string().optional(),
|
||||||
tags: SecretTagsSchema.pick({
|
tags: SecretTagsSchema.pick({
|
||||||
id: true,
|
id: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
name: true,
|
name: true,
|
||||||
color: true
|
color: true
|
||||||
}).array()
|
}).array()
|
||||||
})
|
})
|
||||||
)
|
|
||||||
.array(),
|
.array(),
|
||||||
imports: z
|
imports: z
|
||||||
.object({
|
.object({
|
||||||
@@ -648,7 +661,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
environment: req.query.environment,
|
environment: req.query.environment,
|
||||||
projectId: req.query.workspaceId,
|
projectId: req.query.workspaceId,
|
||||||
path: req.query.secretPath,
|
path: req.query.secretPath,
|
||||||
includeImports: req.query.include_imports
|
includeImports: req.query.include_imports,
|
||||||
|
recursive: req.query.recursive
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.services.auditLog.createAuditLog({
|
await server.services.auditLog.createAuditLog({
|
||||||
|
|||||||
@@ -70,9 +70,31 @@ export const secretImportDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findByFolderIds = async (folderIds: string[], tx?: Knex) => {
|
||||||
|
try {
|
||||||
|
const docs = await (tx || db)(TableName.SecretImport)
|
||||||
|
.whereIn("folderId", folderIds)
|
||||||
|
.join(TableName.Environment, `${TableName.SecretImport}.importEnv`, `${TableName.Environment}.id`)
|
||||||
|
.select(
|
||||||
|
db.ref("*").withSchema(TableName.SecretImport) as unknown as keyof TSecretImports,
|
||||||
|
db.ref("slug").withSchema(TableName.Environment),
|
||||||
|
db.ref("name").withSchema(TableName.Environment),
|
||||||
|
db.ref("id").withSchema(TableName.Environment).as("envId")
|
||||||
|
)
|
||||||
|
.orderBy("position", "asc");
|
||||||
|
return docs.map(({ envId, slug, name, ...el }) => ({
|
||||||
|
...el,
|
||||||
|
importEnv: { id: envId, slug, name }
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "Find secret imports" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...secretImportOrm,
|
...secretImportOrm,
|
||||||
find,
|
find,
|
||||||
|
findByFolderIds,
|
||||||
findLastImportPosition,
|
findLastImportPosition,
|
||||||
updateAllPosition
|
updateAllPosition
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -171,6 +171,50 @@ export const secretDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findByFolderIds = async (folderIds: string[], userId?: string, tx?: Knex) => {
|
||||||
|
try {
|
||||||
|
// check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo)
|
||||||
|
if (userId && !uuidValidate(userId)) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
userId = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const secs = await (tx || db)(TableName.Secret)
|
||||||
|
.whereIn("folderId", folderIds)
|
||||||
|
.where((bd) => {
|
||||||
|
void bd.whereNull("userId").orWhere({ userId: userId || null });
|
||||||
|
})
|
||||||
|
.leftJoin(TableName.JnSecretTag, `${TableName.Secret}.id`, `${TableName.JnSecretTag}.${TableName.Secret}Id`)
|
||||||
|
.leftJoin(TableName.SecretTag, `${TableName.JnSecretTag}.${TableName.SecretTag}Id`, `${TableName.SecretTag}.id`)
|
||||||
|
.select(selectAllTableCols(TableName.Secret))
|
||||||
|
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
|
||||||
|
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
|
||||||
|
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
|
||||||
|
.select(db.ref("name").withSchema(TableName.SecretTag).as("tagName"))
|
||||||
|
.orderBy("id", "asc");
|
||||||
|
const data = sqlNestRelationships({
|
||||||
|
data: secs,
|
||||||
|
key: "id",
|
||||||
|
parentMapper: (el) => ({ _id: el.id, ...SecretsSchema.parse(el) }),
|
||||||
|
childrenMapper: [
|
||||||
|
{
|
||||||
|
key: "tagId",
|
||||||
|
label: "tags" as const,
|
||||||
|
mapper: ({ tagId: id, tagColor: color, tagSlug: slug, tagName: name }) => ({
|
||||||
|
id,
|
||||||
|
color,
|
||||||
|
slug,
|
||||||
|
name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "get all secret" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const findByBlindIndexes = async (
|
const findByBlindIndexes = async (
|
||||||
folderId: string,
|
folderId: string,
|
||||||
blindIndexes: Array<{ blindIndex: string; type: SecretType }>,
|
blindIndexes: Array<{ blindIndex: string; type: SecretType }>,
|
||||||
@@ -207,6 +251,7 @@ export const secretDALFactory = (db: TDbClient) => {
|
|||||||
bulkUpdateNoVersionIncrement,
|
bulkUpdateNoVersionIncrement,
|
||||||
getSecretTags,
|
getSecretTags,
|
||||||
findByFolderId,
|
findByFolderId,
|
||||||
|
findByFolderIds,
|
||||||
findByBlindIndexes
|
findByBlindIndexes
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import { subject } from "@casl/ability";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -7,8 +8,11 @@ import {
|
|||||||
SecretType,
|
SecretType,
|
||||||
TableName,
|
TableName,
|
||||||
TSecretBlindIndexes,
|
TSecretBlindIndexes,
|
||||||
|
TSecretFolders,
|
||||||
TSecrets
|
TSecrets
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import {
|
import {
|
||||||
buildSecretBlindIndexFromName,
|
buildSecretBlindIndexFromName,
|
||||||
@@ -18,7 +22,9 @@ import {
|
|||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { groupBy, unique } from "@app/lib/fn";
|
import { groupBy, unique } from "@app/lib/fn";
|
||||||
|
|
||||||
|
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
|
||||||
import { getBotKeyFnFactory } from "../project-bot/project-bot-fns";
|
import { getBotKeyFnFactory } from "../project-bot/project-bot-fns";
|
||||||
|
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||||
import { TSecretDALFactory } from "./secret-dal";
|
import { TSecretDALFactory } from "./secret-dal";
|
||||||
import {
|
import {
|
||||||
@@ -45,6 +51,133 @@ export const generateSecretBlindIndexBySalt = async (secretName: string, secretB
|
|||||||
return secretBlindIndex;
|
return secretBlindIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type TRecursivelyFetchSecretsFromFoldersArg = {
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
|
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath" | "find">;
|
||||||
|
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
|
||||||
|
};
|
||||||
|
|
||||||
|
type TGetPathsDTO = {
|
||||||
|
projectId: string;
|
||||||
|
environment: string;
|
||||||
|
currentPath: string;
|
||||||
|
|
||||||
|
auth: {
|
||||||
|
actor: ActorType;
|
||||||
|
actorId: string;
|
||||||
|
actorAuthMethod: ActorAuthMethod;
|
||||||
|
actorOrgId: string | undefined;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Introduce a new interface for mapping parent IDs to their children
|
||||||
|
interface FolderMap {
|
||||||
|
[parentId: string]: TSecretFolders[];
|
||||||
|
}
|
||||||
|
const buildHierarchy = (folders: TSecretFolders[]): FolderMap => {
|
||||||
|
const map: FolderMap = {};
|
||||||
|
map.null = []; // Initialize mapping for root directory
|
||||||
|
|
||||||
|
folders.forEach((folder) => {
|
||||||
|
const parentId = folder.parentId || "null";
|
||||||
|
if (!map[parentId]) {
|
||||||
|
map[parentId] = [];
|
||||||
|
}
|
||||||
|
map[parentId].push(folder);
|
||||||
|
});
|
||||||
|
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generatePaths = (
|
||||||
|
map: FolderMap,
|
||||||
|
parentId: string = "null",
|
||||||
|
basePath: string = ""
|
||||||
|
): { path: string; folderId: string }[] => {
|
||||||
|
const children = map[parentId || "null"] || [];
|
||||||
|
let paths: { path: string; folderId: string }[] = [];
|
||||||
|
|
||||||
|
children.forEach((child) => {
|
||||||
|
// Determine if this is the root folder of the environment. If no parentId is present and the name is root, it's the root folder
|
||||||
|
const isRootFolder = child.name === "root" && !child.parentId;
|
||||||
|
|
||||||
|
// Form the current path based on the base path and the current child
|
||||||
|
// eslint-disable-next-line no-nested-ternary
|
||||||
|
const currPath = basePath === "" ? (isRootFolder ? "/" : `/${child.name}`) : `${basePath}/${child.name}`;
|
||||||
|
|
||||||
|
paths.push({
|
||||||
|
path: currPath,
|
||||||
|
folderId: child.id
|
||||||
|
}); // Add the current path
|
||||||
|
|
||||||
|
// Recursively generate paths for children, passing down the formatted pathh
|
||||||
|
const childPaths = generatePaths(map, child.id, currPath);
|
||||||
|
paths = paths.concat(
|
||||||
|
childPaths.map((p) => ({
|
||||||
|
path: p.path,
|
||||||
|
folderId: p.folderId
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const recursivelyGetSecretPaths = ({
|
||||||
|
folderDAL,
|
||||||
|
projectEnvDAL,
|
||||||
|
permissionService
|
||||||
|
}: TRecursivelyFetchSecretsFromFoldersArg) => {
|
||||||
|
const getPaths = async ({ projectId, environment, currentPath, auth }: TGetPathsDTO) => {
|
||||||
|
const env = await projectEnvDAL.findOne({
|
||||||
|
projectId,
|
||||||
|
slug: environment
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!env) {
|
||||||
|
throw new Error(`'${environment}' environment not found in project with ID ${projectId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all folders in env once with a single query
|
||||||
|
const folders = await folderDAL.find({
|
||||||
|
envId: env.id
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build the folder hierarchy map
|
||||||
|
const folderMap = buildHierarchy(folders);
|
||||||
|
|
||||||
|
// Generate the paths paths and normalize the root path to /
|
||||||
|
const paths = generatePaths(folderMap).map((p) => ({
|
||||||
|
path: p.path === "/" ? p.path : p.path.substring(1),
|
||||||
|
folderId: p.folderId
|
||||||
|
}));
|
||||||
|
|
||||||
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
|
auth.actor,
|
||||||
|
auth.actorId,
|
||||||
|
projectId,
|
||||||
|
auth.actorAuthMethod,
|
||||||
|
auth.actorOrgId
|
||||||
|
);
|
||||||
|
|
||||||
|
// Filter out paths that the user does not have permission to access, and paths that are not in the current path
|
||||||
|
const allowedPaths = paths.filter(
|
||||||
|
(folder) =>
|
||||||
|
permission.can(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment,
|
||||||
|
secretPath: folder.path
|
||||||
|
})
|
||||||
|
) && folder.path.startsWith(currentPath === "/" ? "" : currentPath)
|
||||||
|
);
|
||||||
|
|
||||||
|
return allowedPaths;
|
||||||
|
};
|
||||||
|
|
||||||
|
return getPaths;
|
||||||
|
};
|
||||||
|
|
||||||
type TInterpolateSecretArg = {
|
type TInterpolateSecretArg = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
secretEncKey: string;
|
secretEncKey: string;
|
||||||
@@ -202,9 +335,7 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
|
|||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
secrets[key].value = secrets[key].skipMultilineEncoding
|
secrets[key].value = secrets[key].skipMultilineEncoding ? expandedVal : formatMultiValueEnv(expandedVal);
|
||||||
? expandedVal
|
|
||||||
: formatMultiValueEnv(expandedVal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return secrets;
|
return secrets;
|
||||||
@@ -212,7 +343,10 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
|
|||||||
return expandSecrets;
|
return expandSecrets;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decryptSecretRaw = (secret: TSecrets & { workspace: string; environment: string }, key: string) => {
|
export const decryptSecretRaw = (
|
||||||
|
secret: TSecrets & { workspace: string; environment: string; secretPath?: string },
|
||||||
|
key: string
|
||||||
|
) => {
|
||||||
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
const secretKey = decryptSymmetric128BitHexKeyUTF8({
|
||||||
ciphertext: secret.secretKeyCiphertext,
|
ciphertext: secret.secretKeyCiphertext,
|
||||||
iv: secret.secretKeyIV,
|
iv: secret.secretKeyIV,
|
||||||
@@ -240,6 +374,7 @@ export const decryptSecretRaw = (secret: TSecrets & { workspace: string; environ
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
secretKey,
|
secretKey,
|
||||||
|
secretPath: secret.secretPath,
|
||||||
workspace: secret.workspace,
|
workspace: secret.workspace,
|
||||||
environment: secret.environment,
|
environment: secret.environment,
|
||||||
secretValue,
|
secretValue,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* eslint-disable no-unreachable-loop */
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
import { ForbiddenError, subject } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
|
||||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretsSchema, SecretType } from "@app/db/schemas";
|
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretsSchema, SecretType } from "@app/db/schemas";
|
||||||
@@ -13,13 +15,20 @@ import { logger } from "@app/lib/logger";
|
|||||||
import { ActorType } from "../auth/auth-type";
|
import { ActorType } from "../auth/auth-type";
|
||||||
import { TProjectDALFactory } from "../project/project-dal";
|
import { TProjectDALFactory } from "../project/project-dal";
|
||||||
import { TProjectBotServiceFactory } from "../project-bot/project-bot-service";
|
import { TProjectBotServiceFactory } from "../project-bot/project-bot-service";
|
||||||
|
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||||
import { TSecretBlindIndexDALFactory } from "../secret-blind-index/secret-blind-index-dal";
|
import { TSecretBlindIndexDALFactory } from "../secret-blind-index/secret-blind-index-dal";
|
||||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||||
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
|
||||||
import { fnSecretsFromImports } from "../secret-import/secret-import-fns";
|
import { fnSecretsFromImports } from "../secret-import/secret-import-fns";
|
||||||
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
|
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
|
||||||
import { TSecretDALFactory } from "./secret-dal";
|
import { TSecretDALFactory } from "./secret-dal";
|
||||||
import { decryptSecretRaw, fnSecretBlindIndexCheck, fnSecretBulkInsert, fnSecretBulkUpdate } from "./secret-fns";
|
import {
|
||||||
|
decryptSecretRaw,
|
||||||
|
fnSecretBlindIndexCheck,
|
||||||
|
fnSecretBulkInsert,
|
||||||
|
fnSecretBulkUpdate,
|
||||||
|
recursivelyGetSecretPaths
|
||||||
|
} from "./secret-fns";
|
||||||
import { TSecretQueueFactory } from "./secret-queue";
|
import { TSecretQueueFactory } from "./secret-queue";
|
||||||
import {
|
import {
|
||||||
TAttachSecretTagsDTO,
|
TAttachSecretTagsDTO,
|
||||||
@@ -47,20 +56,25 @@ type TSecretServiceFactoryDep = {
|
|||||||
secretDAL: TSecretDALFactory;
|
secretDAL: TSecretDALFactory;
|
||||||
secretTagDAL: TSecretTagDALFactory;
|
secretTagDAL: TSecretTagDALFactory;
|
||||||
secretVersionDAL: TSecretVersionDALFactory;
|
secretVersionDAL: TSecretVersionDALFactory;
|
||||||
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath" | "updateById" | "findById" | "findByManySecretPath">;
|
|
||||||
projectDAL: Pick<TProjectDALFactory, "checkProjectUpgradeStatus" | "findProjectBySlug">;
|
projectDAL: Pick<TProjectDALFactory, "checkProjectUpgradeStatus" | "findProjectBySlug">;
|
||||||
|
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
|
||||||
|
folderDAL: Pick<
|
||||||
|
TSecretFolderDALFactory,
|
||||||
|
"findBySecretPath" | "updateById" | "findById" | "findByManySecretPath" | "find"
|
||||||
|
>;
|
||||||
secretBlindIndexDAL: TSecretBlindIndexDALFactory;
|
secretBlindIndexDAL: TSecretBlindIndexDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
|
||||||
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "handleSecretReminder" | "removeSecretReminder">;
|
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "handleSecretReminder" | "removeSecretReminder">;
|
||||||
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
|
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
|
||||||
secretImportDAL: Pick<TSecretImportDALFactory, "find">;
|
secretImportDAL: Pick<TSecretImportDALFactory, "find" | "findByFolderIds">;
|
||||||
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
|
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TSecretServiceFactory = ReturnType<typeof secretServiceFactory>;
|
export type TSecretServiceFactory = ReturnType<typeof secretServiceFactory>;
|
||||||
export const secretServiceFactory = ({
|
export const secretServiceFactory = ({
|
||||||
secretDAL,
|
secretDAL,
|
||||||
|
projectEnvDAL,
|
||||||
secretTagDAL,
|
secretTagDAL,
|
||||||
secretVersionDAL,
|
secretVersionDAL,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
@@ -425,7 +439,8 @@ export const secretServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
includeImports
|
includeImports,
|
||||||
|
recursive
|
||||||
}: TGetSecretsDTO) => {
|
}: TGetSecretsDTO) => {
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
@@ -434,19 +449,52 @@ export const secretServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
|
||||||
ProjectPermissionActions.Read,
|
let paths: { folderId: string; path: string }[] = [];
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
|
||||||
|
if (recursive) {
|
||||||
|
const getPaths = recursivelyGetSecretPaths({
|
||||||
|
permissionService,
|
||||||
|
folderDAL,
|
||||||
|
projectEnvDAL
|
||||||
|
});
|
||||||
|
|
||||||
|
const deepPaths = await getPaths({
|
||||||
|
projectId,
|
||||||
|
environment,
|
||||||
|
currentPath: path,
|
||||||
|
auth: {
|
||||||
|
actor,
|
||||||
|
actorId,
|
||||||
|
actorAuthMethod,
|
||||||
|
actorOrgId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!deepPaths) return { secrets: [], imports: [] };
|
||||||
|
|
||||||
|
paths = deepPaths.map(({ folderId, path: p }) => ({ folderId, path: p }));
|
||||||
|
} else {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||||
|
);
|
||||||
|
|
||||||
|
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||||
|
if (!folder) return { secrets: [], imports: [] };
|
||||||
|
|
||||||
|
paths = [{ folderId: folder.id, path }];
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupedPaths = groupBy(paths, (p) => p.folderId);
|
||||||
|
|
||||||
|
const secrets = await secretDAL.findByFolderIds(
|
||||||
|
paths.map((p) => p.folderId),
|
||||||
|
actorId
|
||||||
);
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
|
||||||
if (!folder) return { secrets: [], imports: [] };
|
|
||||||
const folderId = folder.id;
|
|
||||||
|
|
||||||
const secrets = await secretDAL.findByFolderId(folderId, actorId);
|
|
||||||
|
|
||||||
if (includeImports) {
|
if (includeImports) {
|
||||||
const secretImports = await secretImportDAL.find({ folderId });
|
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
|
||||||
const allowedImports = secretImports.filter(({ importEnv, importPath }) =>
|
const allowedImports = secretImports.filter(({ importEnv, importPath }) =>
|
||||||
// if its service token allow full access over imported one
|
// if its service token allow full access over imported one
|
||||||
actor === ActorType.SERVICE
|
actor === ActorType.SERVICE
|
||||||
@@ -464,12 +512,26 @@ export const secretServiceFactory = ({
|
|||||||
secretDAL,
|
secretDAL,
|
||||||
folderDAL
|
folderDAL
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
secrets: secrets.map((el) => ({ ...el, workspace: projectId, environment })),
|
secrets: secrets.map((secret) => ({
|
||||||
|
...secret,
|
||||||
|
workspace: projectId,
|
||||||
|
environment,
|
||||||
|
secretPath: groupedPaths[secret.folderId][0].path
|
||||||
|
})),
|
||||||
imports: importedSecrets
|
imports: importedSecrets
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return { secrets: secrets.map((el) => ({ ...el, workspace: projectId, environment })) };
|
|
||||||
|
return {
|
||||||
|
secrets: secrets.map((secret) => ({
|
||||||
|
...secret,
|
||||||
|
workspace: projectId,
|
||||||
|
environment,
|
||||||
|
secretPath: groupedPaths[secret.folderId][0].path
|
||||||
|
}))
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSecretByName = async ({
|
const getSecretByName = async ({
|
||||||
@@ -789,7 +851,8 @@ export const secretServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
environment,
|
environment,
|
||||||
includeImports
|
includeImports,
|
||||||
|
recursive
|
||||||
}: TGetSecretsRawDTO) => {
|
}: TGetSecretsRawDTO) => {
|
||||||
const botKey = await projectBotService.getBotKey(projectId);
|
const botKey = await projectBotService.getBotKey(projectId);
|
||||||
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
|
if (!botKey) throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
|
||||||
@@ -802,7 +865,8 @@ export const secretServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
path,
|
path,
|
||||||
includeImports
|
includeImports,
|
||||||
|
recursive
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -810,7 +874,10 @@ export const secretServiceFactory = ({
|
|||||||
imports: (imports || [])?.map(({ secrets: importedSecrets, ...el }) => ({
|
imports: (imports || [])?.map(({ secrets: importedSecrets, ...el }) => ({
|
||||||
...el,
|
...el,
|
||||||
secrets: importedSecrets.map((sec) =>
|
secrets: importedSecrets.map((sec) =>
|
||||||
decryptSecretRaw({ ...sec, environment: el.environment, workspace: projectId }, botKey)
|
decryptSecretRaw(
|
||||||
|
{ ...sec, environment: el.environment, workspace: projectId, secretPath: el.secretPath },
|
||||||
|
botKey
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export type TGetSecretsDTO = {
|
|||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
includeImports?: boolean;
|
includeImports?: boolean;
|
||||||
|
recursive?: boolean;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TGetASecretDTO = {
|
export type TGetASecretDTO = {
|
||||||
@@ -140,6 +141,7 @@ export type TGetSecretsRawDTO = {
|
|||||||
path: string;
|
path: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
includeImports?: boolean;
|
includeImports?: boolean;
|
||||||
|
recursive?: boolean;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TGetASecretRawDTO = {
|
export type TGetASecretRawDTO = {
|
||||||
|
|||||||
@@ -277,6 +277,10 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req
|
|||||||
SetQueryParam("environment", request.Environment).
|
SetQueryParam("environment", request.Environment).
|
||||||
SetQueryParam("workspaceId", request.WorkspaceId)
|
SetQueryParam("workspaceId", request.WorkspaceId)
|
||||||
|
|
||||||
|
if request.Recursive {
|
||||||
|
httpRequest.SetQueryParam("recursive", "true")
|
||||||
|
}
|
||||||
|
|
||||||
if request.IncludeImport {
|
if request.IncludeImport {
|
||||||
httpRequest.SetQueryParam("include_imports", "true")
|
httpRequest.SetQueryParam("include_imports", "true")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ type GetEncryptedSecretsV3Request struct {
|
|||||||
WorkspaceId string `json:"workspaceId"`
|
WorkspaceId string `json:"workspaceId"`
|
||||||
SecretPath string `json:"secretPath"`
|
SecretPath string `json:"secretPath"`
|
||||||
IncludeImport bool `json:"include_imports"`
|
IncludeImport bool `json:"include_imports"`
|
||||||
|
Recursive bool `json:"recursive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetFoldersV1Request struct {
|
type GetFoldersV1Request struct {
|
||||||
@@ -510,7 +511,7 @@ type CreateDynamicSecretLeaseV1Request struct {
|
|||||||
|
|
||||||
type CreateDynamicSecretLeaseV1Response struct {
|
type CreateDynamicSecretLeaseV1Response struct {
|
||||||
Lease struct {
|
Lease struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
ExpireAt time.Time `json:"expireAt"`
|
ExpireAt time.Time `json:"expireAt"`
|
||||||
} `json:"lease"`
|
} `json:"lease"`
|
||||||
DynamicSecret struct {
|
DynamicSecret struct {
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ func ParseAgentConfig(configFile []byte) (*Config, error) {
|
|||||||
|
|
||||||
func secretTemplateFunction(accessToken string, existingEtag string, currentEtag *string) func(string, string, string) ([]models.SingleEnvironmentVariable, error) {
|
func secretTemplateFunction(accessToken string, existingEtag string, currentEtag *string) func(string, string, string) ([]models.SingleEnvironmentVariable, error) {
|
||||||
return func(projectID, envSlug, secretPath string) ([]models.SingleEnvironmentVariable, error) {
|
return func(projectID, envSlug, secretPath string) ([]models.SingleEnvironmentVariable, error) {
|
||||||
res, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false)
|
res, err := util.GetPlainTextSecretsViaMachineIdentity(accessToken, projectID, envSlug, secretPath, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,12 @@ var runCmd = &cobra.Command{
|
|||||||
util.HandleError(err, "Unable to parse flag")
|
util.HandleError(err, "Unable to parse flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}, projectConfigDir)
|
recursive, err := cmd.Flags().GetBool("recursive")
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to parse flag")
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, projectConfigDir)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid")
|
util.HandleError(err, "Could not fetch secrets", "If you are using a service token to fetch secrets, please ensure it is valid")
|
||||||
@@ -202,6 +207,7 @@ func init() {
|
|||||||
runCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from")
|
runCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from")
|
||||||
runCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets")
|
runCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets")
|
||||||
runCmd.Flags().Bool("include-imports", true, "Import linked secrets ")
|
runCmd.Flags().Bool("include-imports", true, "Import linked secrets ")
|
||||||
|
runCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders")
|
||||||
runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets")
|
runCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets")
|
||||||
runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")")
|
runCmd.Flags().StringP("command", "c", "", "chained commands to execute (e.g. \"npm install && npm run dev; echo ...\")")
|
||||||
runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ")
|
runCmd.Flags().StringP("tags", "t", "", "filter secrets by tag slugs ")
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ var secretsCmd = &cobra.Command{
|
|||||||
util.HandleError(err)
|
util.HandleError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recursive, err := cmd.Flags().GetBool("recursive")
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err)
|
||||||
|
}
|
||||||
|
|
||||||
tagSlugs, err := cmd.Flags().GetString("tags")
|
tagSlugs, err := cmd.Flags().GetString("tags")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "Unable to parse flag")
|
util.HandleError(err, "Unable to parse flag")
|
||||||
@@ -73,7 +78,7 @@ var secretsCmd = &cobra.Command{
|
|||||||
util.HandleError(err, "Unable to parse flag")
|
util.HandleError(err, "Unable to parse flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports}, "")
|
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: includeImports, Recursive: recursive}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err)
|
util.HandleError(err)
|
||||||
}
|
}
|
||||||
@@ -413,12 +418,17 @@ func getSecretsByNames(cmd *cobra.Command, args []string) {
|
|||||||
util.HandleError(err, "Unable to parse path flag")
|
util.HandleError(err, "Unable to parse path flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recursive, err := cmd.Flags().GetBool("recursive")
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to parse recursive flag")
|
||||||
|
}
|
||||||
|
|
||||||
showOnlyValue, err := cmd.Flags().GetBool("raw-value")
|
showOnlyValue, err := cmd.Flags().GetBool("raw-value")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "Unable to parse path flag")
|
util.HandleError(err, "Unable to parse path flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true}, "")
|
secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath, IncludeImport: true, Recursive: recursive}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.HandleError(err, "To fetch all secrets")
|
util.HandleError(err, "To fetch all secrets")
|
||||||
}
|
}
|
||||||
@@ -727,6 +737,7 @@ func init() {
|
|||||||
secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on")
|
secretsCmd.PersistentFlags().String("env", "dev", "Used to select the environment name on which actions should be taken on")
|
||||||
secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets")
|
secretsCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets")
|
||||||
secretsCmd.Flags().Bool("include-imports", true, "Imported linked secrets ")
|
secretsCmd.Flags().Bool("include-imports", true, "Imported linked secrets ")
|
||||||
|
secretsCmd.Flags().Bool("recursive", false, "Fetch secrets from all sub-folders")
|
||||||
secretsCmd.PersistentFlags().StringP("tags", "t", "", "filter secrets by tag slugs")
|
secretsCmd.PersistentFlags().StringP("tags", "t", "", "filter secrets by tag slugs")
|
||||||
secretsCmd.Flags().String("path", "/", "get secrets within a folder path")
|
secretsCmd.Flags().String("path", "/", "get secrets within a folder path")
|
||||||
rootCmd.AddCommand(secretsCmd)
|
rootCmd.AddCommand(secretsCmd)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ type GetAllSecretsParameters struct {
|
|||||||
WorkspaceId string
|
WorkspaceId string
|
||||||
SecretsPath string
|
SecretsPath string
|
||||||
IncludeImport bool
|
IncludeImport bool
|
||||||
|
Recursive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetAllFoldersParameters struct {
|
type GetAllFoldersParameters struct {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string, includeImports bool) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) {
|
func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment string, secretPath string, includeImports bool, recursive bool) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) {
|
||||||
serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4)
|
serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4)
|
||||||
if len(serviceTokenParts) < 4 {
|
if len(serviceTokenParts) < 4 {
|
||||||
return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again")
|
return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again")
|
||||||
@@ -49,6 +49,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str
|
|||||||
Environment: environment,
|
Environment: environment,
|
||||||
SecretPath: secretPath,
|
SecretPath: secretPath,
|
||||||
IncludeImport: includeImports,
|
IncludeImport: includeImports,
|
||||||
|
Recursive: recursive,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -80,7 +81,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str
|
|||||||
return plainTextSecrets, serviceTokenDetails, nil
|
return plainTextSecrets, serviceTokenDetails, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string, includeImports bool) ([]models.SingleEnvironmentVariable, error) {
|
func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string, secretsPath string, includeImports bool, recursive bool) ([]models.SingleEnvironmentVariable, error) {
|
||||||
httpClient := resty.New()
|
httpClient := resty.New()
|
||||||
httpClient.SetAuthToken(JTWToken).
|
httpClient.SetAuthToken(JTWToken).
|
||||||
SetHeader("Accept", "application/json")
|
SetHeader("Accept", "application/json")
|
||||||
@@ -125,6 +126,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work
|
|||||||
WorkspaceId: workspaceId,
|
WorkspaceId: workspaceId,
|
||||||
Environment: environmentName,
|
Environment: environmentName,
|
||||||
IncludeImport: includeImports,
|
IncludeImport: includeImports,
|
||||||
|
Recursive: recursive,
|
||||||
// TagSlugs: tagSlugs,
|
// TagSlugs: tagSlugs,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +154,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work
|
|||||||
return plainTextSecrets, nil
|
return plainTextSecrets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool) (models.PlaintextSecretResult, error) {
|
func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId string, environmentName string, secretsPath string, includeImports bool, recursive bool) (models.PlaintextSecretResult, error) {
|
||||||
httpClient := resty.New()
|
httpClient := resty.New()
|
||||||
httpClient.SetAuthToken(accessToken).
|
httpClient.SetAuthToken(accessToken).
|
||||||
SetHeader("Accept", "application/json")
|
SetHeader("Accept", "application/json")
|
||||||
@@ -161,6 +163,7 @@ func GetPlainTextSecretsViaMachineIdentity(accessToken string, workspaceId strin
|
|||||||
WorkspaceId: workspaceId,
|
WorkspaceId: workspaceId,
|
||||||
Environment: environmentName,
|
Environment: environmentName,
|
||||||
IncludeImport: includeImports,
|
IncludeImport: includeImports,
|
||||||
|
Recursive: recursive,
|
||||||
// TagSlugs: tagSlugs,
|
// TagSlugs: tagSlugs,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +332,7 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, infisicalDotJson.WorkspaceId,
|
secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, infisicalDotJson.WorkspaceId,
|
||||||
params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport)
|
params.Environment, params.TagSlugs, params.SecretsPath, params.IncludeImport, params.Recursive)
|
||||||
log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn)
|
log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn)
|
||||||
|
|
||||||
backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32]
|
backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32]
|
||||||
@@ -350,10 +353,10 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters, projectCo
|
|||||||
} else {
|
} else {
|
||||||
if params.InfisicalToken != "" {
|
if params.InfisicalToken != "" {
|
||||||
log.Debug().Msg("Trying to fetch secrets using service token")
|
log.Debug().Msg("Trying to fetch secrets using service token")
|
||||||
secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(params.InfisicalToken, params.Environment, params.SecretsPath, params.IncludeImport)
|
secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(params.InfisicalToken, params.Environment, params.SecretsPath, params.IncludeImport, params.Recursive)
|
||||||
} else if params.UniversalAuthAccessToken != "" {
|
} else if params.UniversalAuthAccessToken != "" {
|
||||||
log.Debug().Msg("Trying to fetch secrets using universal auth")
|
log.Debug().Msg("Trying to fetch secrets using universal auth")
|
||||||
res, err := GetPlainTextSecretsViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.SecretsPath, params.IncludeImport)
|
res, err := GetPlainTextSecretsViaMachineIdentity(params.UniversalAuthAccessToken, params.WorkspaceId, params.Environment, params.SecretsPath, params.IncludeImport, params.Recursive)
|
||||||
|
|
||||||
errorToReturn = err
|
errorToReturn = err
|
||||||
secretsToReturn = res.Secrets
|
secretsToReturn = res.Secrets
|
||||||
|
|||||||
Reference in New Issue
Block a user