mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 05:26:25 +00:00
feat(secret-ref): removed migration field unset op, refactored service token scope check to a utility fn
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import picomatch from "picomatch";
|
|
||||||
import { ISecret, Secret, ServiceTokenData } from "../../models";
|
import { ISecret, Secret, ServiceTokenData } from "../../models";
|
||||||
import { IAction, SecretVersion } from "../../ee/models";
|
import { IAction, SecretVersion } from "../../ee/models";
|
||||||
import {
|
import {
|
||||||
@@ -33,6 +32,7 @@ import {
|
|||||||
getFolderIdFromServiceToken,
|
getFolderIdFromServiceToken,
|
||||||
searchByFolderId
|
searchByFolderId
|
||||||
} from "../../services/FolderService";
|
} from "../../services/FolderService";
|
||||||
|
import { isValidScope } from "../../helpers/secrets";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peform a batch of any specified CUD secret operations
|
* Peform a batch of any specified CUD secret operations
|
||||||
@@ -74,16 +74,11 @@ export const batchSecrets = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req.authData.authPayload instanceof ServiceTokenData) {
|
if (req.authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = req.authData.authPayload;
|
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, secretPath);
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
// in service token when not giving secretpath folderid must be root
|
// in service token when not giving secretpath folderid must be root
|
||||||
// this is to avoid giving folderid when service tokens are used
|
// this is to avoid giving folderid when service tokens are used
|
||||||
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
|
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -447,16 +442,15 @@ export const createSecrets = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req.authData.authPayload instanceof ServiceTokenData) {
|
if (req.authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = req.authData.authPayload;
|
const isValidScopeAccess = isValidScope(
|
||||||
const validScope = tkScopes.find(
|
req.authData.authPayload,
|
||||||
(scope) =>
|
environment,
|
||||||
picomatch.isMatch(secretPath || "/", scope.secretPath, { strictSlashes: false }) &&
|
secretPath || "/"
|
||||||
scope.environment === environment
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// in service token when not giving secretpath folderid must be root
|
// in service token when not giving secretpath folderid must be root
|
||||||
// this is to avoid giving folderid when service tokens are used
|
// this is to avoid giving folderid when service tokens are used
|
||||||
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
|
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -704,17 +698,15 @@ export const getSecrets = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req.authData.authPayload instanceof ServiceTokenData) {
|
if (req.authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = req.authData.authPayload;
|
const isValidScopeAccess = isValidScope(
|
||||||
const validScope = tkScopes.find(
|
req.authData.authPayload,
|
||||||
(scope) =>
|
environment,
|
||||||
picomatch.isMatch((secretPath as string) || "/", scope.secretPath, {
|
(secretPath as string) || "/"
|
||||||
strictSlashes: false
|
|
||||||
}) && scope.environment === environment
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// in service token when not giving secretpath folderid must be root
|
// in service token when not giving secretpath folderid must be root
|
||||||
// this is to avoid giving folderid when service tokens are used
|
// this is to avoid giving folderid when service tokens are used
|
||||||
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
|
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ import {
|
|||||||
GetSecretsParams,
|
GetSecretsParams,
|
||||||
UpdateSecretParams
|
UpdateSecretParams
|
||||||
} from "../interfaces/services/SecretService";
|
} from "../interfaces/services/SecretService";
|
||||||
import { ISecret, Secret, SecretBlindIndexData, ServiceTokenData } from "../models";
|
import {
|
||||||
|
ISecret,
|
||||||
|
IServiceTokenData,
|
||||||
|
Secret,
|
||||||
|
SecretBlindIndexData,
|
||||||
|
ServiceTokenData
|
||||||
|
} from "../models";
|
||||||
import { SecretVersion } from "../ee/models";
|
import { SecretVersion } from "../ee/models";
|
||||||
import {
|
import {
|
||||||
BadRequestError,
|
BadRequestError,
|
||||||
@@ -39,6 +45,21 @@ import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/aut
|
|||||||
import { getFolderIdFromServiceToken } from "../services/FolderService";
|
import { getFolderIdFromServiceToken } from "../services/FolderService";
|
||||||
import picomatch from "picomatch";
|
import picomatch from "picomatch";
|
||||||
|
|
||||||
|
export const isValidScope = (
|
||||||
|
authPayload: IServiceTokenData,
|
||||||
|
environment: string,
|
||||||
|
secretPath: string
|
||||||
|
) => {
|
||||||
|
const { scopes: tkScopes } = authPayload;
|
||||||
|
const validScope = tkScopes.find(
|
||||||
|
(scope) =>
|
||||||
|
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
||||||
|
scope.environment === environment
|
||||||
|
);
|
||||||
|
|
||||||
|
return Boolean(validScope);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
@@ -306,14 +327,7 @@ export const createSecretHelper = async ({
|
|||||||
|
|
||||||
// if using service token filter towards the folderId by secretpath
|
// if using service token filter towards the folderId by secretpath
|
||||||
if (authData.authPayload instanceof ServiceTokenData) {
|
if (authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = authData.authPayload;
|
if (!isValidScope(authData.authPayload, environment, secretPath)) {
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validScope) {
|
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,14 +473,7 @@ export const getSecretsHelper = async ({
|
|||||||
let secrets: ISecret[] = [];
|
let secrets: ISecret[] = [];
|
||||||
// if using service token filter towards the folderId by secretpath
|
// if using service token filter towards the folderId by secretpath
|
||||||
if (authData.authPayload instanceof ServiceTokenData) {
|
if (authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = authData.authPayload;
|
if (!isValidScope(authData.authPayload, environment, secretPath)) {
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validScope) {
|
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,14 +569,7 @@ export const getSecretHelper = async ({
|
|||||||
let secret: ISecret | null = null;
|
let secret: ISecret | null = null;
|
||||||
// if using service token filter towards the folderId by secretpath
|
// if using service token filter towards the folderId by secretpath
|
||||||
if (authData.authPayload instanceof ServiceTokenData) {
|
if (authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = authData.authPayload;
|
if (!isValidScope(authData.authPayload, environment, secretPath)) {
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validScope) {
|
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,14 +671,7 @@ export const updateSecretHelper = async ({
|
|||||||
let secret: ISecret | null = null;
|
let secret: ISecret | null = null;
|
||||||
// if using service token filter towards the folderId by secretpath
|
// if using service token filter towards the folderId by secretpath
|
||||||
if (authData.authPayload instanceof ServiceTokenData) {
|
if (authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = authData.authPayload;
|
if (!isValidScope(authData.authPayload, environment, secretPath)) {
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validScope) {
|
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,14 +819,7 @@ export const deleteSecretHelper = async ({
|
|||||||
|
|
||||||
// if using service token filter towards the folderId by secretpath
|
// if using service token filter towards the folderId by secretpath
|
||||||
if (authData.authPayload instanceof ServiceTokenData) {
|
if (authData.authPayload instanceof ServiceTokenData) {
|
||||||
const { scopes: tkScopes } = authData.authPayload;
|
if (!isValidScope(authData.authPayload, environment, secretPath)) {
|
||||||
const validScope = tkScopes.find(
|
|
||||||
(scope) =>
|
|
||||||
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
|
|
||||||
scope.environment === environment
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validScope) {
|
|
||||||
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,9 +446,6 @@ export const backfillServiceTokenMultiScope = async () => {
|
|||||||
$set: {
|
$set: {
|
||||||
scopes: [{ environment: "$environment", secretPath: "$secretPath" }]
|
scopes: [{ environment: "$environment", secretPath: "$secretPath" }]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
$unset: ["environment", "secretPath"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -292,7 +292,11 @@ func recursivelyExpandSecret(expandedSecs map[string]string, interpolatedSecs ma
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolatedVal := interpolatedSecs[key]
|
interpolatedVal, ok := interpolatedSecs[key]
|
||||||
|
if !ok {
|
||||||
|
HandleError(fmt.Errorf("Could not find refered secret - %s", key), "Kindly check whether its provided")
|
||||||
|
}
|
||||||
|
|
||||||
refs := secRefRegex.FindAllStringSubmatch(interpolatedVal, -1)
|
refs := secRefRegex.FindAllStringSubmatch(interpolatedVal, -1)
|
||||||
for _, val := range refs {
|
for _, val := range refs {
|
||||||
// key: "${something}" val: [${something},something]
|
// key: "${something}" val: [${something},something]
|
||||||
|
|||||||
Reference in New Issue
Block a user