mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 05:27:48 +00:00
auto scope raw secrets GET with service token
This commit is contained in:
@@ -3,12 +3,15 @@ import { Types } from "mongoose";
|
|||||||
import { EventService, SecretService } from "../../services";
|
import { EventService, SecretService } from "../../services";
|
||||||
import { eventPushSecrets } from "../../events";
|
import { eventPushSecrets } from "../../events";
|
||||||
import { BotService } from "../../services";
|
import { BotService } from "../../services";
|
||||||
import { repackageSecretToRaw } from "../../helpers/secrets";
|
import { containsGlobPatterns, repackageSecretToRaw } from "../../helpers/secrets";
|
||||||
import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto";
|
import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto";
|
||||||
import { getAllImportedSecrets } from "../../services/SecretImportService";
|
import { getAllImportedSecrets } from "../../services/SecretImportService";
|
||||||
import Folder from "../../models/folder";
|
import Folder from "../../models/folder";
|
||||||
import { getFolderByPath } from "../../services/FolderService";
|
import { getFolderByPath } from "../../services/FolderService";
|
||||||
import { BadRequestError } from "../../utils/errors";
|
import { BadRequestError } from "../../utils/errors";
|
||||||
|
import { IServiceTokenData } from "../../models";
|
||||||
|
import { requireWorkspaceAuth } from "../../middleware";
|
||||||
|
import { ADMIN, MEMBER, PERMISSION_READ_SECRETS } from "../../variables";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return secrets for workspace with id [workspaceId] and environment
|
* Return secrets for workspace with id [workspaceId] and environment
|
||||||
@@ -17,11 +20,31 @@ import { BadRequestError } from "../../utils/errors";
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const getSecretsRaw = async (req: Request, res: Response) => {
|
export const getSecretsRaw = async (req: Request, res: Response) => {
|
||||||
const workspaceId = req.query.workspaceId as string;
|
let workspaceId = req.query.workspaceId as string;
|
||||||
const environment = req.query.environment as string;
|
let environment = req.query.environment as string;
|
||||||
const secretPath = req.query.secretPath as string;
|
let secretPath = req.query.secretPath as string;
|
||||||
const includeImports = req.query.include_imports as string;
|
const includeImports = req.query.include_imports as string;
|
||||||
|
|
||||||
|
// if the service token has single scope, it will get all secrets for that scope by default
|
||||||
|
const serviceTokenDetails: IServiceTokenData = req?.serviceTokenData
|
||||||
|
if (serviceTokenDetails) {
|
||||||
|
if (serviceTokenDetails.scopes.length == 1 && !containsGlobPatterns(serviceTokenDetails.scopes[0].secretPath)) {
|
||||||
|
const scope = serviceTokenDetails.scopes[0]
|
||||||
|
secretPath = scope.secretPath
|
||||||
|
environment = scope.environment
|
||||||
|
workspaceId = serviceTokenDetails.workspace.toString()
|
||||||
|
} else {
|
||||||
|
requireWorkspaceAuth({
|
||||||
|
acceptedRoles: [ADMIN, MEMBER],
|
||||||
|
locationWorkspaceId: "query",
|
||||||
|
locationEnvironment: "query",
|
||||||
|
requiredPermissions: [PERMISSION_READ_SECRETS],
|
||||||
|
requireBlindIndicesEnabled: true,
|
||||||
|
requireE2EEOff: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const secrets = await SecretService.getSecrets({
|
const secrets = await SecretService.getSecrets({
|
||||||
workspaceId: new Types.ObjectId(workspaceId),
|
workspaceId: new Types.ObjectId(workspaceId),
|
||||||
environment,
|
environment,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import { EELogService, EESecretService } from "../ee/services";
|
|||||||
import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/auth";
|
import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/auth";
|
||||||
import { getFolderIdFromServiceToken } from "../services/FolderService";
|
import { getFolderIdFromServiceToken } from "../services/FolderService";
|
||||||
import picomatch from "picomatch";
|
import picomatch from "picomatch";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
export const isValidScope = (
|
export const isValidScope = (
|
||||||
authPayload: IServiceTokenData,
|
authPayload: IServiceTokenData,
|
||||||
@@ -60,6 +61,13 @@ export const isValidScope = (
|
|||||||
return Boolean(validScope);
|
return Boolean(validScope);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function containsGlobPatterns(secretPath: string) {
|
||||||
|
const globChars = ["*", "?", "[", "]", "{", "}", "**"];
|
||||||
|
const normalizedPath = path.normalize(secretPath);
|
||||||
|
return globChars.some(char => normalizedPath.includes(char));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object containing secret [secret] but with its value, key, comment decrypted.
|
* Returns an object containing secret [secret] but with its value, key, comment decrypted.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import {
|
|||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
"/raw",
|
"/raw",
|
||||||
query("workspaceId").exists().isString().trim(),
|
query("workspaceId").optional().isString().trim(),
|
||||||
query("environment").exists().isString().trim(),
|
query("environment").optional().isString().trim(),
|
||||||
query("secretPath").default("/").isString().trim(),
|
query("secretPath").default("/").isString().trim(),
|
||||||
query("include_imports").optional().isBoolean().default(false),
|
query("include_imports").optional().isBoolean().default(false),
|
||||||
validateRequest,
|
validateRequest,
|
||||||
@@ -31,14 +31,6 @@ router.get(
|
|||||||
AUTH_MODE_SERVICE_ACCOUNT
|
AUTH_MODE_SERVICE_ACCOUNT
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
requireWorkspaceAuth({
|
|
||||||
acceptedRoles: [ADMIN, MEMBER],
|
|
||||||
locationWorkspaceId: "query",
|
|
||||||
locationEnvironment: "query",
|
|
||||||
requiredPermissions: [PERMISSION_READ_SECRETS],
|
|
||||||
requireBlindIndicesEnabled: true,
|
|
||||||
requireE2EEOff: true
|
|
||||||
}),
|
|
||||||
secretsController.getSecretsRaw
|
secretsController.getSecretsRaw
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ in plaintext. Effectively, this means each such secret operation only requires 1
|
|||||||
|
|
||||||
<AccordionGroup>
|
<AccordionGroup>
|
||||||
<Accordion title="Retrieve secrets">
|
<Accordion title="Retrieve secrets">
|
||||||
Retrieve all secrets for an Infisical project and environment.
|
Retrieve all secrets for an Infisical project and environment.
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab title="cURL">
|
<Tab title="cURL">
|
||||||
```bash
|
```bash
|
||||||
@@ -18,7 +17,12 @@ in plaintext. Effectively, this means each such secret operation only requires 1
|
|||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
####
|
||||||
|
<Info>
|
||||||
|
When using a [service token](../../../documentation/platform/token) with access to a single environment and path, you don't need to provide request parameters because the server will automatically scope the request to the defined environment/secrets path of the service token used.
|
||||||
|
For all other cases, request parameters are required.
|
||||||
|
</Info>
|
||||||
|
####
|
||||||
<ParamField query="workspaceId" type="string" required>
|
<ParamField query="workspaceId" type="string" required>
|
||||||
The ID of the workspace
|
The ID of the workspace
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|||||||
Reference in New Issue
Block a user