mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-03 01:25:47 +00:00
feat(infisical-pg): added single scope service token auto filling for get secret by name raw and version option for both get secret by name
This commit is contained in:
@@ -71,7 +71,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
environment,
|
environment,
|
||||||
projectId: workspaceId as string,
|
projectId: workspaceId,
|
||||||
path: secretPath,
|
path: secretPath,
|
||||||
includeImports: req.query.include_imports
|
includeImports: req.query.include_imports
|
||||||
});
|
});
|
||||||
@@ -100,9 +100,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
secretName: z.string().trim()
|
secretName: z.string().trim()
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
workspaceId: z.string().trim(),
|
workspaceId: z.string().trim().optional(),
|
||||||
environment: z.string().trim(),
|
environment: z.string().trim().optional(),
|
||||||
secretPath: z.string().trim().default("/"),
|
secretPath: z.string().trim().default("/"),
|
||||||
|
version: z.coerce.number().optional(),
|
||||||
type: z.nativeEnum(SecretType).default(SecretType.Shared),
|
type: z.nativeEnum(SecretType).default(SecretType.Shared),
|
||||||
include_imports: z
|
include_imports: z
|
||||||
.enum(["true", "false"])
|
.enum(["true", "false"])
|
||||||
@@ -122,15 +123,30 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
AuthMode.IDENTITY_ACCESS_TOKEN
|
AuthMode.IDENTITY_ACCESS_TOKEN
|
||||||
]),
|
]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const secret = await server.services.secret.getASecretRaw({
|
let { secretPath, environment, workspaceId } = req.query;
|
||||||
|
if (req.auth.actor === ActorType.SERVICE) {
|
||||||
|
const scope = ServiceTokenScopes.parse(req.auth.serviceToken.scopes);
|
||||||
|
const isSingleScope = scope.length === 1;
|
||||||
|
if (isSingleScope && !picomatch.scan(scope[0].secretPath).isGlob) {
|
||||||
|
secretPath = scope[0].secretPath;
|
||||||
|
environment = scope[0].environment;
|
||||||
|
workspaceId = req.auth.serviceToken.projectId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspaceId || !environment)
|
||||||
|
throw new BadRequestError({ message: "Missing workspace id or environment" });
|
||||||
|
|
||||||
|
const secret = await server.services.secret.getSecretByNameRaw({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
environment: req.query.environment,
|
environment,
|
||||||
projectId: req.query.workspaceId,
|
projectId: workspaceId,
|
||||||
path: req.query.secretPath,
|
path: secretPath,
|
||||||
secretName: req.params.secretName,
|
secretName: req.params.secretName,
|
||||||
type: req.query.type,
|
type: req.query.type,
|
||||||
includeImports: req.query.include_imports
|
includeImports: req.query.include_imports,
|
||||||
|
version: req.query.version
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.services.auditLog.createAuditLog({
|
await server.services.auditLog.createAuditLog({
|
||||||
@@ -411,6 +427,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
environment: z.string().trim(),
|
environment: z.string().trim(),
|
||||||
secretPath: z.string().trim().default("/"),
|
secretPath: z.string().trim().default("/"),
|
||||||
type: z.nativeEnum(SecretType).default(SecretType.Shared),
|
type: z.nativeEnum(SecretType).default(SecretType.Shared),
|
||||||
|
version: z.coerce.number().optional(),
|
||||||
include_imports: z
|
include_imports: z
|
||||||
.enum(["true", "false"])
|
.enum(["true", "false"])
|
||||||
.default("false")
|
.default("false")
|
||||||
@@ -429,7 +446,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
AuthMode.IDENTITY_ACCESS_TOKEN
|
AuthMode.IDENTITY_ACCESS_TOKEN
|
||||||
]),
|
]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const secret = await server.services.secret.getASecret({
|
const secret = await server.services.secret.getSecretByName({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
environment: req.query.environment,
|
environment: req.query.environment,
|
||||||
@@ -437,7 +454,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
path: req.query.secretPath,
|
path: req.query.secretPath,
|
||||||
secretName: req.params.secretName,
|
secretName: req.params.secretName,
|
||||||
type: req.query.type,
|
type: req.query.type,
|
||||||
includeImports: req.query.include_imports
|
includeImports: req.query.include_imports,
|
||||||
|
version: req.query.version
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.services.auditLog.createAuditLog({
|
await server.services.auditLog.createAuditLog({
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { ForbiddenError, subject } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
|
||||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "@app/db/schemas";
|
import {
|
||||||
|
SecretEncryptionAlgo,
|
||||||
|
SecretKeyEncoding,
|
||||||
|
SecretsSchema,
|
||||||
|
SecretType,
|
||||||
|
TableName
|
||||||
|
} from "@app/db/schemas";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
@@ -530,7 +536,7 @@ export const secretServiceFactory = ({
|
|||||||
return { secrets: secrets.map((el) => ({ ...el, workspace: projectId, environment })) };
|
return { secrets: secrets.map((el) => ({ ...el, workspace: projectId, environment })) };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getASecret = async ({
|
const getSecretByName = async ({
|
||||||
actorId,
|
actorId,
|
||||||
actor,
|
actor,
|
||||||
projectId,
|
projectId,
|
||||||
@@ -538,6 +544,7 @@ export const secretServiceFactory = ({
|
|||||||
path,
|
path,
|
||||||
type,
|
type,
|
||||||
secretName,
|
secretName,
|
||||||
|
version,
|
||||||
includeImports
|
includeImports
|
||||||
}: TGetASecretDTO) => {
|
}: TGetASecretDTO) => {
|
||||||
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
|
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
|
||||||
@@ -551,12 +558,21 @@ export const secretServiceFactory = ({
|
|||||||
|
|
||||||
const secretBlindIndex = await interalGenSecBlindIndexByName(projectId, secretName);
|
const secretBlindIndex = await interalGenSecBlindIndexByName(projectId, secretName);
|
||||||
|
|
||||||
const secret = await secretDal.findOne({
|
const secret = await (typeof version !== undefined
|
||||||
folderId,
|
? secretDal.findOne({
|
||||||
type,
|
folderId,
|
||||||
userId: type === SecretType.Personal ? actorId : null,
|
type,
|
||||||
secretBlindIndex
|
userId: type === SecretType.Personal ? actorId : null,
|
||||||
});
|
secretBlindIndex
|
||||||
|
})
|
||||||
|
: secretVersionDal
|
||||||
|
.findOne({
|
||||||
|
folderId,
|
||||||
|
type,
|
||||||
|
userId: type === SecretType.Personal ? actorId : null,
|
||||||
|
secretBlindIndex
|
||||||
|
})
|
||||||
|
.then((el) => SecretsSchema.parse({ ...el, id: el.secretId })));
|
||||||
// now if secret is not found
|
// now if secret is not found
|
||||||
// then search for imported secrets
|
// then search for imported secrets
|
||||||
// here we consider the import order also thus starting from bottom
|
// here we consider the import order also thus starting from bottom
|
||||||
@@ -831,7 +847,7 @@ export const secretServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getASecretRaw = async ({
|
const getSecretByNameRaw = async ({
|
||||||
type,
|
type,
|
||||||
path,
|
path,
|
||||||
actor,
|
actor,
|
||||||
@@ -839,13 +855,14 @@ export const secretServiceFactory = ({
|
|||||||
projectId,
|
projectId,
|
||||||
actorId,
|
actorId,
|
||||||
secretName,
|
secretName,
|
||||||
includeImports
|
includeImports,
|
||||||
|
version
|
||||||
}: TGetASecretRawDTO) => {
|
}: TGetASecretRawDTO) => {
|
||||||
const botKey = await projectBotService.getBotKey(projectId);
|
const botKey = await projectBotService.getBotKey(projectId);
|
||||||
if (!botKey)
|
if (!botKey)
|
||||||
throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
|
throw new BadRequestError({ message: "Project bot not found", name: "bot_not_found_error" });
|
||||||
|
|
||||||
const secret = await getASecret({
|
const secret = await getSecretByName({
|
||||||
actorId,
|
actorId,
|
||||||
projectId,
|
projectId,
|
||||||
environment,
|
environment,
|
||||||
@@ -853,7 +870,8 @@ export const secretServiceFactory = ({
|
|||||||
path,
|
path,
|
||||||
secretName,
|
secretName,
|
||||||
type,
|
type,
|
||||||
includeImports
|
includeImports,
|
||||||
|
version
|
||||||
});
|
});
|
||||||
return decryptSecretRaw(secret, botKey);
|
return decryptSecretRaw(secret, botKey);
|
||||||
};
|
};
|
||||||
@@ -1007,10 +1025,10 @@ export const secretServiceFactory = ({
|
|||||||
createManySecret,
|
createManySecret,
|
||||||
updateManySecret,
|
updateManySecret,
|
||||||
deleteManySecret,
|
deleteManySecret,
|
||||||
getASecret,
|
getSecretByName,
|
||||||
getSecrets,
|
getSecrets,
|
||||||
getSecretsRaw,
|
getSecretsRaw,
|
||||||
getASecretRaw,
|
getSecretByNameRaw,
|
||||||
createSecretRaw,
|
createSecretRaw,
|
||||||
updateSecretRaw,
|
updateSecretRaw,
|
||||||
deleteSecretRaw,
|
deleteSecretRaw,
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ export type TGetASecretDTO = {
|
|||||||
environment: string;
|
environment: string;
|
||||||
type: "shared" | "personal";
|
type: "shared" | "personal";
|
||||||
includeImports?: boolean;
|
includeImports?: boolean;
|
||||||
|
version?: number;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TCreateBulkSecretDTO = {
|
export type TCreateBulkSecretDTO = {
|
||||||
@@ -145,6 +146,7 @@ export type TGetASecretRawDTO = {
|
|||||||
environment: string;
|
environment: string;
|
||||||
type: "shared" | "personal";
|
type: "shared" | "personal";
|
||||||
includeImports?: boolean;
|
includeImports?: boolean;
|
||||||
|
version?: number;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TCreateSecretRawDTO = TProjectPermission & {
|
export type TCreateSecretRawDTO = TProjectPermission & {
|
||||||
|
|||||||
Reference in New Issue
Block a user